diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c919b1d..89261e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,13 +24,24 @@ jobs: # default build, so lint it in a dedicated pass. - run: cargo clippy -p exav-core --all-targets --features unstable-internals -- -D warnings - run: cargo clippy -p exav-render --all-targets --features dwg -- -D warnings - - run: cargo clippy -p exav-render --all-targets --no-default-features --features ifc,stl -- -D warnings + - run: cargo clippy -p exav-render --all-targets --no-default-features --features ifc,stl,obj,ply,gltf -- -D warnings + - run: cargo clippy -p exav-render --all-targets --no-default-features --features markdown -- -D warnings + - run: cargo clippy -p exav-render --all-targets --no-default-features --features text-pdf -- -D warnings + - run: cargo clippy -p exav-render --all-targets --no-default-features --features office-sheets -- -D warnings + - run: cargo clippy -p exav-render --all-targets --no-default-features --features office-slides -- -D warnings + - run: cargo clippy -p exav-render --all-targets --no-default-features --features office-docs -- -D warnings + - run: cargo clippy -p exav-render --all-targets --no-default-features --features office,office-test-util -- -D warnings + - run: cargo clippy -p exav-render --all-targets --no-default-features -- -D warnings + - run: cargo clippy -p exav-render --all-targets --no-default-features --features text-office,office-test-util -- -D warnings + - run: cargo clippy -p exav-core --all-targets --features visible-text-office -- -D warnings + - run: cargo clippy -p exav-grep --all-targets --features text-office -- -D warnings + - run: cargo clippy -p exav-unpack --all-targets --features text-pdf -- -D warnings # The full native test matrix, every feature pass. Defined once in the # Makefile so this and a local `make test` can't drift. - run: make test-native - # The promised floor is `rust-version` in Cargo.toml (1.92, imposed by the - # hayro image decoders). `make msrv` reads it there and installs that toolchain on + # The promised floor is `rust-version` in Cargo.toml (1.95, imposed by the + # delharc LHA reader). `make msrv` reads it there and installs that toolchain on # demand, so a bump flows through with no edit here, and a contributor on # stable can't land a newer feature without this going red. msrv: @@ -194,7 +205,7 @@ jobs: # the masked fixtures are unmasked. seeds="$RUNNER_TEMP/fuzz-seeds" scripts/fuzz-seeds.sh "$seeds" - for t in filetype sigs cvd pe unpack analyze bytecode full_pipeline seekable yara pcre clamd icap volumes authenticode database ndb_compile rar3_ppmd pe_emulator x86_decode parser_recursion imagehash drawing cad_dxf cad_dwg ifc; do + for t in filetype sigs cvd pe unpack analyze bytecode full_pipeline seekable yara pcre clamd icap volumes authenticode database ndb_compile rar3_ppmd pe_emulator x86_decode parser_recursion imagehash drawing cad_dxf cad_dwg ifc mesh; do mkdir -p "fuzz/corpus/$t" extra="" [ -d "$seeds/$t" ] && extra="$seeds/$t" diff --git a/.github/workflows/www.yml b/.github/workflows/www.yml index bdf952f..68659e8 100644 --- a/.github/workflows/www.yml +++ b/.github/workflows/www.yml @@ -49,6 +49,10 @@ jobs: --site "${{ steps.pages.outputs.origin }}" \ --base "${{ steps.pages.outputs.base_path }}" working-directory: ${{ env.BUILD_PATH }} + # Every internal link and #anchor of the built pages must resolve (offline, + # a second or two). The demo's own pages are copied in below. + - name: Check internal links + run: node scripts/check-links.mjs ${{ env.BUILD_PATH }}/dist # The @exav/viewer demo, served at /viewer/demo/: the package and its wasm # modules built from this commit, the archive engine's pkg/ too. - uses: dtolnay/rust-toolchain@stable @@ -71,8 +75,14 @@ jobs: npm ci npm run build:wasm npm run build - # The sidebar's files: github.com/sylvinus/exav-samples, HEAD. + # The sidebar's files, from the network: github.com/sylvinus/exav-samples, HEAD. npm run demo:showcase + # `demo:build` runs `npm run demo:examples` first: the example files + # committed under demo/examples/files/ are copied, and the others (tens + # of MB, from Zenodo, figshare, Wikimedia Commons and the like) are + # downloaded at build time, each checked against its size and SHA-256 in + # demo/examples/examples.json. The build fails when one cannot be fetched + # or has changed. # DEMO_ORIGIN goes into the sandboxed frame's policy, for Safari. DEMO_BASE="${{ steps.pages.outputs.base_path }}/viewer/demo/" DEMO_ORIGIN="${{ steps.pages.outputs.origin }}" npm run demo:build # dist/viewer/ holds the File viewer docs; the demo must not land on them. diff --git a/.oss-scanner/Dockerfile b/.oss-scanner/Dockerfile index 420c585..9795919 100644 --- a/.oss-scanner/Dockerfile +++ b/.oss-scanner/Dockerfile @@ -4,7 +4,7 @@ # # Build it the way the scanner does, from the repository root: # docker build -f .oss-scanner/Dockerfile -t exav-oss-scanner . -FROM rust:1.92-bookworm +FROM rust:1.95-bookworm # Frame pointers and line tables for a debugger, without the full debug info # that makes the build several times larger. diff --git a/CHANGELOG.md b/CHANGELOG.md index 3df5588..16744a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,484 @@ follow [semantic versioning](https://semver.org/). ## [Unreleased] +### Added + +- **Pictures of pages from the formats that draw something.** + `controllers.pictures` gives `raster(page, options)`, `toBlob(page, options)` + and `render(page, longEdge)`. A page is drawn again from the document's own + data at the size asked for, with a `region` in the format's coordinates (a + fraction of a page, pixels of an image, drawing units with `layout`, a 3D + camera) or `"current"`, `fit` ("contain" or "cover"), `lineweight`, + `background` and an `AbortSignal`. The result reports the region actually + drawn. `controllers.viewport` is what the session shows now, in the same + coordinates. Errors are a `RasterError` (`unsupported`, `too-large`, + `aborted`, `invalid`, `failed`). Pictures are limited to 16,384 px a side and + 64 Mi pixels in all, in the page and in the sandboxed frame, and are encoded + by the host page. The demo has an "Export image" button beside the file's + name, which opens a dialog of options. +- **A full screen button** in the viewer's tools (`FullscreenToggle`, a piece a + host can replace) puts the viewer's box in full screen, from the host page, + and leaves it. It is not shown where the browser has no full screen. Hosts + drawing their own controls get `useFullscreen(() => element)` and + `usePanel(info?)` (the side panel's fold state, shared by the rails and the + toggle) from `@exav/viewer/react`. +- **`session.replace` works in the sandboxed frame**, so zoom and place are + kept when a host swaps a document, for PDF and images. +- **A format registry** (`formats/registry.json`, 117 formats) from which the + format matrix page and the viewer summary are generated, and which + `make test-formats` and the viewer's and the scanner's tests check against + the extractor's formats, the scanner's file types and the viewer's matchers. +- **Virtual disks read in place.** VHD (fixed and dynamic), VHDX, QCOW2 + (stored, deflate and zstd clusters) and VMDK (sparse and streamOptimized) are + read through a `Read + Seek` that reads the container's tables as the walk + reaches them and keeps only a 32 MiB cache of decoded units, so a disk of any + declared size costs what it holds. A disk over the buffer limit is walked + through its partitions and its NTFS and FAT files come out one at a time; a + smaller one is still one member. What a disk decodes is counted against the + scan budget. NTFS and FAT are read in place too, and a raw NTFS or FAT image + or partition over the limit is walked instead of refused or streamed whole. + ext is still copied into memory, as its volume only. +- **3D model pictures and viewport.** IFC, STL, OBJ, PLY and glTF expose + `controllers.pictures` (one page) and `controllers.viewport`. A picture is + redrawn from the geometry by an off-screen renderer at the requested size, in + tiles beyond GPU limits, with MSAA or supersampling and a transparent or any + CSS colour background. Regions are cameras in the file's own coordinates. + `region: "current"` is the live camera, `fit` contain or cover applies, and + hidden categories stay hidden. The `rasterTile` and `rasterSupersample` + plugin options are for testing and tuning. +- **DWG and DXF pictures and viewport.** `pictures.raster` draws any layout + again from the drawing's vectors at the asked pixel size, in a WebGL context + of its own (tiled and composed past the GPU's limits). It takes a region in + drawing units (y up, model units or a sheet's paper units), a size, `fit`, + `lineweight` "screen" or "scaled", any CSS colour or a transparent ground, + and a `layout` id, and reports the region actually drawn. The `viewport` + store gives the layout and region in view, and `region: "current"` draws it. + One picture is drawn at a time per session, abortable. The `rasterTile` + option tunes the tile size. +- **Pictures and viewport for Word, PowerPoint, Excel and CSV.** + `controllers.pictures` draws a page, slide or sheet at any size and region + (fractions of the page; a sheet's page is its used area at 100% without + headers), and `controllers.viewport` reports the page most in view and the + visible part. The converted formats (DOC, ODT, RTF, XLS, ODS, Numbers, PPT, + ODP, Keynote, ODG and the external converter's PDF or XLSX) get them too. + Pictures are drawn from a second copy of the document and queued one at a + time. A region whose whole page would pass the engines' 16.7 M pixel limit is + refused as too large, and `background: "transparent"` is refused. +- **Pictures of a video's current frame.** `controllers.pictures` on video + (page 1, space "frame"). A video the page cannot read (another origin without + CORS, or a URL given to the sandboxed frame) is refused as unsupported + instead of drawn blank. +- **IFC curved faces, trimming, alignments and storeys.** B-rep faces on + spheres, tori and cylinders (sphere caps and seamless tubes included) are + meshed in their surface's parameters instead of flat. B-spline faces are cut + by their bounds, holes included. `StartParam`/`EndParam` of swept disks and + directrix sweeps are honoured. IFC4X3 curve segments (lines, circles, + clothoid and polynomial spirals, polynomial curves), gradient curves and + linear placements without a Cartesian position are evaluated, and + `IfcGridPlacement` sits at its grid intersection. exav-render reports + `Element::storey`, `Batch::storey` and `Node::elevation`, and `@exav/viewer` + has a `storeys` controller with a show/hide list. Conical faces + (`IfcSurfaceOfRevolution`) are still drawn flat. +- **Camera RAW files open in the viewer and in exav-render**, shown by the + largest JPEG or RGB preview they embed, turned by their Exif orientation + (`exav_render::image::raw`, feature `raw`, default; `decode_any` reads a RAW + file by its preview, `Format::detect` and `decode` still read a TIFF-structured + one as the TIFF it also is, so exav-imagehash is unchanged). DNG, Canon CR2, + CR3 and CRW, Nikon NEF and NRW, Sony ARW, SR2 and SRF, Olympus ORF, Panasonic + RW2, RAW and Leica RWL, Fujifilm RAF, Pentax PEF, Samsung SRW, Hasselblad 3FR, + Phase One IIQ, Sigma X3F, Kodak, Epson and Leaf files are told by their bytes, + never their names, and a plain TIFF stays a TIFF. The sensor data is not + decoded: a file that embeds no preview (most phones' DNG, Minolta MRW, the + newest CR3 whose preview is HEIF) is `Error::NoPreview`, and the viewer says + so (`image_no_preview`). Every offset and count in the file is bounds-checked, + directory chains and loops are capped, and previews count against the decode + budget as the RGBA a page holds. New `raw_preview` fuzz target. +- **The visible text of legacy and flat office files.** `text-office` + (`exav-render`, `exav-grep`) and `visible-text-office` (`exav-core`, `exav`), + opt-in, put the text of DOC, XLS, PPT, RTF, Word 2003 XML, SpreadsheetML 2003, + SYLK, FODT, FODS, FODP, FODG, Numbers, Pages and Keynote in the text view. A + match is located by sheet or slide, a link is `label (target)` and + `--detect phishing` judges it; an encrypted, over-limit or damaged file makes + the scan PARTIAL, never clean. Compound files are read as office documents by + their extension only. +- **Demo examples.** 243 freely licensed example files (145 committed, 98 + fetched by `npm run demo:examples` and checked against their SHA-256), with a + manifest, an attributions page and a NOTICE. +- **Office documents, spreadsheets, presentations and drawings converted in + safe Rust, inside exav-render.** The features `office-sheets`, + `office-slides`, `office-docs` and `office` (`exav_render::office`; none is + a default feature) turn XLS (BIFF2 to BIFF8), ODS, FODS, OTS, Numbers ('08 and + later), Excel 2003 XML, HTML tables and SYLK into XLSX; PowerPoint 95 to 2003 + (with .pps and .pot), ODP, OTP, FODP and Keynote 1 and later into PPTX; + DOC and DOT (Word 6 to 2003), ODT, OTT, FODT, RTF, Word 2003 XML and Apple + Pages (5 and later) into DOCX; and ODG, OTG, FODG and Visio 2013+ (VSDX, VSDM, + VSTX, VSTM) drawings into PPTX, a page to a slide. @exav/viewer shows the + result with `xlsx()`, `pptx()` and `docx()`, in a worker per file, from the + `sheets`, `slides` and `docs` wasm modules (450, 434 and 359 KB brotli). The + files are read as they are + stored, nothing recalculated; tables, lists, sections, notes, fields, + pictures, charts and shapes are kept; tracked changes in DOC are drawn as + strike-through and underline. Input, cells, paragraphs, memory and + decompressed parts are bounded (`Limits`); an encrypted file, one over its + limits or a damaged one is reported with its reason. Fuzz targets + `sheets_xls`, `sheets_ods`, `sheets_numbers`, `sheets_text`, `slides_ppt`, + `slides_odp`, `slides_keynote`, `slides_odg`, `slides_vsdx`, `docs_doc`, + `docs_odt`, `docs_rtf`, `docs_wml` and `docs_pages`. +- **Older presentations.** PowerPoint 95 and Keynote 1 to 5 (XML) are read. + PowerPoint 2 to 4 (Windows, Macintosh, BinHex) are recognised and reported as + unsupported. A presentation the converter recognises and cannot convert ends + in an error with its kind. Also added: picture bullets (ODP, PPT), + charts stored in PPT files as ODF packages, Keynote tables, charts and movies, + inline pictures and charts in flat ODP, tile sizes from the picture's + resolution, text areas of custom shapes, per-path fill and stroke, even-odd + fills and the default style of unstyled shapes. +- **Large decks and long documents are laid out progressively.** The viewer + asks @silurus/ooxml for `progressiveLayout` past 32 slides or 64 KB of + inflated `document.xml`; on a 300-page document the first page shows in about + 2 s instead of about 19 s. +- **`maxArchiveEntries` for Word, Excel, PowerPoint and CSV** (`docx()`, + `xlsx()`, `pptx()`, `csv()`): the most entries a document's ZIP may list. + The default is now 20000; @silurus/ooxml's own 4096 refused a deck of about a + thousand slides with pictures. The size a document may inflate to keeps its + limit. +- **Volume sets are scanned as the archive they are.** A RAR set + (`x.part1.rar`, `x.r00`), a ZIP set (`x.z01`, ..., `x.zip`) and a CAB set (the + cabinets name one another) are rejoined and scanned whole, when their volumes + sit in one directory (`exav DIR`), when one volume is named and its siblings + are next to it (regular files only, never a symbolic link), and when they are + sent together to the daemon. A set with a volume missing is `PARTIAL`, never + clean. A cabinet read alone now reports the member that continues in another + one instead of leaving it out. +- **ELF and Mach-O `EP` and section offsets** (`EP`, `Sn`, `SL`, `SEn`) match + as they do in clamscan, read from the headers. Each was measured against + clamscan 1.4.3. `EP` on a Mach-O is not resolved there either. +- **The viewer opens more archives:** cab, chm, iso, lzh, arj, ar and deb, + cpio, xar and pkg, dmg, wim, zst, lz4, lz and Z files, tarballs of each + compression, zoo, arc, alz, egg, jar and the other packages that are zips + (apk, ipa, xpi, whl, nupkg, vsix, msix), comic books (cbz, cbr, cb7, cbt), + virtual disks (vhd, vhdx, vmdk, qcow2) and `winmail.dat`, by name, by the + type a desktop gives the file, or by the first bytes for a member of an + archive. A `.tgz` typed `application/x-compressed-tar`, as a Linux desktop + types it, is claimed now. +- **Text previews in the viewer** (`text()`, `@exav/viewer/text`): plain text, + logs, Markdown, JSON, XML, YAML, TOML and INI, source code, subtitles and + diffs, and HTML as source. Nothing in the file is parsed as markup; Markdown + is read in WebAssembly by pulldown-cmark (CommonMark, tables, strikethrough, + entities and reference links) through exav-render's new `markdown` feature + (`forbid(unsafe_code)`, linear on every hostile input tried, a `markdown` + fuzz target), and drawn element by element. A Markdown link shows its address + and opens it on a click, as a PDF's links do (the host asks first in the + frame), images are never loaded, bidirectional and control characters are made + visible, a file is cut at 2 MiB and 50,000 lines with a warning, and a binary + file is refused. The new `exav_viewer_text.wasm` module is about 190 KB (82 KB + gzipped), loaded when a Markdown file is opened; if it fails to load, the + text is shown as it is with a warning. +- **A visible-text layer, in the scanner and in `exav-grep`.** A document is + matched through the text a reader sees as well as its bytes: its words without + the marks, tags, escapes or run boundaries, entities decoded, and each link + followed by where it goes (`label (target)`, even for a `javascript:` target + or one with credentials), as a text view that `Target:0` and `Target:7` + signatures see. That lets a signature match a phrase Word split across runs, + a PDF kerned into pieces, or a link whose label names one site over a target + on another. Read: Markdown (pulldown-cmark), HTML (html5gum's tokenizer, no + tree), the XML parts of Word, PowerPoint, Excel and OpenDocument files by + their path (quick-xml), AutoCAD drawings (the text, attributes, dimension and + multileader texts, block and layer names, from exav-render's drawing model), as + the input or as an archive member; and PDF (hayro) with the `visible-text-pdf` + feature, which is not a default (see below). With `--alert-phishing`, a link + whose label names one site and whose target another is now judged in these + documents as an HTML anchor is, which also catches an HTML link whose target is + written in entities. It is the new `visible-text` feature of `exav-core` and + `exav` (default; off under `--clamav-compat`); an object past + `--max-object-bytes` is not read and the scan is reported incomplete. + `exav-grep --text` searches the same text, reporting `file.md!text` with the + text's line numbers. exav-unpack has the `text` and `text-pdf` features and + `exav_unpack::text`, exav-render `text` and `text-pdf` and + `exav_render::text::visible_text`, and there is a `visible_text` fuzz target. + RTF and email headers have none yet (see `docs/BACKLOG.md`). +- **PDF text is opt-in (`visible-text-pdf`, `exav-grep`'s `text-pdf`).** + hayro-interpret turns on `hayro-syntax`'s `unsafe` feature itself, which + switches every `flate2` in the build to zlib-rs (a damaged stream then gives + back other bytes: two of exav-unpack's tests fail with it) and adds SIMD to + the image decoders. hayro also puts no bound on what a stream decompresses to + (a 1 MB PDF took 2.1 GB), so exav gives it a PDF only after its own reader has + taken every stream within the limits. Built without hayro's predefined CJK + CMaps, which would bring `brotli`. +- **More 3D models in the viewer and exav-render:** Wavefront OBJ, Stanford + PLY (ASCII and binary) and glTF 2.0 (`.gltf` with embedded buffers, `.glb`), + read in safe Rust with bounded triangulation, JSON, node trees and + accessors. Nothing a model names is fetched; a glTF that needs an external + file is reported, not shown. There is a `mesh` fuzz target for them. +- **JPEG XL in the viewer** (`.jxl`, first frame, 8-bit), decoded in + WebAssembly by zenjxl-decoder, a fork of the libjxl team's jxl-rs that is + `forbid(unsafe_code)`, within the viewer's decode budget. The image module + grows from 1.1 to 1.65 MB. exav-render has it as the `jxl` feature, off by + default. +- **A host can draw the whole viewer UI itself, the files still sandboxed.** + The frame draws the document and nothing else; new controllers give the + rest to the page: `media` (play, pause, seek, volume, rate; `video({ + controls: "none" })` drops the browser's own player controls), `sheets` (an + Excel workbook's sheets, whose tabs the UI now draws: the engine's are gone), + `pictures` (a page of a PDF or an image drawn whole as an `ImageBitmap`, for + thumbnails and printing, at most 4096 px a side), and zoom for Word, Excel + and CSV, page jumps for Word and slides. `printPictures` prints from those + pictures, which the frame cannot and which a TIFF or a PDF cannot from its + URL. The arrows and Escape pressed in the frame, when the document does not + use them, reach the page's listeners (navigation keys only, at most 30 a + second; `keys`). The frame takes the page's `--exav-viewer-*` colours and colour + scheme, read where it is mounted (`theme`, `restyle()`), so a text file or a + Markdown page in it follows a dark theme. In the frame, the iframe fills its + element without the stylesheet. `demo/headless.html` is such a host, in + plain DOM, and has the browser tests of all this. +- **SVG in the viewer**: drawn as an ``, which runs none of its script and fetches nothing it names, + and drawn again sharp when zoomed. **FLAC** is played with the rest. +- **The viewer speaks German, Spanish and Dutch**, and its strings are exported + by `@exav/viewer` for hosts without React. +- **The viewer says what a load is doing, and how far it is.** A loading + status carries a `step` (the file's bytes, the engine's download, its start, + reading, converting, drawing) and the share of that step done, where it is + counted; the default UI words each step and draws a bar, and the sandboxed + frame passes both to the host. +- **DWG and DXF drawings closer to AutoCAD's.** A polyline with width is a + filled band (its outline under `$FILLMODE` 0). Lineweights are millimetres on + a layout's sheet, shown when the drawing's `$LWDISPLAY` says so (the cad + `lineweights` option: `"drawing"`, `"always"`, `"never"`). A text crossing a + viewport's edge is cut at it rather than kept or dropped whole. A block + clipped with XCLIP shows only what is inside its boundary, with the frame + `$XCLIPFRAME` asks for. Transparency holds for an entity in its layer's or + block's colour; translucent geometry blends over everything behind it in + draw order, text included, and is no darker where a polyline's segments + meet. What is not drawn is said: entities by type (a warning's new + `names`), xrefs counted with the other external references and their path + drawn where they are inserted, the files they name listed; a drawing with + nothing drawn here (a 3D model) keeps the thumbnail it was saved with. + Text follows its block mirrored or stretched, and TEXT's backward and + upside-down flags; Bottom and Middle alignment sit on the descender as in + AutoCAD; Aligned keeps its width factor. MTEXT takes its style's width + factor and slant, and draws `\W`, `\Q`, `\T`, paragraph justification, + stacked fractions, background masks and frames; multiline attributes and a + multileader's text are drawn as MTEXT. `%%nnn` and `\X` are read; symbol.ttf, + the SHX Greek fonts and gdt.shx show the characters they stand for; text the + stroke font lacks (Chinese in an SHX style) is drawn in an outline face, + completed from the browser's fonts; an invisible constant attribute is not + drawn; Greek and Cyrillic wrap at their own widths. A drawing with more + characters than the glyph atlas affords at a close zoom draws them as + distance fields, sharp at any zoom. A hatch pattern a unit or less apart + fades as it crowds below a pixel instead of turning solid; one too dense to + draw at all fills its region in a half tone instead of leaving it empty. + 3DFACE hides the edges its flags hide; points take `$PDMODE` and + `$PDSIZE`; polyface and polygon meshes and MESH are drawn as their edges; + TOLERANCE draws its feature control frame; a leader's arrowhead is its + style's (`DIMLDRBLK`), and a multileader draws its leader to the landing + with its arrowhead. Circles, arcs and a polyline's bulges are true arcs + however close the view, no longer polygons. A dashed polyline restarts its + pattern at each vertex unless `PLINEGEN` runs it on. AutoCAD's complex + linetypes (TRACKS, ZIGZAG, FENCELINE1 and 2, BATTING) draw their shapes, + and a linetype's text sits in its gap rather than a gap's length early, + over the dash before it. A dimension saved without the block AutoCAD draws + it from, as some generators write them, is drawn from its definition + points and its style: linear, aligned, radius, diameter, angular and + ordinate, its measurement in the style's decimal places, separator and + zero suppression. Yellow, cyan and the + lightest colours are darkened on a light ground, the darkest blues lightened + on a dark one, so a line or a text stays legible (fills keep their colours); + the cad `monochrome` option draws everything in ink, as monochrome.ctb + plots. A layout is drawn on its sheet of paper, with the ground around it. + A line's anti-aliased edge blends over what lies + behind it, without the halo of paper it used to leave where it crossed + another line, and a solid fill's edge is anti-aliased too. A stray entity far from the drawing (a line left at the + origin of a plan in national grid coordinates) no longer shrinks it to a + speck nor costs it its precision; the zoom stops where precision would run + out, and the zoom controller says how far it goes. Tessellating takes a + third less memory at its peak, the page no longer keeps a copy of the + geometry once it is on the GPU, and a lost GL context comes back with the + drawing on it. + +### Changed + +- **Dependencies are at their latest versions**, except the image decoders + pinned to the versions libclamav 1.5.4 links (`image`, `png`, `gif`, + `zune-jpeg`, `fax`, `weezl`), which `exav-imagehash` needs for ClamAV's hash. + Notable: `quick-xml` 0.42, `hfsplus` and `apfs` 0.4, `cfb` 0.15, + `lzma-rust2` 0.23, `sevenz-rust2` 0.24, `delharc` 0.8 (which also reads + PMarc LHA archives), `base64` 0.23, `bit-set` 0.11, `yara-x-parser` 1.19; + and for the viewer and docs, Vite 8, vitest 5, jsdom 30 and Playwright 1.64. + This clears three RustSec advisories (`ctutils`, `rustls-webpki`, + `webpki-roots`). +- **The minimum Rust version is 1.95** (it was 1.92), which `delharc` 0.8 + requires. It also leaves a single `lzma-rust2` in the tree. +- **QCOW2** images with an external data file, extended L2 entries or other + unknown incompatible features are reported instead of misread, and **VMDK** + grain table entries are read with the header's `numGTEsPerGT`. +- **Salvage keeps more of a damaged cabinet and archive.** A CAB MSZIP block cut + or damaged part way keeps what it decoded; a cut at the end of the file is + not reported, damage is. A ZIP member of a codec the `zip` crate lacks that + fails part way keeps the bytes before the failure and is reported. An + InstallShield Z member that stops short or fails part way keeps its decoded + start and is reported, where it used to come out as whole or be dropped. +- The sandboxed frame's protocol is version 5 (it was 4): `draw` and `drawn` + became `raster` and `rastered`, `replace` and `replaced` are new, and each + `read` names its document. `MAX_PICTURE_EDGE` is 16,384 (was 4,096) with a + new `MAX_PICTURE_PIXELS`, and the `pictures` store holds `{ count, space }`. + The page and the frame must come from the same release. +- **`controllers.viewport` is worked out only while it is used.** A session that + never reads it no longer measures the layout of Word, PowerPoint and PDF + pages, and in the sandboxed frame no longer opens a second copy of every + spreadsheet's workbook, which the frame's own reading of it did. The viewport is kept up to date while the store has a + listener, and a `get()` without one works it out once (a sheet's is measured + asynchronously, so its `get()` has the last measure and starts the next). In + the sandboxed frame, the host sends `watch` when the first listener arrives + and `unwatch` when the last leaves; the frame reports the viewport only + between them, and a `get()` without a listener returns the last value the + frame reported and asks for a fresh one. The demo's "Export image" follows it + only while "What I see" is chosen. +- The viewer's description names OBJ, PLY and glTF wherever it named IFC and + STL. +- A batch of an IFC scene now holds one storey's elements, so a scene can hold + more batches. A face whose edge loop cannot be read counts in + `warnings.invalid`, and surface evaluation and edge sampling have their own + per-file budget. +- **External converter for the formats the package does not read.** A binary + Visio, CorelDRAW, Publisher, WordPerfect or other Document Liberation file + goes to an external converter: an ES module exporting + `convert(bytes, { hint, maxMemory, signal, onProgress })` that resolves to + `{ format: "pdf" | "xlsx", bytes }`, set with the `externalConverter` option, + `exavViewer({ externalConverter })` in `@exav/viewer/vite` or + `exav-viewer-assets --external-converter`; the `converter` option is `"exav"` + or `"external"`. Without one, such a file ends in the new error + `needs_converter`. +- `@silurus/ooxml` 0.89.1. +- The PPTX writer names slides (``) and writes another Application + string in `app.xml`. + +- **The sandboxed frame may autoplay** (`allow="autoplay"`, `autoplay=*` in its + `Permissions-Policy`): a player started by the page's controls would + otherwise refuse to play. Update a frame served with its own headers. The + frame's protocol is version 4: the frame and the page must come from the + same release. +- Escape handed back by the frame closes `ViewerDialog`. +- **The viewer's CSS prefix is `exav-viewer-`**, in place of `exv-`: its custom + properties (`--exav-viewer-accent`...) and its class names. Rename them in a + theme or a stylesheet written for 0.0.2. + +- A JBIG2 stream in a PDF has the same bound on the pixels of its regions as a + JBIG2 file (512 MiB), whatever memory the caller allows. +- The `extreme` sweep reports a decoder that does not end (10 s) as well as one + that panics. +- **Fewer dependencies, less `unsafe`.** DMG's LZFSE and LZVN runs are decoded + by a port of Apple's reference decoder in exav-unpack, checked against it on + damaged streams too (differential tests, run on request), in place of + `lzfse_rust`. InstallShield Z archives are + read in-tree, in place of `unshield` and `explode` (and `arraydeque`). The + vendored TIFF decoder holds 16-bit float samples as their bits, which drops + `half` and `zerocopy`; zstd is built without its checksum (`twox-hash`), which + exav never checked; and `goblin` without the parsers exav does not use. A + default build has 8 crates fewer, and 1,155 fewer `unsafe` uses in the code it + links (plus 807 in `zerocopy`'s derive macro). + +### Fixed + +- **A malformed `raster` message to the sandboxed frame is answered.** The frame + dropped one whose options failed the checks, so the host's promise stayed + pending until aborted; the frame now answers `rastered` with the error + `invalid`, which rejects with a `RasterError`. +- **QCOW2:** an L2 entry with flags and no offset read the file's own header as + disk data. **VMDK:** a grain table entry of 1, a zeroed grain, read sector 1 + of the file. +- **LZFSE, LZVN and DCL on damaged streams.** An LZVN payload whose end opcode + was read but whose declared size exceeded the input was reported as cut + instead of damaged. An LZVN instruction past the block's declared size was + called damage before the output limit was applied, dropping the part that + fits. A DCL stream with a bad first header byte and no second was reported + cut. Found by comparing the decoders with Apple's lzfse and zlib's blast on + damaged streams. +- IFC: a cylindrical B-rep face bounded by two circles was drawn flat, a + B-spline face was drawn over its whole surface, and a grid-placed element sat + at its parent's origin. +- **PDF strings:** `\b` and `\f` were read as the letters, which gave a wrong + owner key, so an encrypted PDF that opens with an empty password was reported + password-protected. A short octal escape such as `\0` also swallowed the byte + after it, closing parenthesis included. Found by a differential run against + ClamAV (`docs/DIFFTEST_TRIAGE.md`). +- **An object is scanned once per scan when its bytes were already scanned + clean** in the same place: same container type, same types above it, same + name extension, at the same depth or shallower. A document that holds copies + of itself used to be scanned once per copy (a 5 MB file that unpacks to 660 + MB, 152 members of which 50 differ, took 30 s and now takes 3 s). Only a + member of 64 KiB to 512 MiB that came out clean and complete is remembered, + by a SHA-256 of its bytes and place; a copy that is not clean, or that sits + deeper, is scanned as before. +- **Carving** counts a ZIP stapled into an object once. Each local header after + the first used to be an archive candidate of its own: a zip of a few dozen + entries filled the cap of 32 and the object was reported over a limit, and the + rest of the object was rescanned once per entry. A header at the offset the + previous one says the next entry begins (no data descriptor, encryption or + ZIP64 size) is no longer a candidate; the first one's walk reads it. + +- **A zstd stream of a few kilobytes can no longer take gigabytes of memory** + (RUSTSEC-2026-0344): ruzstd 0.9.1 bounds what one block decodes to. Also + rustls 0.23.46 (RUSTSEC-2026-0346 to 0349), in the `http` builds. +- **Two InstallShield Z members with the same path are both scanned.** The + reader kept only one of them. +- **Each dynamic block in an AutoCAD 2007 or later DWG is drawn as itself.** + AutoCAD's files can name several anonymous blocks plain `*U`, and every + insert of one drew the first; they are numbered as AutoCAD numbers them. + +Found by an 8-hour fuzzing run: + +- **An InstallShield Z archive can no longer ask for billions of members.** A + few hundred bytes of directory records made the reader build an entry for each + declared member before anything was checked (1.5 GB). A table declaring more + than 20,000 is reported as unexamined. +- **A YARA rule with an error deep inside parentheses is refused at once.** The + parser took about 2^d steps for an error inside d open parentheses (5.6 s for + 3.5 KB of rule text). Nesting past 12 is a compile error. +- **RAR key derivation is bounded for the whole scan.** The bound was per + archive, so archives inside archives each paid it, and one header asking for + 2^24 PBKDF2 iterations cost 2.6 s. It is now 2^22 iterations (about 0.7 s) for + RAR5 and 256 derivations for RAR3, counted across the scan. An archive asking + for a larger count is reported as encrypted, like one no password opens. + +Found by fuzzing the virtual disk walker and the Office readers: + +- **A FAT directory or file at cluster 1 no longer ends the walk of the whole + volume.** The `fatfs` crate subtracts 2 from a cluster number it takes from + the volume without looking at it, so a directory entry or a chain naming + cluster 1 made it panic, and the panic was caught at the walk's boundary as + an undecodable volume, losing every other file. It now ends only that + directory or file, which is reported. +- **A PowerPoint 95 bullet size of 4,294,968 percent or more no longer panics.** + The size is dropped when it is not from 25 to 400, but the product was taken + first, and overflowed: a panic in a build that checks overflow. +- **Pinch and ctrl-wheel zoom on a DWG or DXF drawing no longer lags.** A frame + was drawn for every zoom event, and on a drawing that takes the GPU longer + than a frame they queued, so the view followed the fingers seconds late. + While the zoom goes on the canvas is now scaled where it is (a CSS + transform, at most once per animation frame) and the drawing is drawn sharp + when the zoom pauses. The zoom and viewport stores are published once per + frame instead of once per event, which is one message less per event to a + host of the sandboxed frame. The glyph page the closer view needs, made of + distance fields when the text is too large for the atlas budget, was made in + one piece, which held the page's thread for hundreds of milliseconds, when + the zoom stopped; it is now made in slices of 8 ms while the old page stays up. +- **A trackpad pinch on a DWG or DXF drawing zooms in Safari.** Safari reports + the pinch as gesture events, which the drawing only cancelled; they now zoom + by their scale about the fingers, as on an image. The ctrl+wheel events Safari + may send for the same pinch are ignored while the gesture goes on, so the + zoom is not applied twice. +- **A PDF zooms out past the page fitted to the width**, down to a quarter of + it (`pdf({ minZoom })`, default 0.25 instead of 1), so a whole page is in + view on any screen. The button back to the width shows once zoomed either way. +- **The side panel's toggle is among the tools**, bottom right beside the zoom + buttons (a `PanelToggle` piece), instead of in the panel's header and a + square at the top right when it is folded. It stays on a touch screen: what + is for a mouse (the zoom and drag groups, full screen) has the attribute + `data-pointer-only`, which a host's own piece can carry too. +- **The fit button of the zoom controls is shown only once the view is not the + fitted one**, and has a "back to the start" icon instead of the full screen + one. A Word document's zoom controller now reports its scale relative to the + page fitted to the width, as the others do relative to their fit. + ## [0.0.2] - 2026-10-11 The scanner, rebuilt around one streaming scan; three new projects (a browser diff --git a/Cargo.lock b/Cargo.lock index 8737f16..6c41e58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,6 +28,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + [[package]] name = "android_system_properties" version = "0.1.6" @@ -89,19 +98,48 @@ dependencies = [ [[package]] name = "apfs" -version = "0.2.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c1b4ecd96379464ea8b4ef2517c8eb674d8658ad364e9176bf5b8c278aa801e" +checksum = "6f959493f524db6102b1bd1884b58e3d632af70009441645287a7ee072944494" dependencies = [ "byteorder", + "cmpfs", "thiserror", ] [[package]] -name = "arraydeque" -version = "0.4.5" +name = "archmage" +version = "0.9.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0ffd3d69bd89910509a5d31d1f1353f38ccffdd116dd0099bbd6627f7bd8ad8" +checksum = "15785ee3576fbd41276a25f063b1e6b5bf323af9b4924632e25a8de6a3065f06" +dependencies = [ + "archmage-macros", + "safe_unaligned_simd", + "winarm-cpufeatures", +] + +[[package]] +name = "archmage-macros" +version = "0.9.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce7707714970d5cf476caccbae2d282000c6c14ca5aada878e722a10d8e1c153" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "ascii_tree" @@ -110,16 +148,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6c635b3aa665c649ad1415f1573c85957dfa47690ec27aebe7ec17efe3c643" [[package]] -name = "autocfg" -version = "1.5.1" +name = "atomic_refcell" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +checksum = "21e4227379beff4205943696e6c3e0cd809bacdf3f0edd6e3dd153e2269571a4" [[package]] -name = "base64" -version = "0.22.1" +name = "autocfg" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "base64" @@ -127,26 +165,24 @@ version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" -[[package]] -name = "beef" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" - [[package]] name = "bit-set" -version = "0.8.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +checksum = "56d87354e4229f54a44f7bf2435906a4656dba36026ab6eaca629a2c436a691c" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.8.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +checksum = "5727b15fa97d4f4fee0a3b7c3d550ed0269f54329207b86388de918604e31269" +dependencies = [ + "borsh", + "serde", +] [[package]] name = "bitflags" @@ -187,6 +223,30 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "borsh" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "553c5d846a6ba5150c65e3b1b8ec073bcf1abc20f9b7220de384a4443ea4e20a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cdfe656708a01f89b451a7d36466e6fe6c414de0aa18fc54f864f6f9ca9f56" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 3.0.9", +] + [[package]] name = "bstr" version = "1.13.1" @@ -209,6 +269,20 @@ name = "bytemuck" version = "1.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1f896587b6f2c069c73d2f0913e2d590c3990285cd2f0b6aa02b786b4c679c" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] [[package]] name = "byteorder" @@ -260,9 +334,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.5.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" +checksum = "86e055fa6e3e40ad6187ba25b6855eeb635d5271f8e0f0e1e9a5826b8d75bea0" dependencies = [ "find-msvc-tools", "shlex", @@ -270,9 +344,9 @@ dependencies = [ [[package]] name = "cfb" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a347dcabdae9c31b0825fd6a8bed285ec9c2acb89c47827126d52fa4f59cece3" +checksum = "0f13298d9178622b7916ec5d01d470425c04273c8ed07e87b1c38b34c4f4612b" dependencies = [ "fnv", "uuid", @@ -343,7 +417,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -358,6 +432,18 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" +[[package]] +name = "cmpfs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9532b7b405749f94737f0c75eff95f1cdd3ab030754f06998f0206aab060a0d5" +dependencies = [ + "flate2", + "lzfse_rust", + "lzvn-core", + "thiserror", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -378,9 +464,12 @@ checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "9eb6feb175df65d0a3ccd3e73484e940d0ac664e8034f0519fd49a93db3071d9" +dependencies = [ + "rustversion", +] [[package]] name = "core-foundation-sys" @@ -432,19 +521,13 @@ checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" [[package]] name = "crc32fast" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" +checksum = "0ba106e844045ddc02c20768ac4b0b7cb45f2cc2ecbd833ac9f5dacb183c2055" dependencies = [ "cfg-if", ] -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - [[package]] name = "crypto-common" version = "0.2.2" @@ -456,9 +539,9 @@ dependencies = [ [[package]] name = "ctutils" -version = "0.4.2" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +checksum = "38d28fb6aa7dd680b3ffd1a3e64e115c177bdba63c0ae7f9cd48129ff05c4fa0" dependencies = [ "cmov", ] @@ -471,20 +554,21 @@ checksum = "ac6b926516df9c60bfa16e107b21086399f8285a44ca9711344b9e553c5146e2" [[package]] name = "delharc" -version = "0.6.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3658b90877f637514897c3dcbd628e0d290bcc7fee551a398b3994ebdc62d51e" +checksum = "9cfdcd2bee8dc367afd9064f3b0849156a4c29fc70d98370dae62773594d04dd" dependencies = [ "bitflags 2.13.2", + "bytemuck", "chrono", "memchr", ] [[package]] name = "deranged" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +checksum = "9e9de72ce2ad1f90dc62fa25f0f430ef85eb4b0d8fa0be4f30373bc40a21d28e" [[package]] name = "des" @@ -509,9 +593,9 @@ dependencies = [ [[package]] name = "either" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" [[package]] name = "encoding_rs" @@ -527,11 +611,46 @@ dependencies = [ "simdutf8", ] +[[package]] +name = "enough" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877362cb7b70d1c617f0cd3c67708bd58d894a86af5104018e2c10ebaee3c02f" + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "equivalent" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "00d174d5400e5e8fd687ad1049e2f578285fa914201b1af7e8b112a4546bd826" + +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", +] [[package]] name = "exav" @@ -550,12 +669,13 @@ dependencies = [ name = "exav-core" version = "0.0.2" dependencies = [ - "base64 0.22.1", + "base64", "bit-set", "cab", "cfb", "crc32fast", "exav-imagehash", + "exav-render", "exav-unpack", "exav-x86", "flate2", @@ -589,6 +709,7 @@ name = "exav-grep" version = "0.0.2" dependencies = [ "clap", + "exav-render", "exav-unpack", "regex", "walkdir", @@ -617,20 +738,27 @@ name = "exav-render" version = "0.0.2" dependencies = [ "bytemuck", + "cfb", + "encoding_rs", "exav-unpack", "fax", "flate2", "gif", - "half", "hayro-ccitt", "hayro-jbig2", "hayro-jpeg2000", "image", + "md-5", "png", + "pulldown-cmark", "quick-error", + "quick-xml", "serde_json", + "sha1", "sha2", "weezl", + "zenjxl-decoder", + "zip", "zune-core 0.4.12", "zune-core 0.5.0", "zune-jpeg 0.4.21", @@ -643,7 +771,7 @@ version = "0.0.2" dependencies = [ "aes", "apfs", - "base64 0.22.1", + "base64", "bitstream-io", "byteorder", "bzip2", @@ -659,14 +787,17 @@ dependencies = [ "digest", "encoding_rs", "exav-pe-emu", - "explode", "ext4-view", "fatfs", "flate2", + "hayro-interpret", + "hayro-syntax", "hfsplus", "hmac", + "html5gum", + "kurbo", "lzfse_rust", - "lzma-rust2 0.21.0", + "lzma-rust2", "lznt1", "lzxd", "mail-parser", @@ -684,7 +815,6 @@ dependencies = [ "tar", "thiserror", "tinyvec", - "unshield", "xz4rust", "zip", ] @@ -705,15 +835,6 @@ dependencies = [ "iced-x86", ] -[[package]] -name = "explode" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46695dd0a1b7a2a6c3e0800604bd9738c2699682b9fc325d4886b6c1a78025ac" -dependencies = [ - "arraydeque", -] - [[package]] name = "ext4-view" version = "1.0.0" @@ -724,6 +845,12 @@ dependencies = [ "crc", ] +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + [[package]] name = "fatfs" version = "0.3.6" @@ -764,6 +891,12 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "fearless_simd" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3296eb97d869113eaf148a6bdf01884e90b3828ad7ae2340b0f93362fc158611" + [[package]] name = "filetime" version = "0.2.29" @@ -776,9 +909,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" +checksum = "1c66915cc5391097de7a2b0b972e8505aa33c0df401fd3a6811dbdb32881ba48" [[package]] name = "flate2" @@ -797,6 +930,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "font-types" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835ae9d781464a79026cde387f9cbc650c9a4909d7cf7e658b127e3c35d2f35d" +dependencies = [ + "bytemuck", +] + [[package]] name = "futures-core" version = "0.3.34" @@ -865,17 +1007,6 @@ dependencies = [ "scroll", ] -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "cfg-if", - "crunchy", - "zerocopy", -] - [[package]] name = "hashbrown" version = "0.14.5" @@ -906,12 +1037,41 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2866f0d976e76497480b853d5e258dab6e4b89ecfe991124e08f15dfa8fd03ad" +[[package]] +name = "hayro-cmap" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d285dc30731c8485de5fa732fbdf2b3affdf01e4da7c2135022ca6fa664bf6" +dependencies = [ + "hayro-postscript", +] + +[[package]] +name = "hayro-interpret" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac9df074ff163a63864cec9b0bf640ccbff8abf4e44481df7369ce0ac172ffbe" +dependencies = [ + "bitflags 2.13.2", + "hayro-cmap", + "hayro-syntax", + "kurbo", + "moxcms 0.8.1", + "phf", + "rustc-hash 2.1.3", + "siphasher", + "skrifa", + "smallvec", + "yoke", +] + [[package]] name = "hayro-jbig2" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "000e025850f4592ddcaee85640db70704151f2bafd43b6f431aa5b6a2c6a35a9" dependencies = [ + "fearless_simd", "hayro-ccitt", ] @@ -920,6 +1080,31 @@ name = "hayro-jpeg2000" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "122c5f834c37a2260b9c851bb8be685cf539b2a8b94b704a931ef7d2525d5835" +dependencies = [ + "fearless_simd", +] + +[[package]] +name = "hayro-postscript" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "885c5ef0654933139a9b9546fc2c69e18d37f38aa2520f079092b1be18f1fcaa" + +[[package]] +name = "hayro-syntax" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cdc818d8d265dcb42081d488f7599df4f73fb79e9d347ecedcd3c23809d2026" +dependencies = [ + "flate2", + "hayro-ccitt", + "hayro-jbig2", + "hayro-jpeg2000", + "memchr", + "rustc-hash 2.1.3", + "smallvec", + "zune-jpeg 0.5.8", +] [[package]] name = "heck" @@ -929,11 +1114,12 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hfsplus" -version = "0.2.4" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1003d8eed80d61e8e8ea6a958bbe1afd3aef060882b9d6134e50500dd307c0dc" +checksum = "c8dd01379b7ef63f131bcd053ee6acd0fa940cdadec0caae4e3c8d502447fd3d" dependencies = [ "byteorder", + "cmpfs", "thiserror", ] @@ -946,6 +1132,12 @@ dependencies = [ "digest", ] +[[package]] +name = "html5gum" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428502d3ec1742c35e015871aef742bc4722a9acfcb616b8ff79b519922e1c36" + [[package]] name = "http" version = "1.5.0" @@ -1015,7 +1207,7 @@ dependencies = [ "color_quant", "gif", "image-webp", - "moxcms", + "moxcms 0.7.11", "num-traits", "png", "qoi", @@ -1043,9 +1235,9 @@ dependencies = [ [[package]] name = "inout" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" +checksum = "3b5cf4372d022092674a83b8febf5865f7a573cc0c5baec5e49c879b6a20978f" dependencies = [ "block-padding", "hybrid-array", @@ -1059,9 +1251,9 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" dependencies = [ "either", ] @@ -1083,6 +1275,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kurbo" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b60dfc32f652b926df6192e55525b16d186c69d47876c3ead4da5cc9f8450e2" +dependencies = [ + "arrayvec", + "euclid", + "polycool", + "smallvec", +] + [[package]] name = "lazy_static" version = "1.5.1" @@ -1097,9 +1301,9 @@ checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c" [[package]] name = "libc" -version = "0.2.189" +version = "0.2.191" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a" [[package]] name = "log" @@ -1109,34 +1313,32 @@ checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "logos" -version = "0.15.1" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff472f899b4ec2d99161c51f60ff7075eeb3097069a36050d8037a6325eb8154" +checksum = "eb2c55a318a87600ea870ff8c2012148b44bf18b74fad48d0f835c38c7d07c5f" dependencies = [ "logos-derive", ] [[package]] name = "logos-codegen" -version = "0.15.1" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "192a3a2b90b0c05b27a0b2c43eecdb7c415e29243acc3f89cc8247a5b693045c" +checksum = "58b3ffaa284e1350d017a57d04ada118c4583cf260c8fb01e0fe28a2e9cf8970" dependencies = [ - "beef", "fnv", - "lazy_static", "proc-macro2", "quote", + "regex-automata", "regex-syntax", - "rustc_version", "syn 2.0.119", ] [[package]] name = "logos-derive" -version = "0.15.1" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605d9697bcd5ef3a42d38efc51541aa3d6a4a25f7ab6d1ed0da5ac632a26b470" +checksum = "52d3a9855747c17eaf4383823f135220716ab49bea5fbea7dd42cc9a92f8aa31" dependencies = [ "logos-codegen", ] @@ -1149,15 +1351,9 @@ checksum = "5edeac3ec657925dececc672bdd58fa2212291886ddcb3e08aa46924c78340c6" [[package]] name = "lzma-rust2" -version = "0.16.5" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca93e534d1142d1d0dcca6d25fe302508a5dfb40b302802904577725ea0b695b" - -[[package]] -name = "lzma-rust2" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde178a3caf126c440fa15628147772d8ee590a39477d711353fbe2e58a73a5b" +checksum = "f1c46f3fcd2e888afdb01a07efc071cb21300e07c68d32c3e8b01b5c8cb1fcaa" dependencies = [ "sha2", ] @@ -1171,6 +1367,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "lzvn-core" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32c51f6215e459d29ee8b61c52074f545fe5518bcb351c590c6e98aec21a5a00" + [[package]] name = "lzxd" version = "0.2.7" @@ -1208,6 +1410,15 @@ version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1238,6 +1449,16 @@ dependencies = [ "pxfm", ] +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + [[package]] name = "multiversion_no_op" version = "1.0.0" @@ -1280,6 +1501,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "num-integer" version = "0.1.47" @@ -1310,6 +1542,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pbkdf2" version = "0.13.0" @@ -1326,6 +1564,48 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -1351,17 +1631,26 @@ dependencies = [ "miniz_oxide 0.8.9", ] +[[package]] +name = "polycool" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50596ddc09eb5ad5f75cacd40209568e66df71baf86e1499a0e99c4cff12a5a6" +dependencies = [ + "arrayvec", +] + [[package]] name = "powerfmt" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +checksum = "4a6394b9e965e73d0a289ee54f589087e2c676aedf60885baf52c76b771e4958" [[package]] name = "ppmd-rust" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196a7c80b9a7652aba7cc070827516c2abe4ccdf53d128e1944003cf5726cff1" +checksum = "cd4acc8d264ea385db64ccfdcdfd5909ee9eda0975666723d59f3bfec80b3611" [[package]] name = "primal-check" @@ -1372,6 +1661,37 @@ dependencies = [ "num-integer", ] +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "proc-macro2" version = "1.0.107" @@ -1381,6 +1701,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "pulldown-cmark" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" +dependencies = [ + "bitflags 2.13.2", + "memchr", + "unicase", +] + [[package]] name = "pxfm" version = "0.1.30" @@ -1404,9 +1735,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.41.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +checksum = "41b1177fdf999d2321d3fb46ff47159d9c1fb9ad66a4879f8c50a0b504615e9b" dependencies = [ "memchr", ] @@ -1451,6 +1782,17 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" +[[package]] +name = "read-fonts" +version = "0.43.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "005c8acf251756c478b0bf402885bfd88a1476020c4c7e6060edc1aa68da38ea" +dependencies = [ + "bytemuck", + "font-types", + "once_cell", +] + [[package]] name = "regex" version = "1.13.1" @@ -1515,12 +1857,13 @@ dependencies = [ [[package]] name = "rowan" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "417a3a9f582e349834051b8a10c8d71ca88da4211e4093528e36b9845f6b5f21" +checksum = "14b574c58582fa59fa43a2feb6608b8744184659f08a2e0117e4b8224d95ed61" dependencies = [ "countme", "hashbrown 0.14.5", + "memoffset", "rustc-hash 1.1.0", "text-size", ] @@ -1537,15 +1880,6 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - [[package]] name = "rustdct" version = "0.7.1" @@ -1571,9 +1905,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.45" +version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ "log", "once_cell", @@ -1595,9 +1929,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.15" +version = "0.103.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" dependencies = [ "ring", "rustls-pki-types", @@ -1612,12 +1946,15 @@ checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "ruzstd" -version = "0.8.3" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c1c839d570d835527c9a5e4db7cb2198683a988cb9d7293fc8674e6bd58fc8" -dependencies = [ - "twox-hash", -] +checksum = "69e4ce4a039f42bf25920b95667e4d789e98749ab11bbb8d2c2936f788421bb5" + +[[package]] +name = "safe_unaligned_simd" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c874fb993656d484725d58fbfddb39dfcf98ebcadc1a1d09568aa6b39bafba" [[package]] name = "salzweg" @@ -1657,15 +1994,9 @@ checksum = "e1a36a382ed65dbcc0ab47fd5e9a94112417ccd34560a392ef3b7b0f0ec39148" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" - [[package]] name = "serde" version = "1.0.229" @@ -1693,14 +2024,14 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] name = "serde_json" -version = "1.0.151" +version = "1.0.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" dependencies = [ "itoa", "memchr", @@ -1711,14 +2042,14 @@ dependencies = [ [[package]] name = "sevenz-rust2" -version = "0.20.2" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29225600349ef74beda5a9fffb36ac660a24613c0bde9315d0c49be1d51e9c24" +checksum = "2f0c68c0e8289bfd09e49ef433e8de02c7c464afc1d7f5a275c99749a880e301" dependencies = [ "bzip2", "crc32fast", "js-sys", - "lzma-rust2 0.16.5", + "lzma-rust2", "ppmd-rust", "wasm-bindgen", ] @@ -1736,9 +2067,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +checksum = "47d7069beb7d6ac7b9acd1039986e73443f24234f41074da099d6f994ac9ad19" dependencies = [ "cfg-if", "cpufeatures", @@ -1763,12 +2094,40 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" +[[package]] +name = "siphasher" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33f4fe9184a62d842c9ef383018f3306d8ba224fd9d836f56d7288308847c256" + +[[package]] +name = "skrifa" +version = "0.46.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4febebda507fb889c545a37a135517769d1391941013561292897961d1887d6" +dependencies = [ + "bytemuck", + "read-fonts", +] + [[package]] name = "slab" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +[[package]] +name = "smallvec" +version = "1.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d5d4b1981b8bbbb7aed204cae5726d683d5d6ac7e74ec54122ea28f315e7c8" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "strength_reduce" version = "0.2.4" @@ -1811,15 +2170,26 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.6" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + [[package]] name = "tar" version = "0.4.46" @@ -1853,7 +2223,7 @@ checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -1887,6 +2257,36 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7184dfffa0d05e10284df327c6cb52f0d62c5aa6c9a8b9236fa151d4361882f1" +[[package]] +name = "toml_datetime" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b86d767906c6c42421dcba507eb9d203e779497710a47782a224bb871653053" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.17+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3641d5bbb5349a79e1020a242d251efbc546ad8048d133958323ce9c40a9c9c" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" +dependencies = [ + "winnow", +] + [[package]] name = "transpose" version = "0.2.3" @@ -1897,17 +2297,11 @@ dependencies = [ "strength_reduce", ] -[[package]] -name = "twox-hash" -version = "2.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5283634e518fe9e82c7b20520bb4bc209009fd16c82077c802f8111ecbb0117a" - [[package]] name = "typed-path" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" +checksum = "54ec2755506471f54baf5e4bb5499d8e510cc1caf271270e778a736bd2d7336c" [[package]] name = "typenum" @@ -1915,6 +2309,12 @@ version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" +[[package]] +name = "unicase" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357cc3acc6a036009fd6c973ed009037c732d60d0b4f6c673e9041497482a28f" + [[package]] name = "unicode-bidi" version = "0.3.18" @@ -1923,15 +2323,15 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" +checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" [[package]] name = "unicode-normalization" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +checksum = "75cd3fb03d5288b3ba9a1ee103ac7e9cbb59f0b03d64f8ddfcc04dd42758a85d" dependencies = [ "tinyvec", ] @@ -1942,16 +2342,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" -[[package]] -name = "unshield" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd29bc2ffd8a674b7de402169d86b3c083229373d05c388526d626408416c5c" -dependencies = [ - "byteorder", - "explode", -] - [[package]] name = "untrusted" version = "0.9.0" @@ -1960,11 +2350,11 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "3.4.2" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a7ac20be9b7726e0bbdbf974c059676d9acb1cd414961f570a4e8231cacd7fc" +checksum = "cde93ff05758a36a851a398a772b0b79a82fbe3c186a46f2696baaeaf84c966b" dependencies = [ - "base64 0.23.1", + "base64", "flate2", "log", "percent-encoding", @@ -1977,11 +2367,11 @@ dependencies = [ [[package]] name = "ureq-proto" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86fd172ccca569e458f61b6bdd6220965a9ef36e672a6852953b51a0e1583be" +checksum = "841583fc36089d7d59419568ae157f43a5a03a2e5a81ba87c77d1596ef46e922" dependencies = [ - "base64 0.23.1", + "base64", "http", "httparse", "log", @@ -2001,9 +2391,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.26.1" +version = "1.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" +checksum = "4a0e2d11620c50695fe12bbbfde96b3477fe606e7284c22d505c12ce51214514" dependencies = [ "js-sys", "wasm-bindgen", @@ -2057,7 +2447,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", "wasm-bindgen-shared", ] @@ -2082,9 +2472,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +checksum = "f5f280bbb2b287bc8e7de7e3852945a0ff50d1bbcb5ed42b6c7a568c546df171" dependencies = [ "rustls-pki-types", ] @@ -2104,6 +2494,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "winarm-cpufeatures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d107c80dd656e1a2c254dfb1d57ece73b7f515b8a8684c270c23cab68f4a440d" + [[package]] name = "windows-core" version = "0.62.2" @@ -2245,6 +2641,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + [[package]] name = "xz4rust" version = "0.2.3" @@ -2253,9 +2658,9 @@ checksum = "606930b71bad6379f366994e4e6252a3462fa28bfc3695c33b07bef8f967d6d6" [[package]] name = "yara-x-parser" -version = "1.19.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5564d72253142774903eafc8f4c92bebef40d65c176a11d351258e80cc8a1c7" +checksum = "89313553cc4cf8961c257d282c902da1d5de568cd656b39962bdf9edd1e3935e" dependencies = [ "ascii_tree", "bitflags 2.13.2", @@ -2269,36 +2674,103 @@ dependencies = [ ] [[package]] -name = "zerocopy" -version = "0.8.59" +name = "yoke" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6df92bf3d9227be3d53173901ddbffac2babc27ae50f397776ffd6dc33f800cb" +checksum = "417ef3fcf6c300b7dbd25c85531a746931c02ad536f3cf4786ed1e88223340b3" dependencies = [ - "zerocopy-derive", + "stable_deref_trait", + "yoke-derive", + "zerofrom", ] [[package]] -name = "zerocopy-derive" -version = "0.8.59" +name = "yoke-derive" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac4f328cf2f05d084e496c3e9c3f33ed0a183656a16e1fcec4d464d8373aec82" +checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", + "synstructure", +] + +[[package]] +name = "zenjxl-decoder" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d68502daf17b161b6fb73657f4a4c60ba5a0491846aae769e33b34dc5ec513" +dependencies = [ + "aligned-vec", + "array-init", + "atomic_refcell", + "bytemuck", + "byteorder", + "enough", + "num-derive", + "num-traits", + "paste", + "smallvec", + "thiserror", + "zenjxl-decoder-macros", + "zenjxl-decoder-simd", +] + +[[package]] +name = "zenjxl-decoder-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d5f705a56b0a01d283503fbe7d5e3b3e51d7321b5f1bba7b07bdeea7e2c6f3d" +dependencies = [ + "proc-macro-error2", "proc-macro2", "quote", "syn 2.0.119", ] +[[package]] +name = "zenjxl-decoder-simd" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237f3740d3d098854c6008515cdff29d8cbadcb6b4e3a1582e28dd3a04e3213e" +dependencies = [ + "archmage", + "paste", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", + "synstructure", +] + [[package]] name = "zeroize" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879" [[package]] name = "zip" -version = "9.0.1" +version = "9.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e49ade69c4434c55dd651d36fe05f38e0578db948b773cbc01c48c4b5e560692" +checksum = "6e04976da629d3b04204ba8105b396a193af8ad2583b2c79bfb3ab8af580a11e" dependencies = [ "bitstream-io", "crc32fast", diff --git a/Cargo.toml b/Cargo.toml index 8ab9bf7..12f1c33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,14 +11,15 @@ repository = "https://github.com/sylvinus/exav" homepage = "https://exav.org" # Checked by `make msrv` rather than asserted: a floor nothing verifies drifts. # -# The number is set by dependencies, not by this code: exav-render's image -# decoders hayro-jpeg2000 0.4, hayro-jbig2 0.3.1 and hayro-ccitt 0.4 declare -# 1.92 (and `yara-x-parser` 1.91), so cargo refuses to build them on anything -# older. exav's own source needs only 1.88 (`slice::as_chunks`, +# The number is set by dependencies, not by this code: exav-unpack's LHA reader +# delharc 0.8 declares 1.95 (if-let guards), `sevenz-rust2` 0.24 1.93, +# exav-render's image decoders hayro-jpeg2000 0.4, hayro-jbig2 0.3.1 and +# hayro-ccitt 0.4 1.92, and `yara-x-parser` 1.91, so cargo refuses to build them +# on anything older. exav's own source needs only 1.88 (`slice::as_chunks`, # `is_multiple_of`, and the let-chains the `zip` dependency uses). Worth # rechecking when those dependencies move; lowering it means confirming with # `make msrv`, not editing this line. -rust-version = "1.92" +rust-version = "1.95" # crates.io discovery. keywords: max 5, <=20 chars each. categories must be from # https://crates.io/category_slugs (an invalid one fails `cargo publish`). keywords = ["antivirus", "clamav", "malware", "scanner", "security"] @@ -28,7 +29,7 @@ categories = ["command-line-utilities", "filesystem"] # `env` lets every flag name the environment variable it falls back to, so the # precedence (flag, then environment, then default) is one rule the parser # applies and `--help` prints, rather than per-flag code. -clap = { version = "4.5", features = ["derive", "env"] } +clap = { version = "4.6", features = ["derive", "env"] } walkdir = "2.5" # Catch integer overflow in release too: on hostile input a silent wraparound diff --git a/Dockerfile b/Dockerfile index e6c653a..7f6c4d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,9 +38,9 @@ ARG BIN_SOURCE=build # of magnitude slower than cross-compiling it. # rust:alpine targets *-unknown-linux-musl and links statically. `build-base` # provides the C toolchain the TLS stack (ring, via the `http` feature's ureq → -# rustls) needs to compile under musl. Pinned to 1.92, the MSRV floor (see the +# rustls) needs to compile under musl. Pinned to 1.95, the MSRV floor (see the # workspace `rust-version`, which says what sets it); bump both together. -FROM rust:1.92-alpine AS build +FROM rust:1.95-alpine AS build RUN apk add --no-cache musl-dev build-base WORKDIR /src COPY . . diff --git a/Makefile b/Makefile index d235de8..602f981 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ DBDIR ?= exav-db EXAVDB ?= exav.exavdb .DEFAULT_GOAL := build -.PHONY: build release test test-native test-yara-diff test-wasm test-js test-viewer test-www test-helm wasm-sizes lint fmt msrv av-audit miri publish-check publish fuzz db exavdb cache daily clean www-dev www-build help +.PHONY: build release test test-native test-yara-diff test-wasm test-js test-viewer test-www test-formats formats test-helm wasm-sizes lint fmt msrv av-audit miri publish-check publish fuzz db exavdb cache daily clean www-dev www-build help ## build: compile the release binary build release: @@ -71,7 +71,32 @@ test-native: $(CARGO) test -p exav-render --no-default-features --features dwg # IFC and STL, behind `ifc` and `stl`, as @exav/viewer's model module # builds them. - $(CARGO) test -p exav-render --no-default-features --features ifc,stl + $(CARGO) test -p exav-render --no-default-features --features ifc,stl,obj,ply,gltf + # Markdown, behind `markdown`, as @exav/viewer's text module builds it. + $(CARGO) test -p exav-render --no-default-features --features markdown + # The office converters (spreadsheets, presentations, text documents), + # behind `office-*`, as @exav/viewer's sheets, slides and docs modules + # build them: each alone, since slides compile part of sheets, then all + # of them with the test writers the integration tests build documents with. + $(CARGO) test -p exav-render --no-default-features --features office-sheets + $(CARGO) test -p exav-render --no-default-features --features office-slides,office-test-util + $(CARGO) test -p exav-render --no-default-features --features office-docs,office-test-util + $(CARGO) test -p exav-render --no-default-features --features office,office-test-util + # The text a reader sees, behind `text` (HTML, Office XML parts, drawings) + # and `text-pdf` (PDF, through hayro, which switches flate2 to zlib-rs: its + # own pass, so that the default passes do not run with it). + $(CARGO) test -p exav-unpack --features text + $(CARGO) test -p exav-render --no-default-features --features text + $(CARGO) test -p exav-unpack --features text-pdf --test all text:: + $(CARGO) test -p exav-render --no-default-features --features text-pdf + $(CARGO) test -p exav-core --features visible-text-pdf --test all visible_text + $(CARGO) test -p exav-grep --features text-pdf --test text + # The office formats' text (DOC, XLS, PPT, RTF, flat OpenDocument, iWork...), + # behind `text-office`. + $(CARGO) test -p exav-render --no-default-features --features text-office,office-test-util + $(CARGO) test -p exav-core --features visible-text-office --test all visible_text + $(CARGO) test -p exav-grep --features text-office --test text --test text_office + $(CARGO) test -p exav --features visible-text-office --test office_text ## test-yara-diff: the yara-x A/B differential harness. Compiles the SAME rules ## with both engines and asserts equal matching-rule sets. NOT @@ -119,6 +144,19 @@ test-viewer: test-www: ./scripts/test-www.sh +## formats: write the pages generated from the format registry +## (formats/registry.json): the format matrix and the viewer's +## summary sentence in the READMEs and the site. +formats: + node scripts/formats.mjs generate + +## test-formats: the format registry against the extractor's formats, the +## scanner's file types, the viewer's plugins, and the pages +## generated from it (test-www runs it too; the viewer's and the +## scanner's own registry tests are in test-viewer and test-native). +test-formats: + node scripts/formats.mjs check + ## test-helm: render-check the Helm chart (render guards, hardening settings, ## packaging). Needs `helm` on PATH, no cluster. CI runs `ct lint` ## in addition. See scripts/test-helm.sh. @@ -141,7 +179,18 @@ lint: $(CARGO) clippy --all-targets --features exav-core/http -- -D warnings $(CARGO) clippy -p exav-core --all-targets --features unstable-internals -- -D warnings $(CARGO) clippy -p exav-render --all-targets --features dwg -- -D warnings - $(CARGO) clippy -p exav-render --all-targets --no-default-features --features ifc,stl -- -D warnings + $(CARGO) clippy -p exav-render --all-targets --no-default-features --features ifc,stl,obj,ply,gltf -- -D warnings + $(CARGO) clippy -p exav-render --all-targets --no-default-features --features markdown -- -D warnings + $(CARGO) clippy -p exav-render --all-targets --no-default-features --features text-pdf -- -D warnings + $(CARGO) clippy -p exav-render --all-targets --no-default-features --features office-sheets -- -D warnings + $(CARGO) clippy -p exav-render --all-targets --no-default-features --features office-slides -- -D warnings + $(CARGO) clippy -p exav-render --all-targets --no-default-features --features office-docs -- -D warnings + $(CARGO) clippy -p exav-render --all-targets --no-default-features --features office,office-test-util -- -D warnings + $(CARGO) clippy -p exav-render --all-targets --no-default-features -- -D warnings + $(CARGO) clippy -p exav-render --all-targets --no-default-features --features text-office,office-test-util -- -D warnings + $(CARGO) clippy -p exav-core --all-targets --features visible-text-office -- -D warnings + $(CARGO) clippy -p exav-grep --all-targets --features text-office -- -D warnings + $(CARGO) clippy -p exav-unpack --all-targets --features text-pdf -- -D warnings ## fmt: format the code fmt: diff --git a/NOTICE b/NOTICE index a0fb856..f3888ed 100644 --- a/NOTICE +++ b/NOTICE @@ -74,7 +74,12 @@ Copyright (c) 2024. The YARA-X Authors. All Rights Reserved. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Other BSD-3-Clause components linked by exav (same 3-clause terms above, with -their respective copyright holders): subtle, tlsh2. +their respective copyright holders): subtle, tlsh2, and, in exav-render's `jxl` +feature (JPEG XL in @exav/viewer's image module), zenjxl-decoder with its +zenjxl-decoder-simd and zenjxl-decoder-macros: "Copyright (c) the JPEG XL +Project Authors. All rights reserved." It is a fork of the libjxl team's +jxl-rs (https://github.com/libjxl/jxl-rs), built `forbid(unsafe_code)` and +without its SIMD. ------------------------------------------------------------------------------- @@ -255,13 +260,18 @@ Copyright (c) Mike Krüger. ------------------------------------------------------------------------------- -1h1. unshield / explode, MIT (linked dependency + test fixtures) +1h1. unshield / explode, MIT, and blast.c, zlib (source derivatives + test + fixtures) ------------------------------------------------------------------------------- -crates/exav-unpack/src/formats/ishield_z.rs reads InstallShield `.z` archives -through the `unshield` crate, whose only real dependency is `explode`, a leaf -decoder for the PKWARE Data Compression Library "implode" codec those archives -use. Both MIT. +crates/exav-unpack/src/formats/ishield_z.rs reads the table of contents of +InstallShield `.z` archives as the `unshield` crate 0.2.0 does, and +crates/exav-unpack/src/formats/dcl_explode.rs decodes their PKWARE Data +Compression Library "implode" members as the `explode` crate 0.1.2 does. Both +crates are MIT. `explode` is a port of Mark Adler's `blast.c` (zlib +`contrib/blast`, zlib licence, text in section 1l; Copyright (C) Mark Adler), +whose algorithm and code-length tables dcl_explode.rs keeps; it is altered +from both: it decodes a whole slice into a capped buffer. The fixtures in crates/exav-unpack/tests/fixtures/ishieldz/ are that project's own examples, redistributed under the same terms. `undhr.z` is shipped alongside @@ -360,6 +370,44 @@ Copyright © 1995-2011 by Fredrik Lundh and contributors Copyright © 2010 by Jeffrey 'Alex' Clark and contributors +------------------------------------------------------------------------------- +1h6. Apple lzfse, BSD-3-Clause (source derivative) +------------------------------------------------------------------------------- + +crates/exav-unpack/src/formats/lzfse.rs, the LZFSE and LZVN decoder for DMG +runs, is a Rust port of the decoder of Apple's reference implementation +(lzfse_decode_base.c, lzfse_fse.c/.h, lzvn_decode_base.c and the tables of +lzfse_internal.h), changed to decode a whole buffer into a capped one. + +Upstream: https://github.com/lzfse/lzfse +Copyright (c) 2015-2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ------------------------------------------------------------------------------- 1h. oletools test sample, BSD-2-Clause (test fixture) ------------------------------------------------------------------------------- @@ -461,6 +509,9 @@ Copyright (c) Nullsoft and contributors. 3. This notice may not be removed or altered from any source distribution. +The zlib-rs crate (the `text-pdf` features' DEFLATE) is under the same +Zlib terms: (C) 2024 Trifecta Tech Foundation. + ------------------------------------------------------------------------------- 1m. sevenz-rust2, Apache-2.0 (design reference) @@ -494,6 +545,153 @@ Open Font License 1.1. NOTICE.md beside them gives each face's copyright and version, and OFL-1.1.txt the licence. +------------------------------------------------------------------------------- +1o. numbers-parser data (MIT) and the OpenOffice.org Excel format documentation +------------------------------------------------------------------------------- + +These are the office converters of exav-render (the `office-sheets`, +`office-slides` and `office-docs` features, `src/formats/office/`). They reach +the @exav/viewer npm package and, with `text-office`, exav-grep; the default +exav binary contains none of them. Their full notice is +crates/exav-render/NOTICE. + +They are written from published specifications: Microsoft's Open +Specifications ([MS-XLS], [MS-PPT], [MS-DOC], [MS-CFB], [MS-ODRAW], +[MS-OSHARED], [MS-OFFCRYPTO], [MS-VSDX]) and Visio file format reference, +ECMA-376 and ISO/IEC 29500, OpenDocument 1.2 and 1.3 (OASIS), the RTF +specification, Apple's Technical Notes TN2067 and TN2073 (Keynote 1) and RFC +1741 (BinHex 4.0). OpenOffice.org's "Microsoft Excel File Format" documentation +(Public Documentation License) gives the BIFF2 to BIFF5 record layouts. + +Two projects supply data: numbers-parser (https://github.com/masaccio/numbers-parser, +MIT, Copyright 2021 Jon Connell) gave Numbers' function indexes, the families +of macOS fonts' PostScript names and the layout of table records; keynote-parser +(https://github.com/psobot/keynote-parser, MIT, Copyright 2019-2025 Peter +Sobot) gave the Keynote and Pages message layout, and its sample.key and +table.key are test fixtures. + +The readers for PowerPoint 95 and Keynote 2 to 5 follow no published +description: they were written from sample documents, with the output of other +office applications on them used as a black box (rendered pages, never source). +No source of another office application or of a document-format library was +read. + + +------------------------------------------------------------------------------- +1p. Camera RAW previews (exav-render `raw`): specifications and sample files +------------------------------------------------------------------------------- + +crates/exav-render/src/formats/image/raw.rs and raw/ read the previews of +camera RAW files. No code was taken from another implementation. They were +written from these public specifications, which are not redistributed here: + +- TIFF Revision 6.0 (Adobe Systems Incorporated, 1992), published by Adobe for + anyone to implement. +- Adobe Digital Negative (DNG) Specification 1.7.1.0 (Adobe), published with a + royalty-free licence to implement DNG. +- Exif 2.32, CIPA DC-008-2019 (Camera & Imaging Products Association), freely + downloadable. +- ITU-T T.81 | ISO/IEC 10918-1, the JPEG standard. +- ISO/IEC 14496-12, ISO base media file format, from ISO's publicly available + standards. + +What the makers' own containers hold (the signatures of RAF, X3F, CRW, MRW, +ORF, RW2 and IIQ, the compression numbers of their sensor data) was read off +sample files from https://raw.pixls.us, which its contributors dedicate to the +public domain under CC0 1.0 +(https://creativecommons.org/publicdomain/zero/1.0/), with tools written for +the purpose. None of those files is in this repository; the tests use the +synthetic containers of crates/exav-render/tests/fixtures/raw/make.py. + +The Canon CR3 reader (raw/bmff.rs and the CR3 parts of raw.rs and make.py) was +written from ISO/IEC 14496-12 and the Exif and TIFF specifications above, and +from 110 CR3 sample files of the same CC0 source, which a box lister written +for the purpose walked: the box layout (the `crx ` brand of `ftyp`, the `uuid` +boxes of `moov`, the box that holds the Exif of the first directory and its +orientation, the JPEGs the file embeds and where) was read off those files +alone. No CR3 documentation or source code of any other project was read: no +format description, no README, no tag table, and no other RAW reader or +converter. + + +------------------------------------------------------------------------------- +1q. Example files of the @exav/viewer demo +------------------------------------------------------------------------------- + +The @exav/viewer demo lists example files kept in +crates/exav-viewer/demo/examples/. Most are made by scripts of this repository +and given to the public domain (CC0-1.0). The others are public domain, CC0, +CC-BY, MIT, BSD or Apache files, each credited with its author, its +source and the page that states its licence in examples.json, NOTICE.md and +https://exav.org/viewer/examples/. The small ones are committed; the rest are +downloaded by `npm run demo:examples` from pinned addresses and checked against +their SHA-256. They are test inputs only and are not part of any published +package. + + +------------------------------------------------------------------------------- +1r. IFC geometry (exav-render `ifc`): specifications +------------------------------------------------------------------------------- + +The curved-face, sweep-parameter, alignment, grid and storey code is written +from buildingSMART International's published IFC4 and IFC4X3 EXPRESS schemas +and documentation (CC BY-ND 4.0, read, not copied) and the surface and curve +definitions of ISO 10303-42. No code from another IFC library was read. + + +------------------------------------------------------------------------------- +1s. yoke, yoke-derive, zerofrom, zerofrom-derive, Unicode License v3 +------------------------------------------------------------------------------- + +These crates (the ICU4X project's, linked through hayro-interpret, the PDF +interpreter of the `text-pdf` features) carry this licence; reproduce its +notice in distributions. + + UNICODE LICENSE V3 + + COPYRIGHT AND PERMISSION NOTICE + + Copyright © 2020-2024 Unicode, Inc. + + NOTICE TO USER: Carefully read the following legal agreement. BY + DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR + SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE + TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT + DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of data files and any associated documentation (the "Data Files") or + software and any associated documentation (the "Software") to deal in the + Data Files or Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, and/or sell + copies of the Data Files or Software, and to permit persons to whom the + Data Files or Software are furnished to do so, provided that either (a) + this copyright and permission notice appear with all copies of the Data + Files or Software, or (b) this copyright and permission notice appear in + associated Documentation. + + THE DATA FILES AND SOFTWARE ARE 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 OF + THIRD PARTY RIGHTS. + + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE + BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA + FILES OR SOFTWARE. + + Except as contained in this notice, the name of a copyright holder shall + not be used in advertising or otherwise to promote the sale, use or other + dealings in these Data Files or Software without prior written + authorization of the copyright holder. + + Portions of ICU4X may have been adapted from ICU4C and/or ICU4J. + ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines + Corporation and others. + + ------------------------------------------------------------------------------- 2. ISC-licensed components ------------------------------------------------------------------------------- @@ -520,11 +718,23 @@ the distributor's choice. Notable examples: clap CLI parsing sha1, sha2, md-5, digest (RustCrypto) hashing flate2, miniz_oxide DEFLATE / gzip / zlib - lzfse_rust, delharc, lzxd DMG/LHA/CAB codecs + delharc, lzxd LHA/CAB codecs bitstream-io bit-level readers for decoders stringprep PDF password normalization ext4-view ext2/3/4 filesystem reader image image decoding (image hashing) + pulldown-cmark Markdown in exav-render (`markdown` + feature) and @exav/viewer; MIT, + 2015 Google Inc. + html5gum HTML text in exav-unpack (`text` + feature): the tokenizer; MIT, + 2021 Markus Unterwaditzer + hayro-interpret, hayro-syntax, PDF text in exav-unpack (`text-pdf` + hayro-cmap, hayro-postscript feature, off by default): Apache-2.0 + OR MIT, Laurenz Stampfl + phf glyph-name tables in hayro; MIT, + 2014-2022 Steven Fackler, Yuki + Okushi hayro-jpeg2000, hayro-jbig2, JPEG 2000, JBIG2 and CCITT fax in hayro-ccitt exav-render (image hashing) and @exav/viewer; hayro-jpeg2000's @@ -536,16 +746,17 @@ the distributor's choice. Notable examples: wasm-bindgen, js-sys, web-sys, WebAssembly/JS bindings; these reach wasm-bindgen-futures the published npm artifact -sevenz-rust2, bzip2 and ppmd-rust are dev-only: they build test fixtures. The -shipped 7z reader is native (§1m) and the bzip2 decoder is vendored (§1h3). +sevenz-rust2, bzip2, ppmd-rust and lzfse_rust are dev-only: they build test +fixtures. The shipped 7z reader is native (§1m), the bzip2 decoder is vendored +(§1h3) and the LZFSE decoder is ported from Apple's (§1h6). MIT-only components (the MIT copyright and permission notice must be retained; the MIT text is in the exav LICENSE file): apfs, ascii_tree, cfb, color_quant, -deflate64, explode, fatfs, fax, fax_derive, goblin, hfsplus, lznt1, quick-xml, +deflate64, fatfs, fax, fax_derive, goblin, hfsplus, lznt1, quick-xml, rmp, rmp-serde, ruzstd, salzweg, scroll, scroll_derive, simd-adler32, slab, -strsim, twox-hash, unshield, xz4rust, zip, zmij, and bytes (`http` features -only). fancy-regex and tiff are vendored, and Pillow's resampler ported -(§1h5). +strsim, xz4rust, zip, zmij, and bytes (`http` features only). fancy-regex and +tiff are vendored, and Pillow's resampler ported (§1h5); unshield and explode +are ported (§1h1). Apache-2.0-only: lzma-rust2 (it ships no NOTICE file of its own; the license text is in section 4). @@ -555,8 +766,9 @@ BSD-3-Clause: yara-x-parser (§1), and subtle (`http` features only). tlsh2 is Apache-2.0 OR BSD-3-Clause. RustCrypto crates are MIT OR Apache-2.0. Offered under Zlib among other -licenses: miniz_oxide, tinyvec, bytemuck. Unicode-3.0: unicode-ident -(build-time). Other permissive +licenses: miniz_oxide, tinyvec, bytemuck. Zlib: zlib-rs (§1l). Unicode-3.0: +unicode-ident (build-time), and yoke, yoke-derive, zerofrom and +zerofrom-derive (§1s). Other permissive licenses: CC0-1.0 OR MIT-0 OR Apache-2.0 (constant_time_eq), CDLA-Permissive-2.0 (webpki-roots, TLS root store, `http` features only). The dev-only crates add CC0-1.0 / MIT-0 (ppmd-rust) and bzip2-1.0.6 diff --git a/README.md b/README.md index 61720a7..4532278 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,7 @@ cargo install exav-unpack ## File viewer: `@exav/viewer` -A file viewer for the browser: PDF, images, DWG and DXF drawings, Office -documents, IFC and STL models, media and archives. Each file can open in a +A file viewer for the browser: PDF, images, DWG and DXF drawings, Word, Excel, PowerPoint and CSV, text (Markdown, JSON, XML, source code), IFC, STL, OBJ, PLY and glTF models, video, audio, and what is inside an archive. Each file can open in a sandboxed frame of its own, and exav's own decoders run in WebAssembly. ```sh @@ -62,7 +61,7 @@ npm install @exav/viewer |---|---| | [`exav-grep`](crates/exav-grep/README.md) | `grep`, but it can see inside archives | | [`exav-core`](crates/exav-core/README.md) | The scanning engine, as a Rust library | -| [`exav-render`](crates/exav-render/README.md) | The decoders behind the viewer: images, DWG, DXF, IFC, STL | +| [`exav-render`](crates/exav-render/README.md) | The decoders behind the viewer: images, DWG, DXF, IFC, STL, OBJ, PLY, glTF, Office documents | | [`exav-imagehash`](crates/exav-imagehash/README.md) | Perceptual image hashes, ClamAV's `fuzzy_img` among them | | [`exav-pe-emu`](crates/exav-pe-emu/README.md) | A bounded x86-32 emulator that runs packer stubs to unpack them | | [`exav-x86`](crates/exav-x86/README.md) | A decode-only x86-32 instruction decoder | diff --git a/crates/exav-core/Cargo.toml b/crates/exav-core/Cargo.toml index ef9104f..49e111d 100644 --- a/crates/exav-core/Cargo.toml +++ b/crates/exav-core/Cargo.toml @@ -32,8 +32,9 @@ memchr = "2" md-5 = "0.11" sha1 = "0.11" sha2 = "0.11" -# executable parsing (PE/ELF/Mach-O) -goblin = "0.10" +# PE and ELF parsing. Without Mach-O, `ar` archives and TE images, which exav +# reads with its own code or not at all: fewer of goblin's parsers compiled. +goblin = { version = "0.10", default-features = false, features = ["std", "elf32", "elf64", "pe32", "pe64"] } # x86 instruction decoder for the bytecode disasm_x86 API. Decode-only, in the # workspace, and dependency-free: a general-purpose decoder covers the whole ISA # at the cost of hundreds of `unsafe` blocks, which is a poor trade for one API. @@ -50,21 +51,26 @@ tlsh2 = { version = "1", features = ["diff"] } # formats past the five clamscan treats as graphics, JPEG 2000 and JBIG2 # included, are hashed except under `--clamav-compat`. exav-imagehash = { path = "../exav-imagehash", version = "0.0.2", default-features = false, features = ["webp", "ico", "pnm", "qoi", "dds", "ff", "hdr", "jp2", "jbig2"], optional = true } +# The text of a document as a reader sees it (`visible-text` feature): +# exav-render's `text`: Markdown (pulldown-cmark without its `html` and `simd` +# features), HTML (html5gum's tokenizer), Office and OpenDocument XML parts, +# PDF (hayro) and drawings. +exav-render = { path = "../exav-render", version = "0.0.2", default-features = false, features = ["text"], optional = true } # HTTP(S) range-request backend (optional) ureq = { version = "3", optional = true } # Anchor-frequency counting at database build: tens of millions of u64 gram # keys, where the hash is the whole cost of the lookup. rustc-hash = "2" -serde = { version = "1.0.228", features = ["derive"] } +serde = { version = "1.0.229", features = ["derive"] } rmp-serde = "1.3.1" # The `.exavdb` binary blobs, written and read directly (see `database::enc_bytes`). rmp = "0.8.15" -regex = "1.12.4" +regex = "1.13.1" # The backtracking engine for the PCRE subsignatures `regex` cannot run # (lookaround, backreferences, atomic groups) is fancy-regex, vendored in # `src/fancy_regex/` (its README says why). It needs this beside `regex-automata` # and `regex-syntax` below. -bit-set = { version = "0.8", default-features = false, features = ["std"] } +bit-set = { version = "0.11", default-features = false, features = ["std"] } # YARA rule support (ClamAV loads .yar/.yara by default, so a drop-in must too), # via exav's native YARA engine under `src/yara/`. It compiles rules to a native # tree-walking evaluator (no runtime codegen at scan time, W^X preserved) and @@ -75,7 +81,7 @@ bit-set = { version = "0.8", default-features = false, features = ["std"] } # # Parser + AST only. The AST borrows the source, so the compiler lowers it into # an owned IR. -yara-x-parser = { version = "1.18", optional = true } +yara-x-parser = { version = "1.19", optional = true } # Byte-oriented regex engine with anchored search: YARA regexp patterns, the # `matches` operator and hex patterns (lowered to byte regexes), and the lazy # DFAs that run a regex over an object read through the block cache. @@ -87,14 +93,30 @@ regex-automata = "0.4" # match is ever missed). regex-syntax = "0.8" # base64 alphabet handling for the `base64`/`base64wide` string modifiers. -base64 = { version = "0.22", optional = true } +base64 = { version = "0.23", optional = true } # The database file's checksum, and crc32/checksum32 for YARA's `hash` module. crc32fast = "1" # JSON output for the WASI binary (`wasi-bin`), nothing else. -serde_json = { version = "1.0.140", optional = true } +serde_json = { version = "1.0.154", optional = true } [features] -default = ["yara", "all-formats", "decrypt", "dlp", "phishing", "image-hash"] +default = ["yara", "all-formats", "decrypt", "dlp", "phishing", "image-hash", "visible-text"] +# A document's visible text (its words, and where each link leads) is matched +# as a text view, as well as its bytes: Markdown, HTML, Office and OpenDocument +# XML parts, PDF and drawings. Not under `--clamav-compat`. +visible-text = ["dep:exav-render"] +# And PDF's, read by hayro. Not a default: hayro-interpret turns on +# hayro-syntax's `unsafe` feature, which switches every `flate2` in the build to +# zlib-rs (and changes what a damaged stream gives back) and adds SIMD to the +# image decoders; it also adds some 40 crates. See docs/DEPENDENCIES.md. +visible-text-pdf = ["visible-text", "exav-render/text-pdf"] +# And the office formats the XML parts do not reach: DOC, XLS, PPT, RTF, Word +# 2003 XML, SpreadsheetML 2003, SYLK, flat OpenDocument, Numbers, Pages and +# Keynote, from exav-render's converters (`office`). Safe Rust and within the +# scan's limits, but the largest readers of the scan: not a default. A document +# of those formats whose text cannot be read (encrypted, past a limit, damaged) +# marks the scan incomplete. +visible-text-office = ["visible-text", "exav-render/text-office"] # `fuzzy_img#` subsignatures, through exav-imagehash and its image decoders. # Without it they load as unsupported, and no image is ever decoded. image-hash = ["dep:exav-imagehash"] @@ -235,18 +257,20 @@ zip = { version = "9", default-features = false, features = ["deflate-flate2"] } # into the build at all. flate2 = "1" tar = { version = "0.4", default-features = false } -cfb = "0.14" +cfb = "0.15" # Writes the MSZIP cabinets the damaged-member tests break. cab = "0.6.0" # only for the base64-embedded-executable end-to-end test -base64 = "0.22" +base64 = "0.23" +# Reads formats/registry.json, which the detection is checked against. +serde_json = "1.0.154" # The reference PPMd8 encoder, for the ZIP method-98 end-to-end test. ppmd-rust = "1" # Encodes the images the `fuzzy_img#` tests scan. image = { version = "=0.25.9", default-features = false, features = ["png", "webp"] } # The unit tests of the vendored `src/fancy_regex/`, as upstream wrote them. matches = "0.1.10" -quickcheck = { version = "1.0", default-features = false } +quickcheck = { version = "1.1", default-features = false } # Small chunks when reading a source, so tests on small inputs cross many # chunk seams. Features only: which formats are built stays with the # dependency above. diff --git a/crates/exav-core/src/engine/mod.rs b/crates/exav-core/src/engine/mod.rs index f95e442..f495798 100644 --- a/crates/exav-core/src/engine/mod.rs +++ b/crates/exav-core/src/engine/mod.rs @@ -432,6 +432,53 @@ pub fn reset_scan_truncated() { SCAN_TRUNCATED.with(|c| c.set(false)); SCAN_OVER_SIZE.with(|r| r.borrow_mut().take()); SCAN_CAPPED.with(|r| r.borrow_mut().take()); + CLEAN_SEEN.with(|m| m.borrow_mut().clear()); +} + +/// Most objects remembered as scanned clean in one scan. +const CLEAN_SEEN_MAX: usize = 4096; + +thread_local! { + /// Objects this scan has scanned to the end and found clean, by a digest of + /// their bytes and of everything about where they sit that a scan reads, + /// with the shallowest depth one was scanned at. Cleared with the + /// truncation flags, at the start of each top-level scan. + static CLEAN_SEEN: RefCell> = + RefCell::new(std::collections::HashMap::new()); +} + +/// Whether an object with this digest was already scanned clean at `depth` or +/// shallower. Deeper copies are not covered: the walk has fewer levels left +/// there, so the same bytes could be reported over the limit. +pub(crate) fn clean_seen(key: &[u8; 32], depth: u32) -> bool { + let seen = CLEAN_SEEN.with(|m| m.borrow().get(key).is_some_and(|&d| d <= depth)); + #[cfg(test)] + if seen { + CLEAN_SKIPS.with(|c| c.set(c.get() + 1)); + } + seen +} + +#[cfg(test)] +thread_local! { + /// How many objects [`clean_seen`] let a scan skip on this thread. + pub(crate) static CLEAN_SKIPS: std::cell::Cell = const { std::cell::Cell::new(0) }; +} + +/// Remember an object scanned clean at `depth`. +pub(crate) fn clean_seen_insert(key: [u8; 32], depth: u32) { + CLEAN_SEEN.with(|m| { + let mut m = m.borrow_mut(); + if m.len() < CLEAN_SEEN_MAX || m.contains_key(&key) { + m.entry(key).and_modify(|d| *d = (*d).min(depth)).or_insert(depth); + } + }); +} + +/// The container types above the object being scanned, outermost first, as +/// `Intermediates:` reads them. +pub(crate) fn ancestry_snapshot() -> Vec> { + ANCESTRY.with(|a| a.borrow().clone()) } /// Record that carving reached its cap with more to carve, and why. Unlike a diff --git a/crates/exav-core/src/jsnorm.rs b/crates/exav-core/src/jsnorm.rs index 8311967..2e11fa1 100644 --- a/crates/exav-core/src/jsnorm.rs +++ b/crates/exav-core/src/jsnorm.rs @@ -22,11 +22,10 @@ //! purely static rewriter: it never executes code, so runtime-assembled payloads //! (numeric-array VMs, dynamic dispatch) are intentionally out of scope. //! -//! Not yet implemented (tracked in tmp/GAPS.md): -//! * **Microsoft Script Encoder** (`#@~^…^#~@`, JScript.Encode/VBScript.Encode) -//! decoding — needs the exact published 119×3 translation + 64-entry pick -//! tables; deferred rather than ship an unverified table (and near-absent in -//! the current corpus). +//! Not done here: Microsoft Script Encoder (`#@~^…^#~@`) blobs are decoded by +//! exav-unpack's `screnc`, which surfaces the plaintext as a member of its own. +//! +//! Not yet implemented: //! * **base64→script rescan** — decoding long base64 runs to *script/text* (not //! just exec-magic payloads, which `exav-unpack::base64_payloads` already //! covers). The higher-yield lever per corpus evidence, but needs a distinct diff --git a/crates/exav-core/src/lib.rs b/crates/exav-core/src/lib.rs index eab32a2..86cd5f9 100644 --- a/crates/exav-core/src/lib.rs +++ b/crates/exav-core/src/lib.rs @@ -1829,7 +1829,7 @@ fn visit_member( // of it is a real Clean: exav scans for malware, it is not a // file-integrity validator. Undecodable bytes still present // keep the not-fully-scanned verdict. - let o = member_content_scan(cx, tally, &data, budget, findings, sink); + let o = member_content_scan(cx, tally, &meta.name, &data, budget, findings, sink); if o.is_none() && unpack::decode_error_hides_content(&e) { tally.unscannable.get_or_insert_with(|| { format!( @@ -1848,10 +1848,10 @@ fn visit_member( unpack::volume::Offer::Held => return None, unpack::volume::Offer::PassThrough { data, .. } => data, }; - member_content_scan(cx, tally, &data, budget, findings, sink) + member_content_scan(cx, tally, &meta.name, &data, budget, findings, sink) } Body::Spilled(spilled) => { - let o = member_content_scan(cx, tally, &spilled, budget, findings, sink); + let o = member_content_scan(cx, tally, &meta.name, &spilled, budget, findings, sink); if let Some(e) = spilled.read_error() { tally .unscannable @@ -1957,7 +1957,7 @@ fn walk_members( break; } let _mpg = MatchPathGuard::enter(&name); - terminal = member_content_scan(&cx, &mut tally, &buf, budget, findings, sink); + terminal = member_content_scan(&cx, &mut tally, &name, &buf, budget, findings, sink); } if let Some(name) = tally.encrypted.take() { if !matches!(terminal, Some(DeepOutcome::Infected { .. })) { @@ -2087,6 +2087,235 @@ where out } +/// The sets of **format-aware volumes** among a group of files that arrived +/// together, each put back into the one archive it was cut from and scanned: +/// RAR (`x.part1.rar`, `x.part2.rar`, ..., or `x.rar`, `x.r00`, ...), ZIP +/// (`x.z01`, `x.z02`, ..., `x.zip`) and CAB (`a.cab`, `b.cab`, as each header +/// names the one after it). Each volume carries its own headers, so the join is +/// the format's, not a concatenation, and the parts of a set scanned alone are +/// cut short. +/// +/// `fetch(name, None)` is a whole file and `fetch(name, Some(n))` its first `n` +/// bytes. Whole files are fetched only for the parts of a set, up to +/// `max-object-bytes` of them together; the heads of `.cab` files are read to +/// find which of them name a neighbour. Names are labels, never paths: a +/// cabinet's own header names its neighbours, and they are looked for in +/// `names` only. +/// +/// As [`analyze_volume_sets`]: one entry per *part*, with the verdict of the +/// archive that part belongs to, `Unscannable` for a set with a hole in it or +/// one that does not fit together. A file that is not part of a set is not in +/// the result. +#[cfg(feature = "all-formats")] +pub fn analyze_split_sets( + db: &Scanner, + names: &[String], + opts: &ScanOptions, + mut fetch: F, +) -> Vec +where + F: FnMut(&str, Option) -> io::Result>, +{ + use unpack::volume::{group, parse, Scheme}; + + #[derive(Clone, Copy, PartialEq)] + enum Kind { + Rar, + Zip, + Cab, + } + struct Set { + name: String, + kind: Kind, + parts: Vec, + /// Why the set cannot be joined, when it is known from the names. + broken: Option<&'static str>, + } + let mut sets: Vec = Vec::new(); + let lower = |s: &str| s.to_ascii_lowercase(); + + // RAR: the naming schemes say the order, and a gap says a part is missing. + let rar: Vec<&str> = names + .iter() + .map(String::as_str) + .filter(|n| { + matches!( + parse(n).map(|v| v.scheme), + Some(Scheme::RarPart { .. } | Scheme::RarOld) + ) + }) + .collect(); + for set in group(&rar) { + let parts: Vec<&str> = set.iter().map(|&i| rar[i]).collect(); + let first = parse(parts[0]).expect("grouped by name"); + let contiguous = parts + .iter() + .enumerate() + .all(|(i, p)| parse(p).is_some_and(|v| v.index == i)); + sets.push(Set { + name: format!("{}.rar", first.stem), + kind: Kind::Rar, + parts: parts.iter().map(|p| (*p).to_string()).collect(), + broken: (!contiguous).then_some("part of a multi-volume RAR set with a volume missing"), + }); + } + + // ZIP: `x.z01` ... and the `x.zip` that comes last and holds the directory. + let mut stems: Vec = Vec::new(); + for n in names { + if let Some(v) = parse(n).filter(|v| v.scheme == Scheme::ZipSplit) { + if !stems.iter().any(|s| s.eq_ignore_ascii_case(&v.stem)) { + stems.push(v.stem); + } + } + } + for stem in stems { + let mut numbered: Vec<(usize, &String)> = names + .iter() + .filter_map(|n| { + parse(n) + .filter(|v| v.scheme == Scheme::ZipSplit && v.stem.eq_ignore_ascii_case(&stem)) + .map(|v| (v.index, n)) + }) + .collect(); + numbered.sort(); + let last = names + .iter() + .find(|n| lower(n) == lower(&format!("{stem}.zip"))); + let contiguous = numbered.iter().enumerate().all(|(i, (idx, _))| *idx == i); + let mut parts: Vec = numbered.iter().map(|(_, n)| (*n).clone()).collect(); + let broken = match last { + Some(l) => { + parts.push(l.clone()); + (!contiguous).then_some("part of a multi-volume ZIP set with a volume missing") + } + None => Some( + "part of a multi-volume ZIP set whose last volume, the `.zip`, was not present", + ), + }; + sets.push(Set { + name: format!("{stem}.zip"), + kind: Kind::Zip, + parts, + broken, + }); + } + + // CAB: no naming scheme; each header names its neighbours. + let mut cabs: Vec<(String, unpack::CabLinks)> = Vec::new(); + for n in names.iter().filter(|n| lower(n).ends_with(".cab")) { + // The header, its reserved area and the two names fit in 64 KiB. + if let Some(l) = fetch(n, Some(64 * 1024)) + .ok() + .and_then(|h| unpack::cab_links(&h)) + { + cabs.push((n.clone(), l)); + } + } + let mut ids: Vec = cabs.iter().map(|(_, l)| l.set_id).collect(); + ids.sort_unstable(); + ids.dedup(); + for id in ids { + let mut members: Vec<&(String, unpack::CabLinks)> = + cabs.iter().filter(|(_, l)| l.set_id == id).collect(); + members.sort_by_key(|(_, l)| l.index); + // The header's name is a label: its last component, whatever separator. + let leaf = |s: &str| lower(s.rsplit(['/', '\\']).next().unwrap_or(s)); + let chained = members.iter().enumerate().all(|(i, (name, l))| { + usize::from(l.index) == i + && (i == 0) == l.prev.is_none() + && (i + 1 == members.len()) == l.next.is_none() + && l.next + .as_deref() + .is_none_or(|n| members.get(i + 1).is_some_and(|m| leaf(n) == lower(&m.0))) + && l.prev + .as_deref() + .is_none_or(|p| i > 0 && leaf(p) == lower(&members[i - 1].0)) + && !name.is_empty() + }); + sets.push(Set { + name: members[0].0.clone(), + kind: Kind::Cab, + parts: members.iter().map(|(n, _)| n.clone()).collect(), + broken: (!chained).then_some("part of a multi-volume CAB set whose cabinets do not follow one another as their headers say"), + }); + } + + let mut out = Vec::new(); + let mut held_total = 0usize; + for set in sets { + let verdict = |report: ScanReport, out: &mut Vec| { + for part in &set.parts { + out.push(VolumeSetVerdict { + name: part.clone(), + set: set.name.clone(), + report: report.clone(), + }); + } + }; + if let Some(reason) = set.broken { + verdict( + ScanReport::unscannable(reason.to_string(), Vec::new()), + &mut out, + ); + continue; + } + let mut data: Vec> = Vec::new(); + let mut lost = None; + for part in &set.parts { + match fetch(part, None) { + Ok(d) => { + held_total = held_total.saturating_add(d.len()); + if held_total > opts.deep_analysis_max as usize { + lost = Some("part of a multi-volume set too large to hold for rejoining (--max-object-bytes)"); + break; + } + data.push(d); + } + Err(_) => { + lost = + Some("part of a multi-volume set one of whose volumes could not be read"); + break; + } + } + } + held_total = held_total.saturating_sub(data.iter().map(Vec::len).sum()); + if let Some(reason) = lost { + verdict( + ScanReport::unscannable(reason.to_string(), Vec::new()), + &mut out, + ); + continue; + } + let joined: Result = match set.kind { + Kind::Rar | Kind::Cab => { + let refs: Vec<&[u8]> = data.iter().map(Vec::as_slice).collect(); + let joined = if set.kind == Kind::Rar { + unpack::join_rar_volumes(&refs) + } else { + unpack::join_cab_volumes(&refs) + }; + joined.map(|j| analyze(db, &j, opts)) + } + Kind::Zip => { + let parts = data + .into_iter() + .map(|d| Box::new(d) as Box) + .collect(); + unpack::span::ZipSpan::new(parts).map(|s| analyze_source(db, &s, opts)) + } + }; + let report = joined.unwrap_or_else(|e| { + ScanReport::unscannable( + format!("part of a multi-volume set that could not be rejoined: {e}"), + Vec::new(), + ) + }); + verdict(report, &mut out); + } + out +} + /// The name a part's SET is reported under, matching what /// `unpack::volume::Collector` names a joined set. A name that does not parse as /// a volume is its own set of one. @@ -2790,6 +3019,54 @@ fn member_metadata_scan( None } +/// Smallest and largest member worth remembering as scanned clean: below the +/// first, scanning again costs about what the digest does; past the second, the +/// digest is another read of a very large object. +const CLEAN_MEMO_MIN: usize = 64 * 1024; +const CLEAN_MEMO_MAX: usize = 512 * 1024 * 1024; + +/// A digest of a member's bytes and of what a scan of it reads from its place: +/// the type of its container, the type its container forces on it, the types +/// above it, and the extension of its name. `None` for a member outside the +/// sizes worth remembering. +fn clean_memo_key( + cx: &MemberCtx<'_>, + name: &str, + core_type: Option, + data: &dyn ByteSource, +) -> Option<[u8; 32]> { + use sha2::Digest; + let len = data.len(); + if !(CLEAN_MEMO_MIN..=CLEAN_MEMO_MAX).contains(&len) { + return None; + } + let ext = name + .rsplit_once('.') + .map_or("", |(_, e)| e) + .to_ascii_lowercase(); + let mut h = sha2::Sha256::new(); + h.update( + format!( + "{:?}|{core_type:?}|{:?}|{ext}|{len}|", + cx.member_container, + engine::ancestry_snapshot() + ) + .as_bytes(), + ); + let mut at = 0; + while at < len { + let w = data.window(at, byte_source::CHUNK.min(len - at)); + if w.is_empty() { + return None; + } + h.update(&w[..]); + at += w.len(); + } + let mut key = [0u8; 32]; + key.copy_from_slice(&h.finalize()); + Some(key) +} + /// Scan one member's bytes, as an object one level below its container. /// /// Split from [`member_metadata_scan`] because a member of a multi-volume set @@ -2800,6 +3077,7 @@ fn member_metadata_scan( fn member_content_scan( cx: &MemberCtx<'_>, tally: &mut MemberTally, + name: &str, data: &dyn ByteSource, budget: &mut Budget, findings: &mut Vec, @@ -2825,11 +3103,30 @@ fn member_content_scan( container: cx.member_container, core_type, filename: None, + name: Some(name), core: true, carve: true, embedded: false, }; - match scan_object(cx.db, data, obj, cx.opts, budget, findings, sink) { + // The same bytes in the same place, already scanned clean at this depth or + // shallower, cannot give a different answer, and a document that holds + // copies of itself would otherwise be scanned once per copy. + let seen = clean_memo_key(cx, name, core_type, data); + if seen + .as_ref() + .is_some_and(|k| engine::clean_seen(k, obj.depth)) + { + return None; + } + let truncated_before = engine::scan_was_truncated(); + let outcome = scan_object(cx.db, data, obj, cx.opts, budget, findings, sink); + if let (DeepOutcome::Clean, Some(k)) = (&outcome, seen) { + // A scan that stopped short on the way has not seen all of it. + if truncated_before || !engine::scan_was_truncated() { + engine::clean_seen_insert(k, obj.depth); + } + } + match outcome { DeepOutcome::Clean => None, // Nested unscannable/encrypted members are remembered, not propagated as // a stop: keep scanning the rest of this container. @@ -2866,6 +3163,11 @@ struct Obj<'a> { /// The input's name, for YARA's filename externals. Nothing inside the /// input has one. filename: Option<&'a str>, + /// The name the object has where it sits (the input's, or a member's), for + /// what only a name says, like which text format a plain file is. Unlike + /// `filename`, a member has one; what is carved or decoded does not. + #[cfg_attr(not(feature = "visible-text"), allow(dead_code))] + name: Option<&'a str>, /// Whether to match the object's own bytes. Off for an archive carved out /// of an object whose own match already covered them. core: bool, @@ -2888,6 +3190,7 @@ impl<'a> Obj<'a> { container: None, core_type: None, filename: opts.filename.as_deref(), + name: opts.filename.as_deref(), core: true, carve: true, embedded: false, @@ -2901,6 +3204,7 @@ impl<'a> Obj<'a> { container, core_type: None, filename: None, + name: None, core: true, carve: true, embedded: false, @@ -3748,6 +4052,58 @@ fn normalizations(ft: FileType, data: &dyn ByteSource) -> Vec<(ViewKind, FileTyp v } +/// The text a reader sees in the object `data` called `name` (Markdown, HTML, +/// an Office or OpenDocument XML part, PDF, a drawing): its words, and where +/// each link leads (`exav_render::text`). +/// +/// The text as a text view is matched, and each link whose label is not its +/// target as `(label, target)`. +/// +/// `None` when the object has none, or when it cannot be made, and the scan is +/// then marked incomplete: the object is past `deep_analysis_max`, so it is +/// neither held in memory nor read whole. A text cut at four times the object and a little, +/// which no real document comes to, and a PDF past the extraction limits, mark +/// the scan incomplete too; what was made is still scanned. So does an +/// office document (with `visible-text-office`) whose text cannot be taken +/// out: encrypted, past a limit, damaged. +#[cfg(feature = "visible-text")] +fn visible_text_view(name: &str, data: &dyn ByteSource, opts: &ScanOptions) -> Option { + if !exav_render::text::wants(name, &data.window(0, 1024)) { + return None; + } + let bytes = whole(data, opts, "the reading of its visible text")?; + let cap = bytes + .len() + .saturating_mul(4) + .saturating_add(64 << 10) + .min(usize::try_from(opts.deep_analysis_max).unwrap_or(usize::MAX)); + let visible = exav_render::text::visible_text(name, &bytes, cap, &opts.limits)?; + if visible.truncated { + engine::mark_scan_truncated(); + } + // A document of a kind that has text, whose text could not be taken out + // (encrypted, past a limit, damaged): its bytes are still scanned, and the + // scan is not complete. + if visible.unreadable.is_some() { + engine::mark_scan_truncated(); + return None; + } + // As any text view is, so that `Target:7` signatures, written against the + // lowercased, whitespace-collapsed form, apply. + Some(VisibleView { + text: normalize::text(visible.text.as_bytes()), + links: visible.links, + }) +} + +/// A document's visible text as a text view, and its links. +#[cfg(feature = "visible-text")] +struct VisibleView { + text: Vec, + /// Each link whose label is not its target, as `(label, target)`. + links: Vec<(String, String)>, +} + /// A normalised view of an object: [`normalize`]'s three, and [`jsnorm`]'s. #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum ViewKind { @@ -3938,8 +4294,13 @@ fn core_matches( }; // A PE's structure (layout, icons, section table) is parsed from all of it. let image = pe_image(ft, data, opts); - // PE layout lets the engine resolve EP/section-relative offsets. - let layout = image.as_deref().and_then(pe::layout); + // PE layout lets the engine resolve EP/section-relative offsets, and so + // does an ELF's or a Mach-O's, read from its headers. + let layout = image.as_deref().and_then(pe::layout).or_else(|| match ft { + FileType::Elf => pe::elf_layout(data), + FileType::MachO => pe::macho_layout(data), + _ => None, + }); // PE-icon perceptual metrics for `IconGroup1/2`-constrained logical // signatures: computed only for a PE when `.idb` entries are loaded. They // gate such sigs (the structural condition must also hold); see [`icon`]. @@ -4001,6 +4362,30 @@ fn core_matches( engine_pass(view.source(), as_type, None, None, None)?; } } + // The words of a document, and where each link leads: what a reader sees, + // which the bytes above do not give (a label naming one site over a target + // on another, markup, an entity, a compressed stream or an escape in the + // middle of a signature's text). + #[cfg(feature = "visible-text")] + if !opts.clamav_compat && !db.engine.is_empty() { + if let Some(view) = profile::timed("visible-text", data.len() as u64, || { + visible_text_view(obj.name.unwrap_or(""), data, opts) + }) { + // Reported where the document is, as the other views are. + engine_pass(&view.text, FileType::TextView, None, None, None)?; + // A link that says one site and goes to another, in a document + // that is not HTML: judged as an anchor of an HTML one is. + if opts.alert_phishing { + let (found, complete) = phishing::scan_links(&view.links, &db.phishing); + if !complete { + engine::mark_scan_truncated(); + } + if let Some(p) = found { + hit(p.signature(), false, 0, Method::Heuristic)?; + } + } + } + } // Bytecode programs whose trigger/hook fires (gated execution). Their // names are reported verbatim, never `.UNOFFICIAL`-suffixed. let mut unpacked = Vec::new(); @@ -5123,6 +5508,111 @@ mod tests { } } + /// 128 KiB of text that differs with `seed`. + #[cfg(feature = "all-formats")] + fn memo_body(seed: usize) -> Vec { + let text: String = (0..4096) + .map(|i| format!("line {seed} {i} of a member with nothing in it\n")) + .collect(); + text.as_bytes()[..128 * 1024].to_vec() + } + + /// A stored zip of `n` members of `memo_body`, the same in each when `same`. + #[cfg(feature = "all-formats")] + fn memo_zip(n: usize, same: bool) -> Vec { + use std::io::Write; + let stored = zip::write::SimpleFileOptions::default() + .compression_method(zip::CompressionMethod::Stored); + let mut z = zip::ZipWriter::new(std::io::Cursor::new(Vec::new())); + for k in 0..n { + z.start_file(format!("member{k}.txt"), stored).unwrap(); + z.write_all(&memo_body(if same { 0 } else { k })).unwrap(); + } + z.finish().unwrap().into_inner() + } + + fn clean_skips_of(data: &[u8]) -> (Verdict, u64) { + engine::CLEAN_SKIPS.with(|c| c.set(0)); + let v = analyze(&Scanner::builtin(), data, &ScanOptions::default()).verdict; + (v, engine::CLEAN_SKIPS.with(|c| c.get())) + } + + /// Bytes already scanned clean in the same place are not scanned again: + /// the first of 40 copies is scanned and the other 39 are not. + #[test] + #[cfg(feature = "all-formats")] + fn copies_of_a_clean_member_are_scanned_once() { + assert_eq!(clean_skips_of(&memo_zip(40, true)), (Verdict::Clean, 39)); + } + + /// The control: members that differ are each scanned. + #[test] + #[cfg(feature = "all-formats")] + fn members_that_differ_are_each_scanned() { + assert_eq!(clean_skips_of(&memo_zip(40, false)), (Verdict::Clean, 0)); + } + + /// Members under the size worth remembering are scanned every time. + #[test] + #[cfg(feature = "all-formats")] + fn small_copies_are_each_scanned() { + use std::io::Write; + let stored = zip::write::SimpleFileOptions::default() + .compression_method(zip::CompressionMethod::Stored); + let mut z = zip::ZipWriter::new(std::io::Cursor::new(Vec::new())); + for k in 0..10 { + z.start_file(format!("m{k}.txt"), stored).unwrap(); + z.write_all(&memo_body(0)[..1000]).unwrap(); + } + let z = z.finish().unwrap().into_inner(); + assert_eq!(clean_skips_of(&z), (Verdict::Clean, 0)); + } + + /// A copy that is not clean is found wherever it is, after clean ones with + /// the same start. + #[test] + #[cfg(feature = "all-formats")] + fn an_infected_member_after_clean_copies_is_found() { + use std::io::Write; + let stored = zip::write::SimpleFileOptions::default() + .compression_method(zip::CompressionMethod::Stored); + // Deflated, so the signature is in the member only, not in the zip's bytes. + let deflated = zip::write::SimpleFileOptions::default() + .compression_method(zip::CompressionMethod::Deflated); + let mut z = zip::ZipWriter::new(std::io::Cursor::new(Vec::new())); + for k in 0..3 { + z.start_file(format!("clean{k}.bin"), stored).unwrap(); + z.write_all(&memo_body(0)).unwrap(); + } + let mut dirty = memo_body(0); + dirty.extend_from_slice(&[eicar(), b"\n"].concat().repeat(64)); + z.start_file("dirty.bin", deflated).unwrap(); + z.write_all(&dirty).unwrap(); + let z = z.finish().unwrap().into_inner(); + let (v, skips) = clean_skips_of(&z); + assert_eq!(skips, 2); + assert!(matches!(v, Verdict::Infected { .. }), "{v:?}"); + } + + /// The memo remembers the shallowest depth a clean scan was at: a copy + /// deeper than that is covered, one shallower is not. + #[test] + fn a_clean_copy_covers_only_the_same_depth_or_deeper() { + engine::reset_scan_truncated(); + let key = [7u8; 32]; + assert!(!engine::clean_seen(&key, 3)); + engine::clean_seen_insert(key, 3); + assert!(!engine::clean_seen(&key, 2)); + assert!(engine::clean_seen(&key, 3)); + assert!(engine::clean_seen(&key, 9)); + engine::clean_seen_insert(key, 1); + assert!(engine::clean_seen(&key, 1)); + assert!(!engine::clean_seen(&key, 0)); + // A new scan starts with nothing remembered. + engine::reset_scan_truncated(); + assert!(!engine::clean_seen(&key, 9)); + } + #[test] fn detects_eicar_pattern() { let db = Scanner::builtin(); diff --git a/crates/exav-core/src/pe.rs b/crates/exav-core/src/pe.rs index a8723f2..6634894 100644 --- a/crates/exav-core/src/pe.rs +++ b/crates/exav-core/src/pe.rs @@ -538,6 +538,160 @@ pub fn layout(data: &[u8]) -> Option { }) } +/// Most sections an ELF or Mach-O layout lists: a section table is a `u16` +/// long in an ELF, and nothing a real file has comes near it. +const MAX_EXEC_SECTIONS: u64 = 1 << 16; + +/// [`PeLayout`] of an ELF file, for the `EP`, `Sn`, `SL` and `SEn` offsets of a +/// `Target:6` signature, read from the headers alone (the object is not held). +/// +/// As clamscan resolves them (measured, with one signature per offset and one +/// wrong by three bytes as the control): `EP` is the entry point's file +/// offset, found by the loadable segment whose memory image holds it (the +/// part past the file's bytes, the `.bss`, included), and `Sn` is the file +/// offset of section header `n`, counted from the null section at 0. +/// A section with no bytes in the file (`SHT_NOBITS`) is a point. +pub fn elf_layout(src: &dyn ByteSource) -> Option { + let mut f = Fields::new(src); + let ident = f.get(0, 16)?; + if &ident[..4] != b"\x7fELF" { + return None; + } + let wide = match ident[4] { + 1 => false, + 2 => true, + _ => return None, + }; + // Anything but little-endian is read as big-endian, as `elf_broken` does. + f.be = ident[5] != 1; + let (header, ph_min, sh_min) = if wide { (64, 56, 64) } else { (52, 32, 40) }; + f.get(0, header)?; + let w = if wide { 8 } else { 4 }; + let entry_va = f.word(24, wide)?; + let (phoff, shoff) = (f.word(24 + w, wide)?, f.word(24 + 2 * w, wide)?); + let fields = 28 + 3 * w; + let [ph_entsize, phnum, sh_entsize, shnum] = + [2, 4, 6, 8].map(|i| f.u16(fields + i).map(u64::from)); + let (ph_entsize, phnum, sh_entsize, shnum) = + (ph_entsize?, phnum?, sh_entsize?, shnum?); + + let mut entry = None; + if ph_entsize >= ph_min { + let (offset_at, vaddr_at, memsz_at) = if wide { (8, 16, 40) } else { (4, 8, 20) }; + for i in 0..phnum { + let p = phoff.checked_add(i * ph_entsize)?; + let (Some(kind), Some(offset), Some(vaddr), Some(memsz)) = ( + f.u32(p), + f.word(p + offset_at, wide), + f.word(p + vaddr_at, wide), + f.word(p + memsz_at, wide), + ) else { + break; + }; + // PT_LOAD + if kind == 1 && entry_va >= vaddr && entry_va - vaddr < memsz { + entry = offset.checked_add(entry_va - vaddr); + break; + } + } + } + + let mut section_rawptrs = Vec::new(); + let mut section_rawsizes = Vec::new(); + if sh_entsize >= sh_min { + let (offset_at, size_at) = if wide { (24, 32) } else { (16, 20) }; + for i in 0..shnum.min(MAX_EXEC_SECTIONS) { + let Some(s) = shoff.checked_add(i * sh_entsize) else { + break; + }; + let (Some(kind), Some(offset), Some(size)) = + (f.u32(s + 4), f.word(s + offset_at, wide), f.word(s + size_at, wide)) + else { + break; + }; + section_rawptrs.push(offset); + // SHT_NOBITS + section_rawsizes.push(if kind == 8 { 0 } else { size }); + } + } + Some(PeLayout { + entry, + section_rawptrs, + section_rawsizes, + version_info: Vec::new(), + }) +} + +/// [`PeLayout`] of a thin Mach-O file, for the `Sn`, `SL` and `SEn` offsets +/// of a `Target:9` signature. `n` counts the sections of every segment in the +/// order of the load commands, and an offset is the section's own. +/// +/// `EP` is left unresolved: clamscan 1.4.3 does not resolve it on a Mach-O of +/// either width, from `LC_MAIN` or from `LC_UNIXTHREAD` (a signature +/// anchored there never fired in any of eight variants, where the section +/// offsets did, each with a control), so a signature using it matches +/// nowhere, as it does there. +pub fn macho_layout(src: &dyn ByteSource) -> Option { + let mut f = Fields::new(src); + let (wide, be) = match f.get(0, 4)? { + [0xCE, 0xFA, 0xED, 0xFE] => (false, false), + [0xCF, 0xFA, 0xED, 0xFE] => (true, false), + [0xFE, 0xED, 0xFA, 0xCE] => (false, true), + [0xFE, 0xED, 0xFA, 0xCF] => (true, true), + _ => return None, + }; + f.be = be; + let header: u64 = if wide { 32 } else { 28 }; + let (ncmds, sizeofcmds) = (u64::from(f.u32(16)?), u64::from(f.u32(20)?)); + let end = header.checked_add(sizeofcmds)?; + if end > src.len() as u64 { + return None; + } + // LC_SEGMENT and LC_SEGMENT_64, and what each one's sections are like. + let (segment, nsects_at, first_section, section_len, size_at, offset_at) = if wide { + (0x19u32, 64u64, 72u64, 80u64, 40u64, 48u64) + } else { + (0x1, 48, 56, 68, 36, 40) + }; + let mut section_rawptrs = Vec::new(); + let mut section_rawsizes = Vec::new(); + let mut at = header; + 'commands: for _ in 0..ncmds.min(MAX_EXEC_SECTIONS) { + let (Some(cmd), Some(size)) = (f.u32(at), f.u32(at + 4).map(u64::from)) else { + break; + }; + if size < 8 || at.checked_add(size)? > end { + break; + } + if cmd == segment { + let Some(nsects) = f.u32(at + nsects_at).map(u64::from) else { + break; + }; + for i in 0..nsects { + let s = at + first_section + i * section_len; + if s + section_len > at + size || section_rawptrs.len() as u64 >= MAX_EXEC_SECTIONS { + break 'commands; + } + let (Some(offset), Some(len)) = + (f.u32(s + offset_at).map(u64::from), f.word(s + size_at, wide)) + else { + break 'commands; + }; + section_rawptrs.push(offset); + // A zero-fill section has no bytes in the file. + section_rawsizes.push(if offset == 0 { 0 } else { len }); + } + } + at += size; + } + Some(PeLayout { + entry: None, + section_rawptrs, + section_rawsizes, + version_info: Vec::new(), + }) +} + /// One PE section in the shape the bytecode PE APIs expect /// (`cli_exe_section`). /// @@ -778,9 +932,34 @@ pub(crate) fn embedded_in(data: &dyn ByteSource) -> Embedded { pub(crate) struct Carving { finders: Vec>, hits: Vec<(usize, Magic)>, + /// Where the last ZIP local header seen says the next entry begins, when + /// it can say (see [`zip_next_header`]). + zip_next: Option, pub(crate) found: Embedded, } +/// Where the ZIP local header at `off` says the next entry begins: after its +/// name, extra field and compressed data. `None` when it cannot say: the entry +/// is encrypted, its sizes follow the data (a data descriptor), or its size is +/// ZIP64's. +fn zip_next_header(data: &dyn ByteSource, off: usize) -> Option { + let h = data.window(off, 30); + if h.len() != 30 || h[..4] != *b"PK\x03\x04" { + return None; + } + let flags = u16::from_le_bytes([h[6], h[7]]); + if flags & 0b1001 != 0 { + return None; + } + let csize = u32::from_le_bytes([h[18], h[19], h[20], h[21]]); + if csize == u32::MAX { + return None; + } + let name = usize::from(u16::from_le_bytes([h[26], h[27]])); + let extra = usize::from(u16::from_le_bytes([h[28], h[29]])); + off.checked_add(30 + name + extra)?.checked_add(csize as usize) +} + impl Carving { /// Bytes each window must run into the next, so a magic across the seam /// is seen whole. @@ -800,6 +979,7 @@ impl Carving { Carving { finders: CARVE_MAGICS.iter().map(|(m, _)| memchr::memmem::Finder::new(m)).collect(), hits: Vec::new(), + zip_next: None, found: Embedded::default(), } } @@ -822,14 +1002,30 @@ impl Carving { pub(crate) fn feed(&mut self, data: &dyn ByteSource, at: usize, w: &[u8], owned: usize) { let found = &mut self.found; let hits = &mut self.hits; + let zip_next = &mut self.zip_next; hits.clear(); for (f, (_, kind)) in self.finders.iter().zip(CARVE_MAGICS) { hits.extend(f.find_iter(w).take_while(|&p| p < owned).map(|p| (at + p, kind))); } hits.sort_unstable_by_key(|&(off, _)| off); for &(off, kind) in hits.iter() { + let zip = matches!(kind, Magic::Archive) && data.window(off, 4)[..] == *b"PK\x03\x04"; if off == 0 { - continue; // the object's own image or archive + // The object's own image or archive; a ZIP's later entries + // are its own, not archives stapled inside it. + if zip { + *zip_next = zip_next_header(data, off); + } + continue; + } + // The next entry of a ZIP already taken is read when that ZIP is: + // its walk reaches every local header after its own, wherever the + // directory points. Counting each as an archive of its own would + // fill the cap with one zip's members and rescan the rest of the + // object once per member. + if zip && *zip_next == Some(off) { + *zip_next = zip_next_header(data, off); + continue; } let (list, cap, ok) = match kind { Magic::Pe => (&mut found.pe, MAX_EMBEDDED_PE, pe_at(data, off)), @@ -838,9 +1034,16 @@ impl Carving { Magic::MachoFat => (&mut found.macho, MAX_EMBEDDED_PE, macho_fat_at(data, off)), Magic::Archive => (&mut found.archives, MAX_EMBEDDED_ARCHIVES, archive_at(data, off)), }; + // The chain follows only a ZIP that will be scanned. + if zip { + *zip_next = None; + } if ok { if list.len() < cap { list.push(off); + if zip { + *zip_next = zip_next_header(data, off); + } } else if matches!(kind, Magic::Pe) { found.pe_capped = true; } else { @@ -1235,6 +1438,82 @@ mod tests { assert!(found.others_capped); } + /// A ZIP local header for an entry named `name` holding `len` bytes, with + /// the general-purpose `flags` and a declared compressed size of `csize`, + /// followed by `len` bytes of data. + fn zip_entry(name: &str, flags: u16, csize: u32, len: usize) -> Vec { + let mut e = b"PK\x03\x04\x14\0".to_vec(); + e.extend_from_slice(&flags.to_le_bytes()); + e.extend_from_slice(&[0, 0, 0, 0, 0x21, 0, 0, 0, 0, 0]); + e.extend_from_slice(&csize.to_le_bytes()); + e.extend_from_slice(&(len as u32).to_le_bytes()); + e.extend_from_slice(&(name.len() as u16).to_le_bytes()); + e.extend_from_slice(&[0, 0]); + e.extend_from_slice(name.as_bytes()); + e.extend_from_slice(&vec![b'.'; len]); + e + } + + /// `entries` entries of a ZIP (each declaring its size truthfully) after a + /// text prefix. + fn zip_after_prefix(entries: usize, flags: u16) -> (Vec, usize) { + let mut data = b"a carrier with a zip stapled inside it\n".to_vec(); + let first = data.len(); + for k in 0..entries { + data.extend(zip_entry(&format!("m{k}"), flags, 20, 20)); + } + (data, first) + } + + /// The entries of one ZIP stapled into an object are read when the ZIP is, + /// so only the first is a candidate: they neither fill the cap nor are the + /// object rescanned once per entry. + #[test] + fn the_entries_of_a_zip_are_not_archives_of_their_own() { + let (data, first) = zip_after_prefix(MAX_EMBEDDED_ARCHIVES * 2, 0); + let found = embedded_in(&&data[..]); + assert_eq!(found.archives, [first]); + assert!(!found.others_capped); + } + + /// A ZIP that is the object itself: every header after its own is an entry. + #[test] + fn the_entries_of_a_zip_at_offset_zero_are_not_archives_of_their_own() { + let (data, first) = zip_after_prefix(40, 0); + let found = embedded_in(&&data[first..]); + assert!(found.archives.is_empty() && !found.others_capped); + } + + /// Where the header does not say where the next entry begins, each header + /// stays a candidate: a data descriptor, encryption or ZIP64's size leaves + /// the position unknown. + #[test] + fn a_header_that_cannot_place_the_next_one_keeps_every_candidate() { + for flags in [0b1000, 0b0001] { + let (data, _) = zip_after_prefix(5, flags); + assert_eq!(embedded_in(&&data[..]).archives.len(), 5, "flags {flags:#b}"); + } + let mut data = b"carrier\n".to_vec(); + for k in 0..5 { + data.extend(zip_entry(&format!("m{k}"), 0, u32::MAX, 20)); + } + assert_eq!(embedded_in(&&data[..]).archives.len(), 5, "ZIP64 size"); + } + + /// A header that names a size that does not lead to the next header does + /// not hide it: a second archive placed anywhere else is still a + /// candidate. + #[test] + fn a_size_that_misses_the_next_header_keeps_it_a_candidate() { + let mut data = b"carrier\n".to_vec(); + let first = data.len(); + // Declares 10 bytes of data, holds 20: the chain lands inside them. + data.extend(zip_entry("a", 0, 10, 20)); + let second = data.len(); + data.extend(zip_entry("b", 0, 20, 20)); + assert_eq!(embedded_in(&&data[..]).archives, [first, second]); + } + #[test] fn embedded_macho_carved_and_java_rejected() { // A 64-bit LE Mach-O executable header (MH_MAGIC_64 = CF FA ED FE) at a diff --git a/crates/exav-core/src/phishing.rs b/crates/exav-core/src/phishing.rs index 6a01295..ace8d4a 100644 --- a/crates/exav-core/src/phishing.rs +++ b/crates/exav-core/src/phishing.rs @@ -235,6 +235,30 @@ pub(crate) fn scan_complete_source( (None, true) } +/// [`scan_complete`] over links already read: `(display, href)` pairs, from a +/// document that is not HTML (Markdown, a PDF) and has its own way of saying +/// where a link goes. Judged as an anchor is, allow-list included. +#[cfg(feature = "visible-text")] +pub(crate) fn scan_links(links: &[(String, String)], db: &PhishingDb) -> (Option, bool) { + let mut allow_checks = 0usize; + for (display, href) in links { + let Some(p) = classify(href, display, db) else { + continue; + }; + if db.has_allow_list() { + if allow_checks == MAX_ALLOW_CHECKS { + return (None, false); + } + allow_checks += 1; + if allow_listed(href, display, db) { + continue; + } + } + return (Some(p), true); + } + (None, true) +} + /// Offset of the next ` Result<&mut Self> { + check_paren_depth(src)?; let ast = AST::from(src); if let Some(err) = ast.errors().first() { return Err(Error::new(format!("parse error: {err:?}"))); @@ -190,6 +191,10 @@ impl Compiler { /// the returned list. pub fn add_source_lenient(&mut self, src: &str) -> Vec<(String, Error)> { let mut rejected = Vec::new(); + if let Err(e) = check_paren_depth(src) { + rejected.push((String::new(), e)); + return rejected; + } let ast = AST::from(src); if let Some(err) = ast.errors().first() { rejected.push((String::new(), Error::new(format!("parse error: {err:?}")))); @@ -1419,6 +1424,72 @@ fn const_to_cond(v: crate::yara::ir::Value) -> Cond { /// Maps an integer file-read function name to its [`IntKind`], or `None` for /// non-integer reads (e.g. `float32`, which is not implemented). Single-byte /// `_be` variants are equivalent to their little-endian forms. +/// Deepest parenthesis nesting a rule source may have. The parser tries each +/// `(` twice, as a boolean group and as an arithmetic one, and does not keep +/// what the first try parsed, so a rule with an error inside `d` open +/// parentheses costs about 2^d steps (a 3.5 KB rule with 15 took 5.6 s). +const MAX_PAREN_DEPTH: usize = 12; + +/// Refuses a source nested deeper than [`MAX_PAREN_DEPTH`] before it is parsed. +/// Strings, comments and regular expressions are skipped. +fn check_paren_depth(src: &str) -> Result<()> { + let b = src.as_bytes(); + let (mut i, mut depth) = (0, 0usize); + // The last byte that was not whitespace, to tell a regex from a division. + let mut prev = 0u8; + while i < b.len() { + let c = b[i]; + match c { + b'"' => { + i += 1; + while i < b.len() && b[i] != b'"' { + i += if b[i] == b'\\' { 2 } else { 1 }; + } + } + b'/' if b.get(i + 1) == Some(&b'/') => { + while i < b.len() && b[i] != b'\n' { + i += 1; + } + } + b'/' if b.get(i + 1) == Some(&b'*') => { + i += 2; + while i < b.len() && !b[i..].starts_with(b"*/") { + i += 1; + } + i += 1; + } + b'/' if prev == b'=' || b[..i].trim_ascii_end().ends_with(b"matches") => { + i += 1; + let mut class = false; + while i < b.len() && (class || b[i] != b'/') { + match b[i] { + b'\\' => i += 1, + b'[' => class = true, + b']' => class = false, + _ => {} + } + i += 1; + } + } + b'(' => { + depth += 1; + if depth > MAX_PAREN_DEPTH { + return Err(Error::new(format!( + "parentheses nested more than {MAX_PAREN_DEPTH} deep" + ))); + } + } + b')' => depth = depth.saturating_sub(1), + _ => {} + } + if !c.is_ascii_whitespace() { + prev = c; + } + i += 1; + } + Ok(()) +} + fn int_kind(name: &str) -> Option { Some(match name { "uint8" | "uint8be" => IntKind::U8, @@ -1434,3 +1505,59 @@ fn int_kind(name: &str) -> Option { _ => return None, }) } + +#[cfg(test)] +mod paren_depth_tests { + use super::{Compiler, MAX_PAREN_DEPTH}; + use std::time::{Duration, Instant}; + + fn nested(depth: usize) -> String { + format!( + "rule r {{ condition: {}true{} }}", + "(".repeat(depth), + ")".repeat(depth) + ) + } + + /// A 3.5 KB rule with an error inside 15 open parentheses (`yara`, fuzz + /// timeout): the parser took 5.6 s to refuse it. + #[test] + fn a_rule_with_an_error_deep_in_parentheses_is_refused_fast() { + let src = include_str!("../../tests/fixtures/fuzz/yara_nested_parens.yar"); + let start = Instant::now(); + let err = Compiler::new().add_source(src).err().expect("refused"); + assert!( + start.elapsed() < Duration::from_millis(500), + "{:?}", + start.elapsed() + ); + assert!(err.to_string().contains("nested"), "{err}"); + let start = Instant::now(); + let rejected = Compiler::new().add_source_lenient(src); + assert!( + start.elapsed() < Duration::from_millis(500), + "{:?}", + start.elapsed() + ); + assert_eq!(rejected.len(), 1); + } + + #[test] + fn nesting_up_to_the_bound_compiles_and_one_more_is_refused() { + assert!(Compiler::new().add_source(&nested(MAX_PAREN_DEPTH)).is_ok()); + assert!(Compiler::new() + .add_source(&nested(MAX_PAREN_DEPTH + 1)) + .is_err()); + } + + #[test] + fn parentheses_in_strings_comments_and_regexes_are_not_counted() { + let many = "(".repeat(40); + let src = format!( + "rule r {{ strings: $a = \"{many}\" $b = /x\\({many_esc}y/ $c = /[{many}]/ \ + condition: // {many}\n /* {many} */ ($a or $b or $c) and \"{many}\" contains \"(\" }}", + many_esc = "\\(".repeat(40) + ); + Compiler::new().add_source(&src).expect("compiles"); + } +} diff --git a/crates/exav-core/tests/fixtures/fuzz/yara_nested_parens.yar b/crates/exav-core/tests/fixtures/fuzz/yara_nested_parens.yar new file mode 100644 index 0000000..68cb702 Binary files /dev/null and b/crates/exav-core/tests/fixtures/fuzz/yara_nested_parens.yar differ diff --git a/crates/exav-core/tests/fixtures/volumes/set4.r00 b/crates/exav-core/tests/fixtures/volumes/set4.r00 new file mode 100644 index 0000000..3cd62dc Binary files /dev/null and b/crates/exav-core/tests/fixtures/volumes/set4.r00 differ diff --git a/crates/exav-core/tests/fixtures/volumes/set4.r01 b/crates/exav-core/tests/fixtures/volumes/set4.r01 new file mode 100644 index 0000000..a2f7ed6 Binary files /dev/null and b/crates/exav-core/tests/fixtures/volumes/set4.r01 differ diff --git a/crates/exav-core/tests/fixtures/volumes/set4.rar b/crates/exav-core/tests/fixtures/volumes/set4.rar new file mode 100644 index 0000000..a7a9a8a Binary files /dev/null and b/crates/exav-core/tests/fixtures/volumes/set4.rar differ diff --git a/crates/exav-core/tests/fixtures/volumes/set5.part1.rar b/crates/exav-core/tests/fixtures/volumes/set5.part1.rar new file mode 100644 index 0000000..b95cd62 Binary files /dev/null and b/crates/exav-core/tests/fixtures/volumes/set5.part1.rar differ diff --git a/crates/exav-core/tests/fixtures/volumes/set5.part2.rar b/crates/exav-core/tests/fixtures/volumes/set5.part2.rar new file mode 100644 index 0000000..344e4d8 Binary files /dev/null and b/crates/exav-core/tests/fixtures/volumes/set5.part2.rar differ diff --git a/crates/exav-core/tests/fixtures/volumes/set5.part3.rar b/crates/exav-core/tests/fixtures/volumes/set5.part3.rar new file mode 100644 index 0000000..dedba0a Binary files /dev/null and b/crates/exav-core/tests/fixtures/volumes/set5.part3.rar differ diff --git a/crates/exav-core/tests/fixtures/volumes/split.z01 b/crates/exav-core/tests/fixtures/volumes/split.z01 new file mode 100644 index 0000000..24bd103 Binary files /dev/null and b/crates/exav-core/tests/fixtures/volumes/split.z01 differ diff --git a/crates/exav-core/tests/fixtures/volumes/split.zip b/crates/exav-core/tests/fixtures/volumes/split.zip new file mode 100644 index 0000000..05bd743 Binary files /dev/null and b/crates/exav-core/tests/fixtures/volumes/split.zip differ diff --git a/crates/exav-core/tests/suites/embedded_carve.rs b/crates/exav-core/tests/suites/embedded_carve.rs index 0331c0f..8618356 100644 --- a/crates/exav-core/tests/suites/embedded_carve.rs +++ b/crates/exav-core/tests/suites/embedded_carve.rs @@ -110,6 +110,80 @@ fn appended_overlay_zip_is_carved_and_scanned() { } } +/// A zip of a few hundred entries stapled into a document is one archive, not +/// one per entry: it is scanned once and does not trip the carving cap. +#[test] +fn a_zip_of_many_entries_stapled_into_a_document_is_clean() { + let stored = + zip::write::SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored); + let mut z = zip::ZipWriter::new(std::io::Cursor::new(Vec::new())); + for k in 0..300 { + z.start_file(format!("entry{k}.txt"), stored).unwrap(); + z.write_all(b"nothing to see here").unwrap(); + } + let z = z.finish().unwrap().into_inner(); + let mut doc = b"a document with a zip stapled inside it\n".to_vec(); + doc.extend_from_slice(&z); + doc.extend_from_slice(&[b'.'; 100]); + assert_eq!(verdict(&doc), Verdict::Clean); +} + +/// A zip whose first header names a size that lands on a second archive does +/// not hide that archive: the first one's walk reaches every local header +/// after its own, whether the second sits inside the first one's span (before +/// its central directory) or after its end. +#[test] +fn a_second_zip_at_the_offset_the_first_one_names_is_still_found() { + let eicar = exav_core::unpack::eicar(); + let deflated = zip::write::SimpleFileOptions::default() + .compression_method(zip::CompressionMethod::Deflated); + let mut x = zip::ZipWriter::new(std::io::Cursor::new(Vec::new())); + x.start_file("p.txt", deflated).unwrap(); + x.write_all(&[eicar, b"\n"].concat().repeat(64)).unwrap(); + let x = x.finish().unwrap().into_inner(); + assert!(!x.windows(eicar.len()).any(|w| w == eicar)); + + // A: one stored entry "a.txt", then `middle`, then its directory. + let a = |middle: &[u8]| { + let data = b"hello"; + let mut crc = flate2::Crc::new(); + crc.update(data); + let mut out = b"PK\x03\x04\x14\0\0\0\0\0\0\0\x21\0".to_vec(); + out.extend_from_slice(&crc.sum().to_le_bytes()); + out.extend_from_slice(&[5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0]); + out.extend_from_slice(b"a.txt"); + out.extend_from_slice(data); + let cd_at = out.len() + middle.len(); + out.extend_from_slice(middle); + let cd = out.len(); + out.extend_from_slice(b"PK\x01\x02\x14\0\x14\0\0\0\0\0\0\0\x21\0"); + out.extend_from_slice(&crc.sum().to_le_bytes()); + // Sizes, name length 5, then the extra, comment, disk, attribute and + // local header offset fields, all zero. + out.extend_from_slice(&[5, 0, 0, 0, 5, 0, 0, 0, 5, 0]); + out.extend_from_slice(&[0; 16]); + out.extend_from_slice(b"a.txt"); + let size = (out.len() - cd) as u32; + out.extend_from_slice(b"PK\x05\x06\0\0\0\0\x01\0\x01\0"); + out.extend_from_slice(&size.to_le_bytes()); + out.extend_from_slice(&(cd_at as u32).to_le_bytes()); + out.extend_from_slice(&[0, 0]); + out + }; + for (what, zip) in [("inside", a(&x)), ("after", [a(b""), x.clone()].concat())] { + let mut doc = b"a document with two zips stapled inside it\n".to_vec(); + doc.extend_from_slice(&zip); + doc.extend_from_slice(&[b'.'; 100]); + match verdict(&doc) { + Verdict::Infected { signature, .. } => assert!( + signature.to_ascii_uppercase().contains("EICAR"), + "{what}: unexpected signature {signature}" + ), + other => panic!("{what}: EICAR in the second zip must be found, got {other:?}"), + } + } +} + /// An executable in an OLE2 file is also carved from the file's own bytes and /// scanned to the end of the file, as ClamAV carves it: a PE-only signature on /// bytes of a later stream matches, which carving inside the executable's own diff --git a/crates/exav-core/tests/suites/exec_offsets.rs b/crates/exav-core/tests/suites/exec_offsets.rs new file mode 100644 index 0000000..5084024 --- /dev/null +++ b/crates/exav-core/tests/suites/exec_offsets.rs @@ -0,0 +1,370 @@ +//! `EP`, `Sn`, `SL` and `SEn` offsets on ELF (`Target:6`) and Mach-O +//! (`Target:9`) files. +//! +//! Until a layout was read from their headers these offsets matched nothing +//! there: a signature anchored at an ELF's entry point was in the database, the +//! file was that ELF, and the scan said `OK`. +//! +//! The expectations are clamscan 1.4.3's, measured one signature at a time on +//! a gcc-built ELF and on hand-built Mach-O files, each offset with a control +//! (the same bytes at an offset wrong by three, which must not fire): +//! +//! * ELF `EP`: the entry point's file offset, through the loadable segment +//! whose memory image holds it, the `.bss` part included; nothing past it, +//! nothing for another file type. +//! * ELF and Mach-O `Sn`: section `n`'s file offset, counted from the null +//! section 0 (ELF) or over the segments in load order (Mach-O); `SL` the last. +//! * `SEn`: the match starts inside section `n`, its end included. +//! * Mach-O `EP`: never resolved (`LC_MAIN` and `LC_UNIXTHREAD`, both widths). + +use exav_core::{analyze, loader, ScanOptions, Verdict}; + +/// 64 bytes of distinct content for a section: `seed` and the position. +fn block(seed: u8) -> Vec { + (0..64u32) + .map(|j| ((u32::from(seed) * 61 + j * 7 + 13) % 251 + 1) as u8) + .collect() +} + +fn put(v: &mut Vec, at: usize, bytes: &[u8]) { + if v.len() < at + bytes.len() { + v.resize(at + bytes.len(), 0); + } + v[at..at + bytes.len()].copy_from_slice(bytes); +} + +/// Bytes of an integer field of `width` bytes in the file's order. +fn int(v: u64, width: usize, be: bool) -> Vec { + let mut b = v.to_le_bytes()[..width].to_vec(); + if be { + b.reverse(); + } + b +} + +/// An ELF with a null section, `.text`, `.rodata`, `.data` and a `.bss`: +/// two loadable segments, the second at a virtual address that is not its file +/// offset plus the first's, and with memory past its bytes. Returns the file, +/// and the file offsets of the sections' contents. +fn elf(wide: bool, be: bool, entry: u64) -> Vec { + let w = if wide { 8 } else { 4 }; + let (ehsize, phsize, shsize) = if wide { (64, 56, 64) } else { (52, 32, 40) }; + let mut f = vec![0u8; 0x600]; + put(&mut f, 0, b"\x7fELF"); + f[4] = if wide { 2 } else { 1 }; + f[5] = if be { 2 } else { 1 }; + f[6] = 1; + let mut at = 16; + for (v, n) in [(2u64, 2), (62, 2), (1, 4)] { + put(&mut f, at, &int(v, n, be)); + at += n; + } + let (phoff, shoff) = (ehsize as u64, 0x400u64); + for v in [entry, phoff, shoff] { + put(&mut f, at, &int(v, w, be)); + at += w; + } + put(&mut f, at, &int(0, 4, be)); // e_flags + at += 4; + for v in [ehsize as u64, phsize as u64, 2, shsize as u64, 5, 0] { + put(&mut f, at, &int(v, 2, be)); + at += 2; + } + // Program headers: (type, offset, vaddr, filesz, memsz). + let segments = [ + (1u64, 0u64, 0x10000u64, 0x300u64, 0x300u64), + (1, 0x300, 0x30000, 0x40, 0x80), + ]; + for (i, (kind, offset, vaddr, filesz, memsz)) in segments.iter().enumerate() { + let p = ehsize + i * phsize; + put(&mut f, p, &int(*kind, 4, be)); + if wide { + for (off, v) in [ + (8, offset), + (16, vaddr), + (24, vaddr), + (32, filesz), + (40, memsz), + ] { + put(&mut f, p + off, &int(*v, 8, be)); + } + } else { + for (off, v) in [ + (4, offset), + (8, vaddr), + (12, vaddr), + (16, filesz), + (20, memsz), + ] { + put(&mut f, p + off, &int(*v, 4, be)); + } + } + } + // Section contents, then the section headers: (type, offset, size). + for (i, off) in [0x200usize, 0x240, 0x300].iter().enumerate() { + put(&mut f, *off, &block(i as u8)); + } + // What follows `.rodata`, which is not in it, and what the file holds + // where the `.bss` would be, so that a wrong offset reads other bytes. + put(&mut f, 0x280, &block(9)[..32]); + put(&mut f, 0x340, &block(7)); + let sections = [ + (0u64, 0u64, 0u64), + (1, 0x200, 0x40), + (1, 0x240, 0x40), + (1, 0x300, 0x40), + (8, 0x340, 0x40), + ]; + for (i, (kind, offset, size)) in sections.iter().enumerate() { + let s = shoff as usize + i * shsize; + put(&mut f, s + 4, &int(*kind, 4, be)); + let (off_at, size_at) = if wide { (24, 32) } else { (16, 20) }; + put(&mut f, s + off_at, &int(*offset, w, be)); + put(&mut f, s + size_at, &int(*size, w, be)); + } + f +} + +/// A Mach-O with `__text` and `__cstring` in `__TEXT`, `__data` in `__DATA`, +/// and an `LC_MAIN` whose entry is at 0x210. +fn macho(wide: bool, be: bool) -> Vec { + let (seg_cmd, seg_head, sect_len, sect_fields) = if wide { + (0x19u64, 72usize, 80usize, 8usize) + } else { + (0x1, 56, 68, 4) + }; + let sections = [ + ("__text", "__TEXT", 0x200u64), + ("__cstring", "__TEXT", 0x240), + ("__data", "__DATA", 0x280), + ]; + let mut cmds = Vec::new(); + for (segname, group) in [("__TEXT", §ions[..2]), ("__DATA", §ions[2..])] { + let size = seg_head + group.len() * sect_len; + let mut c = vec![0u8; size]; + put(&mut c, 0, &int(seg_cmd, 4, be)); + put(&mut c, 4, &int(size as u64, 4, be)); + put(&mut c, 8, segname.as_bytes()); + let nsects_at = if wide { 64 } else { 48 }; + put(&mut c, nsects_at, &int(group.len() as u64, 4, be)); + for (i, (name, seg, offset)) in group.iter().enumerate() { + let s = seg_head + i * sect_len; + put(&mut c, s, name.as_bytes()); + put(&mut c, s + 16, seg.as_bytes()); + put( + &mut c, + s + 32, + &int(0x1_0000_0000 + offset, sect_fields, be), + ); + put(&mut c, s + 32 + sect_fields, &int(0x40, sect_fields, be)); + put(&mut c, s + 32 + 2 * sect_fields, &int(*offset, 4, be)); + } + cmds.extend(c); + } + let mut main = vec![0u8; 24]; + put(&mut main, 0, &int(0x8000_0028, 4, be)); + put(&mut main, 4, &int(24, 4, be)); + put(&mut main, 8, &int(0x210, 8, be)); + cmds.extend(main); + let header = if wide { 32 } else { 28 }; + let mut f = vec![0u8; 0x300]; + let magic: [u8; 4] = match (wide, be) { + (true, false) => [0xCF, 0xFA, 0xED, 0xFE], + (false, false) => [0xCE, 0xFA, 0xED, 0xFE], + (true, true) => [0xFE, 0xED, 0xFA, 0xCF], + (false, true) => [0xFE, 0xED, 0xFA, 0xCE], + }; + put(&mut f, 0, &magic); + put(&mut f, 4, &int(if wide { 0x0100_000c } else { 7 }, 4, be)); + put(&mut f, 12, &int(2, 4, be)); + put(&mut f, 16, &int(3, 4, be)); + put(&mut f, 20, &int(cmds.len() as u64, 4, be)); + put(&mut f, header, &cmds); + for (i, (_, _, offset)) in sections.iter().enumerate() { + put(&mut f, *offset as usize, &block(i as u8)); + } + f +} + +fn hex(b: &[u8]) -> String { + b.iter().map(|x| format!("{x:02x}")).collect() +} + +/// The names of the signatures among `lines` (`name:target:offset:bytes`) +/// that fire on `file`, all of them listed. +fn fired(file: &[u8], lines: &[(&str, &str, &str, &[u8])]) -> Vec { + let mut found = Vec::new(); + // One signature a database: a first-match scan would stop at the first. + for (name, target, offset, bytes) in lines { + let mut b = loader::Builder::new(); + b.add_named_bytes( + "t.ndb", + format!("{name}:{target}:{offset}:{}\n", hex(bytes)).as_bytes(), + true, + ); + let Ok(db) = b.build() else { + continue; + }; + if matches!( + analyze(&db, file, &ScanOptions::default()).verdict, + Verdict::Infected { .. } + ) { + found.push((*name).to_string()); + } + } + found +} + +fn names(v: &[&str]) -> Vec { + v.iter().map(|s| (*s).to_string()).collect() +} + +#[test] +fn an_elf_resolves_its_entry_point_and_its_sections_in_every_class_and_order() { + for (wide, be) in [(true, false), (false, false), (true, true), (false, true)] { + let f = elf(wide, be, 0x10210); + let at = |o: usize| f[o..o + 12].to_vec(); + let got = fired( + &f, + &[ + ("EP", "6", "EP+0", &at(0x210)), + ("EPwrong", "6", "EP+3", &at(0x210)), + ("EPelsewhere", "6", "EP+0", &at(0x200)), + ("S0", "6", "S0+0", &at(0)), + ("S1", "6", "S1+0", &at(0x200)), + ("S1wrong", "6", "S1+3", &at(0x200)), + ("S2", "6", "S2+0", &at(0x240)), + ("S3", "6", "S3+0", &at(0x300)), + ("S3wrong", "6", "S3+3", &at(0x300)), + ("S4", "6", "S4+0", &at(0x340)), + ("S5none", "6", "S5+0", &at(0x200)), + ("SL", "6", "SL+0", &at(0x340)), + ("SLwrong", "6", "SL+3", &at(0x340)), + // Another file type's target. + ("EPasPe", "1", "EP+0", &at(0x210)), + ], + ); + assert_eq!( + got, + names(&["EP", "S0", "S1", "S2", "S3", "S4", "SL"]), + "wide {wide} big-endian {be}" + ); + } +} + +#[test] +fn an_elf_entry_point_is_found_through_the_segment_that_maps_it() { + // In the second segment, whose address is not its offset plus the first's. + let f = elf(true, false, 0x30010); + let sig = |o: usize| f[o..o + 12].to_vec(); + assert_eq!( + fired( + &f, + &[ + ("EP", "6", "EP+0", &sig(0x310)), + ("EPasAddr", "6", "EP+0", &sig(0x10)), + ("EPwrong", "6", "EP+3", &sig(0x310)) + ] + ), + names(&["EP"]) + ); + // In the memory past the segment's bytes, which has an offset all the same. + let f = elf(true, false, 0x30050); + assert_eq!( + fired(&f, &[("EP", "6", "EP+0", &f[0x350..0x35c])]), + names(&["EP"]) + ); + // Past the segment's memory, in none. + let f = elf(true, false, 0x30080); + assert_eq!( + fired( + &f, + &[ + ("EP", "6", "EP+0", &f[0x380..0x38c]), + ("EP0", "6", "EP+0", &f[0..12]) + ] + ), + Vec::::new() + ); +} + +#[test] +fn se_means_a_start_inside_the_section_its_end_included() { + let f = elf(true, false, 0x10210); + // `.rodata` is 0x240..0x280. + let got = fired( + &f, + &[ + ("inside", "6", "SE2", &f[0x244..0x24a]), + ("first", "6", "SE2", &f[0x240..0x246]), + ("lastByteRunningOut", "6", "SE2", &f[0x27e..0x286]), + ("atTheEnd", "6", "SE2", &f[0x280..0x288]), + ("inTheNextOne", "6", "SE2", &f[0x304..0x30a]), + ("inThePrevious", "6", "SE2", &f[0x204..0x20a]), + ], + ); + assert_eq!( + got, + names(&["inside", "first", "lastByteRunningOut", "atTheEnd"]) + ); +} + +#[test] +fn a_macho_resolves_its_sections_in_load_order_and_never_its_entry_point() { + for (wide, be) in [(true, false), (false, false), (true, true), (false, true)] { + let f = macho(wide, be); + let at = |o: usize| f[o..o + 8].to_vec(); + let got = fired( + &f, + &[ + ("S0", "9", "S0+0", &at(0x200)), + ("S0wrong", "9", "S0+3", &at(0x200)), + ("S1", "9", "S1+0", &at(0x240)), + ("S2", "9", "S2+0", &at(0x280)), + ("S3none", "9", "S3+0", &at(0x280)), + ("SL", "9", "SL+0", &at(0x280)), + ("SLwrong", "9", "SL+3", &at(0x280)), + ("SE1", "9", "SE1", &f[0x244..0x24a]), + ("SE1elsewhere", "9", "SE1", &f[0x284..0x28a]), + ("EP", "9", "EP+0", &at(0x210)), + ], + ); + assert_eq!( + got, + names(&["S0", "S1", "S2", "SL", "SE1"]), + "wide {wide} big-endian {be}" + ); + } +} + +#[test] +fn headers_that_lie_give_no_layout_and_no_panic() { + let elf = elf(true, false, 0x10210); + let macho = macho(true, false); + for file in [&elf, &macho] { + // Every field at its extremes, 4 bytes at a time, and the file cut short. + for at in (0..file.len().min(0x120)).step_by(4) { + for v in [0xFFFF_FFFFu32, 0x8000_0000, 0x7FFF_FFFF, 0] { + let mut f = file.clone(); + f[at..at + 4].copy_from_slice(&v.to_le_bytes()); + let _ = fired( + &f, + &[ + ("S1", "6", "S1+0", &[1, 2, 3, 4]), + ("S1m", "9", "S1+0", &[1, 2, 3, 4]), + ("EP", "6", "EP+0", &[1, 2, 3, 4]), + ], + ); + } + } + for cut in (0..file.len()).step_by(37) { + let _ = fired( + &file[..cut], + &[ + ("SL", "6", "SL+0", &[1, 2, 3, 4]), + ("SLm", "9", "SL+0", &[1, 2, 3, 4]), + ], + ); + } + } +} diff --git a/crates/exav-core/tests/suites/format_registry.rs b/crates/exav-core/tests/suites/format_registry.rs new file mode 100644 index 0000000..4cd403c --- /dev/null +++ b/crates/exav-core/tests/suites/format_registry.rs @@ -0,0 +1,82 @@ +//! The scanner's detection against the format registry (`formats/registry.json`, +//! checked against the rest of the code by `scripts/formats.mjs`): the magic +//! bytes the registry gives a format, written into an otherwise empty buffer, +//! are typed as the format's scanner type. + +use exav_core::filetype::identify; + +fn registry() -> serde_json::Value { + let path = concat!(env!("CARGO_MANIFEST_DIR"), "/../../formats/registry.json"); + serde_json::from_str(&std::fs::read_to_string(path).expect("formats/registry.json")).unwrap() +} + +fn hex(s: &str) -> Vec { + (0..s.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&s[i..i + 2], 16).unwrap()) + .collect() +} + +/// A buffer holding `conditions` (`offset:hex`) and zeros elsewhere. +fn buffer(conditions: &[&str]) -> Vec { + let parts: Vec<(usize, Vec)> = conditions + .iter() + .map(|c| { + let (offset, bytes) = c.split_once(':').unwrap(); + (offset.parse().unwrap(), hex(bytes)) + }) + .collect(); + let end = parts.iter().map(|(o, b)| o + b.len()).max().unwrap(); + let mut buf = vec![0u8; end.max(1024)]; + for (offset, bytes) in parts { + buf[offset..offset + bytes.len()].copy_from_slice(&bytes); + } + buf +} + +#[test] +fn the_magic_of_a_format_is_typed_as_that_format() { + let registry = registry(); + let mut checked = 0; + let mut skipped = 0; + let mut wrong = Vec::new(); + for f in registry["formats"].as_array().unwrap() { + let scan = &f["scan"]; + let Some(want) = scan["type"].as_str() else { + continue; + }; + if !matches!(scan["mode"].as_str(), Some("container" | "reported")) { + continue; + } + let id = f["id"].as_str().unwrap(); + // A format the scanner types only when more than the magic holds (a + // header's checksum, a structure that parses) says so in the registry. + if scan.get("needs").is_some() { + skipped += 1; + continue; + } + for alt in f["magic"].as_array().into_iter().flatten() { + let conditions: Vec<&str> = alt + .as_array() + .unwrap() + .iter() + .map(|c| c.as_str().unwrap()) + .collect(); + let got = identify(&buffer(&conditions)).as_str(); + checked += 1; + if got != want { + wrong.push(format!( + "{id} {conditions:?}: typed {got}, the registry says {want}" + )); + } + } + } + assert!(wrong.is_empty(), "{}", wrong.join("\n")); + assert!(checked > 20, "only {checked} magics were checked"); + assert!(skipped <= 3, "{skipped} formats are excused from the check"); +} + +#[test] +fn a_buffer_with_no_magic_of_the_registry_is_data() { + assert_eq!(identify(&vec![0u8; 4096]).as_str(), "data"); +} diff --git a/crates/exav-core/tests/suites/mod.rs b/crates/exav-core/tests/suites/mod.rs index 26f6924..788f847 100644 --- a/crates/exav-core/tests/suites/mod.rs +++ b/crates/exav-core/tests/suites/mod.rs @@ -27,6 +27,9 @@ mod cut_short_members; mod embedded_carve; #[cfg(feature = "all-formats")] mod encrypted_archives; +mod exec_offsets; +#[cfg(feature = "all-formats")] +mod format_registry; #[cfg(feature = "image-hash")] mod fuzzy_img_formats; #[cfg(feature = "all-formats")] @@ -51,12 +54,18 @@ mod salvage; #[cfg(feature = "all-formats")] mod sevenz_ppmd; mod size_caps; +#[cfg(feature = "all-formats")] +mod split_sets; mod tar_size_terminator; mod target_flash; mod target_text; #[cfg(feature = "all-formats")] mod tdb_attributes; mod untyped_container_dispatch; +#[cfg(feature = "visible-text")] +mod visible_text; +#[cfg(feature = "visible-text-office")] +mod visible_text_office; #[cfg(feature = "yara")] mod yara_dotnet; #[cfg(feature = "all-formats")] diff --git a/crates/exav-core/tests/suites/split_sets.rs b/crates/exav-core/tests/suites/split_sets.rs new file mode 100644 index 0000000..28c22e1 --- /dev/null +++ b/crates/exav-core/tests/suites/split_sets.rs @@ -0,0 +1,305 @@ +//! Sets of volumes whose headers say how they join (RAR, ZIP, CAB), scanned as +//! the archives they are. +//! +//! Each volume holds part of a member's bytes, so no volume read alone shows +//! what the member is. The signatures here are the ones only the whole member +//! satisfies: its MD5 (`.hdb`) for the RAR and ZIP sets, and for the CAB a +//! marker that straddles the place the folder was cut. A control in each test +//! scans the parts one at a time and finds nothing. +//! +//! Fixtures: the RAR sets are official RAR's (`rar a -ma5 -m3 -v8k` and +//! `-ma4 -m3 -vn -v8k`, `text.txt` and `noise.bin`; the MD5s are of the inputs, +//! made by `random.Random(20261001)`, see exav-unpack's `rar_solid` suite); the +//! ZIP is `zip -0 -s 64k split.zip payload.bin` of 100,000 bytes of +//! `random.Random(77)`, whose rejoined archive (`zip -s 0`) holds the payload. + +use exav_core::{analyze, analyze_split_sets, loader, ScanOptions, Scanner, Verdict}; +use std::cell::RefCell; + +fn fixture(name: &str) -> Vec { + let path = format!( + "{}/tests/fixtures/volumes/{name}", + env!("CARGO_MANIFEST_DIR") + ); + std::fs::read(&path).unwrap_or_else(|e| panic!("{path}: {e}")) +} + +fn db(files: &[(&str, &str)]) -> Scanner { + let mut b = loader::Builder::new(); + for (name, text) in files { + b.add_named_bytes(name, text.as_bytes(), true); + } + b.build().expect("database") +} + +fn infected(v: &Verdict) -> Option<&str> { + match v { + Verdict::Infected { signature, .. } => Some(signature.as_str()), + _ => None, + } +} + +fn names(v: &[&str]) -> Vec { + v.iter().map(|s| (*s).to_string()).collect() +} + +const NOISE_MD5: &str = "147b5c8ca1767bca1ef297b3024fb0dd"; +const PAYLOAD_MD5: &str = "2e94a8cfc2ebdd36f886a897aeb0cf96"; + +#[test] +fn rar_sets_are_scanned_as_the_archive_they_are() { + let scanner = db(&[("t.hdb", &format!("{NOISE_MD5}:20000:Test.Noise\n"))]); + let opts = ScanOptions::default(); + for (set, parts) in [ + ( + "set5.rar", + ["set5.part1.rar", "set5.part2.rar", "set5.part3.rar"], + ), + ("set4.rar", ["set4.rar", "set4.r00", "set4.r01"]), + ] { + // Alone, no volume shows the member. + for p in parts { + assert!( + infected(&analyze(&scanner, &fixture(p), &opts).verdict).is_none(), + "{p} alone" + ); + } + let mut given = names(&parts); + given.push("notes.txt".into()); + let fetched = RefCell::new(Vec::new()); + let got = analyze_split_sets(&scanner, &given, &opts, |n, head| { + fetched.borrow_mut().push(n.to_string()); + assert!(head.is_none(), "a RAR volume is read whole or not at all"); + Ok(fixture(n)) + }); + assert_eq!(got.len(), 3, "{set}"); + for v in &got { + assert_eq!( + infected(&v.report.verdict), + Some("Test.Noise"), + "{set}: {}", + v.name + ); + assert_eq!(v.set, set); + } + assert!( + !fetched.borrow().iter().any(|n| n == "notes.txt"), + "a file of no set is not read" + ); + } +} + +#[test] +fn a_rar_set_with_a_volume_missing_is_unscannable_not_clean() { + let scanner = db(&[("t.hdb", &format!("{NOISE_MD5}:20000:Test.Noise\n"))]); + let given = names(&["set5.part1.rar", "set5.part3.rar"]); + let got = analyze_split_sets(&scanner, &given, &ScanOptions::default(), |n, _| { + Ok(fixture(n)) + }); + assert_eq!(got.len(), 2); + for v in &got { + assert!( + matches!(v.report.verdict, Verdict::Unscannable { .. }), + "{}: {:?}", + v.name, + v.report.verdict + ); + } + // One volume of a set is a file, not a set. + let alone = analyze_split_sets( + &scanner, + &names(&["set5.part1.rar"]), + &ScanOptions::default(), + |n, _| Ok(fixture(n)), + ); + assert!(alone.is_empty()); +} + +#[test] +fn a_split_zip_is_scanned_as_the_archive_it_is() { + let scanner = db(&[("t.hdb", &format!("{PAYLOAD_MD5}:100000:Test.Payload\n"))]); + let opts = ScanOptions::default(); + for p in ["split.z01", "split.zip"] { + assert!( + infected(&analyze(&scanner, &fixture(p), &opts).verdict).is_none(), + "{p} alone" + ); + } + let got = analyze_split_sets( + &scanner, + &names(&["split.zip", "other.bin", "split.z01"]), + &opts, + |n, _| Ok(fixture(n)), + ); + assert_eq!(got.len(), 2); + for v in &got { + assert_eq!( + infected(&v.report.verdict), + Some("Test.Payload"), + "{}", + v.name + ); + assert_eq!(v.set, "split.zip"); + } + // Without its last part, the `.zip`, the others are a set with a hole. + let hole = analyze_split_sets( + &scanner, + &names(&["split.z01", "other.bin"]), + &opts, + |n, _| Ok(fixture(n)), + ); + assert_eq!(hole.len(), 1); + assert!( + matches!(hole[0].report.verdict, Verdict::Unscannable { .. }), + "{:?}", + hole[0].report.verdict + ); +} + +/// A cabinet of one folder, uncompressed, as exav-unpack's tests build them. +fn cab( + prev: Option<&str>, + next: Option<&str>, + index: u16, + files: &[(u32, u32, u16, &str)], + blocks: &[(u16, &[u8])], +) -> Vec { + let flags = u16::from(prev.is_some()) | (u16::from(next.is_some()) << 1); + let mut links = Vec::new(); + for n in [prev, next].into_iter().flatten() { + links.extend_from_slice(n.as_bytes()); + links.extend_from_slice(b"\0disk\0"); + } + let mut records = Vec::new(); + for (size, offset, place, name) in files { + records.extend_from_slice(&size.to_le_bytes()); + records.extend_from_slice(&offset.to_le_bytes()); + records.extend_from_slice(&place.to_le_bytes()); + records.extend_from_slice(&[0x21, 0x5a, 0x00, 0x60, 0x20, 0x00]); + records.extend_from_slice(name.as_bytes()); + records.push(0); + } + let coff_files = 36 + links.len() + 8; + let data_at = coff_files + records.len(); + let mut data = Vec::new(); + for (uncompressed, payload) in blocks { + data.extend_from_slice(&0u32.to_le_bytes()); + data.extend_from_slice(&(payload.len() as u16).to_le_bytes()); + data.extend_from_slice(&uncompressed.to_le_bytes()); + data.extend_from_slice(payload); + } + let mut out = b"MSCF".to_vec(); + out.extend_from_slice(&0u32.to_le_bytes()); + out.extend_from_slice(&((data_at + data.len()) as u32).to_le_bytes()); + out.extend_from_slice(&0u32.to_le_bytes()); + out.extend_from_slice(&(coff_files as u32).to_le_bytes()); + out.extend_from_slice(&0u32.to_le_bytes()); + out.extend_from_slice(&[3, 1]); + for v in [1u16, files.len() as u16, flags, 5, index] { + out.extend_from_slice(&v.to_le_bytes()); + } + out.extend(links); + out.extend_from_slice(&(data_at as u32).to_le_bytes()); + out.extend_from_slice(&(blocks.len() as u16).to_le_bytes()); + out.extend_from_slice(&0u16.to_le_bytes()); + out.extend(records); + out.extend(data); + out +} + +const MARKER: &[u8] = b"exav-cab-set-marker-0123456789-end"; + +fn cab_set() -> (Vec, Vec) { + let mut stream = vec![b'.'; 600]; + stream.extend_from_slice(MARKER); + stream.extend_from_slice(&[b'.'; 600]); + // One block cut inside the marker. + let cut = 600 + MARKER.len() / 2; + let one = cab( + None, + Some("part2.cab"), + 0, + &[(stream.len() as u32, 0, 0xFFFE, "marker.txt")], + &[(0, &stream[..cut])], + ); + let two = cab( + Some("part1.cab"), + None, + 1, + &[(stream.len() as u32, 0, 0xFFFD, "marker.txt")], + &[(stream.len() as u16, &stream[cut..])], + ); + (one, two) +} + +fn cab_db() -> Scanner { + let hex: String = MARKER.iter().map(|b| format!("{b:02x}")).collect(); + db(&[("t.ndb", &format!("Test.Cab:0:*:{hex}\n"))]) +} + +#[test] +fn a_cab_set_is_found_by_the_names_its_headers_give() { + let (one, two) = cab_set(); + let scanner = cab_db(); + let opts = ScanOptions::default(); + for (p, name) in [(&one, "part1.cab"), (&two, "part2.cab")] { + assert!( + infected(&analyze(&scanner, p, &opts).verdict).is_none(), + "{name} alone" + ); + } + let files = [ + ("part1.cab", one.clone()), + ("part2.cab", two.clone()), + ("Readme.txt", b"hello".to_vec()), + ]; + let given = names(&["part2.cab", "readme.txt", "part1.cab", "solo.cab"]); + let reads = RefCell::new(Vec::new()); + let got = analyze_split_sets(&scanner, &given, &opts, |n, head| { + reads.borrow_mut().push((n.to_string(), head)); + files + .iter() + .find(|(f, _)| *f == n) + .map(|(_, d)| d.clone()) + .ok_or_else(|| std::io::Error::other("no such file")) + }); + assert_eq!(got.len(), 2, "{got:?}"); + for v in &got { + assert_eq!(infected(&v.report.verdict), Some("Test.Cab"), "{}", v.name); + assert_eq!(v.set, "part1.cab"); + } + // A text file is not read at all; a cabinet is read by its head to see whether it names a neighbour. + assert!(!reads.borrow().iter().any(|(n, _)| n == "readme.txt")); + assert!(reads + .borrow() + .iter() + .any(|(n, h)| n == "part1.cab" && h.is_some())); +} + +#[test] +fn cabinets_that_do_not_follow_one_another_as_their_headers_say_are_not_joined() { + let (one, two) = cab_set(); + let scanner = cab_db(); + let files = [("part1.cab", one), ("renamed.cab", two)]; + let got = analyze_split_sets( + &scanner, + &names(&["part1.cab", "renamed.cab"]), + &ScanOptions::default(), + |n, _| { + files + .iter() + .find(|(f, _)| *f == n) + .map(|(_, d)| d.clone()) + .ok_or_else(|| std::io::Error::other("no such file")) + }, + ); + assert_eq!(got.len(), 2); + for v in &got { + assert!( + matches!(v.report.verdict, Verdict::Unscannable { .. }), + "{}: {:?}", + v.name, + v.report.verdict + ); + } +} diff --git a/crates/exav-core/tests/suites/target_text.rs b/crates/exav-core/tests/suites/target_text.rs index 2c15a85..04284af 100644 --- a/crates/exav-core/tests/suites/target_text.rs +++ b/crates/exav-core/tests/suites/target_text.rs @@ -12,6 +12,11 @@ //! //! exav ran 3, 4 and 7 over raw bytes of any text-like type, and HTML and text //! views over every one of them: matches clamscan cannot make. +//! +//! The clamscan cases hold under `ScanOptions::clamav_compat()`. With the +//! `visible-text` feature, the default options add a text view of the words a +//! reader sees in an HTML file (Markdown, Office XML and drawings too), which +//! `Target:7` signatures match: a widening on purpose, tested in `visible_text`. use exav_core::{analyze, loader, ScanOptions, Scanner, Verdict}; @@ -31,6 +36,12 @@ fn found(target: u8, body: &str, file: &[u8]) -> bool { matches!(v, Verdict::Infected { .. }) } +/// As clamscan scans: no visible-text view. +fn found_compat(target: u8, body: &str, file: &[u8]) -> bool { + let v = analyze(&scanner(target, body), file, &ScanOptions::clamav_compat()).verdict; + matches!(v, Verdict::Infected { .. }) +} + const TEXT: &[u8] = b"Some text HELLO WORLD MARKER here\n"; const RTF: &[u8] = b"{\\rtf1\\ansi HELLO WORLD MARKER}\n"; const HTML: &[u8] = b"HELLO WORLD MARKER\n"; @@ -44,13 +55,24 @@ fn text_signatures_match_the_text_view_alone() { assert!(found(0, lower, TEXT)); assert!(found(7, lower, TEXT)); assert!(!found(7, upper, TEXT), "never the raw bytes"); - assert!(!found(7, lower, HTML), "nor an HTML file"); + assert!(!found_compat(7, lower, HTML), "nor an HTML file"); assert!( !found(0, lower, b"Some text hello world marker\n"), "a text file's entities are not decoded" ); } +/// The visible-text view is what lets a text signature see an HTML file; its +/// markup is still not part of it. +#[cfg(feature = "visible-text")] +#[test] +fn text_signatures_see_the_words_of_an_html_file_by_default() { + let lower = "hello world marker"; + assert!(found(7, lower, HTML)); + assert!(!found(7, "hello world marker", HTML), "no tags"); + assert!(!found(7, "HELLO WORLD MARKER", HTML), "never the raw bytes"); +} + #[test] fn html_signatures_match_the_html_view_alone() { let lower = "hello world marker"; diff --git a/crates/exav-core/tests/suites/visible_text.rs b/crates/exav-core/tests/suites/visible_text.rs new file mode 100644 index 0000000..a907594 --- /dev/null +++ b/crates/exav-core/tests/suites/visible_text.rs @@ -0,0 +1,345 @@ +//! A Markdown document is matched through the text a reader sees as well as +//! its bytes: its words without the marks, entities decoded, and where each +//! link leads. Which files are Markdown is their name's: `.md` and +//! `.markdown`, the input's or a member's. + +use exav_core::{analyze, loader, ScanOptions, Scanner, Verdict}; + +/// A one-signature database: `Target:7`, which a text view alone matches. +fn scanner(target: u8, body: &str) -> Scanner { + let hex: String = body.bytes().map(|b| format!("{b:02x}")).collect(); + let mut l = loader::Builder::new(); + l.add_named_bytes( + "t.ndb", + format!("Test.Visible:{target}:*:{hex}\n").as_bytes(), + true, + ); + l.build().unwrap() +} + +fn verdict(db: &Scanner, name: Option<&str>, file: &[u8], compat: bool) -> Verdict { + let mut o = ScanOptions::default(); + o.filename = name.map(str::to_string); + o.clamav_compat = compat; + analyze(db, file, &o).verdict +} + +fn found(target: u8, body: &str, name: Option<&str>, file: &[u8]) -> bool { + matches!( + verdict(&scanner(target, body), name, file, false), + Verdict::Infected { .. } + ) +} + +#[test] +fn the_words_are_matched_without_the_marks_between_them() { + let md = b"Please *Download* the **new** version.\n"; + let sig = "please download the new version."; + assert!(found(7, sig, Some("README.md"), md)); + assert!(found(7, sig, Some("notes.MARKDOWN"), md)); + // The same bytes under another name are text, whose view keeps the marks. + assert!(!found(7, sig, Some("notes.txt"), md)); + assert!(!found(7, sig, None, md)); +} + +#[test] +fn an_entity_is_matched_as_the_character_it_is() { + let md = b"Fish & chips <now>\n"; + assert!(found(7, "fish & chips ", Some("a.md"), md)); + assert!(!found(7, "fish & chips ", Some("a.txt"), md)); +} + +#[test] +fn a_link_is_matched_as_its_label_and_where_it_goes() { + let md = b"[Click here](https://evil.example/payload.exe) to continue\n"; + assert!(found( + 7, + "click here (https://evil.example/payload.exe) to continue", + Some("a.md"), + md + )); + // The label names one site, the target another. + let spoof = b"Sign in at [https://www.paypal.com/login](https://evil.example/steal)\n"; + assert!(found( + 7, + "https://www.paypal.com/login (https://evil.example/steal)", + Some("a.md"), + spoof + )); + // A target the viewer would refuse is still seen. + assert!(found( + 7, + "run (javascript:alert(1))", + Some("a.md"), + b"[run](javascript:alert(1))\n" + )); +} + +#[test] +fn target_zero_signatures_see_it_too_and_html_ones_do_not() { + let md = b"a *b* c\n"; + assert!(found(0, "a b c", Some("a.md"), md)); + assert!(!found(3, "a b c", Some("a.md"), md)); +} + +#[test] +fn the_bytes_are_still_matched_as_before() { + assert!(found(0, "a *b* c", Some("a.md"), b"A *B* C\n")); +} + +#[test] +fn not_under_clamav_compat() { + let md = b"Please *download* it\n"; + let db = scanner(7, "please download it"); + assert!(matches!( + verdict(&db, Some("a.md"), md, false), + Verdict::Infected { .. } + )); + assert!(matches!( + verdict(&db, Some("a.md"), md, true), + Verdict::Clean + )); +} + +/// A stored-only ZIP holding one member. +fn zip_with(name: &str, data: &[u8]) -> Vec { + let crc = { + let mut c = !0u32; + for &b in data { + c ^= b as u32; + for _ in 0..8 { + c = if c & 1 != 0 { + (c >> 1) ^ 0xEDB8_8320 + } else { + c >> 1 + }; + } + } + !c + }; + let mut out = Vec::new(); + out.extend_from_slice(b"PK\x03\x04"); + for v in [20u16, 0, 0, 0, 0] { + out.extend_from_slice(&v.to_le_bytes()); + } + out.extend_from_slice(&crc.to_le_bytes()); + out.extend_from_slice(&(data.len() as u32).to_le_bytes()); + out.extend_from_slice(&(data.len() as u32).to_le_bytes()); + out.extend_from_slice(&(name.len() as u16).to_le_bytes()); + out.extend_from_slice(&0u16.to_le_bytes()); + out.extend_from_slice(name.as_bytes()); + out.extend_from_slice(data); + let cd = out.len() as u32; + let mut c = Vec::new(); + c.extend_from_slice(b"PK\x01\x02"); + for v in [20u16, 20, 0, 0, 0, 0] { + c.extend_from_slice(&v.to_le_bytes()); + } + c.extend_from_slice(&crc.to_le_bytes()); + c.extend_from_slice(&(data.len() as u32).to_le_bytes()); + c.extend_from_slice(&(data.len() as u32).to_le_bytes()); + c.extend_from_slice(&(name.len() as u16).to_le_bytes()); + for v in [0u16, 0, 0, 0] { + c.extend_from_slice(&v.to_le_bytes()); + } + c.extend_from_slice(&0u32.to_le_bytes()); + c.extend_from_slice(&0u32.to_le_bytes()); + c.extend_from_slice(name.as_bytes()); + let cl = c.len() as u32; + out.extend_from_slice(&c); + out.extend_from_slice(b"PK\x05\x06"); + for v in [0u16, 0, 1, 1] { + out.extend_from_slice(&v.to_le_bytes()); + } + out.extend_from_slice(&cl.to_le_bytes()); + out.extend_from_slice(&cd.to_le_bytes()); + out.extend_from_slice(&0u16.to_le_bytes()); + out +} + +#[test] +fn a_member_is_markdown_by_its_own_name() { + let md = b"Please *download* the **new** version.\n"; + let sig = scanner(7, "please download the new version."); + let yes = zip_with("docs/Readme.md", md); + let no = zip_with("docs/readme.txt", md); + assert!(matches!( + verdict(&sig, None, &yes, false), + Verdict::Infected { .. } + )); + assert!(matches!(verdict(&sig, None, &no, false), Verdict::Clean)); + // The archive's own name does not make its members Markdown. + assert!(matches!( + verdict(&sig, Some("x.md"), &no, false), + Verdict::Clean + )); +} + +/// A one-page PDF, its text drawn by `content`, padded to `pad` bytes. +#[cfg(feature = "visible-text-pdf")] +fn pdf_with(content: &str, pad: usize) -> Vec { + let mut v = format!( + "%PDF-1.4\n1 0 obj<>endobj\n\ + 2 0 obj<>endobj\n\ + 3 0 obj<>>>/Contents 4 0 R>>endobj\n\ + 4 0 obj<>\nstream\n{content}\nendstream\nendobj\n\ + 5 0 obj<>endobj\n\ + trailer<>\n%%EOF\n", + content.len() + ) + .into_bytes(); + if v.len() < pad { + v.resize(pad, b'\n'); + } + v +} + +#[cfg(feature = "visible-text-pdf")] +#[test] +fn a_pdfs_text_is_matched_though_its_bytes_hold_it_in_pieces() { + let pdf = pdf_with( + "BT /F1 12 Tf 72 700 Td [(Pay to ev) 10 (il.exa) 5 (mple)] TJ ET", + 0, + ); + assert!(found(7, "pay to evil.example", None, &pdf)); + assert!(found(0, "pay to evil.example", None, &pdf)); +} + +#[cfg(feature = "visible-text-pdf")] +#[test] +fn a_compressed_pdf_stream_is_read_through() { + use std::io::Write; + let content = "BT /F1 12 Tf 72 700 Td (Compressed bait text) Tj ET"; + let mut z = flate2::write::ZlibEncoder::new(Vec::new(), flate2::Compression::default()); + z.write_all(content.as_bytes()).unwrap(); + let z = z.finish().unwrap(); + let mut pdf = b"%PDF-1.4\n1 0 obj<>endobj\n2 0 obj<>endobj\n3 0 obj<>>>/Contents 4 0 R>>endobj\n".to_vec(); + pdf.extend_from_slice( + format!( + "4 0 obj<>\nstream\n", + z.len() + ) + .as_bytes(), + ); + pdf.extend_from_slice(&z); + pdf.extend_from_slice(b"\nendstream\nendobj\n5 0 obj<>endobj\ntrailer<>\n%%EOF\n"); + assert!(found(7, "compressed bait text", None, &pdf)); +} + +#[test] +fn html_is_matched_without_its_tags() { + let html = b"

Click here to continue

"; + assert!(found( + 7, + "click here to continue (http://evil.example/x)", + Some("mail.html"), + html + )); + // Found by its content too, with no name. + assert!(found( + 7, + "click here to continue (http://evil.example/x)", + None, + html + )); + // A link whose label names another site. + let spoof = b"https://www.paypal.com/login"; + assert!(found( + 7, + "https://www.paypal.com/login (https://evil.example/steal)", + None, + spoof + )); +} + +fn phishing(name: &str, file: &[u8], alert: bool) -> Verdict { + let mut o = ScanOptions::default(); + o.filename = Some(name.to_string()); + o.alert_phishing = alert; + analyze(&scanner(7, "never present"), file, &o).verdict +} + +#[test] +fn a_link_that_says_one_site_and_goes_to_another_is_phishing_in_markdown_too() { + let md = b"Sign in at [https://www.paypal.com/login](https://evil.example/steal) today\n"; + match phishing("mail.md", md, true) { + Verdict::Infected { signature, .. } => { + assert_eq!(signature, "Heuristics.Phishing.Email.SpoofedDomain") + } + v => panic!("{v:?}"), + } + // Off unless asked for, as for HTML. + assert!(matches!(phishing("mail.md", md, false), Verdict::Clean)); + // A link that is what it says is not. + assert!(matches!( + phishing( + "mail.md", + b"[www.paypal.com](https://www.paypal.com/login)\n", + true + ), + Verdict::Clean + )); + // Nor a label that names no site. + assert!(matches!( + phishing("mail.md", b"[click here](https://evil.example/x)\n", true), + Verdict::Clean + )); +} + +#[test] +fn an_html_link_whose_target_is_written_in_entities_is_judged_as_it_reads() { + // The raw anchor reader sees `https://...`; the page reads `https://...`. + let html = b"www.paypal.com"; + assert!(matches!( + phishing("mail.html", html, true), + Verdict::Infected { .. } + )); +} + +#[test] +fn the_parts_of_an_office_file_are_matched_by_their_path() { + let part = b"Please download the attachment"; + let sig = scanner(7, "please download the attachment"); + let docx = zip_with("word/document.xml", part); + let other = zip_with("word/other.xml", part); + assert!(matches!( + verdict(&sig, None, &docx, false), + Verdict::Infected { .. } + )); + assert!(matches!(verdict(&sig, None, &other, false), Verdict::Clean)); +} + +#[test] +fn a_drawings_text_is_matched_without_its_formatting() { + let dxf = " 0\nSECTION\n 2\nENTITIES\n 0\nMTEXT\n 8\n0\n 10\n0.0\n 20\n0.0\n 30\n0.0\n 40\n2.5\n 1\nPay\\Pnow\n 0\nENDSEC\n 0\nEOF\n"; + assert!(found(7, "pay now", Some("plan.dxf"), dxf.as_bytes())); + assert!(!found(7, "pay now", Some("plan.txt"), b"Pay\\Pnow")); +} + +#[test] +fn an_object_not_held_in_memory_is_not_reported_clean_when_it_has_text() { + let db = scanner(7, "never present"); + // An HTML page: binary objects get no text view for the size to matter to. + let mut page = b"

words

".to_vec(); + page.resize(16 * 1024, b' '); + let verdict = |max: u64| { + let mut o = ScanOptions::default(); + o.deep_analysis_max = max; + o.filename = Some("page.html".to_string()); + analyze(&db, &page, &o).verdict + }; + assert!(matches!(verdict(1 << 20), Verdict::Clean)); + // `analyze` holds the bytes whatever the limit; a larger input is read through a cache. + let mut o = ScanOptions::default(); + o.deep_analysis_max = 4096; + o.filename = Some("page.html".to_string()); + let v = exav_core::scan_seekable( + &db, + std::io::Cursor::new(page.clone()), + page.len() as u64, + &o, + ) + .expect("scan") + .verdict; + assert!(!matches!(v, Verdict::Clean), "{v:?}"); +} diff --git a/crates/exav-core/tests/suites/visible_text_office.rs b/crates/exav-core/tests/suites/visible_text_office.rs new file mode 100644 index 0000000..e3e4cec --- /dev/null +++ b/crates/exav-core/tests/suites/visible_text_office.rs @@ -0,0 +1,138 @@ +//! The office formats' text (`visible-text-office`): a DOC, an XLS, a PPT, an +//! RTF, a flat OpenDocument file is matched through the words a reader sees, +//! its links are judged, and one whose text cannot be taken out is never +//! reported clean. + +use exav_core::{analyze, loader, ScanOptions, Scanner, Verdict}; + +const DOC: &[u8] = include_bytes!("../../../exav-render/tests/fixtures/office/docs/sample.doc"); +const XLS: &[u8] = include_bytes!("../../../exav-render/tests/fixtures/office/sheets/sample.xls"); +const PPT: &[u8] = include_bytes!("../../../exav-render/tests/fixtures/office/slides/sample.ppt"); + +/// A one-signature database: `Target:7`, which a text view alone matches. +fn scanner(body: &str) -> Scanner { + let hex: String = body.bytes().map(|b| format!("{b:02x}")).collect(); + let mut l = loader::Builder::new(); + l.add_named_bytes( + "t.ndb", + format!("Test.Visible:7:*:{hex}\n").as_bytes(), + true, + ); + l.build().unwrap() +} + +fn verdict(db: &Scanner, name: &str, file: &[u8], phishing: bool) -> Verdict { + let mut o = ScanOptions::default(); + o.filename = Some(name.to_string()); + o.alert_phishing = phishing; + analyze(db, file, &o).verdict +} + +fn found(words: &str, name: &str, file: &[u8]) -> bool { + matches!( + verdict(&scanner(words), name, file, false), + Verdict::Infected { .. } + ) +} + +#[test] +fn an_rtf_phrase_split_by_its_groups_is_matched_as_the_words() { + let rtf = b"{\\rtf1\\ansi Please down{\\b load} the \\i attach\\i0 ment\\par}"; + assert!(found("please download the attachment", "mail.rtf", rtf)); + // The words of another document are not there. + assert!(!found("please upload the attachment", "mail.rtf", rtf)); +} + +#[test] +fn the_words_of_a_doc_an_xls_and_a_ppt_are_matched() { + assert!(found("revenue grew by twelve percent", "report.doc", DOC)); + assert!(found("merged note across three columns", "budget.xls", XLS)); + assert!(found("revenue up 12%", "deck.ppt", PPT)); + // A compound file is read by its name: another one is not read. + assert!(!found("revenue up 12%", "deck.bin", PPT)); +} + +#[test] +fn a_flat_opendocument_file_is_matched_without_its_markup() { + let fodt = br#"Wire the funds today"#; + assert!(found("wire the funds today", "invoice.fodt", fodt)); +} + +#[test] +fn a_link_that_says_one_site_and_goes_to_another_is_phishing_in_a_legacy_format_too() { + let rtf = b"{\\rtf1\\ansi Sign in: {\\field{\\*\\fldinst HYPERLINK \"https://evil.example/steal\"}{\\fldrslt https://www.paypal.com/login}}\\par}"; + let db = scanner("never present"); + match verdict(&db, "mail.rtf", rtf, true) { + Verdict::Infected { signature, .. } => { + assert_eq!(signature, "Heuristics.Phishing.Email.SpoofedDomain") + } + v => panic!("{v:?}"), + } + assert!(matches!( + verdict(&db, "mail.rtf", rtf, false), + Verdict::Clean + )); +} + +/// The sample DOC with its FIB's encrypted flag set. +fn encrypted_doc() -> Vec { + let mut d = DOC.to_vec(); + // The WordDocument stream starts a sector with the FIB's magic, 0xA5EC. + let at = (1..d.len() / 512) + .map(|s| s * 512) + .find(|&o| d[o] == 0xEC && d[o + 1] == 0xA5) + .expect("the FIB"); + // fEncrypted: bit 8 of the flags word at 0x0A. + d[at + 0x0B] |= 0x01; + d +} + +#[test] +fn a_document_whose_text_cannot_be_read_is_not_reported_clean() { + let db = scanner("never present"); + // Read, nothing found: clean. + assert!(matches!( + verdict(&db, "report.doc", DOC, false), + Verdict::Clean + )); + // Encrypted: its text is not seen, and the scan says so. + let v = verdict(&db, "report.doc", &encrypted_doc(), false); + assert!( + !matches!(v, Verdict::Clean | Verdict::Infected { .. }), + "{v:?}" + ); +} + +#[test] +fn a_damaged_document_whose_text_cannot_be_taken_out_makes_the_scan_incomplete() { + // The FIB's fields erased: the reader refuses it as damaged, and nothing + // else in the scan looks at what a reader would see. + let mut d = DOC.to_vec(); + let at = (1..d.len() / 512) + .map(|s| s * 512) + .find(|&o| d[o] == 0xEC && d[o + 1] == 0xA5) + .expect("the FIB"); + d[at + 0x20..at + 0x60].fill(0xFF); + let db = scanner("never present"); + let v = verdict(&db, "broken.doc", &d, false); + assert!( + !matches!(v, Verdict::Clean | Verdict::Infected { .. }), + "{v:?}" + ); + // The same bytes under a name that is not an office document's: read as + // nothing, clean. + assert!(matches!( + verdict(&db, "broken.bin", &d, false), + Verdict::Clean + )); +} + +#[test] +fn a_file_that_only_looks_like_a_document_by_its_name_is_not_reported_incomplete() { + // Not a compound file at all, under a .doc name: nothing to read. + let db = scanner("never present"); + assert!(matches!( + verdict(&db, "notes.doc", b"just some plain words", false), + Verdict::Clean + )); +} diff --git a/crates/exav-grep/Cargo.toml b/crates/exav-grep/Cargo.toml index d6be113..f5fe5b3 100644 --- a/crates/exav-grep/Cargo.toml +++ b/crates/exav-grep/Cargo.toml @@ -20,9 +20,22 @@ exav-unpack = { path = "../exav-unpack", version = "0.0.2", default-features = f regex = "1" clap = { workspace = true } walkdir = { workspace = true } +# The text of a document as a reader sees it (`text` feature): exav-render's +# `text`: Markdown, HTML, Office and OpenDocument XML parts, PDF and drawings. +exav-render = { path = "../exav-render", version = "0.0.2", default-features = false, features = ["text"], optional = true } [features] -default = ["decrypt"] +default = ["decrypt", "text"] +# `--text`: search the text a reader sees rather than the bytes, for the +# formats that have one (Markdown, HTML, Office and OpenDocument XML parts, +# PDF, drawings). +text = ["dep:exav-render"] +# And PDF's, read by hayro. +text-pdf = ["text", "exav-render/text-pdf"] +# And the office formats the XML parts do not reach: DOC, XLS, PPT, RTF, Word +# 2003 XML, SpreadsheetML 2003, SYLK, flat OpenDocument, Numbers, Pages and +# Keynote, by sheet, slide and part. The largest readers: not a default. +text-office = ["text", "exav-render/text-office"] # Decrypt encrypted members (ZIP/7z/DMG/Office) so their contents are searchable # rather than reported as unreadable. decrypt = ["exav-unpack/decrypt"] diff --git a/crates/exav-grep/src/lib.rs b/crates/exav-grep/src/lib.rs index ac0a8b3..e574428 100644 --- a/crates/exav-grep/src/lib.rs +++ b/crates/exav-grep/src/lib.rs @@ -103,6 +103,14 @@ pub struct Options { pub max_count: usize, /// Treat a member as binary and report only that it matched, not the line. pub binary_as_matches: bool, + /// Search the text a reader sees rather than the bytes, for a member that + /// has one: Markdown, HTML, the XML parts of Office and OpenDocument files, + /// PDF and drawings are searched as their words, with entities decoded and + /// each link followed by where it goes, under the path `file.md!text`, its + /// line numbers being the text's. A document that is also a container (a + /// PDF, a drawing) is walked for its members as before. Does nothing + /// without the `text` feature. + pub text: bool, } /// One result of the search. @@ -280,8 +288,8 @@ impl Searcher { }); } let Some(fmt) = exav_unpack::detect(&data).or_else(|| packed_executable(data)) else { - // A leaf: search its bytes. - return self.search_one(label, data, sink); + // A leaf: search its bytes, or its text. + return self.search_leaf(label, data, sink); }; // A container is searched through its MEMBERS, not its raw bytes — for a // stored member those are the same bytes, and reporting both would @@ -350,9 +358,88 @@ impl Searcher { if keep_going && members == 0 { return self.search_one(label, data, sink); } + // A container with text of its own (a PDF, a drawing) is searched as + // that too, besides its members. + #[cfg(feature = "text")] + if keep_going && self.opts.text { + if let Some(go) = self.search_text(label, data, sink) { + return go; + } + } keep_going } + /// Search a leaf: its text under `--text` when it has one, else its bytes. + fn search_leaf(&mut self, label: &str, data: &[u8], sink: Sink) -> bool { + #[cfg(feature = "text")] + if self.opts.text { + if let Some(go) = self.search_text(label, data, sink) { + return go; + } + } + self.search_one(label, data, sink) + } + + /// Search the text a reader sees in `data`, as `label!text` (and + /// `label!text/
` for a sheet or a slide), when it is a kind of + /// document that has some (`None` when it is not, and also when its text + /// could not be taken out: that is reported unreadable and its bytes are + /// searched instead). A text cut short is reported unreadable, as a + /// member that failed part way is. + #[cfg(feature = "text")] + fn search_text(&mut self, label: &str, data: &[u8], sink: Sink) -> Option { + let name = label.rsplit(NESTING_SEP).next().unwrap_or(label); + let cap = usize::try_from(self.opts.limits.max_buffer_bytes).unwrap_or(usize::MAX); + let cap = data + .len() + .saturating_mul(4) + .saturating_add(64 << 10) + .min(cap); + let visible = exav_render::text::visible_text(name, data, cap, &self.opts.limits)?; + let path = format!("{label}{NESTING_SEP}text"); + if let Some(why) = &visible.unreadable { + // A document of a kind that has text whose text could not be + // taken out: said, and its bytes are searched instead. + self.unreadable += 1; + if !sink(Event::Unreadable { + path, + reason: format!("visible text: {why}"), + }) { + return Some(false); + } + return None; + } + // One search to a section (a sheet, a slide), so that a match says + // where it is: `book.xls!text/sheet "Budget"`; what comes before the + // first section, and a document of one block, is `!text`. + let mut at = 0; + let mut parts: Vec<(String, std::ops::Range)> = Vec::new(); + for (section, range) in &visible.sections { + if range.start > at { + parts.push((path.clone(), at..range.start)); + } + parts.push((format!("{path}/{section}"), range.clone())); + at = range.end; + } + if at < visible.text.len() || parts.is_empty() { + parts.push((path.clone(), at..visible.text.len())); + } + for (part, range) in parts { + let bytes = visible.text.as_bytes().get(range).unwrap_or_default(); + if !self.search_one(&part, bytes, sink) { + return Some(false); + } + } + if visible.truncated { + self.unreadable += 1; + return Some(sink(Event::Unreadable { + path, + reason: format!("visible text cut at {cap} bytes"), + })); + } + Some(true) + } + /// Line-match a single object's bytes. fn search_one(&mut self, path: &str, data: &[u8], sink: Sink) -> bool { if looks_binary(data) { diff --git a/crates/exav-grep/src/main.rs b/crates/exav-grep/src/main.rs index 2dacb59..070b426 100644 --- a/crates/exav-grep/src/main.rs +++ b/crates/exav-grep/src/main.rs @@ -101,6 +101,15 @@ struct Cli { /// hiding them turns "I couldn't look" into an indistinguishable "no match". #[arg(long)] quiet_unreadable: bool, + + /// Search the text a reader sees rather than the bytes, for the files that + /// have one: Markdown, HTML, Office and OpenDocument XML parts, PDF and + /// drawings (DXF, DWG). Entities are decoded and each link is followed by + /// where it goes; matches are reported under `file.md!text`, with the + /// text's line numbers. + #[cfg(feature = "text")] + #[arg(long)] + text: bool, } fn main() -> ExitCode { @@ -137,6 +146,10 @@ fn main() -> ExitCode { after_context: cli.after_context.max(ctx), max_count: cli.max_count, binary_as_matches: true, + #[cfg(feature = "text")] + text: cli.text, + #[cfg(not(feature = "text"))] + text: false, }; let mut searcher = Searcher::new(matcher, opts); diff --git a/crates/exav-grep/tests/text.rs b/crates/exav-grep/tests/text.rs new file mode 100644 index 0000000..bf90bea --- /dev/null +++ b/crates/exav-grep/tests/text.rs @@ -0,0 +1,178 @@ +//! `--text`: a Markdown file is searched as the text a reader sees. + +#![cfg(feature = "text")] + +use std::path::{Path, PathBuf}; +use std::process::{Command, Output}; + +const BIN: &str = env!("CARGO_BIN_EXE_exav-grep"); + +/// A scratch directory unique to one test, removed when the test ends. +struct Scratch(PathBuf); + +impl Scratch { + fn new(tag: &str) -> Self { + let d = std::env::temp_dir().join(format!("exav-grep-text-{}-{tag}", std::process::id())); + let _ = std::fs::remove_dir_all(&d); + std::fs::create_dir_all(&d).expect("scratch dir"); + Scratch(d) + } + + fn write(&self, name: &str, bytes: &[u8]) -> PathBuf { + let p = self.0.join(name); + std::fs::write(&p, bytes).expect("write fixture"); + p + } +} + +impl Drop for Scratch { + fn drop(&mut self) { + let _ = std::fs::remove_dir_all(&self.0); + } +} + +fn run(args: &[&str], file: &Path) -> Output { + Command::new(BIN) + .args(args) + .arg(file) + .output() + .expect("spawn exav-grep") +} + +fn code(o: &Output) -> i32 { + o.status.code().expect("exited normally, not by signal") +} + +fn stdout(o: &Output) -> String { + String::from_utf8_lossy(&o.stdout).into_owned() +} + +/// Minimal stored-member ZIP (local headers only: exav reads those). +fn zip_of(name: &str, body: &[u8]) -> Vec { + let mut v = Vec::new(); + v.extend_from_slice(b"PK\x03\x04"); + for n in [20u16, 0, 0, 0, 0] { + v.extend_from_slice(&n.to_le_bytes()); + } + v.extend_from_slice(&0u32.to_le_bytes()); + v.extend_from_slice(&(body.len() as u32).to_le_bytes()); + v.extend_from_slice(&(body.len() as u32).to_le_bytes()); + v.extend_from_slice(&(name.len() as u16).to_le_bytes()); + v.extend_from_slice(&0u16.to_le_bytes()); + v.extend_from_slice(name.as_bytes()); + v.extend_from_slice(body); + v +} + +#[test] +fn words_split_by_marks_are_found_only_with_text() { + let s = Scratch::new("marks"); + let f = s.write( + "notes.md", + b"# Title\n\nPlease *download* the **new** version.\n", + ); + let with = run(&["--text", "-F", "Please download the new version"], &f); + assert_eq!(code(&with), 0, "{}", stdout(&with)); + assert_eq!( + stdout(&with), + format!("{}!text:2:Please download the new version.\n", f.display()) + ); + // Without it, the bytes are searched, marks and all. + assert_eq!( + code(&run(&["-F", "Please download the new version"], &f)), + 1 + ); + // And what is in the bytes still is, with it, only as the reader sees it. + assert_eq!(code(&run(&["--text", "-F", "**new**"], &f)), 1); +} + +#[test] +fn a_link_is_followed_by_where_it_goes_and_an_entity_is_decoded() { + let s = Scratch::new("links"); + let f = s.write( + "a.markdown", + b"Sign in at [https://www.paypal.com/login](https://evil.example/steal) & pay\n", + ); + let o = run(&["--text", "evil.example/steal"], &f); + assert_eq!(code(&o), 0); + assert!( + stdout(&o).contains("https://www.paypal.com/login (https://evil.example/steal) & pay"), + "{}", + stdout(&o) + ); +} + +#[test] +fn a_member_of_an_archive_is_searched_by_its_own_name() { + let s = Scratch::new("zip"); + let body = b"Please *download* it\n"; + let md = s.write("a.zip", &zip_of("docs/readme.md", body)); + let o = run(&["--text", "-F", "Please download it"], &md); + assert_eq!(code(&o), 0); + assert_eq!( + stdout(&o), + format!( + "{}!docs/readme.md!text:1:Please download it\n", + md.display() + ) + ); + let txt = s.write("b.zip", &zip_of("docs/readme.txt", body)); + assert_eq!(code(&run(&["--text", "-F", "Please download it"], &txt)), 1); +} + +#[test] +fn html_is_searched_without_its_tags() { + let s = Scratch::new("html"); + let f = s.write( + "page.html", + b"

Click here to go on

", + ); + let o = run( + &[ + "--text", + "-F", + "Click here to go on (http://evil.example/x)", + ], + &f, + ); + assert_eq!(code(&o), 0, "{}", stdout(&o)); + assert_eq!( + stdout(&o), + format!( + "{}!text:1:Click here to go on (http://evil.example/x)\n", + f.display() + ) + ); + assert_eq!(code(&run(&["-F", "Click here to go on"], &f)), 1); +} + +#[cfg(feature = "text-pdf")] +#[test] +fn a_pdf_is_searched_as_its_text_besides_its_streams() { + let s = Scratch::new("pdf"); + let content = "BT /F1 12 Tf 72 700 Td [(Pay to ev) 10 (il.exa) 5 (mple)] TJ ET"; + let pdf = format!( + "%PDF-1.4\n1 0 obj<>endobj\n2 0 obj<>endobj\n\ + 3 0 obj<>>>/Contents 4 0 R>>endobj\n\ + 4 0 obj<>\nstream\n{content}\nendstream\nendobj\n\ + 5 0 obj<>endobj\ntrailer<>\n%%EOF\n", + content.len() + ); + let f = s.write("doc.pdf", pdf.as_bytes()); + let o = run(&["--text", "-F", "Pay to evil.example"], &f); + assert_eq!(code(&o), 0, "{}", stdout(&o)); + assert_eq!( + stdout(&o), + format!("{}!text:1:Pay to evil.example\n", f.display()) + ); + assert_eq!(code(&run(&["-F", "Pay to evil.example"], &f)), 1); +} + +#[test] +fn other_files_are_searched_as_they_are() { + let s = Scratch::new("other"); + let f = s.write("notes.txt", b"a *b* c\n"); + let o = run(&["--text", "-F", "a *b* c"], &f); + assert_eq!(code(&o), 0); + assert_eq!(stdout(&o), format!("{}:1:a *b* c\n", f.display())); +} diff --git a/crates/exav-grep/tests/text_office.rs b/crates/exav-grep/tests/text_office.rs new file mode 100644 index 0000000..b811184 --- /dev/null +++ b/crates/exav-grep/tests/text_office.rs @@ -0,0 +1,129 @@ +//! `--text` on the office formats the XML parts do not reach: a match says +//! its sheet or slide, and a document whose text cannot be taken out is +//! reported unreadable. + +#![cfg(feature = "text-office")] + +use std::path::{Path, PathBuf}; +use std::process::{Command, Output}; + +const BIN: &str = env!("CARGO_BIN_EXE_exav-grep"); + +const XLS: &[u8] = include_bytes!("../../exav-render/tests/fixtures/office/sheets/sample.xls"); +const PPT: &[u8] = include_bytes!("../../exav-render/tests/fixtures/office/slides/sample.ppt"); +const DOC: &[u8] = include_bytes!("../../exav-render/tests/fixtures/office/docs/sample.doc"); + +/// A scratch directory unique to one test, removed when the test ends. +struct Scratch(PathBuf); + +impl Scratch { + fn new(tag: &str) -> Self { + let d = std::env::temp_dir().join(format!("exav-grep-office-{}-{tag}", std::process::id())); + let _ = std::fs::remove_dir_all(&d); + std::fs::create_dir_all(&d).expect("scratch dir"); + Scratch(d) + } + + fn write(&self, name: &str, bytes: &[u8]) -> PathBuf { + let p = self.0.join(name); + std::fs::write(&p, bytes).expect("write fixture"); + p + } +} + +impl Drop for Scratch { + fn drop(&mut self) { + let _ = std::fs::remove_dir_all(&self.0); + } +} + +fn run(args: &[&str], file: &Path) -> Output { + Command::new(BIN) + .args(args) + .arg(file) + .output() + .expect("spawn exav-grep") +} + +fn code(o: &Output) -> i32 { + o.status.code().expect("exited normally, not by signal") +} + +fn stdout(o: &Output) -> String { + String::from_utf8_lossy(&o.stdout).into_owned() +} + +#[test] +fn a_match_in_a_workbook_says_its_sheet() { + let s = Scratch::new("xls"); + let f = s.write("budget.xls", XLS); + let o = run(&["--text", "-F", "Second sheet"], &f); + assert_eq!(code(&o), 0, "{}", stdout(&o)); + // The text, by sheet (the workbook's own stream is a member too, and its + // bytes match as well). + let line = format!("{}!text/sheet \"Notes\":2:Second sheet\t1\n", f.display()); + assert!(stdout(&o).contains(&line), "{}", stdout(&o)); + assert!(!stdout(&o).contains("sheet \"Budget\""), "{}", stdout(&o)); + // Another sheet's words are in that sheet. + let o = run(&["--text", "-F", "Merged note"], &f); + assert!( + stdout(&o).contains(&format!("{}!text/sheet \"Budget\":", f.display())), + "{}", + stdout(&o) + ); +} + +#[test] +fn a_match_in_a_presentation_says_its_slide() { + let s = Scratch::new("ppt"); + let f = s.write("deck.ppt", PPT); + let o = run(&["--text", "-F", "Second slide text"], &f); + assert_eq!(code(&o), 0, "{}", stdout(&o)); + assert_eq!( + stdout(&o), + format!("{}!text/slide 2:2:Second slide text\n", f.display()) + ); +} + +#[test] +fn a_documents_words_are_found_without_its_formatting_and_one_block_is_the_text() { + let s = Scratch::new("doc"); + let f = s.write("report.doc", DOC); + let o = run(&["--text", "-F", "costs stayed flat"], &f); + assert_eq!(code(&o), 0, "{}", stdout(&o)); + assert!( + stdout(&o).starts_with(&format!("{}!text:", f.display())), + "{}", + stdout(&o) + ); +} + +#[test] +fn an_encrypted_document_is_reported_unreadable_and_its_bytes_are_searched() { + let s = Scratch::new("locked"); + let mut doc = DOC.to_vec(); + let at = (1..doc.len() / 512) + .map(|n| n * 512) + .find(|&o| doc[o] == 0xEC && doc[o + 1] == 0xA5) + .expect("the FIB"); + doc[at + 0x0B] |= 0x01; + let f = s.write("locked.doc", &doc); + let o = run(&["--text", "-F", "no such words"], &f); + // No match, and a part that could not be read: the search is incomplete. + assert_eq!(code(&o), 3, "{}", stdout(&o)); + let all = format!("{}{}", stdout(&o), String::from_utf8_lossy(&o.stderr)); + assert!( + all.contains("visible text") && all.contains("ncrypted"), + "{all}" + ); +} + +#[test] +fn without_text_the_bytes_are_searched_as_before() { + let s = Scratch::new("bytes"); + let f = s.write("deck.ppt", PPT); + let o = run(&["-a", "-F", "Second slide text"], &f); + // The text is stored as UTF-16 or 8-bit in a compound file: the word + // search on bytes may or may not see it, and never says a sheet or a slide. + assert!(!stdout(&o).contains("!text"), "{}", stdout(&o)); +} diff --git a/crates/exav-pe-emu/NOTICE b/crates/exav-pe-emu/NOTICE index d61ed5d..c0b3d88 100644 --- a/crates/exav-pe-emu/NOTICE +++ b/crates/exav-pe-emu/NOTICE @@ -1,7 +1,85 @@ exav-pe-emu: third-party notices +================================ -This crate is part of exav and contains no third-party source. The notices -for the components exav links are in the NOTICE file at the root of the exav -repository, which also ships in every release archive: +exav-pe-emu is licensed under the MIT License (see LICENSE). This file gives the +notices for the third-party data in this crate's source. The notices for the +components the exav binaries link are in the NOTICE file at the root of the +exav repository: https://github.com/sylvinus/exav/blob/main/NOTICE -https://github.com/sylvinus/exav/blob/main/NOTICE + +Microsoft API documentation, CC BY 4.0 (export name lists) +---------------------------------------------------------- + +src/exports/{kernel32,ntdll,user32,advapi32}.txt list the export names the +synthetic system DLLs advertise. scripts/gen-exports.py, in this crate, +extracts them from the metadata of Microsoft's API reference pages: for each +page marked as a DLL export, the function name and the DLLs that export it. +Nothing else from the pages is used. The lists are a selection and +rearrangement of that metadata (names only, sorted, one per line). One name is +added by the script with its reason stated there: ntdll's RtlDecompressBuffer, +which the documentation records only under NtosKrnl.exe. + +Sources, pinned by commit: + + MicrosoftDocs/sdk-api + https://github.com/MicrosoftDocs/sdk-api + commit 9e0d205d747b5e0f08019cc7e202112c3aa1f68c + MicrosoftDocs/windows-driver-docs-ddi + https://github.com/MicrosoftDocs/windows-driver-docs-ddi + commit 7515063cea4c9e98db6a92986c5b4ddb0463fd16 + +Copyright (c) Microsoft Corporation. + +The documentation is licensed under the Creative Commons Attribution 4.0 +International Public License (CC BY 4.0): +https://creativecommons.org/licenses/by/4.0/legalcode + +The material is provided as-is, without warranties of any kind, as stated in +section 5 of that licence. + + +Layout facts for the synthetic TEB, PEB, loader lists and KUSER_SHARED_DATA +--------------------------------------------------------------------------- + +src/win.rs tags each field it writes with where its offset comes from. No text +is copied; these are the sources of the facts, all Microsoft documentation +under the CC BY 4.0 notice above: + + [pe] PE Format specification, "The .tls Section" (TEB+0x2C TLS array) + MicrosoftDocs/win32, desktop-src/Debug/pe-format.md, + commit 8a9c5d8f32001411f5e572a17e6d736d6fcc055f + [dbg] Debugger documentation, `dt` output from 32-bit Windows: TEB NtTib + (0x00), ClientId (0x20), ThreadLocalStoragePointer (0x2C), + ProcessEnvironmentBlock (0x30); PEB Ldr (0x0C); PEB_LDR_DATA Length + (0x28), Initialized (0x04) and its three list heads (0x0C, 0x14, 0x1C). + MicrosoftDocs/windows-driver-docs, commit + 6de78e042e0eaba466569c7f5ed65c250c644a0b: debugger/ + debugging-a-stack-overflow.md, debuggercmds/dt--display-type-.md, + debuggercmds/c---numbers-and-operators.md + [wtl] winternl.h reference: LDR_DATA_TABLE_ENTRY (InMemoryOrderLinks 0x08, + DllBase 0x18, FullDllName 0x24, and the positions of the reserved + slots at 0x00, 0x10, 0x1C and 0x2C), MicrosoftDocs/sdk-api (commit + above), ns-winternl-peb_ldr_data.md + [kus] KUSER_SHARED_DATA reference: field order only, + MicrosoftDocs/windows-driver-docs-ddi (commit above), + ns-ntddk-kuser_shared_data.md + +Fields tagged [obs] are not given by these sources. Each holds a value a +32-bit Windows process can compare against an API that reports the same thing, +which is how the offset is established: + + TEB 0x00/0x04/0x08 ExceptionList, StackBase, StackLimit: the SEH chain + head and the stack bounds of the running thread + TEB 0x18 Self: equals the TEB address + TEB 0x20/0x24 GetCurrentProcessId(), GetCurrentThreadId() + PEB 0x08 GetModuleHandle(NULL) + PEB 0x18 GetProcessHeap() + PEB 0x64 GetSystemInfo().dwNumberOfProcessors + PEB 0x68 global flags as set with gflags for the image + PEB 0xA4..0xB0 RtlGetVersion(): major, minor, build, platform id + LDR entry 0x00/0x10 walking the load-order and initialisation-order lists + reaches the same entries the memory-order list does + LDR entry 0x1C/0x20 the module's entry point and SizeOfImage from its headers + LDR entry 0x2C the module's file name + KUSER 0x00..0x270 GetTickCount(), the system time, the system root and + RtlGetVersion() major/minor diff --git a/crates/exav-pe-emu/scripts/gen-exports.py b/crates/exav-pe-emu/scripts/gen-exports.py new file mode 100644 index 0000000..afe9fdb --- /dev/null +++ b/crates/exav-pe-emu/scripts/gen-exports.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 +# Regenerate src/exports/.txt: the export-name sets the synthetic system +# DLLs advertise, so a stub that resolves imports by hashing export names finds +# the function it looks for even when the emulator does not implement it. +# +# Source: Microsoft's own API documentation, which records for every exported +# function the DLLs that export it. Each reference page carries YAML front +# matter with `UID: NF:
.` (the exact exported name; ANSI and +# Unicode variants each have their own page), `api_type: DllExport` and an +# `api_location` list of DLLs. Only those three fields are read. +# +# MicrosoftDocs/sdk-api (Win32 API reference) +# MicrosoftDocs/windows-driver-docs-ddi (WDK reference; Rtl*/Zw* in ntdll) +# +# Both are (c) Microsoft Corporation, documentation licensed under CC BY 4.0. +# The attribution is in this crate's NOTICE. Nothing else is taken from them. +# +# Usage: download the two archives below (any path), then +# gen-exports.py sdk-api.tar.gz windows-driver-docs-ddi.tar.gz +# The archives are read in place, never extracted. The commit is the pin; the +# SHA-256 is of GitHub's tar.gz for that commit as downloaded on 2026-10-18. +# GitHub does not promise byte-stable archives, so on a hash mismatch rebuild the +# archive from the pinned commit (`git archive --format=tar.gz`) and re-pin. + +import hashlib +import os +import re +import sys +import tarfile + +SOURCES = [ + { + "repo": "MicrosoftDocs/sdk-api", + "commit": "9e0d205d747b5e0f08019cc7e202112c3aa1f68c", + "url": "https://codeload.github.com/MicrosoftDocs/sdk-api/tar.gz/" + "9e0d205d747b5e0f08019cc7e202112c3aa1f68c", + "sha256": "7ea18a09a9eb9dc2d50fddc8835f488bb349c6763a2e4eff1d1d3f99a4b53928", + }, + { + "repo": "MicrosoftDocs/windows-driver-docs-ddi", + "commit": "7515063cea4c9e98db6a92986c5b4ddb0463fd16", + "url": "https://codeload.github.com/MicrosoftDocs/windows-driver-docs-ddi/tar.gz/" + "7515063cea4c9e98db6a92986c5b4ddb0463fd16", + "sha256": "3c3fb42a76ec66aa3b7d61a78901ad1d5612220f9e89847f61ae94a5c11dc2fc", + }, +] + +# The preloaded DLLs the documentation records exports for. `msvcrt.dll` is +# absent: the CRT reference does not map functions to it. +DLLS = ["kernel32.dll", "ntdll.dll", "user32.dll", "advapi32.dll"] + +# Names added by hand, each with its justification. The documentation records +# the DLLs a function is exported from, and a few user-mode ntdll exports are +# documented only under the kernel. +ADDED = { + "ntdll.dll": [ + # Documented in the WDK (ntifs.h, nf-ntifs-rtldecompressbuffer) with + # api_location NtosKrnl.exe only. ntdll.dll exports it too, and + # Alienyze resolves it there by hashing ntdll's export names; without + # it the stub skips decompression. + "RtlDecompressBuffer", + ], +} + +# Cap per module, so a synthetic module's export directory stays inside the +# region below its trap range (see `MAX_EXPORT_DIR` in src/win.rs). +MAX_PER_MODULE = 2000 + +IDENT = re.compile(r"[A-Za-z_][A-Za-z0-9_]*") + + +def front_matter(text): + """The scalar and list fields of a page's leading `---` block.""" + if not text.startswith("---"): + return None + end = text.find("\n---", 3) + if end < 0: + return None + fields, key = {}, None + for line in text[3:end].splitlines(): + if line.startswith(" - ") and key is not None: + fields.setdefault(key, []).append(line[3:].strip()) + continue + m = re.match(r"([A-Za-z0-9_.-]+):\s*(.*)$", line) + if m: + key, value = m.group(1), m.group(2).strip() + fields[key] = [value] if value else [] + return fields + + +def exports_in(archive, out): + with tarfile.open(archive, "r:gz") as tar: + for member in tar: + if not member.isfile() or not member.name.endswith(".md"): + continue + # Reference pages only; a page is a few kilobytes, so anything far + # larger is not one and is skipped unread. + if member.size > 1 << 20: + continue + raw = tar.extractfile(member).read().decode("utf-8", "replace") + fm = front_matter(raw) + if not fm: + continue + if "DllExport" not in fm.get("api_type", []): + continue + # VersionHelpers.h functions are inline in the header, not exports, + # though their pages list ntdll.dll. + if (fm.get("req.header") or [""])[0].lower() == "versionhelpers.h": + continue + uid = (fm.get("UID") or [""])[0] + if not uid.startswith("NF:") or "." not in uid: + continue + name = uid.rsplit(".", 1)[1] + if not IDENT.fullmatch(name) or name not in fm.get("api_name", []): + continue + for loc in fm.get("api_location", []): + dll = loc.strip().lower() + if dll in out: + out[dll].add(name) + + +def sha256(path): + h = hashlib.sha256() + with open(path, "rb") as f: + for block in iter(lambda: f.read(1 << 20), b""): + h.update(block) + return h.hexdigest() + + +def main(): + if len(sys.argv) != len(SOURCES) + 1: + sys.exit("usage: gen-exports.py sdk-api.tar.gz windows-driver-docs-ddi.tar.gz") + out = {dll: set() for dll in DLLS} + for src, path in zip(SOURCES, sys.argv[1:]): + got = sha256(path) + if got != src["sha256"]: + sys.exit(f"{path}: sha256 {got}, expected {src['sha256']} ({src['repo']}@{src['commit']})") + exports_in(path, out) + for dll, names in ADDED.items(): + out[dll].update(names) + out_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "src", "exports") + os.makedirs(out_dir, exist_ok=True) + for dll in DLLS: + names = sorted(out[dll])[:MAX_PER_MODULE] + dest = os.path.join(out_dir, dll.removesuffix(".dll") + ".txt") + with open(dest, "w") as f: + f.write("".join(n + "\n" for n in names)) + print(f"{dll}: {len(names)} names") + + +if __name__ == "__main__": + main() diff --git a/crates/exav-pe-emu/src/cpu.rs b/crates/exav-pe-emu/src/cpu.rs index f060be5..cdce6a5 100644 --- a/crates/exav-pe-emu/src/cpu.rs +++ b/crates/exav-pe-emu/src/cpu.rs @@ -1559,7 +1559,8 @@ impl Cpu { }; self.cf = r & 1 != 0; if count == 1 { - self.of = ((r ^ (r << 1)) & sign_bit(size)) != 0; + // MSB of the result xor the bit rotated into CF. + self.of = (r & sign_bit(size) != 0) != self.cf; } r } @@ -1592,7 +1593,16 @@ impl Cpu { } } self.cf = (acc >> bits) & 1 != 0; - (acc as u32) & mask(size) + let r = (acc as u32) & mask(size); + if count == 1 { + let msb = r & sign_bit(size) != 0; + self.of = if m == Rcl { + msb != self.cf + } else { + msb != (r & (sign_bit(size) >> 1) != 0) + }; + } + r } _ => unreachable!("shift dispatch"), }; @@ -2442,6 +2452,30 @@ mod tests { assert!(cpu.cf); } + #[test] + fn rotate_by_one_sets_overflow_from_the_result() { + // OF after a 1-bit rotate is MSB(result) xor CF-bit-rotated. A tElock + // decryptor branches on it; getting it wrong sent the stub into an + // `EB FE` self-loop. Values checked against a reference x86. + // rol: 0x80000000 rol 1 -> CF=1, result MSB=0, so OF = 1 ^ 0 = 1. + let (cpu, _) = run(&[0xb8, 0, 0, 0, 0x80, 0xd1, 0xc0], |_| {}); + assert_eq!(cpu.regs[EAX], 1); + assert!(cpu.cf && cpu.of, "rol: CF=1, OF=1"); + // rol 0x40000000 by 1 -> 0x80000000, CF=0, MSB=1, OF = 1 ^ 0 = 1. + let (cpu, _) = run(&[0xb8, 0, 0, 0, 0x40, 0xd1, 0xc0], |_| {}); + assert_eq!(cpu.regs[EAX], 0x8000_0000); + assert!(!cpu.cf && cpu.of, "rol: CF=0, OF=1"); + // ror 1 of odd value: 0x00000001 -> 0x80000000, CF=1, top two bits + // 10, so OF = MSB xor next-bit = 1 ^ 0 = 1. + let (cpu, _) = run(&[0xb8, 1, 0, 0, 0, 0xd1, 0xc8], |_| {}); + assert_eq!(cpu.regs[EAX], 0x8000_0000); + assert!(cpu.cf && cpu.of, "ror: CF=1, OF=1"); + // rcr 1 with CF=0 of 1 -> 0, CF out = 1, both top bits 0, OF = 0. + let (cpu, _) = run(&[0xb8, 1, 0, 0, 0, 0xd1, 0xd8], |c| c.cf = false); + assert_eq!(cpu.regs[EAX], 0); + assert!(cpu.cf && !cpu.of, "rcr: CF=1, OF=0"); + } + #[test] fn mul_and_div_roundtrip() { // b8 00 00 10 00 mov eax, 0x100000 diff --git a/crates/exav-pe-emu/src/exports/advapi32.txt b/crates/exav-pe-emu/src/exports/advapi32.txt new file mode 100644 index 0000000..907e3c8 --- /dev/null +++ b/crates/exav-pe-emu/src/exports/advapi32.txt @@ -0,0 +1,541 @@ +AbortSystemShutdownA +AbortSystemShutdownW +AccessCheck +AccessCheckAndAuditAlarmA +AccessCheckAndAuditAlarmW +AccessCheckByType +AccessCheckByTypeAndAuditAlarmA +AccessCheckByTypeAndAuditAlarmW +AccessCheckByTypeResultList +AccessCheckByTypeResultListAndAuditAlarmA +AccessCheckByTypeResultListAndAuditAlarmByHandleA +AccessCheckByTypeResultListAndAuditAlarmByHandleW +AccessCheckByTypeResultListAndAuditAlarmW +AddAccessAllowedAce +AddAccessAllowedAceEx +AddAccessAllowedObjectAce +AddAccessDeniedAce +AddAccessDeniedAceEx +AddAccessDeniedObjectAce +AddAce +AddAuditAccessAce +AddAuditAccessAceEx +AddAuditAccessObjectAce +AddConditionalAce +AddMandatoryAce +AddUsersToEncryptedFile +AdjustTokenGroups +AdjustTokenPrivileges +AllocateAndInitializeSid +AllocateLocallyUniqueId +AreAllAccessesGranted +AreAnyAccessesGranted +AuditComputeEffectivePolicyBySid +AuditComputeEffectivePolicyByToken +AuditEnumerateCategories +AuditEnumeratePerUserPolicy +AuditEnumerateSubCategories +AuditFree +AuditLookupCategoryGuidFromCategoryId +AuditLookupCategoryIdFromCategoryGuid +AuditLookupCategoryNameA +AuditLookupCategoryNameW +AuditLookupSubCategoryNameA +AuditLookupSubCategoryNameW +AuditQueryGlobalSaclA +AuditQueryGlobalSaclW +AuditQueryPerUserPolicy +AuditQuerySecurity +AuditQuerySystemPolicy +AuditSetGlobalSaclA +AuditSetGlobalSaclW +AuditSetPerUserPolicy +AuditSetSecurity +AuditSetSystemPolicy +BackupEventLogA +BackupEventLogW +BuildExplicitAccessWithNameA +BuildExplicitAccessWithNameW +BuildSecurityDescriptorA +BuildSecurityDescriptorW +BuildTrusteeWithNameA +BuildTrusteeWithNameW +BuildTrusteeWithObjectsAndNameA +BuildTrusteeWithObjectsAndNameW +BuildTrusteeWithObjectsAndSidA +BuildTrusteeWithObjectsAndSidW +BuildTrusteeWithSidA +BuildTrusteeWithSidW +ChangeServiceConfig2A +ChangeServiceConfig2W +ChangeServiceConfigA +ChangeServiceConfigW +CheckTokenMembership +ClearEventLogA +ClearEventLogW +CloseEncryptedFileRaw +CloseEventLog +CloseServiceHandle +CloseThreadWaitChainSession +ControlService +ControlServiceExA +ControlServiceExW +ConvertSecurityDescriptorToStringSecurityDescriptorA +ConvertSecurityDescriptorToStringSecurityDescriptorW +ConvertSidToStringSidA +ConvertSidToStringSidW +ConvertStringSecurityDescriptorToSecurityDescriptorA +ConvertStringSecurityDescriptorToSecurityDescriptorW +ConvertStringSidToSidA +ConvertStringSidToSidW +ConvertToAutoInheritPrivateObjectSecurity +CopySid +CreatePrivateObjectSecurity +CreatePrivateObjectSecurityEx +CreatePrivateObjectSecurityWithMultipleInheritance +CreateProcessAsUserA +CreateProcessAsUserW +CreateProcessWithLogonW +CreateProcessWithTokenW +CreateRestrictedToken +CreateServiceA +CreateServiceW +CreateWellKnownSid +CredDeleteA +CredDeleteW +CredEnumerateA +CredEnumerateW +CredFindBestCredentialA +CredFindBestCredentialW +CredFree +CredGetSessionTypes +CredGetTargetInfoA +CredGetTargetInfoW +CredIsMarshaledCredentialA +CredIsMarshaledCredentialW +CredIsProtectedA +CredIsProtectedW +CredMarshalCredentialA +CredMarshalCredentialW +CredMarshalTargetInfo +CredProtectA +CredProtectW +CredReadA +CredReadDomainCredentialsA +CredReadDomainCredentialsW +CredReadW +CredRenameA +CredRenameW +CredUnmarshalCredentialA +CredUnmarshalCredentialW +CredUnprotectA +CredUnprotectW +CredWriteA +CredWriteDomainCredentialsA +CredWriteDomainCredentialsW +CredWriteW +CryptAcquireContextA +CryptAcquireContextW +CryptContextAddRef +CryptCreateHash +CryptDecrypt +CryptDeriveKey +CryptDestroyHash +CryptDestroyKey +CryptDuplicateHash +CryptDuplicateKey +CryptEncrypt +CryptEnumProviderTypesA +CryptEnumProviderTypesW +CryptEnumProvidersA +CryptEnumProvidersW +CryptExportKey +CryptGenKey +CryptGenRandom +CryptGetDefaultProviderA +CryptGetDefaultProviderW +CryptGetHashParam +CryptGetKeyParam +CryptGetProvParam +CryptGetUserKey +CryptHashData +CryptHashSessionKey +CryptImportKey +CryptReleaseContext +CryptSetHashParam +CryptSetKeyParam +CryptSetProvParam +CryptSetProviderA +CryptSetProviderExA +CryptSetProviderExW +CryptSetProviderW +CryptSignHashA +CryptSignHashW +CryptVerifySignatureA +CryptVerifySignatureW +CveEventWrite +DecryptFileA +DecryptFileW +DeleteAce +DeleteService +DeregisterEventSource +DestroyPrivateObjectSecurity +DuplicateEncryptionInfoFile +DuplicateToken +DuplicateTokenEx +EncryptFileA +EncryptFileW +EncryptionDisable +EnumDependentServicesA +EnumDependentServicesW +EnumDynamicTimeZoneInformation +EnumServicesStatusA +EnumServicesStatusExA +EnumServicesStatusExW +EnumServicesStatusW +EqualDomainSid +EqualPrefixSid +EqualSid +EventAccessControl +EventAccessQuery +EventAccessRemove +FileEncryptionStatusA +FileEncryptionStatusW +FindFirstFreeAce +FreeEncryptionCertificateHashList +FreeInheritedFromArray +FreeSid +GetAce +GetAclInformation +GetAuditedPermissionsFromAclA +GetAuditedPermissionsFromAclW +GetCurrentHwProfileA +GetCurrentHwProfileW +GetDynamicTimeZoneInformationEffectiveYears +GetEffectiveRightsFromAclA +GetEffectiveRightsFromAclW +GetEventLogInformation +GetExplicitEntriesFromAclA +GetExplicitEntriesFromAclW +GetFileSecurityA +GetFileSecurityW +GetInheritanceSourceA +GetInheritanceSourceW +GetKernelObjectSecurity +GetLengthSid +GetLocalManagedApplications +GetManagedApplicationCategories +GetManagedApplications +GetNamedSecurityInfoA +GetNamedSecurityInfoW +GetNumberOfEventLogRecords +GetOldestEventLogRecord +GetPrivateObjectSecurity +GetSecurityDescriptorControl +GetSecurityDescriptorDacl +GetSecurityDescriptorGroup +GetSecurityDescriptorLength +GetSecurityDescriptorOwner +GetSecurityDescriptorRMControl +GetSecurityDescriptorSacl +GetSecurityInfo +GetServiceDisplayNameA +GetServiceDisplayNameW +GetServiceKeyNameA +GetServiceKeyNameW +GetSidIdentifierAuthority +GetSidLengthRequired +GetSidSubAuthority +GetSidSubAuthorityCount +GetThreadWaitChain +GetTokenInformation +GetTrusteeFormA +GetTrusteeFormW +GetTrusteeNameA +GetTrusteeNameW +GetTrusteeTypeA +GetTrusteeTypeW +GetUserNameA +GetUserNameW +GetWindowsAccountDomainSid +ImpersonateAnonymousToken +ImpersonateLoggedOnUser +ImpersonateNamedPipeClient +ImpersonateSelf +InitializeAcl +InitializeSecurityDescriptor +InitializeSid +InitiateShutdownA +InitiateShutdownW +InitiateSystemShutdownA +InitiateSystemShutdownExA +InitiateSystemShutdownExW +InitiateSystemShutdownW +InstallApplication +IsTextUnicode +IsTokenRestricted +IsValidAcl +IsValidSecurityDescriptor +IsValidSid +IsWellKnownSid +LockServiceDatabase +LogonUserA +LogonUserExA +LogonUserExW +LogonUserW +LookupAccountNameA +LookupAccountNameW +LookupAccountSidA +LookupAccountSidW +LookupPrivilegeDisplayNameA +LookupPrivilegeDisplayNameW +LookupPrivilegeNameA +LookupPrivilegeNameW +LookupPrivilegeValueA +LookupPrivilegeValueW +LookupSecurityDescriptorPartsA +LookupSecurityDescriptorPartsW +LsaAddAccountRights +LsaClose +LsaCreateTrustedDomainEx +LsaDeleteTrustedDomain +LsaEnumerateAccountRights +LsaEnumerateAccountsWithUserRight +LsaEnumerateTrustedDomains +LsaEnumerateTrustedDomainsEx +LsaFreeMemory +LsaGetAppliedCAPIDs +LsaLookupNames +LsaLookupNames2 +LsaLookupPrivilegeValue +LsaLookupSids +LsaLookupSids2 +LsaNtStatusToWinError +LsaOpenPolicy +LsaOpenTrustedDomainByName +LsaQueryCAPs +LsaQueryDomainInformationPolicy +LsaQueryForestTrustInformation +LsaQueryInformationPolicy +LsaQueryTrustedDomainInfo +LsaQueryTrustedDomainInfoByName +LsaRemoveAccountRights +LsaRetrievePrivateData +LsaSetDomainInformationPolicy +LsaSetForestTrustInformation +LsaSetInformationPolicy +LsaSetTrustedDomainInfoByName +LsaSetTrustedDomainInformation +LsaStorePrivateData +MSChapSrvChangePassword +MSChapSrvChangePassword2 +MakeAbsoluteSD +MakeSelfRelativeSD +MapGenericMask +NotifyBootConfigStatus +NotifyChangeEventLog +NotifyServiceStatusChangeA +NotifyServiceStatusChangeW +ObjectCloseAuditAlarmA +ObjectCloseAuditAlarmW +ObjectDeleteAuditAlarmA +ObjectDeleteAuditAlarmW +ObjectOpenAuditAlarmA +ObjectOpenAuditAlarmW +ObjectPrivilegeAuditAlarmA +ObjectPrivilegeAuditAlarmW +OpenBackupEventLogA +OpenBackupEventLogW +OpenEncryptedFileRawA +OpenEncryptedFileRawW +OpenEventLogA +OpenEventLogW +OpenProcessToken +OpenSCManagerA +OpenSCManagerW +OpenServiceA +OpenServiceW +OpenThreadToken +OpenThreadWaitChainSession +OperationEnd +OperationStart +PerfAddCounters +PerfCloseQueryHandle +PerfCreateInstance +PerfDecrementULongCounterValue +PerfDecrementULongLongCounterValue +PerfDeleteCounters +PerfDeleteInstance +PerfEnumerateCounterSet +PerfEnumerateCounterSetInstances +PerfIncrementULongCounterValue +PerfIncrementULongLongCounterValue +PerfOpenQueryHandle +PerfQueryCounterData +PerfQueryCounterInfo +PerfQueryCounterSetRegistrationInfo +PerfQueryInstance +PerfSetCounterRefValue +PerfSetCounterSetInfo +PerfSetULongCounterValue +PerfSetULongLongCounterValue +PerfStartProvider +PerfStartProviderEx +PerfStopProvider +PrivilegeCheck +PrivilegedServiceAuditAlarmA +PrivilegedServiceAuditAlarmW +QueryRecoveryAgentsOnEncryptedFile +QuerySecurityAccessMask +QueryServiceConfig2A +QueryServiceConfig2W +QueryServiceConfigA +QueryServiceConfigW +QueryServiceDynamicInformation +QueryServiceLockStatusA +QueryServiceLockStatusW +QueryServiceObjectSecurity +QueryServiceStatus +QueryServiceStatusEx +QueryUsersOnEncryptedFile +ReadEncryptedFileRaw +ReadEventLogA +ReadEventLogW +RegCloseKey +RegConnectRegistryA +RegConnectRegistryW +RegCopyTreeA +RegCopyTreeW +RegCreateKeyA +RegCreateKeyExA +RegCreateKeyExW +RegCreateKeyTransactedA +RegCreateKeyTransactedW +RegCreateKeyW +RegDeleteKeyA +RegDeleteKeyExA +RegDeleteKeyExW +RegDeleteKeyTransactedA +RegDeleteKeyTransactedW +RegDeleteKeyValueA +RegDeleteKeyValueW +RegDeleteKeyW +RegDeleteTreeA +RegDeleteTreeW +RegDeleteValueA +RegDeleteValueW +RegDisablePredefinedCache +RegDisablePredefinedCacheEx +RegDisableReflectionKey +RegEnableReflectionKey +RegEnumKeyA +RegEnumKeyExA +RegEnumKeyExW +RegEnumKeyW +RegEnumValueA +RegEnumValueW +RegFlushKey +RegGetKeySecurity +RegGetValueA +RegGetValueW +RegLoadAppKeyA +RegLoadAppKeyW +RegLoadKeyA +RegLoadKeyW +RegLoadMUIStringA +RegLoadMUIStringW +RegNotifyChangeKeyValue +RegOpenCurrentUser +RegOpenKeyA +RegOpenKeyExA +RegOpenKeyExW +RegOpenKeyTransactedA +RegOpenKeyTransactedW +RegOpenKeyW +RegOpenUserClassesRoot +RegOverridePredefKey +RegQueryInfoKeyA +RegQueryInfoKeyW +RegQueryMultipleValuesA +RegQueryMultipleValuesW +RegQueryReflectionKey +RegQueryValueA +RegQueryValueExA +RegQueryValueExW +RegQueryValueW +RegReplaceKeyA +RegReplaceKeyW +RegRestoreKeyA +RegRestoreKeyW +RegSaveKeyA +RegSaveKeyExA +RegSaveKeyExW +RegSaveKeyW +RegSetKeySecurity +RegSetKeyValueA +RegSetKeyValueW +RegSetValueA +RegSetValueExA +RegSetValueExW +RegSetValueW +RegUnLoadKeyA +RegUnLoadKeyW +RegisterEventSourceA +RegisterEventSourceW +RegisterServiceCtrlHandlerA +RegisterServiceCtrlHandlerExA +RegisterServiceCtrlHandlerExW +RegisterServiceCtrlHandlerW +RegisterWaitChainCOMCallback +RemoveUsersFromEncryptedFile +ReportEventA +ReportEventW +RevertToSelf +RtlDecryptMemory +RtlEncryptMemory +RtlGenRandom +SaferCloseLevel +SaferComputeTokenFromLevel +SaferCreateLevel +SaferGetLevelInformation +SaferGetPolicyInformation +SaferIdentifyLevel +SaferRecordEventLogEntry +SaferSetLevelInformation +SaferSetPolicyInformation +SaferiIsExecutableFileType +SetAclInformation +SetEntriesInAclA +SetEntriesInAclW +SetFileSecurityA +SetFileSecurityW +SetKernelObjectSecurity +SetNamedSecurityInfoA +SetNamedSecurityInfoW +SetPrivateObjectSecurity +SetPrivateObjectSecurityEx +SetSecurityAccessMask +SetSecurityDescriptorControl +SetSecurityDescriptorDacl +SetSecurityDescriptorGroup +SetSecurityDescriptorOwner +SetSecurityDescriptorRMControl +SetSecurityDescriptorSacl +SetSecurityInfo +SetServiceBits +SetServiceObjectSecurity +SetServiceStatus +SetThreadToken +SetTokenInformation +SetUserFileEncryptionKey +StartServiceA +StartServiceCtrlDispatcherA +StartServiceCtrlDispatcherW +StartServiceW +TreeResetNamedSecurityInfoA +TreeResetNamedSecurityInfoW +TreeSetNamedSecurityInfoA +TreeSetNamedSecurityInfoW +UninstallApplication +UnlockServiceDatabase +WriteEncryptedFileRaw diff --git a/crates/exav-pe-emu/src/exports/kernel32.txt b/crates/exav-pe-emu/src/exports/kernel32.txt new file mode 100644 index 0000000..4c5c232 --- /dev/null +++ b/crates/exav-pe-emu/src/exports/kernel32.txt @@ -0,0 +1,1267 @@ +AcquireSRWLockExclusive +AcquireSRWLockShared +ActivateActCtx +AddAtomA +AddAtomW +AddDllDirectory +AddIntegrityLabelToBoundaryDescriptor +AddRefActCtx +AddResourceAttributeAce +AddSIDToBoundaryDescriptor +AddScopedPolicyIDAce +AddSecureMemoryCacheCallback +AddVectoredContinueHandler +AddVectoredExceptionHandler +AllocateUserPhysicalPages +AllocateUserPhysicalPagesNuma +AppPolicyGetCreateFileAccess +AppPolicyGetProcessTerminationMethod +AppPolicyGetShowDeveloperDiagnostic +AppPolicyGetThreadInitializationType +AppPolicyGetWindowingModel +ApplicationRecoveryFinished +ApplicationRecoveryInProgress +AreFileApisANSI +AssignProcessToJobObject +BackupRead +BackupSeek +BackupWrite +Beep +BeginUpdateResourceA +BeginUpdateResourceW +BindIoCompletionCallback +BuildCommDCBA +BuildCommDCBAndTimeoutsA +BuildCommDCBAndTimeoutsW +BuildCommDCBW +CallEnclave +CallNamedPipeA +CallNamedPipeW +CallbackMayRunLong +CancelIo +CancelIoEx +CancelSynchronousIo +CancelThreadpoolIo +CancelWaitableTimer +CeipIsOptedIn +ChangeTimerQueueTimer +CheckNameLegalDOS8Dot3A +CheckNameLegalDOS8Dot3W +CheckRemoteDebuggerPresent +CheckTokenCapability +CheckTokenMembershipEx +ClearCommBreak +ClearCommError +CloseHandle +ClosePackageInfo +ClosePrivateNamespace +CloseThreadpool +CloseThreadpoolCleanupGroup +CloseThreadpoolCleanupGroupMembers +CloseThreadpoolIo +CloseThreadpoolTimer +CloseThreadpoolWait +CloseThreadpoolWork +CommConfigDialogA +CommConfigDialogW +CompareFileTime +CompareObjectHandles +CompareString +CompareStringA +CompareStringEx +CompareStringOrdinal +CompareStringW +ConnectNamedPipe +ContinueDebugEvent +ConvertAuxiliaryCounterToPerformanceCounter +ConvertDefaultLocale +ConvertFiberToThread +ConvertPerformanceCounterToAuxiliaryCounter +ConvertThreadToFiber +ConvertThreadToFiberEx +CopyContext +CopyFile +CopyFile2 +CopyFileA +CopyFileExA +CopyFileExW +CopyFileTransactedA +CopyFileTransactedW +CopyFileW +CreateActCtxA +CreateActCtxW +CreateBoundaryDescriptorA +CreateBoundaryDescriptorW +CreateDirectory +CreateDirectoryA +CreateDirectoryExA +CreateDirectoryExW +CreateDirectoryTransactedA +CreateDirectoryTransactedW +CreateDirectoryW +CreateEnclave +CreateEventA +CreateEventExA +CreateEventExW +CreateEventW +CreateFiber +CreateFiberEx +CreateFile2 +CreateFileA +CreateFileMapping2 +CreateFileMappingA +CreateFileMappingFromApp +CreateFileMappingNumaA +CreateFileMappingNumaW +CreateFileMappingW +CreateFileTransactedA +CreateFileTransactedW +CreateFileW +CreateHardLinkA +CreateHardLinkTransactedA +CreateHardLinkTransactedW +CreateHardLinkW +CreateIoCompletionPort +CreateJobObjectA +CreateJobObjectW +CreateMailslotA +CreateMailslotW +CreateMemoryResourceNotification +CreateMutexA +CreateMutexExA +CreateMutexExW +CreateMutexW +CreateNamedPipeA +CreateNamedPipeW +CreatePipe +CreatePrivateNamespaceA +CreatePrivateNamespaceW +CreateProcessA +CreateProcessAsUserA +CreateProcessAsUserW +CreateProcessW +CreateRemoteThread +CreateRemoteThreadEx +CreateSemaphoreA +CreateSemaphoreExA +CreateSemaphoreExW +CreateSemaphoreW +CreateSymbolicLinkA +CreateSymbolicLinkTransactedA +CreateSymbolicLinkTransactedW +CreateSymbolicLinkW +CreateTapePartition +CreateThread +CreateThreadpool +CreateThreadpoolCleanupGroup +CreateThreadpoolIo +CreateThreadpoolTimer +CreateThreadpoolWait +CreateThreadpoolWork +CreateTimerQueue +CreateTimerQueueTimer +CreateToolhelp32Snapshot +CreateUmsCompletionList +CreateUmsThreadContext +CreateWaitableTimerExW +CreateWaitableTimerW +DeactivateActCtx +DebugActiveProcess +DebugActiveProcessStop +DebugBreak +DebugBreakProcess +DebugSetProcessKillOnExit +DefineDosDeviceA +DefineDosDeviceW +DeleteAtom +DeleteBoundaryDescriptor +DeleteCriticalSection +DeleteEnclave +DeleteFiber +DeleteFile +DeleteFileA +DeleteFileTransactedA +DeleteFileTransactedW +DeleteFileW +DeleteProcThreadAttributeList +DeleteSynchronizationBarrier +DeleteTimerQueue +DeleteTimerQueueEx +DeleteTimerQueueTimer +DeleteUmsCompletionList +DeleteUmsThreadContext +DeleteVolumeMountPointA +DeleteVolumeMountPointW +DequeueUmsCompletionListItems +DeviceIoControl +DisableThreadLibraryCalls +DisableThreadProfiling +DisassociateCurrentThreadFromCallback +DiscardVirtualMemory +DisconnectNamedPipe +DnsHostnameToComputerNameA +DnsHostnameToComputerNameW +DosDateTimeToFileTime +DuplicateHandle +EmptyWorkingSet +EnableThreadProfiling +EndUpdateResourceA +EndUpdateResourceW +EnterCriticalSection +EnterSynchronizationBarrier +EnterUmsSchedulingMode +EnumCalendarInfoA +EnumCalendarInfoExA +EnumCalendarInfoExEx +EnumCalendarInfoExW +EnumCalendarInfoW +EnumDateFormatsA +EnumDateFormatsExA +EnumDateFormatsExEx +EnumDateFormatsExW +EnumDateFormatsW +EnumDeviceDrivers +EnumDynamicTimeZoneInformation +EnumLanguageGroupLocalesA +EnumLanguageGroupLocalesW +EnumPageFilesA +EnumPageFilesW +EnumProcessModules +EnumProcessModulesEx +EnumProcesses +EnumResourceLanguagesA +EnumResourceLanguagesExA +EnumResourceLanguagesExW +EnumResourceLanguagesW +EnumResourceNamesA +EnumResourceNamesExA +EnumResourceNamesExW +EnumResourceNamesW +EnumResourceTypesA +EnumResourceTypesExA +EnumResourceTypesExW +EnumResourceTypesW +EnumSystemCodePagesA +EnumSystemCodePagesW +EnumSystemFirmwareTables +EnumSystemGeoID +EnumSystemGeoNames +EnumSystemLanguageGroupsA +EnumSystemLanguageGroupsW +EnumSystemLocalesA +EnumSystemLocalesEx +EnumSystemLocalesW +EnumTimeFormatsA +EnumTimeFormatsEx +EnumTimeFormatsW +EnumUILanguagesA +EnumUILanguagesW +EraseTape +EscapeCommFunction +ExecuteUmsThread +ExitProcess +ExitThread +ExpandEnvironmentStringsA +ExpandEnvironmentStringsW +FatalAppExitA +FatalAppExitW +FatalExit +FileTimeToDosDateTime +FileTimeToLocalFileTime +FileTimeToSystemTime +FindActCtxSectionGuid +FindActCtxSectionStringA +FindActCtxSectionStringW +FindAtomA +FindAtomW +FindClose +FindCloseChangeNotification +FindFirstChangeNotificationA +FindFirstChangeNotificationW +FindFirstFileA +FindFirstFileExA +FindFirstFileExW +FindFirstFileNameTransactedW +FindFirstFileNameW +FindFirstFileTransactedA +FindFirstFileTransactedW +FindFirstFileW +FindFirstStreamTransactedW +FindFirstStreamW +FindFirstVolumeA +FindFirstVolumeMountPointA +FindFirstVolumeMountPointW +FindFirstVolumeW +FindNLSString +FindNLSStringEx +FindNextChangeNotification +FindNextFileA +FindNextFileNameW +FindNextFileW +FindNextStreamW +FindNextVolumeA +FindNextVolumeMountPointA +FindNextVolumeMountPointW +FindNextVolumeW +FindPackagesByPackageFamily +FindResourceA +FindResourceExA +FindResourceExW +FindResourceW +FindStringOrdinal +FindVolumeClose +FindVolumeMountPointClose +FlsAlloc +FlsFree +FlsGetValue +FlsSetValue +FlushFileBuffers +FlushInstructionCache +FlushProcessWriteBuffers +FlushViewOfFile +FoldStringA +FoldStringW +FormatApplicationUserModelId +FormatMessage +FormatMessageA +FormatMessageW +FreeEnvironmentStringsA +FreeEnvironmentStringsW +FreeLibrary +FreeLibraryAndExitThread +FreeLibraryWhenCallbackReturns +FreeMemoryJobObject +FreeResource +FreeUserPhysicalPages +GetACP +GetActiveProcessorCount +GetActiveProcessorGroupCount +GetAppContainerNamedObjectPath +GetApplicationRecoveryCallback +GetApplicationRestartSettings +GetApplicationUserModelId +GetApplicationUserModelIdFromToken +GetAtomNameA +GetAtomNameW +GetBinaryTypeA +GetBinaryTypeW +GetCPInfo +GetCPInfoExA +GetCPInfoExW +GetCalendarInfoA +GetCalendarInfoEx +GetCalendarInfoW +GetCommConfig +GetCommMask +GetCommModemStatus +GetCommProperties +GetCommState +GetCommTimeouts +GetCommandLineA +GetCommandLineW +GetCompressedFileSizeA +GetCompressedFileSizeTransactedA +GetCompressedFileSizeTransactedW +GetCompressedFileSizeW +GetComputerNameA +GetComputerNameExA +GetComputerNameExW +GetComputerNameW +GetCurrencyFormatA +GetCurrencyFormatEx +GetCurrencyFormatW +GetCurrentActCtx +GetCurrentApplicationUserModelId +GetCurrentDirectory +GetCurrentPackageFamilyName +GetCurrentPackageFullName +GetCurrentPackageId +GetCurrentPackageInfo +GetCurrentPackagePath +GetCurrentProcess +GetCurrentProcessId +GetCurrentProcessorNumber +GetCurrentProcessorNumberEx +GetCurrentThread +GetCurrentThreadId +GetCurrentThreadStackLimits +GetCurrentUmsThread +GetDateFormatA +GetDateFormatEx +GetDateFormatW +GetDefaultCommConfigA +GetDefaultCommConfigW +GetDeviceDriverBaseNameA +GetDeviceDriverBaseNameW +GetDeviceDriverFileNameA +GetDeviceDriverFileNameW +GetDevicePowerState +GetDiskFreeSpaceA +GetDiskFreeSpaceExA +GetDiskFreeSpaceExW +GetDiskFreeSpaceW +GetDiskSpaceInformationA +GetDiskSpaceInformationW +GetDllDirectoryA +GetDllDirectoryW +GetDriveTypeA +GetDriveTypeW +GetDurationFormat +GetDurationFormatEx +GetDynamicTimeZoneInformation +GetDynamicTimeZoneInformationEffectiveYears +GetEnabledXStateFeatures +GetEnvironmentStrings +GetEnvironmentStringsW +GetEnvironmentVariable +GetEnvironmentVariableA +GetEnvironmentVariableW +GetErrorMode +GetExitCodeProcess +GetExitCodeThread +GetFileAttributesA +GetFileAttributesExA +GetFileAttributesExW +GetFileAttributesTransactedA +GetFileAttributesTransactedW +GetFileAttributesW +GetFileBandwidthReservation +GetFileInformationByHandle +GetFileInformationByHandleEx +GetFileMUIInfo +GetFileMUIPath +GetFileSize +GetFileSizeEx +GetFileTime +GetFileType +GetFinalPathNameByHandleA +GetFinalPathNameByHandleW +GetFirmwareEnvironmentVariableA +GetFirmwareEnvironmentVariableExA +GetFirmwareEnvironmentVariableExW +GetFirmwareEnvironmentVariableW +GetFirmwareType +GetFullPathNameA +GetFullPathNameTransactedA +GetFullPathNameTransactedW +GetFullPathNameW +GetGeoInfoA +GetGeoInfoEx +GetGeoInfoW +GetHandleInformation +GetLargePageMinimum +GetLastError +GetLocalTime +GetLocaleInfoA +GetLocaleInfoEx +GetLocaleInfoW +GetLogicalDriveStringsA +GetLogicalDriveStringsW +GetLogicalDrives +GetLogicalProcessorInformation +GetLogicalProcessorInformationEx +GetLongPathNameA +GetLongPathNameTransactedA +GetLongPathNameTransactedW +GetLongPathNameW +GetMachineTypeAttributes +GetMailslotInfo +GetMappedFileNameA +GetMappedFileNameW +GetMaximumProcessorCount +GetMaximumProcessorGroupCount +GetMemoryErrorHandlingCapabilities +GetModuleBaseNameA +GetModuleBaseNameW +GetModuleFileNameA +GetModuleFileNameExA +GetModuleFileNameExW +GetModuleFileNameW +GetModuleHandleA +GetModuleHandleExA +GetModuleHandleExW +GetModuleHandleW +GetModuleInformation +GetNLSVersion +GetNLSVersionEx +GetNamedPipeClientComputerNameA +GetNamedPipeClientComputerNameW +GetNamedPipeClientProcessId +GetNamedPipeClientSessionId +GetNamedPipeHandleStateA +GetNamedPipeHandleStateW +GetNamedPipeInfo +GetNamedPipeServerProcessId +GetNamedPipeServerSessionId +GetNativeSystemInfo +GetNextUmsListItem +GetNumaAvailableMemoryNode +GetNumaAvailableMemoryNodeEx +GetNumaHighestNodeNumber +GetNumaNodeNumberFromHandle +GetNumaNodeProcessorMask +GetNumaNodeProcessorMaskEx +GetNumaProcessorNode +GetNumaProcessorNodeEx +GetNumaProximityNode +GetNumaProximityNodeEx +GetNumberFormatA +GetNumberFormatEx +GetNumberFormatW +GetOEMCP +GetOverlappedResult +GetOverlappedResultEx +GetPackageApplicationIds +GetPackageFamilyName +GetPackageFamilyNameFromToken +GetPackageFullName +GetPackageFullNameFromToken +GetPackageId +GetPackageInfo +GetPackagePath +GetPackagePathByFullName +GetPackagesByPackageFamily +GetPerformanceInfo +GetPhysicallyInstalledSystemMemory +GetPriorityClass +GetPrivateProfileInt +GetPrivateProfileIntA +GetPrivateProfileIntW +GetPrivateProfileSection +GetPrivateProfileSectionA +GetPrivateProfileSectionNames +GetPrivateProfileSectionNamesA +GetPrivateProfileSectionNamesW +GetPrivateProfileSectionW +GetPrivateProfileString +GetPrivateProfileStringA +GetPrivateProfileStringW +GetPrivateProfileStruct +GetPrivateProfileStructA +GetPrivateProfileStructW +GetProcAddress +GetProcessAffinityMask +GetProcessDEPPolicy +GetProcessDefaultCpuSetMasks +GetProcessGroupAffinity +GetProcessHandleCount +GetProcessHeap +GetProcessHeaps +GetProcessId +GetProcessIdOfThread +GetProcessImageFileNameA +GetProcessImageFileNameW +GetProcessInformation +GetProcessIoCounters +GetProcessMemoryInfo +GetProcessMitigationPolicy +GetProcessPreferredUILanguages +GetProcessPriorityBoost +GetProcessShutdownParameters +GetProcessTimes +GetProcessVersion +GetProcessWorkingSetSize +GetProcessWorkingSetSizeEx +GetProcessorSystemCycleTime +GetProductInfo +GetProfileIntA +GetProfileIntW +GetProfileSectionA +GetProfileSectionW +GetProfileStringA +GetProfileStringW +GetQueuedCompletionStatus +GetQueuedCompletionStatusEx +GetShortPathNameA +GetShortPathNameW +GetStagedPackageOrigin +GetStagedPackagePathByFullName +GetStartupInfoW +GetStringScripts +GetStringTypeA +GetStringTypeExW +GetStringTypeW +GetSystemDEPPolicy +GetSystemDefaultLCID +GetSystemDefaultLangID +GetSystemDefaultLocaleName +GetSystemDefaultUILanguage +GetSystemDirectoryA +GetSystemDirectoryW +GetSystemFileCacheSize +GetSystemFirmwareTable +GetSystemInfo +GetSystemPowerStatus +GetSystemPreferredUILanguages +GetSystemRegistryQuota +GetSystemTime +GetSystemTimeAdjustment +GetSystemTimeAsFileTime +GetSystemTimePreciseAsFileTime +GetSystemTimes +GetSystemWindowsDirectoryA +GetSystemWindowsDirectoryW +GetSystemWow64Directory2A +GetSystemWow64Directory2W +GetSystemWow64DirectoryA +GetSystemWow64DirectoryW +GetTapeParameters +GetTapePosition +GetTapeStatus +GetTempFileName +GetTempFileNameA +GetTempFileNameW +GetTempPath2A +GetTempPath2W +GetTempPathA +GetTempPathW +GetThreadContext +GetThreadDescription +GetThreadErrorMode +GetThreadGroupAffinity +GetThreadIOPendingFlag +GetThreadId +GetThreadIdealProcessorEx +GetThreadInformation +GetThreadLocale +GetThreadPreferredUILanguages +GetThreadPriority +GetThreadPriorityBoost +GetThreadSelectedCpuSetMasks +GetThreadSelectorEntry +GetThreadTimes +GetThreadUILanguage +GetTickCount +GetTickCount64 +GetTimeFormatA +GetTimeFormatEx +GetTimeFormatW +GetTimeZoneInformation +GetTimeZoneInformationForYear +GetUILanguageInfo +GetUmsCompletionListEvent +GetUmsSystemThreadInformation +GetUserDefaultGeoName +GetUserDefaultLCID +GetUserDefaultLangID +GetUserDefaultLocaleName +GetUserDefaultUILanguage +GetUserGeoID +GetUserPreferredUILanguages +GetVersion +GetVersionExA +GetVersionExW +GetVolumeInformationA +GetVolumeInformationByHandleW +GetVolumeInformationW +GetVolumeNameForVolumeMountPointA +GetVolumeNameForVolumeMountPointW +GetVolumePathNameA +GetVolumePathNameW +GetVolumePathNamesForVolumeNameA +GetVolumePathNamesForVolumeNameW +GetWindowsDirectoryA +GetWindowsDirectoryW +GetWriteWatch +GetWsChanges +GetWsChangesEx +GetXStateFeaturesMask +GlobalAddAtomA +GlobalAddAtomExA +GlobalAddAtomExW +GlobalAddAtomW +GlobalAlloc +GlobalDeleteAtom +GlobalFindAtomA +GlobalFindAtomW +GlobalFlags +GlobalFree +GlobalGetAtomNameA +GlobalGetAtomNameW +GlobalHandle +GlobalLock +GlobalMemoryStatus +GlobalMemoryStatusEx +GlobalReAlloc +GlobalSize +GlobalUnlock +Heap32First +Heap32ListFirst +Heap32ListNext +Heap32Next +HeapAlloc +HeapCompact +HeapCreate +HeapDestroy +HeapFree +HeapLock +HeapQueryInformation +HeapReAlloc +HeapSetInformation +HeapSize +HeapSummary +HeapUnlock +HeapValidate +HeapWalk +IdnToAscii +ImpersonateNamedPipeClient +InitAtomTable +InitOnceBeginInitialize +InitOnceComplete +InitOnceExecuteOnce +InitOnceInitialize +InitSecurityInterfaceA +InitSecurityInterfaceW +InitializeConditionVariable +InitializeContext +InitializeCriticalSection +InitializeCriticalSectionAndSpinCount +InitializeCriticalSectionEx +InitializeEnclave +InitializeProcThreadAttributeList +InitializeProcessForWsWatch +InitializeSListHead +InitializeSRWLock +InitializeSynchronizationBarrier +InstallELAMCertificateInfo +InterlockedCompareExchange +InterlockedCompareExchange64 +InterlockedDecrement +InterlockedExchange +InterlockedExchangeAdd +InterlockedFlushSList +InterlockedIncrement +InterlockedPopEntrySList +InterlockedPushEntrySList +InterlockedPushListSListEx +IsBadCodePtr +IsBadReadPtr +IsBadStringPtrA +IsBadStringPtrW +IsBadWritePtr +IsDBCSLeadByte +IsDBCSLeadByteEx +IsDebuggerPresent +IsEnclaveTypeSupported +IsNLSDefinedString +IsNativeVhdBoot +IsProcessCritical +IsProcessInJob +IsProcessorFeaturePresent +IsSystemResumeAutomatic +IsThreadAFiber +IsThreadpoolTimerSet +IsValidCodePage +IsValidLanguageGroup +IsValidLocale +IsValidLocaleName +IsValidNLSVersion +IsWow64GuestMachineSupported +IsWow64Process +IsWow64Process2 +LCIDToLocaleName +LCMapStringA +LCMapStringEx +LCMapStringW +LeaveCriticalSection +LeaveCriticalSectionWhenCallbackReturns +LoadEnclaveData +LoadEnclaveImageA +LoadEnclaveImageW +LoadLibraryA +LoadLibraryExA +LoadLibraryExW +LoadLibraryW +LoadModule +LoadPackagedLibrary +LoadResource +LoadStringA +LoadStringByReference +LoadStringW +LocalAlloc +LocalFileTimeToFileTime +LocalFlags +LocalFree +LocalHandle +LocalLock +LocalReAlloc +LocalSize +LocalUnlock +LocaleNameToLCID +LocateXStateFeature +LockFile +LockFileEx +LockResource +MapUserPhysicalPages +MapUserPhysicalPagesScatter +MapViewOfFile +MapViewOfFile2 +MapViewOfFile3 +MapViewOfFile3FromApp +MapViewOfFileEx +MapViewOfFileExNuma +MapViewOfFileFromApp +Module32First +Module32FirstW +Module32Next +Module32NextW +MoveFile +MoveFileA +MoveFileExA +MoveFileExW +MoveFileTransactedA +MoveFileTransactedW +MoveFileW +MoveFileWithProgressA +MoveFileWithProgressW +MulDiv +MultiByteToWideChar +NdisAllocateBuffer +NdisAllocateBufferPool +NdisAllocatePacketPoolEx +NdisCancelSendPackets +NdisCloseAdapter +NdisCopyFromPacketToPacketSafe +NdisDeregisterProtocol +NdisFreePacketPool +NdisGetReceivedPacket +NdisIMCopySendCompletePerPacketInfo +NdisIMCopySendPerPacketInfo +NdisIMDeregisterLayeredMiniport +NdisIMGetDeviceContext +NdisIMNotifyPnPEvent +NdisIMRegisterLayeredMiniport +NdisMDeregisterDevice +NdisMIndicateStatus +NdisMInitializeWrapper +NdisMRegisterDevice +NdisMRegisterUnloadHandler +NdisMSetAttributesEx +NdisOpenAdapter +NdisOpenProtocolConfiguration +NdisPacketPoolUsage +NdisRegisterProtocol +NdisRequest +NdisScheduleWorkItem +NdisTerminateWrapper +NdisUnchainBufferAtBack +NeedCurrentDirectoryForExePathA +NeedCurrentDirectoryForExePathW +NotifyUILanguageChange +OfferVirtualMemory +OpenEventA +OpenEventW +OpenFile +OpenFileById +OpenFileMappingA +OpenFileMappingFromApp +OpenFileMappingW +OpenJobObjectA +OpenJobObjectW +OpenMutexW +OpenPackageInfoByFullName +OpenPrivateNamespaceA +OpenPrivateNamespaceW +OpenProcess +OpenProcessToken +OpenSemaphoreW +OpenThread +OpenThreadToken +OpenWaitableTimerW +OutputDebugStringA +OutputDebugStringW +PackageFamilyNameFromFullName +PackageFamilyNameFromId +PackageFullNameFromId +PackageIdFromFullName +PackageNameAndPublisherIdFromFamilyName +ParseApplicationUserModelId +PeekNamedPipe +PostQueuedCompletionStatus +PowerClearRequest +PowerCreateRequest +PowerSetRequest +PrefetchVirtualMemory +PrepareTape +Process32First +Process32FirstW +Process32Next +Process32NextW +ProcessIdToSessionId +PssCaptureSnapshot +PssDuplicateSnapshot +PssFreeSnapshot +PssQuerySnapshot +PssWalkMarkerCreate +PssWalkMarkerFree +PssWalkMarkerGetPosition +PssWalkMarkerSeekToBeginning +PssWalkMarkerSetPosition +PssWalkSnapshot +PulseEvent +PurgeComm +QueryActCtxSettingsW +QueryActCtxW +QueryAuxiliaryCounterFrequency +QueryDepthSList +QueryDosDeviceA +QueryDosDeviceW +QueryFullProcessImageNameA +QueryFullProcessImageNameW +QueryIdleProcessorCycleTime +QueryIdleProcessorCycleTimeEx +QueryInformationJobObject +QueryInterruptTime +QueryInterruptTimePrecise +QueryIoRateControlInformationJobObject +QueryMemoryResourceNotification +QueryPerformanceCounter +QueryPerformanceFrequency +QueryProcessAffinityUpdateMode +QueryProcessCycleTime +QueryProtectedPolicy +QueryThreadCycleTime +QueryThreadProfiling +QueryThreadpoolStackInformation +QueryUmsThreadInformation +QueryUnbiasedInterruptTime +QueryUnbiasedInterruptTimePrecise +QueryWorkingSet +QueryWorkingSetEx +QueueUserAPC +QueueUserWorkItem +RaiseException +RaiseFailFastException +ReOpenFile +ReadDirectoryChangesExW +ReadDirectoryChangesW +ReadFile +ReadFileEx +ReadFileScatter +ReadProcessMemory +ReadThreadProfilingData +ReclaimVirtualMemory +RegCloseKey +RegDeleteKeyA +RegDeleteKeyExA +RegDeleteKeyExW +RegDeleteKeyValueA +RegDeleteTreeA +RegDeleteTreeW +RegEnumKeyExA +RegEnumValueA +RegNotifyChangeKeyValue +RegOpenKeyExA +RegQueryInfoKeyA +RegQueryValueExA +RegQueryValueExW +RegisterApplicationRecoveryCallback +RegisterApplicationRestart +RegisterBadMemoryNotification +RegisterWaitForSingleObject +RegisterWaitUntilOOBECompleted +ReleaseActCtx +ReleaseMutex +ReleaseMutexWhenCallbackReturns +ReleaseSRWLockExclusive +ReleaseSRWLockShared +ReleaseSemaphore +ReleaseSemaphoreWhenCallbackReturns +RemoveDirectoryA +RemoveDirectoryTransactedA +RemoveDirectoryTransactedW +RemoveDirectoryW +RemoveDllDirectory +RemoveSecureMemoryCacheCallback +RemoveVectoredContinueHandler +RemoveVectoredExceptionHandler +ReplaceFileA +ReplaceFileW +RequestWakeupLatency +ResetEvent +ResetWriteWatch +ResolveLocaleName +RestoreLastError +ResumeThread +RtlAddFunctionTable +RtlCaptureContext +RtlCompareMemory +RtlDeleteFunctionTable +RtlFillMemory +RtlInstallFunctionTableCallback +RtlLookupFunctionEntry +RtlPcToFileHeader +RtlRestoreContext +RtlUnwind +RtlUnwind2 +RtlUnwindEx +RtlVirtualUnwind +SearchPathA +SearchPathW +SetCalendarInfoA +SetCalendarInfoW +SetCommBreak +SetCommConfig +SetCommMask +SetCommState +SetCommTimeouts +SetComputerNameA +SetComputerNameExA +SetComputerNameExW +SetComputerNameW +SetCriticalSectionSpinCount +SetCurrentDirectory +SetDefaultCommConfigA +SetDefaultCommConfigW +SetDefaultDllDirectories +SetDllDirectoryA +SetDllDirectoryW +SetDynamicTimeZoneInformation +SetEndOfFile +SetEnvironmentStringsA +SetEnvironmentStringsW +SetEnvironmentVariable +SetEnvironmentVariableA +SetEnvironmentVariableW +SetErrorMode +SetEvent +SetEventWhenCallbackReturns +SetFileApisToANSI +SetFileApisToOEM +SetFileAttributesA +SetFileAttributesTransactedA +SetFileAttributesTransactedW +SetFileAttributesW +SetFileBandwidthReservation +SetFileCompletionNotificationModes +SetFileInformationByHandle +SetFileIoOverlappedRange +SetFilePointer +SetFilePointerEx +SetFileShortNameA +SetFileShortNameW +SetFileTime +SetFileValidData +SetFirmwareEnvironmentVariableA +SetFirmwareEnvironmentVariableExA +SetFirmwareEnvironmentVariableExW +SetFirmwareEnvironmentVariableW +SetHandleCount +SetHandleInformation +SetInformationJobObject +SetIoRateControlInformationJobObject +SetLastError +SetLocalTime +SetLocaleInfoA +SetLocaleInfoW +SetMailslotInfo +SetNamedPipeHandleState +SetPriorityClass +SetProcessAffinityMask +SetProcessAffinityUpdateMode +SetProcessDEPPolicy +SetProcessDefaultCpuSetMasks +SetProcessInformation +SetProcessMitigationPolicy +SetProcessPreferredUILanguages +SetProcessPriorityBoost +SetProcessShutdownParameters +SetProcessWorkingSetSize +SetProcessWorkingSetSizeEx +SetProtectedPolicy +SetSearchPathMode +SetStdHandleEx +SetSystemFileCacheSize +SetSystemPowerState +SetSystemTime +SetSystemTimeAdjustment +SetTapeParameters +SetTapePosition +SetThreadAffinityMask +SetThreadContext +SetThreadDescription +SetThreadErrorMode +SetThreadExecutionState +SetThreadGroupAffinity +SetThreadIdealProcessor +SetThreadIdealProcessorEx +SetThreadInformation +SetThreadLocale +SetThreadPreferredUILanguages +SetThreadPriority +SetThreadPriorityBoost +SetThreadSelectedCpuSetMasks +SetThreadSelectedCpuSets +SetThreadStackGuarantee +SetThreadToken +SetThreadUILanguage +SetThreadpoolStackInformation +SetThreadpoolThreadMaximum +SetThreadpoolThreadMinimum +SetThreadpoolTimer +SetThreadpoolTimerEx +SetThreadpoolWait +SetThreadpoolWaitEx +SetTimeZoneInformation +SetUmsThreadInformation +SetUnhandledExceptionFilter +SetUserGeoID +SetUserGeoName +SetVolumeLabelA +SetVolumeLabelW +SetVolumeMountPointA +SetVolumeMountPointW +SetWaitableTimer +SetWaitableTimerEx +SetXStateFeaturesMask +SetupComm +SignalObjectAndWait +SizeofResource +Sleep +SleepConditionVariableCS +SleepConditionVariableSRW +SleepEx +StartThreadpoolIo +SubmitThreadpoolWork +SuspendThread +SwitchToFiber +SwitchToThread +SystemTimeToFileTime +SystemTimeToTzSpecificLocalTime +SystemTimeToTzSpecificLocalTimeEx +TerminateEnclave +TerminateJobObject +TerminateProcess +TerminateThread +Thread32First +Thread32Next +TlsAlloc +TlsFree +TlsGetValue +TlsSetValue +Toolhelp32ReadProcessMemory +TransactNamedPipe +TransmitCommChar +TryAcquireSRWLockExclusive +TryAcquireSRWLockShared +TryEnterCriticalSection +TrySubmitThreadpoolCallback +TzSpecificLocalTimeToSystemTime +TzSpecificLocalTimeToSystemTimeEx +UmsThreadYield +UnhandledExceptionFilter +UnlockFile +UnlockFileEx +UnmapViewOfFile +UnmapViewOfFile2 +UnmapViewOfFileEx +UnregisterApplicationRecoveryCallback +UnregisterApplicationRestart +UnregisterBadMemoryNotification +UnregisterWait +UnregisterWaitEx +UnregisterWaitUntilOOBECompleted +UpdateProcThreadAttribute +UpdateResourceA +UpdateResourceW +VerLanguageNameA +VerLanguageNameW +VerSetConditionMask +VerifyScripts +VerifyVersionInfoA +VerifyVersionInfoW +VirtualAlloc +VirtualAlloc2FromApp +VirtualAllocEx +VirtualAllocExNuma +VirtualAllocFromApp +VirtualFree +VirtualFreeEx +VirtualLock +VirtualProtect +VirtualProtectEx +VirtualProtectFromApp +VirtualQuery +VirtualQueryEx +VirtualUnlock +WTSGetActiveConsoleSessionId +WaitCommEvent +WaitForDebugEvent +WaitForDebugEventEx +WaitForMultipleObjects +WaitForMultipleObjectsEx +WaitForSingleObject +WaitForSingleObjectEx +WaitForThreadpoolIoCallbacks +WaitForThreadpoolTimerCallbacks +WaitForThreadpoolWaitCallbacks +WaitForThreadpoolWorkCallbacks +WaitNamedPipeA +WaitNamedPipeW +WaitOnAddress +WakeAllConditionVariable +WakeByAddressAll +WakeByAddressSingle +WakeConditionVariable +WerGetFlags +WerRegisterAdditionalProcess +WerRegisterAppLocalDump +WerRegisterCustomMetadata +WerRegisterExcludedMemoryBlock +WerRegisterFile +WerRegisterMemoryBlock +WerRegisterRuntimeExceptionModule +WerSetFlags +WerUnregisterAdditionalProcess +WerUnregisterAppLocalDump +WerUnregisterExcludedMemoryBlock +WerUnregisterFile +WerUnregisterMemoryBlock +WerUnregisterRuntimeExceptionModule +WideCharToMultiByte +WinExec +Wow64DisableWow64FsRedirection +Wow64GetThreadSelectorEntry +Wow64RevertWow64FsRedirection +Wow64SuspendThread +WriteFile +WriteFileEx +WriteFileGather +WritePrivateProfileSectionA +WritePrivateProfileSectionW +WritePrivateProfileStringA +WritePrivateProfileStringW +WritePrivateProfileStructA +WritePrivateProfileStructW +WriteProcessMemory +WriteProfileSectionA +WriteProfileSectionW +WriteProfileStringA +WriteProfileStringW +WriteTapemark +ZombifyActCtx +_lclose +_lcreat +_llseek +_lopen +_lread +_lwrite +if_nametoindex +lstrcatA +lstrcatW +lstrcmpA +lstrcmpW +lstrcmpiA +lstrcmpiW +lstrcpyA +lstrcpyW +lstrcpynA +lstrcpynW +lstrlenA +lstrlenW +timeBeginPeriod +timeEndPeriod +timeGetDevCaps +timeGetSystemTime +timeGetTime +uaw_wcslen diff --git a/crates/exav-pe-emu/src/exports/ntdll.txt b/crates/exav-pe-emu/src/exports/ntdll.txt new file mode 100644 index 0000000..2a68b6e --- /dev/null +++ b/crates/exav-pe-emu/src/exports/ntdll.txt @@ -0,0 +1,133 @@ +DbgBreakPoint +DbgPrint +DbgPrintEx +DbgPrompt +EtwActivityIdControl +EtwUnregister +EtwWriteTransfer +GetCurrentProcessorNumber +NtClose +NtCreateFile +NtCurrentTeb +NtDeviceIoControlFile +NtNotifyChangeMultipleKeys +NtOpenFile +NtQueryInformationProcess +NtQueryInformationThread +NtQueryMultipleValueKey +NtQueryObject +NtQuerySystemInformation +NtQuerySystemTime +NtRenameKey +NtSetInformationKey +NtWaitForSingleObject +ReleaseSRWLockShared +RtlAbsoluteToSelfRelativeSD +RtlAddAce +RtlAddFunctionTable +RtlAddGrowableFunctionTable +RtlAllocateHeap +RtlAnsiStringToUnicodeString +RtlAppendUnicodeToString +RtlCaptureContext +RtlCaptureStackBackTrace +RtlCharToInteger +RtlClearAllBits +RtlCompareMemory +RtlCompareMemoryUlong +RtlCompareString +RtlConvertDeviceFamilyInfoToString +RtlConvertSidToUnicodeString +RtlCopyMemory +RtlCopyMemoryNonTemporal +RtlCopySid +RtlCopyUnicodeString +RtlCreateHeap +RtlCreateSecurityDescriptor +RtlCreateUnicodeString +RtlDecompressBuffer +RtlDeleteFunctionTable +RtlDeleteGrowableFunctionTable +RtlDowncaseUnicodeChar +RtlEqualPrefixSid +RtlEqualSid +RtlEqualString +RtlEqualUnicodeString +RtlEthernetAddressToStringA +RtlEthernetAddressToStringW +RtlEthernetStringToAddressA +RtlEthernetStringToAddressW +RtlFillMemory +RtlFirstEntrySList +RtlFreeAnsiString +RtlFreeOemString +RtlFreeUnicodeString +RtlGUIDFromString +RtlGetAce +RtlGetEnabledExtendedFeatures +RtlGetOwnerSecurityDescriptor +RtlGrowFunctionTable +RtlInitString +RtlInitUnicodeString +RtlInitializeBitMap +RtlInitializeSListHead +RtlInitializeSid +RtlInstallFunctionTableCallback +RtlIntegerToUnicodeString +RtlInterlockedFlushSList +RtlInterlockedPopEntrySList +RtlInterlockedPushEntrySList +RtlIpv4AddressToStringA +RtlIpv4AddressToStringExA +RtlIpv4AddressToStringExW +RtlIpv4AddressToStringW +RtlIpv4StringToAddressA +RtlIpv4StringToAddressExA +RtlIpv4StringToAddressExW +RtlIpv4StringToAddressW +RtlIpv6AddressToStringA +RtlIpv6AddressToStringExA +RtlIpv6AddressToStringExW +RtlIpv6AddressToStringW +RtlIpv6StringToAddressA +RtlIpv6StringToAddressExA +RtlIpv6StringToAddressExW +RtlIpv6StringToAddressW +RtlIsCloudFilesPlaceholder +RtlIsNameLegalDOS8Dot3 +RtlLengthRequiredSid +RtlLengthSid +RtlLocalTimeToSystemTime +RtlLookupFunctionEntry +RtlMultiByteToUnicodeN +RtlNtStatusToDosError +RtlNumberOfSetBits +RtlPcToFileHeader +RtlQueryDepthSList +RtlRaiseException +RtlRestoreContext +RtlSetBits +RtlSetDaclSecurityDescriptor +RtlSetGroupSecurityDescriptor +RtlSetOwnerSecurityDescriptor +RtlStringFromGUID +RtlSubAuthoritySid +RtlTimeToSecondsSince1970 +RtlTimeToTimeFields +RtlUnicodeStringToAnsiString +RtlUnicodeStringToInteger +RtlUnicodeStringToOemString +RtlUnicodeToMultiByteSize +RtlUniform +RtlUnwind +RtlUnwindEx +RtlUpcaseUnicodeChar +RtlUpcaseUnicodeString +RtlValidSid +RtlVerifyVersionInfo +RtlVirtualUnwind +TryAcquireSRWLockShared +UnhandledExceptionFilter +VerSetConditionMask +vDbgPrintEx +vDbgPrintExWithPrefix diff --git a/crates/exav-pe-emu/src/exports/user32.txt b/crates/exav-pe-emu/src/exports/user32.txt new file mode 100644 index 0000000..ec00b7c --- /dev/null +++ b/crates/exav-pe-emu/src/exports/user32.txt @@ -0,0 +1,755 @@ +ActivateKeyboardLayout +AddClipboardFormatListener +AdjustWindowRect +AdjustWindowRectEx +AdjustWindowRectExForDpi +AllowSetForegroundWindow +AnimateWindow +AnyPopup +AppendMenuA +AppendMenuW +AreDpiAwarenessContextsEqual +ArrangeIconicWindows +AttachThreadInput +BeginDeferWindowPos +BeginPaint +BlockInput +BringWindowToTop +BroadcastSystemMessage +BroadcastSystemMessageA +BroadcastSystemMessageExA +BroadcastSystemMessageExW +BroadcastSystemMessageW +CalculatePopupWindowPosition +CallMsgFilterA +CallMsgFilterW +CallNextHookEx +CallWindowProcA +CallWindowProcW +CascadeWindows +ChangeClipboardChain +ChangeDisplaySettingsA +ChangeDisplaySettingsExA +ChangeDisplaySettingsExW +ChangeDisplaySettingsW +ChangeWindowMessageFilter +ChangeWindowMessageFilterEx +CharLowerA +CharLowerBuffA +CharLowerBuffW +CharLowerW +CharNextA +CharNextExA +CharNextW +CharPrevA +CharPrevExA +CharPrevW +CharToOemA +CharToOemBuffA +CharToOemBuffW +CharToOemW +CharUpperA +CharUpperBuffA +CharUpperBuffW +CharUpperW +CheckDlgButton +CheckMenuItem +CheckMenuRadioItem +CheckRadioButton +ChildWindowFromPoint +ChildWindowFromPointEx +ClientToScreen +ClipCursor +CloseClipboard +CloseDesktop +CloseGestureInfoHandle +CloseTouchInputHandle +CloseWindow +CloseWindowStation +CopyAcceleratorTableA +CopyAcceleratorTableW +CopyIcon +CopyImage +CopyRect +CountClipboardFormats +CreateAcceleratorTableA +CreateAcceleratorTableW +CreateCaret +CreateCursor +CreateDesktopA +CreateDesktopExA +CreateDesktopExW +CreateDesktopW +CreateDialogA +CreateDialogIndirectA +CreateDialogIndirectParamA +CreateDialogIndirectParamW +CreateDialogIndirectW +CreateDialogParamA +CreateDialogParamW +CreateDialogW +CreateIcon +CreateIconFromResource +CreateIconFromResourceEx +CreateIconIndirect +CreateMDIWindowA +CreateMDIWindowW +CreateMenu +CreatePopupMenu +CreateSyntheticPointerDevice +CreateWindowExA +CreateWindowExW +CreateWindowStationA +CreateWindowStationW +DdeAbandonTransaction +DdeAccessData +DdeAddData +DdeClientTransaction +DdeCmpStringHandles +DdeConnect +DdeConnectList +DdeCreateDataHandle +DdeCreateStringHandleA +DdeCreateStringHandleW +DdeDisconnect +DdeDisconnectList +DdeEnableCallback +DdeFreeDataHandle +DdeFreeStringHandle +DdeGetData +DdeGetLastError +DdeImpersonateClient +DdeInitializeA +DdeInitializeW +DdeKeepStringHandle +DdeNameService +DdePostAdvise +DdeQueryConvInfo +DdeQueryNextServer +DdeQueryStringA +DdeQueryStringW +DdeReconnect +DdeSetQualityOfService +DdeSetUserHandle +DdeUnaccessData +DdeUninitialize +DefDlgProcA +DefDlgProcW +DefFrameProcA +DefFrameProcW +DefMDIChildProcA +DefMDIChildProcW +DefRawInputProc +DefWindowProcA +DefWindowProcW +DeferWindowPos +DeleteMenu +DeregisterShellHookWindow +DestroyAcceleratorTable +DestroyCaret +DestroyCursor +DestroyIcon +DestroyMenu +DestroySyntheticPointerDevice +DestroyWindow +DialogBoxA +DialogBoxIndirectA +DialogBoxIndirectParamA +DialogBoxIndirectParamW +DialogBoxIndirectW +DialogBoxParamA +DialogBoxParamW +DialogBoxW +DisableProcessWindowsGhosting +DispatchMessage +DispatchMessageA +DispatchMessageW +DisplayConfigGetDeviceInfo +DisplayConfigSetDeviceInfo +DlgDirListA +DlgDirListComboBoxA +DlgDirListComboBoxW +DlgDirListW +DlgDirSelectComboBoxExA +DlgDirSelectComboBoxExW +DlgDirSelectExA +DlgDirSelectExW +DragDetect +DrawAnimatedRects +DrawCaption +DrawEdge +DrawFocusRect +DrawFrameControl +DrawIcon +DrawIconEx +DrawMenuBar +DrawStateA +DrawStateW +DrawText +DrawTextA +DrawTextExA +DrawTextExW +DrawTextW +EmptyClipboard +EnableMenuItem +EnableMouseInPointer +EnableNonClientDpiScaling +EnableScrollBar +EnableWindow +EndDeferWindowPos +EndDialog +EndMenu +EndPaint +EndTask +EnumChildWindows +EnumClipboardFormats +EnumDesktopWindows +EnumDesktopsA +EnumDesktopsW +EnumDisplayDevicesA +EnumDisplayDevicesW +EnumDisplayMonitors +EnumDisplaySettingsA +EnumDisplaySettingsExA +EnumDisplaySettingsExW +EnumDisplaySettingsW +EnumPropsA +EnumPropsExA +EnumPropsExW +EnumPropsW +EnumThreadWindows +EnumWindowStationsA +EnumWindowStationsW +EnumWindows +EqualRect +EvaluateProximityToPolygon +EvaluateProximityToRect +ExcludeUpdateRgn +ExitWindowsEx +FillRect +FindWindowA +FindWindowExA +FindWindowExW +FindWindowW +FlashWindow +FlashWindowEx +FrameRect +FreeDDElParam +GetActiveWindow +GetAltTabInfoA +GetAltTabInfoW +GetAncestor +GetAsyncKeyState +GetAutoRotationState +GetAwarenessFromDpiAwarenessContext +GetCIMSSM +GetCapture +GetCaretBlinkTime +GetCaretPos +GetClassInfoA +GetClassInfoExA +GetClassInfoExW +GetClassInfoW +GetClassLongA +GetClassLongPtrA +GetClassLongPtrW +GetClassLongW +GetClassName +GetClassNameA +GetClassNameW +GetClassWord +GetClientRect +GetClipCursor +GetClipboardData +GetClipboardFormatNameA +GetClipboardFormatNameW +GetClipboardOwner +GetClipboardSequenceNumber +GetClipboardViewer +GetComboBoxInfo +GetCurrentInputMessageSource +GetCursor +GetCursorInfo +GetCursorPos +GetDC +GetDCEx +GetDesktopWindow +GetDialogBaseUnits +GetDialogControlDpiChangeBehavior +GetDialogDpiChangeBehavior +GetDisplayAutoRotationPreferences +GetDisplayConfigBufferSizes +GetDlgCtrlID +GetDlgItem +GetDlgItemInt +GetDlgItemTextA +GetDlgItemTextW +GetDoubleClickTime +GetDpiAwarenessContextForProcess +GetDpiForSystem +GetDpiForWindow +GetDpiFromDpiAwarenessContext +GetFocus +GetForegroundWindow +GetGUIThreadInfo +GetGestureConfig +GetGestureExtraArgs +GetGestureInfo +GetGuiResources +GetIconInfo +GetIconInfoExA +GetIconInfoExW +GetInputState +GetKBCodePage +GetKeyNameTextA +GetKeyNameTextW +GetKeyState +GetKeyboardLayout +GetKeyboardLayoutList +GetKeyboardLayoutNameA +GetKeyboardLayoutNameW +GetKeyboardState +GetKeyboardType +GetLastActivePopup +GetLastInputInfo +GetLayeredWindowAttributes +GetListBoxInfo +GetMenu +GetMenuBarInfo +GetMenuCheckMarkDimensions +GetMenuContextHelpId +GetMenuDefaultItem +GetMenuInfo +GetMenuItemCount +GetMenuItemID +GetMenuItemInfoA +GetMenuItemInfoW +GetMenuItemRect +GetMenuState +GetMenuStringA +GetMenuStringW +GetMessage +GetMessageA +GetMessageExtraInfo +GetMessagePos +GetMessageTime +GetMessageW +GetMonitorInfoA +GetMonitorInfoW +GetMouseMovePointsEx +GetNextDlgGroupItem +GetNextDlgTabItem +GetOpenClipboardWindow +GetParent +GetPhysicalCursorPos +GetPointerCursorId +GetPointerDevice +GetPointerDeviceCursors +GetPointerDeviceProperties +GetPointerDeviceRects +GetPointerDevices +GetPointerFrameInfo +GetPointerFrameInfoHistory +GetPointerFramePenInfo +GetPointerFramePenInfoHistory +GetPointerFrameTouchInfo +GetPointerFrameTouchInfoHistory +GetPointerInfo +GetPointerInfoHistory +GetPointerInputTransform +GetPointerPenInfo +GetPointerPenInfoHistory +GetPointerTouchInfo +GetPointerTouchInfoHistory +GetPointerType +GetPriorityClipboardFormat +GetProcessDefaultLayout +GetProcessWindowStation +GetPropA +GetPropW +GetQueueStatus +GetRawInputBuffer +GetRawInputData +GetRawInputDeviceInfoA +GetRawInputDeviceInfoW +GetRawInputDeviceList +GetRawPointerDeviceData +GetRegisteredRawInputDevices +GetScrollBarInfo +GetScrollInfo +GetScrollPos +GetScrollRange +GetShellWindow +GetSubMenu +GetSysColor +GetSysColorBrush +GetSystemDpiForProcess +GetSystemMenu +GetSystemMetrics +GetSystemMetricsForDpi +GetTabbedTextExtentA +GetTabbedTextExtentW +GetThreadDesktop +GetThreadDpiAwarenessContext +GetThreadDpiHostingBehavior +GetTitleBarInfo +GetTopWindow +GetTouchInputInfo +GetUnpredictedMessagePos +GetUpdateRect +GetUpdateRgn +GetUpdatedClipboardFormats +GetUserObjectInformationA +GetUserObjectInformationW +GetUserObjectSecurity +GetWindow +GetWindowContextHelpId +GetWindowDC +GetWindowDisplayAffinity +GetWindowDpiAwarenessContext +GetWindowDpiHostingBehavior +GetWindowFeedbackSetting +GetWindowInfo +GetWindowLongA +GetWindowLongPtrA +GetWindowLongPtrW +GetWindowLongW +GetWindowModuleFileNameA +GetWindowModuleFileNameW +GetWindowPlacement +GetWindowRect +GetWindowRgn +GetWindowRgnBox +GetWindowTextA +GetWindowTextLengthA +GetWindowTextLengthW +GetWindowTextW +GetWindowThreadProcessId +GetWindowWord +GrayStringA +GrayStringW +HideCaret +HiliteMenuItem +ImpersonateDdeClientWindow +InSendMessage +InSendMessageEx +InflateRect +InheritWindowMonitor +InitializeTouchInjection +InjectSyntheticPointerInput +InjectTouchInput +InsertMenuA +InsertMenuItemA +InsertMenuItemW +InsertMenuW +InternalGetWindowText +IntersectRect +InvalidateRect +InvalidateRgn +InvertRect +IsCharAlphaA +IsCharAlphaNumericA +IsCharAlphaNumericW +IsCharAlphaW +IsCharLowerA +IsCharLowerW +IsCharUpperA +IsCharUpperW +IsChild +IsClipboardFormatAvailable +IsDialogMessageA +IsDialogMessageW +IsDlgButtonChecked +IsGUIThread +IsHungAppWindow +IsIconic +IsImmersiveProcess +IsMenu +IsMouseInPointerEnabled +IsProcessDPIAware +IsRectEmpty +IsTouchWindow +IsValidDpiAwarenessContext +IsWinEventHookInstalled +IsWindow +IsWindowArranged +IsWindowEnabled +IsWindowUnicode +IsWindowVisible +IsWow64Message +IsZoomed +KillTimer +LoadAcceleratorsA +LoadAcceleratorsW +LoadBitmapA +LoadBitmapW +LoadCursorA +LoadCursorFromFileA +LoadCursorFromFileW +LoadCursorW +LoadIconA +LoadIconW +LoadImageA +LoadImageW +LoadKeyboardLayoutA +LoadKeyboardLayoutW +LoadMenuA +LoadMenuIndirectA +LoadMenuIndirectW +LoadMenuW +LoadStringA +LoadStringW +LockSetForegroundWindow +LockWindowUpdate +LockWorkStation +LogicalToPhysicalPoint +LogicalToPhysicalPointForPerMonitorDPI +LookupIconIdFromDirectory +LookupIconIdFromDirectoryEx +MapDialogRect +MapVirtualKeyA +MapVirtualKeyExA +MapVirtualKeyExW +MapVirtualKeyW +MapWindowPoints +MenuItemFromPoint +MessageBeep +MessageBox +MessageBoxA +MessageBoxExA +MessageBoxExW +MessageBoxIndirectA +MessageBoxIndirectW +MessageBoxW +ModifyMenuA +ModifyMenuW +MonitorFromPoint +MonitorFromRect +MonitorFromWindow +MoveWindow +MsgWaitForMultipleObjects +MsgWaitForMultipleObjectsEx +NotifyWinEvent +OemKeyScan +OemToCharA +OemToCharBuffA +OemToCharBuffW +OemToCharW +OffsetRect +OpenClipboard +OpenDesktopA +OpenDesktopW +OpenIcon +OpenInputDesktop +OpenWindowStationA +OpenWindowStationW +PackDDElParam +PackTouchHitTestingProximityEvaluation +PaintDesktop +PeekMessageA +PeekMessageW +PhysicalToLogicalPoint +PhysicalToLogicalPointForPerMonitorDPI +PostMessageA +PostMessageW +PostQuitMessage +PostThreadMessageA +PostThreadMessageW +PrintWindow +PrivateExtractIconsA +PrivateExtractIconsW +PtInRect +QueryDisplayConfig +RealChildWindowFromPoint +RealGetWindowClassA +RealGetWindowClassW +RedrawWindow +RegisterClassA +RegisterClassExA +RegisterClassExW +RegisterClassW +RegisterClipboardFormatA +RegisterClipboardFormatW +RegisterDeviceNotificationA +RegisterDeviceNotificationW +RegisterHotKey +RegisterPointerDeviceNotifications +RegisterPointerInputTarget +RegisterPointerInputTargetEx +RegisterPowerSettingNotification +RegisterRawInputDevices +RegisterShellHookWindow +RegisterSuspendResumeNotification +RegisterTouchHitTestingWindow +RegisterTouchWindow +RegisterWindowMessageA +RegisterWindowMessageW +ReleaseCapture +ReleaseDC +RemoveClipboardFormatListener +RemoveMenu +RemovePropA +RemovePropW +ReplyMessage +ReuseDDElParam +ScreenToClient +ScrollDC +ScrollWindow +ScrollWindowEx +SendDlgItemMessageA +SendDlgItemMessageW +SendIMEMessageExA +SendIMEMessageExW +SendInput +SendMessage +SendMessageA +SendMessageCallbackA +SendMessageCallbackW +SendMessageTimeoutA +SendMessageTimeoutW +SendMessageW +SendNotifyMessageA +SendNotifyMessageW +SetActiveWindow +SetCapture +SetCaretBlinkTime +SetCaretPos +SetClassLongA +SetClassLongPtrA +SetClassLongPtrW +SetClassLongW +SetClassWord +SetClipboardData +SetClipboardViewer +SetCoalescableTimer +SetCursor +SetCursorPos +SetDialogDpiChangeBehavior +SetDisplayAutoRotationPreferences +SetDisplayConfig +SetDlgItemInt +SetDlgItemTextA +SetDlgItemTextW +SetDoubleClickTime +SetFocus +SetForegroundWindow +SetGestureConfig +SetKeyboardState +SetLastErrorEx +SetLayeredWindowAttributes +SetMenu +SetMenuContextHelpId +SetMenuDefaultItem +SetMenuInfo +SetMenuItemBitmaps +SetMenuItemInfoA +SetMenuItemInfoW +SetMessageExtraInfo +SetParent +SetPhysicalCursorPos +SetProcessDPIAware +SetProcessDefaultLayout +SetProcessDpiAwarenessContext +SetProcessRestrictionExemption +SetProcessWindowStation +SetPropA +SetPropW +SetRect +SetRectEmpty +SetScrollInfo +SetScrollPos +SetScrollRange +SetSysColors +SetSystemCursor +SetThreadCursorCreationScaling +SetThreadDesktop +SetThreadDpiAwarenessContext +SetThreadDpiHostingBehavior +SetTimer +SetUserObjectInformationA +SetUserObjectInformationW +SetUserObjectSecurity +SetWinEventHook +SetWindowContextHelpId +SetWindowDisplayAffinity +SetWindowFeedbackSetting +SetWindowLongA +SetWindowLongPtrA +SetWindowLongPtrW +SetWindowLongW +SetWindowPlacement +SetWindowPos +SetWindowRgn +SetWindowTextA +SetWindowTextW +SetWindowsHookExA +SetWindowsHookExW +ShowCaret +ShowCursor +ShowOwnedPopups +ShowScrollBar +ShowWindow +ShowWindowAsync +ShutdownBlockReasonCreate +ShutdownBlockReasonDestroy +ShutdownBlockReasonQuery +SkipPointerFrameMessages +SoundSentry +SubtractRect +SwapMouseButton +SwitchDesktop +SwitchToThisWindow +SystemParametersInfoA +SystemParametersInfoForDpi +SystemParametersInfoW +TabbedTextOutA +TabbedTextOutW +TileWindows +ToAscii +ToAsciiEx +ToUnicode +ToUnicodeEx +TrackMouseEvent +TrackPopupMenu +TrackPopupMenuEx +TranslateAcceleratorA +TranslateAcceleratorW +TranslateMDISysAccel +TranslateMessage +UnhookWinEvent +UnhookWindowsHookEx +UnionRect +UnloadKeyboardLayout +UnpackDDElParam +UnregisterClassA +UnregisterClassW +UnregisterDeviceNotification +UnregisterHotKey +UnregisterPointerInputTarget +UnregisterPointerInputTargetEx +UnregisterPowerSettingNotification +UnregisterSuspendResumeNotification +UnregisterTouchWindow +UpdateLayeredWindow +UpdateWindow +UserHandleGrantAccess +ValidateRect +ValidateRgn +VkKeyScanA +VkKeyScanExA +VkKeyScanExW +VkKeyScanW +WINNLSEnableIME +WaitForInputIdle +WaitMessage +WinHelpA +WinHelpW +WindowFromDC +WindowFromPhysicalPoint +WindowFromPoint +keybd_event +mouse_event +wsprintfA +wsprintfW +wvsprintfA +wvsprintfW diff --git a/crates/exav-pe-emu/src/image.rs b/crates/exav-pe-emu/src/image.rs index c97a441..fca6fd1 100644 --- a/crates/exav-pe-emu/src/image.rs +++ b/crates/exav-pe-emu/src/image.rs @@ -2,10 +2,17 @@ //! //! Loading follows what the Windows loader does to the parts a stub can //! observe: headers at the image base, each section at its virtual address, -//! zero-fill where the virtual size exceeds the raw size. Nothing else — no -//! relocations (the emulator maps at the image's preferred base, so there are -//! none to apply), no import binding (the stub resolves its own), no TLS -//! callbacks. +//! zero-fill where the virtual size exceeds the raw size. No relocations (the +//! emulator maps at the image's preferred base, so there are none to apply) and +//! no import binding here (the stub resolves its own, with a hand from +//! [`crate::win::Env::bind_imports`]). +//! +//! The one piece of loader work this module parses but [`crate::run`] performs +//! is the **TLS directory** (data directory 9): its callbacks run, with +//! `DLL_PROCESS_ATTACH`, before the entry point, because a packer can put its +//! unpacking there precisely so a tool that starts at the entry point sees +//! nothing. [`PeImage::tls_dir`] is the directory's `(rva, size)`; the run +//! driver reads the `IMAGE_TLS_DIRECTORY32` it points at. //! //! Dumping is the reverse, with one deliberate difference: the dump is written //! in **memory layout**, with `PointerToRawData == VirtualAddress` and the file @@ -46,6 +53,10 @@ pub struct PeImage { /// functions its stub needs, and the *loader* — not the stub — fills those /// slots in. Emulating that binding is what lets the stub call them. pub import_dir: (u32, u32), + /// TLS directory (RVA, size), data directory 9. Zero when absent. The run + /// driver reads the `IMAGE_TLS_DIRECTORY32` here and runs its callbacks + /// before the entry point, as the Windows loader does. + pub tls_dir: (u32, u32), pub sections: Vec
, /// Offset of the section table within the file, so the dump can patch it. sec_table_off: usize, @@ -105,6 +116,15 @@ impl PeImage { } else { (0, 0) }; + // Data directory 9 is the TLS directory, at opt + 96 + 9 * 8. + let tls_dir = if num_dirs >= 10 { + ( + u32_at(data, opt + 168).unwrap_or(0), + u32_at(data, opt + 172).unwrap_or(0), + ) + } else { + (0, 0) + }; let mut sections = Vec::with_capacity(num_sections); for i in 0..num_sections { @@ -140,6 +160,7 @@ impl PeImage { file_align, is_dll, import_dir, + tls_dir, sections, sec_table_off, pe_off, diff --git a/crates/exav-pe-emu/src/run.rs b/crates/exav-pe-emu/src/run.rs index 2d886e6..09f6cd2 100644 --- a/crates/exav-pe-emu/src/run.rs +++ b/crates/exav-pe-emu/src/run.rs @@ -35,6 +35,23 @@ //! handler, and resumes from the context the handler leaves behind — including //! any registers or instruction pointer it edited, which is exactly the //! mechanism those stubs are using. +//! +//! ## TLS callbacks +//! +//! The Windows loader runs a module's TLS callbacks before its entry point, so +//! a packer can hide its unpacking there to defeat a tool that starts at the +//! entry point. The driver does the same: it sets up the static TLS block, +//! writes the index to `AddressOfIndex`, points the TEB's +//! `ThreadLocalStoragePointer` at it, then calls each callback as +//! `cb(image_base, DLL_PROCESS_ATTACH, 0)`, re-reading the callback array after +//! each one as the loader does (a callback may extend it). Only then does it +//! start at the entry point. The directory layout, the TEB+0x2C TLS array and +//! the callback prototype are as Microsoft's PE Format specification gives them +//! (section "The .tls Section"). A callback that faults or raises goes through the +//! same SEH machinery as the stub. If nothing handles it, or a callback runs +//! past its slice of the budget, or the callback count cap is hit, the TLS +//! phase is abandoned and execution proceeds to the entry point rather than +//! ending the run: the payload is still worth trying to recover from there. use crate::cpu::{Cpu, Stop, EAX, EBX, ESP}; use crate::image::PeImage; @@ -80,6 +97,24 @@ const MIN_WRITE_SPREAD: u32 = 6; /// skewed, so a run that makes many of them is not executing anything real. const MAX_UNIMPLEMENTED_CALLS: u32 = 64; +/// Most TLS callbacks a run will invoke before giving up on the rest and +/// starting the entry point. A real image has one or two; a hostile directory +/// can name far more, or point its array at itself. +const MAX_TLS_CALLBACKS: u32 = 64; + +/// Fraction of the whole instruction budget any single TLS callback may spend. +/// A callback is bounded so a stub cannot park the emulator in one forever, but +/// generously, since a packer that unpacks from a callback does real work there. +const TLS_CALLBACK_BUDGET_DIVISOR: u64 = 8; + +/// Largest static TLS block the loader will build, so a crafted +/// `SizeOfZeroFill` cannot demand an arbitrary allocation. +const MAX_TLS_BLOCK: u32 = 1 << 20; + +/// `DLL_PROCESS_ATTACH`, the reason a TLS callback and `DllMain` receive at +/// process start. +const DLL_PROCESS_ATTACH: u32 = 1; + /// Everything that bounds a run. /// /// This is the sandbox's contract. The emulator follows control flow supplied @@ -218,32 +253,39 @@ pub fn unpack(file: &[u8], limits: &EmuLimits) -> Report { let _ = env.bind_imports(&mut mem, image.base, dir_rva, dir_size); let mut cpu = Cpu::new(); - cpu.eip = image.base.wrapping_add(image.entry_rva); - cpu.regs[ESP] = INITIAL_ESP; cpu.fs_base = TEB_BASE; - // What a thread sees at the entry point on Windows: EBX holds the PEB, and - // the return address is into kernel32. - cpu.regs[EBX] = crate::win::PEB_BASE; let process_return = env.process_return(); let seh_return = env.seh_return(); - // A DLL is entered as `DllMain(hinstDLL, DLL_PROCESS_ATTACH, NULL)`. Those - // three arguments have to be on the stack: a packed DLL's stub reads them, - // and without them it faults on its first instruction. - let pushed = if image.is_dll { - cpu.push32(&mut mem, 0) - .and_then(|()| cpu.push32(&mut mem, 1)) - .and_then(|()| cpu.push32(&mut mem, image.base)) - .and_then(|()| cpu.push32(&mut mem, process_return)) - } else { - cpu.push32(&mut mem, process_return) + let tls_return = env.tls_return(); + let image_end = image.base.saturating_add(image.size_of_image); + + // The loader runs TLS callbacks before the entry point. Set the static TLS + // block up and queue the callbacks; if there are none, start at the entry + // point straight away. `tls_cb_array` is the VA of the callback array, re- + // read before each call because a callback can grow it. + let tls_cb_array = setup_tls(&image, &mut env, &mut mem); + let mut tls_next: u32 = 0; + let mut tls_calls: u32 = 0; + let mut in_tls = false; + // Per-callback slice of the budget; a callback that outruns it is abandoned. + let tls_callback_budget = limits.max_ticks / TLS_CALLBACK_BUDGET_DIVISOR; + let mut tls_deadline: u64 = tls_callback_budget; + + let start_ok = match tls_cb_array.and_then(|a| next_tls_callback(&mut mem, a, 0, &image)) { + Some(cb) => { + in_tls = true; + tls_next = 1; + tls_calls = 1; + enter_tls_callback(&mut cpu, &mut mem, cb, image.base, tls_return).is_ok() + } + None => start_entry(&mut cpu, &mut mem, &image, process_return).is_ok(), }; - if pushed.is_err() { + if !start_ok { report.stop = "stack is not mapped".to_string(); return report; } let stub_section = image.section_of(image.entry_rva); - let image_end = image.base.saturating_add(image.size_of_image); let mut seh = SehState { seh_return, @@ -275,8 +317,49 @@ pub fn unpack(file: &[u8], limits: &EmuLimits) -> Report { } progress_deadline = ticks + PROGRESS_WINDOW; } + // A TLS callback that outran its slice of the budget. Abandon the rest + // of the TLS phase and start the entry point with what it produced. + if in_tls && ticks >= tls_deadline { + in_tls = false; + if start_entry(&mut cpu, &mut mem, &image, process_return).is_err() { + stop_reason = "stack is not mapped".to_string(); + break; + } + continue; + } let eip = cpu.eip; + if in_tls && eip == tls_return { + ticks += 1; + // A callback returned. The loader re-reads the array because a + // callback may have appended to it; take the next entry if there is + // one and the count cap allows, otherwise the TLS phase is done. + let next = if tls_calls < MAX_TLS_CALLBACKS { + tls_cb_array.and_then(|a| next_tls_callback(&mut mem, a, tls_next, &image)) + } else { + None + }; + match next { + Some(cb) => { + tls_next += 1; + tls_calls += 1; + tls_deadline = ticks + tls_callback_budget; + if enter_tls_callback(&mut cpu, &mut mem, cb, image.base, tls_return).is_err() { + stop_reason = "stack is not mapped".to_string(); + break; + } + } + None => { + in_tls = false; + if start_entry(&mut cpu, &mut mem, &image, process_return).is_err() { + stop_reason = "stack is not mapped".to_string(); + break; + } + } + } + continue; + } + if eip == process_return { stop_reason = "the stub returned to the loader".to_string(); break; @@ -509,6 +592,123 @@ pub fn unpack(file: &[u8], limits: &EmuLimits) -> Report { report } +/// Point the CPU at the entry point with the stack a thread starts with: EBX at +/// the PEB, and a return address (plus `DllMain`'s three arguments for a DLL). +fn start_entry( + cpu: &mut Cpu, + mem: &mut Mem, + image: &PeImage, + process_return: u32, +) -> Result<(), ()> { + cpu.eip = image.base.wrapping_add(image.entry_rva); + cpu.regs[ESP] = INITIAL_ESP; + cpu.regs[EBX] = crate::win::PEB_BASE; + // A DLL is entered as `DllMain(hinstDLL, DLL_PROCESS_ATTACH, NULL)`. Those + // three arguments have to be on the stack: a packed DLL's stub reads them, + // and without them it faults on its first instruction. + let pushed = if image.is_dll { + cpu.push32(mem, 0) + .and_then(|()| cpu.push32(mem, DLL_PROCESS_ATTACH)) + .and_then(|()| cpu.push32(mem, image.base)) + .and_then(|()| cpu.push32(mem, process_return)) + } else { + cpu.push32(mem, process_return) + }; + pushed.map_err(|_| ()) +} + +/// Enter a TLS callback as `cb(image_base, DLL_PROCESS_ATTACH, 0)`, returning to +/// `tls_return` so the driver can run the next one. +fn enter_tls_callback( + cpu: &mut Cpu, + mem: &mut Mem, + callback: u32, + image_base: u32, + tls_return: u32, +) -> Result<(), ()> { + cpu.regs[ESP] = INITIAL_ESP; + cpu.push32(mem, 0) // reserved + .and_then(|()| cpu.push32(mem, DLL_PROCESS_ATTACH)) + .and_then(|()| cpu.push32(mem, image_base)) + .and_then(|()| cpu.push32(mem, tls_return)) + .map_err(|_| ())?; + cpu.eip = callback; + Ok(()) +} + +/// Set up the static TLS block and return the VA of the callback array, or +/// `None` when the directory is absent, malformed, or points outside the image. +/// +/// The `IMAGE_TLS_DIRECTORY32` fields are virtual addresses (the image is mapped +/// at its preferred base, so a VA is `base + RVA`). Every one is bounds-checked +/// against the mapped image before it is dereferenced, since a packed file's TLS +/// directory is attacker-controlled. +fn setup_tls(image: &PeImage, env: &mut Env, mem: &mut Mem) -> Option { + let (rva, size) = image.tls_dir; + if rva == 0 || size < 0x18 { + return None; + } + let image_end = image.base.saturating_add(image.size_of_image); + let in_image = |va: u32| va >= image.base && va < image_end; + let td = image.base.wrapping_add(rva); + if !in_image(td) || !mem.is_mapped(td, 0x18) { + return None; + } + let raw_start = mem.read_u32(td).ok()?; + let raw_end = mem.read_u32(td + 4).ok()?; + let index_va = mem.read_u32(td + 8).ok()?; + let cb_array = mem.read_u32(td + 12).ok()?; + let zero_fill = mem.read_u32(td + 16).ok()?; + + // The static TLS template: the raw data, then the zero fill. A directory + // whose raw range is backwards or outside the image contributes no data; + // the block is still created so `AddressOfIndex` and the TEB are wired up. + let mut template = Vec::new(); + if raw_end > raw_start && in_image(raw_start) && in_image(raw_end) { + let len = (raw_end - raw_start).min(MAX_TLS_BLOCK); + if mem.is_mapped(raw_start, len) { + template = mem.snapshot(raw_start, len as usize); + } + } + let total = (template.len() as u32) + .saturating_add(zero_fill) + .min(MAX_TLS_BLOCK); + template.resize(total as usize, 0); + + // `AddressOfIndex` must be writable storage inside the image; a directory + // that points it elsewhere gets no index written, matching a loader that + // would fault and abandon the module rather than scribble out of bounds. + let index_va = if index_va != 0 && in_image(index_va) && mem.is_mapped(index_va, 4) { + index_va + } else { + 0 + }; + env.install_static_tls(mem, &template, 0, index_va).ok()??; + + if cb_array != 0 && in_image(cb_array) && mem.is_mapped(cb_array, 4) { + Some(cb_array) + } else { + None + } +} + +/// The `idx`-th callback in the array at `cb_array`, if it is present, non-null +/// and points into the image. Re-read every time because a callback can extend +/// the array. +fn next_tls_callback(mem: &mut Mem, cb_array: u32, idx: u32, image: &PeImage) -> Option { + let slot = cb_array.wrapping_add(idx.wrapping_mul(4)); + if !mem.is_mapped(slot, 4) { + return None; + } + let cb = mem.read_u32(slot).ok()?; + let image_end = image.base.saturating_add(image.size_of_image); + if cb != 0 && cb >= image.base && cb < image_end { + Some(cb) + } else { + None + } +} + /// Whether the section execution just entered was *rebuilt* rather than merely /// touched. /// diff --git a/crates/exav-pe-emu/src/win.rs b/crates/exav-pe-emu/src/win.rs index 4e68ee8..acb4935 100644 --- a/crates/exav-pe-emu/src/win.rs +++ b/crates/exav-pe-emu/src/win.rs @@ -60,15 +60,35 @@ const ENV_BASE: u32 = 0x0009_0000; const HEAP_BASE: u32 = 0x0100_0000; const HEAP_LIMIT: u32 = 0x6000_0000; -/// Address space each synthetic DLL occupies. The first 0x4000 bytes hold the -/// headers and export directory; the rest is the trap range its exports point -/// into. -const MODULE_SIZE: u32 = 0x0001_0000; -const TRAP_OFFSET: u32 = 0x4000; +/// Address space each synthetic DLL occupies. The headers and export directory +/// live below `TRAP_OFFSET`; the trap range its exports point into runs from +/// there. The region is large because a synthetic DLL advertises the real one's +/// documented export names (over a thousand for `kernel32`), so a stub that +/// resolves imports by hashing export names finds what it looks for. +const MODULE_SIZE: u32 = 0x0004_0000; +const TRAP_OFFSET: u32 = 0x0001_8000; const TRAP_STRIDE: u32 = 0x10; -/// Offset within `kernel32` that the emulator's two return sentinels sit at: -/// past the trap range, still inside the module image. -const RETURN_OFFSET: u32 = 0xc000; +/// Offset within `kernel32` that the emulator's return sentinels sit at: past +/// the trap range, still inside the module image. +const RETURN_OFFSET: u32 = 0x0003_f000; + +/// Largest export directory, in bytes, a synthetic module may build below its +/// trap range. Bounds the per-module name set so the directory cannot grow into +/// the traps. +const MAX_EXPORT_DIR: u32 = TRAP_OFFSET - 0x1000; + +/// The documented export-name set each synthetic system DLL advertises, beyond +/// the handful the emulator implements. Names only, extracted from Microsoft's +/// API documentation by `scripts/gen-exports.py` (provenance and licence in +/// this crate's NOTICE). Undocumented exports are not in it. A name here with +/// no implementation resolves to a trap that reports itself and returns +/// failure, never to undefined behaviour. +const EXTRA_EXPORTS: &[(&str, &str)] = &[ + ("kernel32.dll", include_str!("exports/kernel32.txt")), + ("ntdll.dll", include_str!("exports/ntdll.txt")), + ("user32.dll", include_str!("exports/user32.txt")), + ("advapi32.dll", include_str!("exports/advapi32.txt")), +]; /// Handle values with fixed meanings on Windows. const INVALID_HANDLE: u32 = 0xffff_ffff; @@ -162,6 +182,9 @@ enum Api { WriteFile, SetFilePointer, GetFileSize, + GetFileAttributesEx { + wide: bool, + }, CreateFileMapping, MapViewOfFile, GetStdHandle, @@ -484,6 +507,16 @@ const APIS: &[ApiSpec] = &[ k("CreateDirectoryW", 2, Api::Const(0)), k("GetFileAttributesA", 1, Api::Const(0xffff_ffff)), k("GetFileAttributesW", 1, Api::Const(0xffff_ffff)), + k( + "GetFileAttributesExA", + 3, + Api::GetFileAttributesEx { wide: false }, + ), + k( + "GetFileAttributesExW", + 3, + Api::GetFileAttributesEx { wide: true }, + ), k("SetFileAttributesA", 2, Api::Const(0)), k("CopyFileA", 3, Api::Const(0)), k("MoveFileA", 2, Api::Const(0)), @@ -846,6 +879,45 @@ impl<'a> Env<'a> { self.kernel32_base() + RETURN_OFFSET + 0x10 } + /// Return address a TLS callback returns to, so the driver runs the next + /// one. A distinct sentinel from `process_return` because a callback + /// returning is not the stub returning to the loader. + pub fn tls_return(&self) -> u32 { + self.kernel32_base() + RETURN_OFFSET + 0x20 + } + + /// Set up the static TLS block the way the loader does before a TLS + /// callback runs: a copy of the module's TLS template (raw data plus zero + /// fill), the TEB's `ThreadLocalStoragePointer` pointing at a one-slot array + /// that holds it, and the assigned index written to `*index_va`. + /// + /// Returns the block's base, or `None` when the allocation does not fit. + pub fn install_static_tls( + &mut self, + mem: &mut Mem, + template: &[u8], + index: u32, + index_va: u32, + ) -> Result, Stop> { + let block = self.alloc(mem, 0, (template.len() as u32).max(1)); + if block == 0 { + return Ok(None); + } + mem.write_bytes(block, template).map_err(Stop::Fault)?; + let array = self.alloc(mem, 0, (index + 1) * 4); + if array == 0 { + return Ok(None); + } + mem.write_u32(array + index * 4, block) + .map_err(Stop::Fault)?; + // TEB.ThreadLocalStoragePointer is at offset 0x2C on x86 [pe][dbg]. + mem.write_u32(TEB_BASE + 0x2c, array).map_err(Stop::Fault)?; + if index_va != 0 { + mem.write_u32(index_va, index).map_err(Stop::Fault)?; + } + Ok(Some(block)) + } + fn kernel32_base(&self) -> u32 { self.find_module_by_name("kernel32.dll") .map(|m| m.base) @@ -861,18 +933,67 @@ impl<'a> Env<'a> { self.modules.iter().find(|m| m.name == want) } - /// Create a synthetic DLL: PE headers, an export directory naming every API - /// the emulator implements for it, and one trap address per export. + /// The sorted export set a synthetic module advertises: every API the + /// emulator implements for it, plus the real DLL's other documented export + /// names, bounded so the directory stays below the trap range. + /// + /// The list is sorted by name, because Windows keeps the export name table + /// sorted and hand-written resolvers binary-search it. Implemented exports + /// are never dropped by the size bound; only extra names are. + fn module_exports(&self, name: &str) -> Vec<(&'static str, Option, u8)> { + let mut implemented: Vec<(&'static str, Option, u8)> = APIS + .iter() + .filter(|s| s.module == name) + .map(|s| (s.name, Some(s.api), s.argc)) + .collect(); + + // Running size of the export directory below RVA 0x1000: the three + // parallel arrays (10 bytes an entry) plus the name strings, plus the + // module's own name string. Kept under `MAX_EXPORT_DIR`. + let mut used = 40u32 + export_dir_name(name).len() as u32 + 1; + let entry_cost = |s: &str| 10 + s.len() as u32 + 1; + for (ename, ..) in &implemented { + used += entry_cost(ename); + } + + if let Some((_, list)) = EXTRA_EXPORTS.iter().find(|(m, _)| *m == name) { + let known: std::collections::HashSet<&str> = + implemented.iter().map(|(n, ..)| *n).collect(); + for ename in list.lines().map(str::trim).filter(|l| !l.is_empty()) { + if known.contains(ename) { + continue; + } + let cost = entry_cost(ename); + if used + cost > MAX_EXPORT_DIR { + break; + } + used += cost; + // A name this module exports but the emulator implements under + // another module (a forwarder) resolves to that implementation, + // as `export_addr` does by name across modules. Only a name no + // module implements becomes an unimplemented trap. + let spec = APIS.iter().find(|s| s.name == ename); + implemented.push(( + ename, + spec.map(|s| s.api), + spec.map(|s| s.argc).unwrap_or(0), + )); + } + } + implemented.sort_by(|a, b| a.0.cmp(b.0)); + implemented + } + + /// Create a synthetic DLL: PE headers and an export directory. The directory + /// names every API the emulator implements for the module *and* the real + /// DLL's other documented exports (names only), so a stub that resolves imports by + /// hashing export names finds what it looks for. Each export points at a + /// trap; an unimplemented one's trap reports itself and returns failure when + /// called, never undefined behaviour. fn create_module(&mut self, mem: &mut Mem, name: &str, base: u32) -> Result<(), Stop> { map(mem, base, MODULE_SIZE)?; let name = normalize_module(name); - let exports: Vec<&ApiSpec> = { - let mut v: Vec<&ApiSpec> = APIS.iter().filter(|s| s.module == name).collect(); - // Windows keeps the export name table sorted, and hand-written - // resolvers binary-search it. - v.sort_by_key(|s| s.name); - v - }; + let exports = self.module_exports(&name); let mut trap = base + TRAP_OFFSET; // Export directory at RVA 0x1000, arrays and strings after it. @@ -887,11 +1008,7 @@ impl<'a> Env<'a> { ed.extend_from_slice(&0u32.to_le_bytes()); // Characteristics ed.extend_from_slice(&0u32.to_le_bytes()); // TimeDateStamp ed.extend_from_slice(&0u32.to_le_bytes()); // Major/Minor version - ed.extend_from_slice(&strings_rva.to_le_bytes()); // Name (points at the - // first string, which - // is close enough for - // a resolver that - // only reads exports) + ed.extend_from_slice(&0u32.to_le_bytes()); // Name, patched below ed.extend_from_slice(&1u32.to_le_bytes()); // Base ordinal ed.extend_from_slice(&n.to_le_bytes()); // NumberOfFunctions ed.extend_from_slice(&n.to_le_bytes()); // NumberOfNames @@ -901,7 +1018,7 @@ impl<'a> Env<'a> { mem.write_bytes(base + ed_rva, &ed).map_err(Stop::Fault)?; let mut str_rva = strings_rva; - for (i, spec) in exports.iter().enumerate() { + for (i, (ename, api, argc)) in exports.iter().enumerate() { let i = i as u32; mem.write_u32(base + funcs_rva + i * 4, trap - base) .map_err(Stop::Fault)?; @@ -909,19 +1026,27 @@ impl<'a> Env<'a> { .map_err(Stop::Fault)?; mem.write_u16(base + ords_rva + i * 2, i as u16) .map_err(Stop::Fault)?; - write_c_str(mem, base + str_rva, spec.name)?; - str_rva += spec.name.len() as u32 + 1; + write_c_str(mem, base + str_rva, ename)?; + str_rva += ename.len() as u32 + 1; self.traps.insert( trap, Trap { - api: Some(spec.api), - argc: spec.argc, + api: *api, + argc: *argc, module: name.clone(), - name: spec.name.to_string(), + name: ename.to_string(), }, ); trap += TRAP_STRIDE; } + // The DLL's own name, spelled as the real export directory spells it. + // tElock reads it to check that the module it found is `KERNEL32` and + // spins forever when it is not. + let export_name = export_dir_name(&name); + write_c_str(mem, base + str_rva, &export_name)?; + mem.write_u32(base + ed_rva + 12, str_rva) + .map_err(Stop::Fault)?; + str_rva += export_name.len() as u32 + 1; write_module_headers(mem, base, MODULE_SIZE, ed_rva, str_rva - ed_rva)?; self.modules.push(Module { @@ -933,23 +1058,34 @@ impl<'a> Env<'a> { Ok(()) } + // Where each layout fact below comes from (pinned sources in the NOTICE): + // [pe] Microsoft PE Format specification, "The .tls Section". + // [dbg] Microsoft debugger documentation: `dt` output on 32-bit Windows. + // [wtl] Microsoft winternl.h reference; x86 offsets follow from the + // documented member types. + // [kus] Microsoft WDK reference for KUSER_SHARED_DATA, which gives the + // field order but not every type, so not the offsets. + // [obs] Not given by those sources. Each is observable on 32-bit Windows + // by comparing the field with the API that reports the same value + // (listed in the NOTICE); kept on that basis. + /// Fill `KUSER_SHARED_DATA` with the handful of fields a stub reads: the /// interrupt/tick counters (used for timing checks) and the OS version. fn build_shared_user_data(&self, mem: &mut Mem) -> Result<(), Stop> { map(mem, SHARED_USER_DATA, PAGE_SIZE as u32)?; mem.write_u32(SHARED_USER_DATA, 0x0010_0000) - .map_err(Stop::Fault)?; // TickCountLow + .map_err(Stop::Fault)?; // TickCountLowDeprecated [kus][obs] mem.write_u32(SHARED_USER_DATA + 0x04, 0x000f_a000) - .map_err(Stop::Fault)?; // TickCountMultiplier + .map_err(Stop::Fault)?; // TickCountMultiplier [kus][obs] mem.write_u32(SHARED_USER_DATA + 0x08, 0x0010_0000) - .map_err(Stop::Fault)?; // InterruptTime.LowPart + .map_err(Stop::Fault)?; // InterruptTime, low part [kus][obs] mem.write_u32(SHARED_USER_DATA + 0x14, 0x1000_0000) - .map_err(Stop::Fault)?; // SystemTime.LowPart - write_utf16(mem, SHARED_USER_DATA + 0x30, "C:\\WINDOWS")?; // NtSystemRoot + .map_err(Stop::Fault)?; // SystemTime, low part [kus][obs] + write_utf16(mem, SHARED_USER_DATA + 0x30, "C:\\WINDOWS")?; // NtSystemRoot [kus][obs] mem.write_u32(SHARED_USER_DATA + 0x26c, 5) - .map_err(Stop::Fault)?; // NtMajorVersion + .map_err(Stop::Fault)?; // NtMajorVersion [kus][obs] mem.write_u32(SHARED_USER_DATA + 0x270, 1) - .map_err(Stop::Fault)?; // NtMinorVersion + .map_err(Stop::Fault)?; // NtMinorVersion [kus][obs] Ok(()) } @@ -963,35 +1099,36 @@ impl<'a> Env<'a> { map(mem, TEB_BASE, PAGE_SIZE as u32)?; map(mem, PEB_BASE, PAGE_SIZE as u32)?; - // TEB. - mem.write_u32(TEB_BASE, 0xffff_ffff).map_err(Stop::Fault)?; // ExceptionList: chain end + // TEB. NtTib (an NT_TIB) is at 0x00 [dbg]; its members' order is + // consistent with the [dbg] `dd` example, and is [obs]. + mem.write_u32(TEB_BASE, 0xffff_ffff).map_err(Stop::Fault)?; // NtTib.ExceptionList: chain end [obs] mem.write_u32(TEB_BASE + 0x04, STACK_TOP) - .map_err(Stop::Fault)?; // StackBase + .map_err(Stop::Fault)?; // NtTib.StackBase [obs] mem.write_u32(TEB_BASE + 0x08, STACK_BASE) - .map_err(Stop::Fault)?; // StackLimit + .map_err(Stop::Fault)?; // NtTib.StackLimit [obs] mem.write_u32(TEB_BASE + 0x18, TEB_BASE) - .map_err(Stop::Fault)?; // Self + .map_err(Stop::Fault)?; // NtTib.Self [obs] mem.write_u32(TEB_BASE + 0x20, 0x0000_0abc) - .map_err(Stop::Fault)?; // ProcessId + .map_err(Stop::Fault)?; // ClientId.UniqueProcess: ClientId at 0x20 [dbg], member order [obs] mem.write_u32(TEB_BASE + 0x24, 0x0000_0def) - .map_err(Stop::Fault)?; // ThreadId + .map_err(Stop::Fault)?; // ClientId.UniqueThread [obs] mem.write_u32(TEB_BASE + 0x30, PEB_BASE) - .map_err(Stop::Fault)?; // PEB + .map_err(Stop::Fault)?; // ProcessEnvironmentBlock [dbg] // PEB. `BeingDebugged` and `NtGlobalFlag` are the two fields anti-debug // stubs read directly, and both say "no debugger". mem.write_u32(PEB_BASE + 0x08, image_base) - .map_err(Stop::Fault)?; // ImageBaseAddress + .map_err(Stop::Fault)?; // ImageBaseAddress [obs] mem.write_u32(PEB_BASE + 0x0c, LDR_BASE) - .map_err(Stop::Fault)?; // Ldr + .map_err(Stop::Fault)?; // Ldr [dbg] mem.write_u32(PEB_BASE + 0x18, PROCESS_HEAP) - .map_err(Stop::Fault)?; // ProcessHeap - mem.write_u32(PEB_BASE + 0x64, 1).map_err(Stop::Fault)?; // NumberOfProcessors - mem.write_u32(PEB_BASE + 0x68, 0).map_err(Stop::Fault)?; // NtGlobalFlag - mem.write_u32(PEB_BASE + 0xa4, 5).map_err(Stop::Fault)?; // OSMajorVersion - mem.write_u32(PEB_BASE + 0xa8, 1).map_err(Stop::Fault)?; // OSMinorVersion - mem.write_u32(PEB_BASE + 0xac, 2600).map_err(Stop::Fault)?; // OSBuildNumber - mem.write_u32(PEB_BASE + 0xb0, 2).map_err(Stop::Fault)?; // PlatformId + .map_err(Stop::Fault)?; // ProcessHeap [obs] + mem.write_u32(PEB_BASE + 0x64, 1).map_err(Stop::Fault)?; // NumberOfProcessors [obs] + mem.write_u32(PEB_BASE + 0x68, 0).map_err(Stop::Fault)?; // NtGlobalFlag [obs] + mem.write_u32(PEB_BASE + 0xa4, 5).map_err(Stop::Fault)?; // OSMajorVersion [obs] + mem.write_u32(PEB_BASE + 0xa8, 1).map_err(Stop::Fault)?; // OSMinorVersion [obs] + mem.write_u32(PEB_BASE + 0xac, 2600).map_err(Stop::Fault)?; // OSBuildNumber [obs] + mem.write_u32(PEB_BASE + 0xb0, 2).map_err(Stop::Fault)?; // OSPlatformId [obs] // PEB_LDR_DATA followed by one LDR_DATA_TABLE_ENTRY per module. The // executable itself comes first in load and memory order, but not in @@ -1027,8 +1164,10 @@ impl<'a> Env<'a> { let mem_head = ldr + 0x14; let init_head = ldr + 0x1c; - mem.write_u32(ldr, 0x28).map_err(Stop::Fault)?; // Length - mem.write_u32(ldr + 4, 1).map_err(Stop::Fault)?; // Initialized + // PEB_LDR_DATA: Length (0x28), Initialized, and the three list heads at + // 0x0c / 0x14 / 0x1c [dbg]. + mem.write_u32(ldr, 0x28).map_err(Stop::Fault)?; // Length [dbg] + mem.write_u32(ldr + 4, 1).map_err(Stop::Fault)?; // Initialized [dbg] let init_idx: Vec = (0..list.len()).filter(|&i| list[i].in_init).collect(); let all_idx: Vec = (0..list.len()).collect(); @@ -1053,17 +1192,23 @@ impl<'a> Env<'a> { mem.write_u32(head + 4, last).map_err(Stop::Fault)?; Ok(()) }; + // LDR_DATA_TABLE_ENTRY links. InMemoryOrderLinks at 0x08 [wtl]. The + // load-order links at 0x00 follow from the [dbg] example, where the two + // lists' heads point 8 bytes apart into the same entry. The + // initialisation-order links fill the documented reserved slot at 0x10 + // [wtl], their meaning [obs]. link(mem, load_head, 0x00, &all_idx)?; link(mem, mem_head, 0x08, &all_idx)?; link(mem, init_head, 0x10, &init_idx)?; for (i, l) in list.iter().enumerate() { let e = addr_of(i); - mem.write_u32(e + 0x18, l.base).map_err(Stop::Fault)?; // DllBase - mem.write_u32(e + 0x1c, l.base).map_err(Stop::Fault)?; // EntryPoint - mem.write_u32(e + 0x20, l.size).map_err(Stop::Fault)?; // SizeOfImage - // FullDllName / BaseDllName as UNICODE_STRINGs pointing into the - // string area after the entries. + mem.write_u32(e + 0x18, l.base).map_err(Stop::Fault)?; // DllBase [wtl] + mem.write_u32(e + 0x1c, l.base).map_err(Stop::Fault)?; // EntryPoint: reserved slot [wtl], meaning [obs] + mem.write_u32(e + 0x20, l.size).map_err(Stop::Fault)?; // SizeOfImage: reserved slot [wtl], meaning [obs] + // FullDllName at 0x24 [wtl] and BaseDllName at 0x2c (reserved slot + // [wtl], meaning [obs]), as UNICODE_STRINGs into the string area + // after the entries. let str_addr = entry0 + list.len() as u32 * ENTRY_SIZE + i as u32 * 0x80; let wide: Vec = l .name @@ -1518,6 +1663,28 @@ impl<'a> Env<'a> { } self.file.len() as u32 } + Api::GetFileAttributesEx { wide } => { + // The program's own file exists and reports a size; every other + // path is absent, as with `CreateFile`. A stub that stats itself + // before unpacking (Alienyze does) needs the success answer, not + // the "file not found" that stops it. + let p = arg(cpu, mem, 0)?; + let path = read_str(mem, p, wide)?; + let out = arg(cpu, mem, 2)?; + if self.is_own_path(&path) && out != 0 { + // WIN32_FILE_ATTRIBUTE_DATA: attributes, three FILETIMEs, + // then the 64-bit size. Only the attributes and size carry + // information a stub acts on. + let mut data = [0u8; 0x24]; + data[0..4].copy_from_slice(&0x80u32.to_le_bytes()); // FILE_ATTRIBUTE_NORMAL + data[0x20..0x24].copy_from_slice(&(self.file.len() as u32).to_le_bytes()); + mem.write_bytes(out, &data).map_err(Stop::Fault)?; + 1 + } else { + self.last_error = 2; // ERROR_FILE_NOT_FOUND + 0 + } + } Api::CreateFileMapping => { let h = arg(cpu, mem, 0)?; if self.open_files.contains_key(&h) { @@ -1930,6 +2097,18 @@ fn normalize_module(name: &str) -> String { } } +/// The name a DLL's export directory gives itself: `KERNEL32.dll`, `ntdll.dll`. +/// Most system DLLs spell the stem in capitals; `ntdll` and `msvcrt` do not. +fn export_dir_name(normalized: &str) -> String { + if matches!(normalized, "ntdll.dll" | "msvcrt.dll") { + return normalized.to_string(); + } + match normalized.rsplit_once('.') { + Some((stem, ext)) => format!("{}.{ext}", stem.to_ascii_uppercase()), + None => normalized.to_ascii_uppercase(), + } +} + fn write_utf16(mem: &mut Mem, addr: u32, s: &str) -> Result<(), Stop> { let b: Vec = s .encode_utf16() @@ -2092,6 +2271,23 @@ mod tests { ); } + #[test] + fn a_synthetic_dll_names_itself_as_the_real_one_does() { + // The export directory's Name field is `KERNEL32.dll`, not the lower- + // case internal name. A stub that walks the loader list and checks the + // export name (tElock does, and spins when it does not match) has to see + // what a real module shows. + let (mut mem, _env) = env(); + for (base, want) in [(0x7c80_0000u32, "KERNEL32.dll"), (0x7c90_0000, "ntdll.dll")] { + let e_lfanew = mem.read_u32(base + 0x3c).unwrap(); + let dd = base + e_lfanew + 24 + 96; + let ed = base + mem.read_u32(dd).unwrap(); + let name_va = base + mem.read_u32(ed + 12).unwrap(); + let name = read_str(&mut mem, name_va, false).unwrap(); + assert_eq!(name, want); + } + } + /// A block copy reports the volume it moved, so the driver can charge for it. /// /// The tick budget bounds instructions executed, which stands in for work @@ -2264,6 +2460,84 @@ mod tests { assert!(env.is_trap(cpu.regs[EAX])); } + #[test] + fn the_export_directory_advertises_the_real_dll_names_not_just_implemented() { + // A stub that resolves imports by hashing export names walks the name + // table itself. The synthetic kernel32 therefore advertises the real + // DLL's exports, not only the handful the emulator implements, so such a + // walk finds its function. Alienyze fails exactly this way otherwise. + let (mut mem, mut env) = env(); + let base = 0x7c80_0000u32; + let e_lfanew = mem.read_u32(base + 0x3c).unwrap(); + let ed = base + mem.read_u32(base + e_lfanew + 24 + 96).unwrap(); + let n_names = mem.read_u32(ed + 24).unwrap(); + let names = base + mem.read_u32(ed + 32).unwrap(); + let funcs = base + mem.read_u32(ed + 28).unwrap(); + // `GetVolumeInformationA` is a real kernel32 export the emulator does not + // implement. It must still be in the directory, and resolve to a trap. + let mut found = None; + for i in 0..n_names { + let p = base + mem.read_u32(names + i * 4).unwrap(); + if read_str(&mut mem, p, false).unwrap() == "GetVolumeInformationA" { + found = Some(base + mem.read_u32(funcs + i * 4).unwrap()); + } + } + let addr = found.expect("an unimplemented real export is still advertised"); + assert!( + env.is_trap(addr), + "it resolves to a trap the driver services" + ); + + // Calling it is safe and observable: it returns failure and is recorded, + // never undefined behaviour. + let mut cpu = Cpu::new(); + cpu.regs[ESP] = INITIAL_ESP; + cpu.push32(&mut mem, 0xdead_0000).unwrap(); // return address + cpu.eip = addr; + let effect = env.call(&mut cpu, &mut mem).unwrap(); + assert_eq!(effect, ApiEffect::Unimplemented); + assert_eq!(cpu.regs[EAX], 0); + assert!(env + .missing_apis + .iter() + .any(|m| m.ends_with("GetVolumeInformationA"))); + } + + #[test] + fn get_file_attributes_ex_reports_the_program_exists_with_its_size() { + // The program's own file exists and reports its size; a stub that stats + // itself before unpacking (Alienyze does) needs the success answer, not + // the "not found" that stops it. Every other path is absent. + let mut mem = Mem::new(4096); + mem.map(0x0040_0000, 0x1000).unwrap(); + let file: &[u8] = &vec![0u8; 0x1234]; + let mut env = Env::new(&mut mem, 0x0040_0000, 0x1_0000, file).unwrap(); + + let name = 0x0050_0000u32; + let out = 0x0051_0000u32; + mem.map(name, 0x1000).unwrap(); + mem.map(out, 0x1000).unwrap(); + mem.write_bytes(name, b"C:\\sample.exe\0").unwrap(); + // GetFileAttributesExA(lpFileName, GetFileExInfoStandard, out). + assert_eq!( + call_k32(&mut env, &mut mem, "GetFileAttributesExA", &[name, 0, out]), + 1 + ); + assert_eq!(mem.read_u32(out).unwrap(), 0x80, "FILE_ATTRIBUTE_NORMAL"); + assert_eq!( + mem.read_u32(out + 0x20).unwrap(), + 0x1234, + "nFileSizeLow is the file length" + ); + + mem.write_bytes(name, b"C:\\other.exe\0").unwrap(); + assert_eq!( + call_k32(&mut env, &mut mem, "GetFileAttributesExA", &[name, 0, out]), + 0, + "a path that is not the program does not exist" + ); + } + #[test] fn loadlibrary_of_an_unknown_dll_creates_a_module() { let (mut mem, mut env) = env(); diff --git a/crates/exav-pe-emu/tests/end_to_end.rs b/crates/exav-pe-emu/tests/end_to_end.rs new file mode 100644 index 0000000..79fdcd9 --- /dev/null +++ b/crates/exav-pe-emu/tests/end_to_end.rs @@ -0,0 +1,249 @@ +//! End-to-end tests a consumer of the crate can run: build a PE in memory, run +//! its stub through [`exav_pe_emu::unpack`], and check the image that comes out. +//! +//! The fixtures are assembled here rather than committed as binaries, so nothing +//! third-party or packed is checked in. [`pe`] is the generator: a minimal but +//! real PE32 with the sections, entry point and (optionally) TLS directory each +//! test needs. + +use exav_pe_emu::{unpack, EmuLimits}; + +/// A minimal PE32 builder. The image has two sections, `.text` (the empty +/// destination a stub fills) at RVA 0x1000 and `.pack` (the stub's own bytes) +/// at RVA 0x2000, mapped at base 0x400000. The caller supplies `.pack`'s raw +/// bytes, the entry RVA, and an optional TLS directory RVA. +mod pe { + pub const BASE: u32 = 0x0040_0000; + pub const TEXT_RVA: u32 = 0x1000; + pub const PACK_RVA: u32 = 0x2000; + + pub struct Pe { + pub entry_rva: u32, + pub pack: Vec, + pub tls_dir_rva: Option, + } + + impl Pe { + pub fn build(&self) -> Vec { + let pe_off = 0x80usize; + let opt_size = 0xe0usize; + let sec_table = pe_off + 24 + opt_size; + let num = 2usize; + let headers = 0x400usize; + let pack_raw = headers; + let pack_len = self.pack.len().max(0x200); + let mut d = vec![0u8; pack_raw + pack_len]; + + d[..2].copy_from_slice(b"MZ"); + d[0x3c..0x40].copy_from_slice(&(pe_off as u32).to_le_bytes()); + d[pe_off..pe_off + 4].copy_from_slice(b"PE\0\0"); + let coff = pe_off + 4; + d[coff..coff + 2].copy_from_slice(&0x14cu16.to_le_bytes()); // i386 + d[coff + 2..coff + 4].copy_from_slice(&(num as u16).to_le_bytes()); + d[coff + 16..coff + 18].copy_from_slice(&(opt_size as u16).to_le_bytes()); + + let opt = coff + 20; + d[opt..opt + 2].copy_from_slice(&0x10bu16.to_le_bytes()); // PE32 + d[opt + 16..opt + 20].copy_from_slice(&self.entry_rva.to_le_bytes()); + d[opt + 28..opt + 32].copy_from_slice(&BASE.to_le_bytes()); + d[opt + 32..opt + 36].copy_from_slice(&0x1000u32.to_le_bytes()); // SectionAlignment + d[opt + 36..opt + 40].copy_from_slice(&0x200u32.to_le_bytes()); // FileAlignment + d[opt + 56..opt + 60].copy_from_slice(&0x3000u32.to_le_bytes()); // SizeOfImage + d[opt + 60..opt + 64].copy_from_slice(&0x400u32.to_le_bytes()); // SizeOfHeaders + // 16 data directories, so the TLS slot (9) is present. + d[opt + 92..opt + 96].copy_from_slice(&16u32.to_le_bytes()); + if let Some(tls_rva) = self.tls_dir_rva { + let dd = opt + 96 + 9 * 8; // data directory 9 + d[dd..dd + 4].copy_from_slice(&tls_rva.to_le_bytes()); + d[dd + 4..dd + 8].copy_from_slice(&0x18u32.to_le_bytes()); + } + + // Section 0: `.text`, the empty destination (no raw data). + let s0 = sec_table; + d[s0..s0 + 5].copy_from_slice(b".text"); + d[s0 + 8..s0 + 12].copy_from_slice(&0x1000u32.to_le_bytes()); // VirtualSize + d[s0 + 12..s0 + 16].copy_from_slice(&TEXT_RVA.to_le_bytes()); + d[s0 + 36..s0 + 40].copy_from_slice(&0xe000_0020u32.to_le_bytes()); + + // Section 1: `.pack`, holding the stub. + let s1 = sec_table + 40; + d[s1..s1 + 5].copy_from_slice(b".pack"); + d[s1 + 8..s1 + 12].copy_from_slice(&0x1000u32.to_le_bytes()); + d[s1 + 12..s1 + 16].copy_from_slice(&PACK_RVA.to_le_bytes()); + d[s1 + 16..s1 + 20].copy_from_slice(&(self.pack.len() as u32).to_le_bytes()); + d[s1 + 20..s1 + 24].copy_from_slice(&(pack_raw as u32).to_le_bytes()); + d[s1 + 36..s1 + 40].copy_from_slice(&0xe000_0020u32.to_le_bytes()); + + d[pack_raw..pack_raw + self.pack.len()].copy_from_slice(&self.pack); + d + } + } + + /// `.text`'s raw offset inside a dump, so a test can read the bytes a stub + /// wrote there. A memory-layout dump puts `PointerToRawData == VirtualAddress`. + pub fn text_offset_in_dump(dump: &[u8]) -> usize { + let pe = u32::from_le_bytes(dump[0x3c..0x40].try_into().unwrap()) as usize; + let opt = pe + 24; + let sec = opt + u16::from_le_bytes(dump[pe + 20..pe + 22].try_into().unwrap()) as usize; + u32::from_le_bytes(dump[sec + 20..sec + 24].try_into().unwrap()) as usize + } +} + +/// Limits with the dirty-byte floors dropped, because these hand-written stubs +/// rebuild a page, not the tens of kilobytes a real unpack produces. +fn limits() -> EmuLimits { + EmuLimits { + min_unpack_dirty: 0, + min_partial_dirty: 0, + ..Default::default() + } +} + +#[test] +fn a_decrypt_and_jump_stub_unpacks() { + // The archetype: XOR-decrypt a body from `.pack` into `.text`, then jump to + // it. Mirrors a runtime packer's tail transfer. + let plain: &[u8] = b"ORIGINAL PROGRAM"; + let cipher: Vec = plain.iter().map(|b| b ^ 0x5a).collect(); + + // src = PACK_RVA + 0x40 (the cipher text, below the stub). + let src = pe::BASE + pe::PACK_RVA + 0x40; + let dst = pe::BASE + pe::TEXT_RVA; + let mut stub = vec![ + 0xbe, 0, 0, 0, 0, // mov esi, src + 0xbf, 0, 0, 0, 0, // mov edi, dst + 0xb9, 0, 0, 0, 0, // mov ecx, len + 0xac, 0x34, 0x5a, 0xaa, 0xe2, 0xfa, // lodsb; xor al,0x5a; stosb; loop -6 + ]; + stub[1..5].copy_from_slice(&src.to_le_bytes()); + stub[6..10].copy_from_slice(&dst.to_le_bytes()); + stub[11..15].copy_from_slice(&(plain.len() as u32).to_le_bytes()); + // jmp dst (rel32 from the end of this instruction). + let jmp_at = pe::BASE + pe::PACK_RVA + stub.len() as u32; + let rel = dst.wrapping_sub(jmp_at + 5) as i32; + stub.push(0xe9); + stub.extend_from_slice(&rel.to_le_bytes()); + + let mut pack = vec![0u8; 0x40]; + pack[..stub.len()].copy_from_slice(&stub); + pack.extend_from_slice(&cipher); + + let file = pe::Pe { + entry_rva: pe::PACK_RVA, + pack, + tls_dir_rva: None, + } + .build(); + + let r = unpack(&file, &limits()); + let u = r.unpacked.expect("an image was reconstructed"); + assert!(u.reached_oep, "stopped at the tail jump: {}", r.stop); + assert_eq!(u.oep_rva, pe::TEXT_RVA); + let at = pe::text_offset_in_dump(&u.data); + assert_eq!(&u.data[at..at + plain.len()], plain); +} + +#[test] +fn a_stub_that_writes_nothing_yields_no_image() { + // `ret`: a stub that does nothing produces no reconstruction, and the crate + // reports that rather than handing back the input under an "unpacked" name. + let file = pe::Pe { + entry_rva: pe::PACK_RVA, + pack: vec![0xc3], + tls_dir_rva: None, + } + .build(); + let r = unpack(&file, &limits()); + assert!(r.unpacked.is_none(), "{}", r.stop); + assert_eq!(r.dirty_bytes, 0); +} + +/// Build the TLS fixture: a file whose entry point only jumps into `.text`, +/// which is empty until a TLS callback copies the payload there. Reaching the +/// original entry point therefore proves the callback ran before the entry +/// point, as the Windows loader runs it. +fn tls_fixture() -> Vec { + let payload: &[u8] = b"OEP-CODE-PLACED-BY-TLS-CALLBACK"; + + // Layout inside `.pack` (RVA 0x2000): + // 0x00 entry: jmp .text (nothing of its own to unpack) + // 0x10 callback: rep movsb payload -> .text; ret + // 0x60 payload bytes + // 0xA0 callback array: [callback_va, 0] + // 0xC0 TLS directory (IMAGE_TLS_DIRECTORY32) + // 0xE0 AddressOfIndex storage + let entry_off = 0x00u32; + let cb_off = 0x10u32; + let payload_off = 0x60u32; + let cb_array_off = 0xa0u32; + let tls_dir_off = 0xc0u32; + let index_off = 0xe0u32; + let va = |off: u32| pe::BASE + pe::PACK_RVA + off; + let dst = pe::BASE + pe::TEXT_RVA; + + let mut pack = vec![0u8; 0x100]; + + // entry: jmp .text + let rel = dst.wrapping_sub(va(entry_off) + 5) as i32; + pack[entry_off as usize] = 0xe9; + pack[entry_off as usize + 1..entry_off as usize + 5].copy_from_slice(&rel.to_le_bytes()); + + // callback(image_base, reason, reserved): copy the payload into .text, ret. + let cb = [ + vec![0xbf], + dst.to_le_bytes().to_vec(), // mov edi, .text + vec![0xbe], + va(payload_off).to_le_bytes().to_vec(), // mov esi, payload + vec![0xb9], + (payload.len() as u32).to_le_bytes().to_vec(), // mov ecx, len + vec![0xf3, 0xa4], // rep movsb + vec![0xc3], // ret + ] + .concat(); + pack[cb_off as usize..cb_off as usize + cb.len()].copy_from_slice(&cb); + + pack[payload_off as usize..payload_off as usize + payload.len()].copy_from_slice(payload); + + // Callback array: one callback, null-terminated. + pack[cb_array_off as usize..cb_array_off as usize + 4] + .copy_from_slice(&va(cb_off).to_le_bytes()); + + // IMAGE_TLS_DIRECTORY32: no raw data, AddressOfIndex -> our storage, + // AddressOfCallBacks -> the array. + let td = tls_dir_off as usize; + pack[td + 8..td + 12].copy_from_slice(&va(index_off).to_le_bytes()); // AddressOfIndex + pack[td + 12..td + 16].copy_from_slice(&va(cb_array_off).to_le_bytes()); // AddressOfCallBacks + + let _ = index_off; + pe::Pe { + entry_rva: pe::PACK_RVA, + pack, + tls_dir_rva: Some(pe::PACK_RVA + tls_dir_off), + } + .build() +} + +#[test] +fn a_tls_callback_runs_before_the_entry_point() { + // PE-1 coverage. The entry point only jumps into `.text`; `.text` holds the + // original code only because the TLS callback put it there first. If the + // callback did not run, `.text` is empty and nothing is recovered. + let payload: &[u8] = b"OEP-CODE-PLACED-BY-TLS-CALLBACK"; + let file = tls_fixture(); + let r = unpack(&file, &limits()); + let u = r + .unpacked + .expect("the TLS callback filled .text and the entry point reached it"); + assert!( + u.reached_oep, + "did not reach the original entry point: {}", + r.stop + ); + assert_eq!(u.oep_rva, pe::TEXT_RVA); + let at = pe::text_offset_in_dump(&u.data); + assert_eq!( + &u.data[at..at + payload.len()], + payload, + "the dump holds the code the TLS callback wrote" + ); +} diff --git a/crates/exav-render/Cargo.toml b/crates/exav-render/Cargo.toml index 7c574e9..ad3cf5a 100644 --- a/crates/exav-render/Cargo.toml +++ b/crates/exav-render/Cargo.toml @@ -1,17 +1,17 @@ [package] name = "exav-render" -description = "Memory-safe decoders that turn files into something to draw: images into pixels, DWG and DXF drawings and IFC and STL models into GPU-ready geometry." +description = "Memory-safe decoders that turn files into something to draw: images into pixels, DWG and DXF drawings and IFC, STL, OBJ, PLY and glTF models into GPU-ready geometry, and office documents (spreadsheets, presentations, text documents) into XLSX, PPTX and DOCX." version.workspace = true edition.workspace = true license.workspace = true rust-version.workspace = true repository.workspace = true homepage.workspace = true -keywords = ["image", "dwg", "ifc", "decoder", "cad"] +keywords = ["image", "dwg", "ifc", "office", "cad"] categories = ["multimedia::images", "rendering::data-formats"] readme = "README.md" -# The stroke font the build script compiles in, and its licence. -include = ["src/**/*", "fonts/**/*", "build.rs", "README.md", "LICENSE"] +# The stroke font the build script compiles in, and the licences and notices. +include = ["src/**/*", "fonts/**/*", "build.rs", "README.md", "LICENSE", "NOTICE"] # The vendored `tiff` decoder's doc examples are written for it as a crate of # its own: here their `use tiff::...` cannot resolve. @@ -31,12 +31,11 @@ gif = { version = "=0.14.1", optional = true } zune-jpeg = { version = "=0.5.8", default-features = false, features = ["std"], optional = true } zune-core = { version = "=0.5.0", optional = true } zune-core-04 = { package = "zune-core", version = "=0.4.12", optional = true } -# The vendored `tiff` decoder's dependencies, as tiff 0.10.3 has them, and -# `bytemuck` for its byte casts. +# The vendored `tiff` decoder's dependencies, as tiff 0.10.3 has them less +# `half`, and `bytemuck` for its byte casts. zune-jpeg-04 = { package = "zune-jpeg", version = "=0.4.21", default-features = false, features = ["std"], optional = true } fax34 = { package = "fax", version = "=0.2.6", optional = true } -flate2 = { version = "1.0.20", optional = true } -half = { version = "2.4.1", optional = true } +flate2 = { version = "1.1.10", optional = true } quick-error = { version = "2.0.1", optional = true } # Also `gif`'s LZW. 0.1.12, not libclamav's 0.1.10: it only corrects a debug # assertion that a TIFF stream without a clear code tripped; it decodes the same. @@ -49,17 +48,37 @@ bytemuck = { version = "1", optional = true } hayro-jpeg2000 = { version = "=0.4.1", default-features = false, features = ["std"], optional = true } hayro-jbig2 = { version = "=0.3.1", default-features = false, features = ["std"], optional = true } hayro-ccitt = { version = "=0.4.0", optional = true } +# JPEG XL: zenjxl-decoder, a fork of the libjxl team's jxl-rs that is +# `#![forbid(unsafe_code)]` unless its `allow-unsafe` feature is on, with +# limits on pixels and memory. Built without its SIMD (the default +# `all-simd`) and without `threads`; no CMS, no JPEG reconstruction. +zenjxl-decoder = { version = "=0.3.10", default-features = false, optional = true } # DXF's pairs, records and code pages, and DWG's bit codes, sections and # objects, which the drawing model (`cad`) is read from; those formats # alone, none of the scanner's others. exav-unpack = { path = "../exav-unpack", version = "0.0.2", default-features = false, features = ["dxf", "dwg"], optional = true } +# Markdown: CommonMark with tables and strikethrough, read as events. Without +# its `html` and `simd` features: no markup is made, and its only `unsafe` +# (the SIMD scanners) is off. +pulldown-cmark = { version = "=0.13.4", default-features = false, optional = true } +# The office converters (`office-*`): packages are read, and the XLSX, PPTX +# and DOCX written, as ZIP. +zip = { version = "9", default-features = false, features = ["deflate-flate2"], optional = true } +# ODF's XML. 0.41 bounds namespace declarations per element and checks +# duplicate attributes in linear time (RUSTSEC-2026-0194, -0195). +quick-xml = { version = "0.42", optional = true } +# Text in Windows and Mac code pages; the DOS ones are tables of our own. +encoding_rs = { version = "0.8.42", default-features = false, features = ["alloc"], optional = true } +# XLS decryption with the default password ([MS-OFFCRYPTO] RC4, RC4 CryptoAPI). +md-5 = { version = "0.11", optional = true } +sha1 = { version = "0.11", optional = true } [features] -default = ["image", "webp", "ico", "pnm", "qoi", "dds", "ff", "hdr", "jp2", "jbig2", "ccitt"] +default = ["image", "webp", "ico", "pnm", "qoi", "dds", "ff", "hdr", "jp2", "jbig2", "ccitt", "raw"] # Raster images: PNG, GIF, JPEG, TIFF and BMP, plus the formats below. image = [ "dep:image", "dep:png", "dep:gif", "dep:zune-jpeg", "dep:zune-core", "dep:zune-core-04", - "dep:zune-jpeg-04", "dep:fax34", "dep:flate2", "dep:half", "dep:quick-error", "dep:weezl", + "dep:zune-jpeg-04", "dep:fax34", "dep:flate2", "dep:quick-error", "dep:weezl", "dep:bytemuck", ] # Each is a decoder without `unsafe`: image-webp and qoi are @@ -80,6 +99,14 @@ jp2 = ["dep:hayro-jpeg2000"] jbig2 = ["dep:hayro-jbig2"] # A PDF's CCITTFaxDecode streams (`pdf_image`). ccitt = ["dep:hayro-ccitt"] +# Camera RAW files (DNG, CR2, CR3, NEF, ARW, ORF, RW2, RAF, PEF, SRW, 3FR, +# IIQ, X3F...), shown by the largest JPEG or RGB preview they embed +# (`image::raw`). The sensor data is not decoded. +raw = ["image"] +# JPEG XL, first frame, as 8-bit grey or RGBA. Not a default: libclamav does +# not decode it, so the scanner's image hash has no use for it, and it is the +# largest decoder here. +jxl = ["image", "dep:zenjxl-decoder"] # DXF (R12 to 2018) and DWG (R13 to 2018) into the drawing model # (`cad`), tessellated for a GPU. dwg = ["dep:exav-unpack"] @@ -89,11 +116,49 @@ vp-debug = ["dwg"] ifc = [] # Binary and ASCII STL into the same meshes (`stl`, `mesh`). stl = [] +# Wavefront OBJ (`obj`), Stanford PLY (`ply`) and glTF 2.0 with GLB (`gltf`, +# with a JSON reader of its own) into the same meshes. +obj = [] +ply = [] +gltf = [] +# Markdown into a tree of blocks and inlines (`markdown`), as data: no HTML +# is ever made. +markdown = ["dep:pulldown-cmark"] +# The text of a document as a reader sees it, one entry for every kind that has +# some (`text`): Markdown, HTML, Office and OpenDocument XML parts, PDF (hayro) +# and drawings. For a scanner or a search; the viewer does not use it. +text = ["markdown", "dwg", "exav-unpack/text"] +# And PDF's, read by hayro: the largest part of `text`. +text-pdf = ["text", "exav-unpack/text-pdf"] +# And the office formats' the XML parts do not reach, from what `office` +# reads: DOC, XLS, PPT, RTF, Word 2003 XML, SpreadsheetML 2003, SYLK, flat +# OpenDocument, Numbers, Pages, Keynote. +text-office = ["text", "office"] +# What every office converter shares (`formats::office::common`): ZIP +# packages, ODF's XML, code pages. Not a feature to ask for. +_office = ["dep:zip", "dep:flate2", "dep:quick-xml", "dep:encoding_rs"] +# Spreadsheets into XLSX (`sheets`): Excel 2 to 2003, ODS, FODS, OTS, Apple +# Numbers, XML Spreadsheet 2003, HTML tables and SYLK. Also the chart writer +# the presentations use for ODF charts. +office-sheets = ["_office", "dep:md-5", "dep:sha1"] +# Presentations into PPTX (`slides`): PowerPoint 95 and 97 to 2003, ODP, FODP, +# OTP and Apple Keynote; drawings: ODG, OTG, FODG and Visio (VSDX). +office-slides = ["_office", "dep:md-5", "dep:sha1"] +# Text documents into DOCX (`docs`): Word 6 to 2003, ODT, FODT, OTT, RTF, +# Word 2003 XML and Apple Pages. +office-docs = ["_office"] +# Every office converter. +office = ["office-sheets", "office-slides", "office-docs"] +# Writers of compound files, protobuf messages and Snappy blocks, for the +# tests that build the documents they read. Not a feature to ask for. +office-test-util = ["_office"] [dev-dependencies] serde_json = "1" +# The strict compound file reader the lenient one of `office` is checked against. +cfb = "0.15.0" # The drawing fixtures are gzipped. -flate2 = "1.0.20" +flate2 = "1.1.10" # The DWG oracle test names local corpus files by hash. sha2 = "0.11" @@ -129,6 +194,14 @@ required-features = ["dwg"] name = "ifc" required-features = ["ifc"] +[[test]] +name = "ifc_geometry" +required-features = ["ifc"] + +[[test]] +name = "ifc_hostile" +required-features = ["ifc"] + [[test]] name = "ifc_oracle" required-features = ["ifc"] @@ -137,6 +210,102 @@ required-features = ["ifc"] name = "stl" required-features = ["stl"] +[[test]] +name = "obj" +required-features = ["obj"] + +[[test]] +name = "ply" +required-features = ["ply"] + +[[test]] +name = "gltf" +required-features = ["gltf"] + +[[test]] +name = "jxl" +required-features = ["jxl"] + +[[test]] +name = "raw" +required-features = ["raw"] + +[[test]] +name = "markdown" +required-features = ["markdown"] + +[[test]] +name = "markdown_text" +required-features = ["markdown"] + +[[test]] +name = "text" +required-features = ["text"] + +[[test]] +name = "office_sheets" +required-features = ["office-sheets"] + +[[test]] +name = "office_text_sheets" +required-features = ["office-sheets"] + +[[test]] +name = "office_slides" +required-features = ["office-slides", "office-test-util"] + +[[test]] +name = "office_slides_draw" +required-features = ["office-slides"] + +[[test]] +name = "office_text_slides" +required-features = ["office-slides"] + +[[test]] +name = "office_slides_vsdx" +required-features = ["office-slides", "office-test-util"] + +[[test]] +name = "office_slides_keynote_xml" +required-features = ["office-slides"] + +[[test]] +name = "office_slides_odp_features" +required-features = ["office-slides"] + +[[test]] +name = "office_slides_old_ppt" +required-features = ["office-slides", "office-test-util"] + +[[test]] +name = "office_docs_doc" +required-features = ["office-docs", "office-test-util"] + +[[test]] +name = "office_docs_formats" +required-features = ["office-docs", "office-test-util"] + +[[test]] +name = "office_text_docs" +required-features = ["office-docs", "office-test-util"] + +[[example]] +name = "office_docs_convert" +required-features = ["office-docs"] + +[[example]] +name = "office_slides_convert" +required-features = ["office-slides"] + +[[example]] +name = "office_text" +required-features = ["text-office"] + +[[example]] +name = "raw_preview" +required-features = ["raw"] + [[example]] name = "cad_dump" required-features = ["dwg"] diff --git a/crates/exav-render/NOTICE b/crates/exav-render/NOTICE new file mode 100644 index 0000000..65741e1 --- /dev/null +++ b/crates/exav-render/NOTICE @@ -0,0 +1,231 @@ +exav-render: notices +==================== + +exav-render is licensed under the MIT License (see LICENSE). This file +covers the office converters (the `office-sheets`, `office-slides` and +`office-docs` features, `src/formats/office/`). The vendored image decoders +keep their licences in `src/image_codecs/` and the stroke font its +dedication in `fonts/`; the notices of the rest of the workspace are in the +repository's NOTICE. + +The office converters are written from published specifications and from the +black-box behaviour of other converters (their output on sample files). No +code of another office application is in them: + +- no code of another spreadsheet application is in `sheets`; +- no code of another presentation application is in `slides`; +- no code of another word-processing application is in `docs`, and none was + read while writing it; +- `common` is written from published specifications alone. + +Specifications and documentation they follow +-------------------------------------------- + +Shared (`common`): + +- Microsoft's Open Specifications: [MS-CFB], under the Microsoft Open + Specifications Promise. +- OASIS OpenDocument 1.2 and 1.3, for the namespaces. +- Google's Snappy format description, and the protocol buffers encoding + documented at protobuf.dev. + +Spreadsheets (`sheets`): + +- Microsoft's Open Specifications: [MS-XLS], [MS-OFFCRYPTO], [MS-ODRAW], + [MS-CFB], under the Microsoft Open Specifications Promise. +- OpenOffice.org's "Microsoft Excel File Format" documentation (Daniel + Rentz, Public Documentation License 1.0), for the BIFF2 to BIFF5 record + layouts [MS-XLS] does not give, and the argument counts of + src/formats/office/sheets/xls/ftab.rs (generated by + scripts/office/sheets/ftab.py). +- OASIS OpenDocument 1.2 and 1.3, and OpenFormula. +- ECMA-376 (Office Open XML), for the XLSX written. +- Google's Snappy format description, and the protocol buffers encoding + documented at protobuf.dev. +- Microsoft's "XML Spreadsheet Reference" (Office XP, 2001) for + SpreadsheetML; the "Microsoft Office HTML and XML Reference" (Office + 2000) for Excel's HTML; Microsoft's "SYLK summary" (sylksum.doc, 1986) + and knowledge base article Q64338 for SYLK, with ISO 6937 for its + escapes; ECMA-376 for column widths in pixels; the W3C's CSS Color + Module Level 4 for colour names. + +Presentations (`slides`): + +- Microsoft's Open Specifications: [MS-PPT], [MS-ODRAW], [MS-CFB], + [MS-OSHARED] and [MS-OFFCRYPTO] (to recognise encrypted files), under the + Microsoft Open Specifications Promise. +- ECMA-376 (Office Open XML) Part 1, for the PPTX written, and its + presetShapeDefinitions.xml, for the preset shapes' names and adjustments. +- OASIS OpenDocument 1.2 (Part 1) and 1.3 (Part 3, schema). +- Google's Snappy format description, and the protocol buffers encoding + documented at protobuf.dev. +- Apple's Technical Notes TN2067 (About the Keynote XML File Format, APXL + Schema) and TN2073 (Deconstructing a Keynote Document: Part One, + Slides), for Keynote 1 (src/formats/office/slides/keynote/apxl1.rs). +- RFC 1741 (BinHex 4.0), to find the data fork of a Macintosh PowerPoint + file saved as text. +- Visio drawings (src/formats/office/slides/vsdx): Microsoft's Visio file + format reference (Visio 2013 file format, learn.microsoft.com/office/ + client-developer/visio: the Introduction, Schema map, Elements and Types + pages and the ShapeSheet reference pages of the geometry rows, the fill, + line, character, paragraph, text block, layer and hyperlink cells, and the + THEMEVAL and NURBS functions); [MS-VSDX] (Visio Graphics Service VSDX File + Format), under the Microsoft Open Specifications Promise, for the package + parts, the coordinate transforms, the inheritance of masters and styles, + the colour table, the fill patterns, line patterns and line ends (pictures + in it), the formula grammar and the theme; ECMA-376 Part 2 (Open + Packaging Conventions), for the package and its relationships. + +Text documents (`docs`): + +- Microsoft's Open Specifications: [MS-DOC], [MS-ODRAW], [MS-OSHARED] and + [MS-CFB], under the Microsoft Open Specifications Promise. +- ECMA-376 (Office Open XML) Part 1, for the DOCX written. +- OASIS OpenDocument 1.2 (Part 1) and 1.3 (Part 3, schema). +- Microsoft's Rich Text Format specification, version 1.9.1, and the + WordprocessingML 2003 element and attribute names, for + src/formats/office/docs/rtf and src/formats/office/docs/wml. +- Google's Snappy format description, and the protocol buffers encoding + documented at protobuf.dev, for Pages (through `common`). + +Formats nobody published +------------------------ + +- Microsoft published no description of PowerPoint 95 and of PowerPoint 2 to + 4, and Apple none of Keynote 2 to 5. src/formats/office/slides/ppt/ppt95.rs + and src/formats/office/slides/keynote/apxl.rs were written from sample + documents, the output of another office application on them used as a black + box (rendered pages, never its source code), and the structure of the files themselves. + src/formats/office/slides/ppt/old.rs reads only the headers of PowerPoint + 2 to 4, to report them as unsupported. + +- Apple published none of Pages. src/formats/office/docs/pages was written + from sample documents and the structure of the files themselves (the + document message's page size and margin fields were found there), with the + text messages' layout below. + +- The Numbers '08 and '09 reader (src/formats/office/sheets/numbers/v09.rs) + follows no description of the format: Apple published none. It was written + from sample documents (Apache Tika's, below, and others used only as + inputs), with another application's conversions of them as a black-box + reference. + +- The Visio reader (src/formats/office/slides/vsdx) is written from the + specifications listed above and from sample drawings used only as inputs: + 48 VSDX files collected from public bug trackers and test suites of other + projects (not part of this repository), to see what real files hold. Where + the specifications are silent, the reader follows what those files and + another application's rendering of them show, used as a black box (its PDF + of each file compared with ours, never any source code, which was not + read): the quick + style colours 200 to 206 (read as 100 to 106), the side an arc's bow + bulges to, and that a `Themed` value with no quick style of its own is the + root style sheet's. The gradient patterns 25 to 40 are approximations of + the pictures in [MS-VSDX]. Formats the reader leaves out: the binary .vsd + and the Visio 2003 XML .vdx. + +Data from other projects +------------------------ + +- src/formats/office/sheets/numbers/functions.rs (Numbers' function indexes) + and src/formats/office/sheets/numbers/fonts.rs (PostScript names of macOS + fonts and their families) are generated, by + scripts/office/sheets/numbers_functions.py and + scripts/office/sheets/numbers_fonts.py, from numbers-parser + (https://github.com/masaccio/numbers-parser), MIT: + + Copyright 2021 Jon Connell + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + The layout of the Numbers messages read (their field numbers) follows the + message definitions numbers-parser publishes under the same licence; the + older cell records follow SheetJS's reader (Apache-2.0). The record layout + of Keynote tables (src/formats/office/slides/keynote/table.rs) follows, for + the cell records, numbers-parser too, under the same licence. + +- The layout of the Keynote and Pages messages read (their type and field + numbers, named where src/formats/office/slides/keynote and + src/formats/office/docs/pages read them) follows the message definitions + keynote-parser (https://github.com/psobot/keynote-parser) publishes, MIT: + + Copyright 2019-2025 Peter Sobot + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +- The code page tables (src/formats/office/common/codepage_tables.rs and + src/formats/office/sheets/codepage_tables.rs: the DOS and Mac code pages + encoding_rs does not have) are generated by + scripts/office/common/codepages.py and scripts/office/sheets/codepages.py + from the mapping tables of Python's codecs, which are the Unicode + Consortium's published mappings. + +Test fixtures +------------- + +The fixtures are in tests/fixtures/office and are not packaged with the +crate. + +- sheets/sample.numbers is numbers-parser's tests/data/issue-18.numbers (MIT, + as above); see sheets/README.md. + +- sheets/numbers09.numbers is Apache Tika's test document + testNumbers.numbers, unmodified, under the Apache License 2.0 + (https://www.apache.org/licenses/LICENSE-2.0). Apache Tika, Copyright The + Apache Software Foundation; it includes software developed at The Apache + Software Foundation (http://www.apache.org/). It is a test input only. + +- slides/sample.key is keynote-parser's tests/data/simple-oneslide.key, under + the same licence as keynote-parser above. + +- draw/make_vsdx.py writes sample.vsdx and themed.vsdx, Visio drawings of + shapes written for this crate (CC0); see draw/README.md. + +- docs/make.py writes sample.odt, sample.fodt and sample.rtf from text + written for this crate (CC0). docs/sample.doc is a conversion + of sample.odt by an office application, and docs/sample-2003.xml was written by hand; none holds + anyone else's content. + +- tests/fixtures/dwg/make.py writes the drawings as DXF with ezdxf (MIT, + not distributed). The `.dwg.gz` files are those drawings converted to DWG by + the Open Design Alliance's ODA File Converter, run as a black box on the + maintainers' machines: no code or data of the converter is in the repository, + and the drawings are this crate's own, written for the tests and under its + licence. The converter's own terms + (https://www.opendesign.com) apply to the converter, not to the files it was + given. The DWG files carry the file-format markers ODA's writer puts in every + file. diff --git a/crates/exav-render/README.md b/crates/exav-render/README.md index 9ec8a07..25c1eac 100644 --- a/crates/exav-render/README.md +++ b/crates/exav-render/README.md @@ -13,11 +13,40 @@ behind [`@exav/viewer`](../exav-viewer) and the decoding half of code (its only `unsafe`); see the README there. JPEG 2000 and JBIG2 files too (`jp2`, `jbig2`, default), through hayro-jpeg2000 and hayro-jbig2 built without their SIMD code (libclamav decodes neither; - exav-imagehash hashes them like the others). + exav-imagehash hashes them like the others). JPEG XL (`jxl`, not a + default) goes through zenjxl-decoder, a fork of the libjxl team's jxl-rs + that is `forbid(unsafe_code)`, built without its SIMD: the first frame, as + 8-bit grey or RGBA, within the caller's memory budget. +- **Camera RAW files** (`raw`, default): the largest JPEG or RGB preview a + RAW file embeds, as 8-bit pixels with the Exif orientation applied + (`image::raw`, and `decode_any`). DNG, Canon CR2, CR3 and CRW, Nikon NEF and + NRW, Sony ARW, SR2 and SRF, Olympus ORF, Panasonic RW2, RAW and Leica RWL, + Fujifilm RAF, Pentax PEF, Samsung SRW, Hasselblad 3FR, Phase One IIQ, Sigma + X3F, Kodak, Epson, Mamiya and Leaf, told by their bytes, not their names: a + plain TIFF is not one of them and the TIFF decoder reads it. The sensor + data is not decoded, so a file that holds no preview (most phones' DNG) is + `Error::NoPreview`. The previews come from the tags TIFF 6.0 and DNG + define, and from a search of the file for the JPEG streams the makers keep + elsewhere. Written from the public specifications, see `raw.rs`. - **PDF images** (`jp2`, `jbig2`, `ccitt`): the JPXDecode, JBIG2Decode and CCITTFaxDecode images of PDF streams, into the buffers pdf.js reads from its own decoders (`src/formats/pdf_image/`), which @exav/viewer gives pdf.js in place of its OpenJPEG and PDFium builds. +- **Markdown** (`markdown`, not a default): CommonMark with tables and + strikethrough, read by pulldown-cmark (without its `html` and `simd` + features: `forbid(unsafe_code)`) into a tree of blocks and inlines, as + data. Raw HTML is text, an image is its alt text, a link is kept only for + an absolute http, https or mailto address; nesting, columns and nodes are + bounded. `Document::to_json` is the shape @exav/viewer's page reads. +- **The text of a document** (`text`, `text-pdf`, `text-office`; not used by + the viewer): `text::visible_text` gives the words a reader sees, for a + scanner or a search: Markdown, HTML, the XML parts of Office and + OpenDocument files, DWG and DXF, PDF (`text-pdf`, through hayro) and, with + `text-office`, DOC, XLS, PPT, RTF, Word 2003 XML, SpreadsheetML 2003, SYLK, + the flat OpenDocument files, Numbers, Pages and Keynote, taken from what + the office converters read, in sections (a sheet, a slide). A link is its + label then its target. A document of those kinds whose text could not be + taken out says so in `Visible::unreadable`. - **DWG and DXF** (`dwg`): read into the drawing model below and tessellated into GPU-ready buffers: strokes with their lineweight, fills, text runs, layers and layouts. See `src/formats/dwg/`. @@ -37,10 +66,50 @@ behind [`@exav/viewer`](../exav-viewer) and the decoding half of (`mesh::Scene`): batches by class and colour, each element's ranges, its GlobalId, class, name and storey, the spatial tree. Written from buildingSMART's schemas and documentation, booleans and openings - included. See `src/formats/ifc/`. Not drawn faithfully yet: conical, - spherical and toroidal B-rep faces (flat), B-spline face trimming, IFC4X3 - alignments, sweep start/end parameters, grid placements (listed on - exav.org's exav-render page). + included. See `src/formats/ifc/`. Wavefront OBJ (`obj`), Stanford PLY + (`ply`) and glTF 2.0 with GLB (`gltf`, with a JSON reader of its own and + no dependency) read into the same meshes, never opening another file. + B-rep faces on spheres, tori, cylinders and B-spline surfaces are meshed + in their surface's parameters (B-spline faces cut by their bounds), + sweeps honour their start and end parameters, IFC4X3 curve segments + (lines, circles, clothoids and the other spirals, polynomials), gradient + curves and linear placements along them are evaluated, grid placements + sit at their grid intersections, and each element and batch has its + building storey (`Element::storey`, `Batch::storey`, `Node::elevation`). + What is not drawn yet is on exav.org's exav-render page. + +- **Office documents** (`office-sheets`, `office-slides`, `office-docs`, or + `office` for the three; not defaults): converted to the Open XML package an + Open XML renderer draws, in the browser behind `@exav/viewer`. A + conversion is bounded by `Limits` (input, cells, slides, paragraphs, + memory, each decompressed part) and fails with `Error::TooLarge` rather + than convert part of a document. Nothing is recalculated and no macro runs. + - **Spreadsheets** (`sheets`, to XLSX): Excel 2.x to 2003 (BIFF2 to BIFF8, + a lenient compound file reader, default-password encryption), ODS, FODS + and OTS, Apple Numbers (Numbers 3 and later, and '08 and '09), and the + text formats Excel opens from a .xls file: XML Spreadsheet 2003, HTML + tables and SYLK. Values, formulas as text with their cached results, + styles and number formats, merges, conditional formats, validations, + comments, links, pictures, shapes and charts. + - **Presentations** (`slides`, to PPTX): PowerPoint 95 and 97 to 2003 + (2 to 4 are recognised and reported as unsupported), ODP, FODP and OTP, + and Apple Keynote in every version. Masters, placeholders, styles, + shapes and their geometry, text, pictures, tables and charts, every + property resolved in the PPTX written. `convert_first` converts the first + slides only, `convert_first_from` reads a package part by part from any + `Read + Seek` source. Drawings too, a page to a slide in the pages' + largest size: ODG, OTG and FODG, and Visio 2013 and later (VSDX, VSDM, + VSTX, VSTM: shapes through their masters and styles, formulas where a + master's depend on the instance, geometry rows, splines, text, pictures, + layers, hyperlinks, the theme's colours; the binary .vsd and the Visio + 2003 XML .vdx are not read). + - **Text documents** (`docs`, to DOCX): Word 6 to 2003, ODT, OTT and FODT, + RTF, Word 2003 XML and Apple Pages (text, page size and margins). Styles + stay styles; sections with headers and footers, lists, tables, notes, + comments, fields, pictures and OfficeArt shapes. + - Encrypted files are refused. Fuzzed by the `sheets_*`, `slides_*` and + `docs_*` targets (docs/FUZZING.md). See NOTICE for the specifications + and data they are written from. The crate is `forbid(unsafe_code)`. @@ -53,5 +122,12 @@ let rgba = pixels.to_rgba8(); # Ok::<(), Box>(()) ``` +```rust,ignore +// With the `office-sheets` feature. +use exav_render::sheets::{convert, Format, Limits}; + +let xlsx = convert(&bytes, Format::Ods, &Limits::default())?.xlsx; +``` + MIT. The vendored decoders keep their licences (`src/image_codecs/`), and the NewStroke stroke font its CC0-1.0 dedication (`fonts/`). diff --git a/crates/exav-render/examples/office_docs_convert.rs b/crates/exav-render/examples/office_docs_convert.rs new file mode 100644 index 0000000..a72984d --- /dev/null +++ b/crates/exav-render/examples/office_docs_convert.rs @@ -0,0 +1,108 @@ +//! Converts files from the command line: +//! `cargo run -p exav-render --features office-docs --example office_docs_convert -- `. +//! +//! `convert one ` converts one file. +//! `convert batch ` converts every file of a +//! directory, writing `/.docx` and printing one JSON line +//! per file: its name, the outcome, the time in microseconds, the size of +//! the DOCX, and the warnings. + +use exav_render::docs::{convert, Format, Limits}; +use std::time::Instant; + +fn format(name: &str) -> Format { + Format::from_extension(name).unwrap_or_else(|| { + eprintln!("unknown format {name}"); + std::process::exit(2); + }) +} + +fn json(s: &str) -> String { + let mut o = String::from("\""); + for c in s.chars() { + match c { + '"' => o.push_str("\\\""), + '\\' => o.push_str("\\\\"), + '\n' => o.push_str("\\n"), + c if (c as u32) < 0x20 => o.push(' '), + c => o.push(c), + } + } + o.push('"'); + o +} + +fn main() { + let args: Vec = std::env::args().skip(1).collect(); + let limits = Limits::default(); + match args.iter().map(String::as_str).collect::>()[..] { + ["one", fmt, input, output] => { + let bytes = std::fs::read(input).expect("read the input"); + match convert(&bytes, format(fmt), &limits) { + Ok(c) => { + std::fs::write(output, &c.docx).expect("write the output"); + for w in &c.warnings { + eprintln!("warning: {w}"); + } + } + Err(e) => { + eprintln!("{}: {e}", e.kind()); + std::process::exit(1); + } + } + } + ["batch", fmt, dir, out] => { + let fmt = format(fmt); + std::fs::create_dir_all(out).expect("create the output directory"); + let mut names: Vec<_> = std::fs::read_dir(dir) + .expect("read the directory") + .filter_map(|e| e.ok()) + .map(|e| e.path()) + .collect(); + names.sort(); + for p in names { + let name = p + .file_name() + .unwrap_or_default() + .to_string_lossy() + .to_string(); + let Ok(bytes) = std::fs::read(&p) else { + continue; + }; + let t = Instant::now(); + let r = std::panic::catch_unwind(|| convert(&bytes, fmt, &Limits::default())); + let us = t.elapsed().as_micros(); + match r { + Ok(Ok(c)) => { + let stem = name.rsplit_once('.').map(|s| s.0).unwrap_or(&name); + std::fs::write(format!("{out}/{stem}.docx"), &c.docx).expect("write"); + let w: Vec = c.warnings.iter().map(|w| json(w)).collect(); + println!( + "{{\"name\":{},\"ok\":true,\"us\":{us},\"size\":{},\"paragraphs\":{},\"warnings\":[{}]}}", + json(&name), + c.docx.len(), + c.paragraphs, + w.join(",") + ); + } + Ok(Err(e)) => println!( + "{{\"name\":{},\"ok\":false,\"kind\":\"{}\",\"error\":{},\"us\":{us}}}", + json(&name), + e.kind(), + json(&e.to_string()) + ), + Err(_) => println!( + "{{\"name\":{},\"ok\":false,\"kind\":\"panic\",\"error\":\"panic\",\"us\":{us}}}", + json(&name) + ), + } + } + } + _ => { + eprintln!( + "usage: convert one | convert batch " + ); + std::process::exit(2); + } + } +} diff --git a/crates/exav-render/examples/office_slides_convert.rs b/crates/exav-render/examples/office_slides_convert.rs new file mode 100644 index 0000000..864563e --- /dev/null +++ b/crates/exav-render/examples/office_slides_convert.rs @@ -0,0 +1,106 @@ +//! Converts presentations and drawings from the command line: +//! `cargo run -p exav-render --features office-slides --example office_slides_convert -- `. +//! +//! `one ` converts one file. +//! `batch ` converts every file of a directory, +//! writing `/.pptx` and printing one JSON line per file: its +//! name, the outcome, the time in microseconds, the size of the PPTX, the +//! slides, and the warnings. + +use exav_render::slides::{convert, Format, Limits}; +use std::time::Instant; + +fn format(name: &str) -> Format { + Format::from_extension(name).unwrap_or_else(|| { + eprintln!("unknown format {name}"); + std::process::exit(2); + }) +} + +fn json(s: &str) -> String { + let mut o = String::from("\""); + for c in s.chars() { + match c { + '"' => o.push_str("\\\""), + '\\' => o.push_str("\\\\"), + '\n' => o.push_str("\\n"), + c if (c as u32) < 0x20 => o.push(' '), + c => o.push(c), + } + } + o.push('"'); + o +} + +fn main() { + let args: Vec = std::env::args().skip(1).collect(); + let limits = Limits::default(); + match args.iter().map(String::as_str).collect::>()[..] { + ["one", fmt, input, output] => { + let bytes = std::fs::read(input).expect("read the input"); + match convert(&bytes, format(fmt), &limits) { + Ok(c) => { + std::fs::write(output, &c.pptx).expect("write the output"); + for w in &c.warnings { + eprintln!("warning: {w}"); + } + } + Err(e) => { + eprintln!("{}: {e}", e.kind()); + std::process::exit(1); + } + } + } + ["batch", fmt, dir, out] => { + let fmt = format(fmt); + std::fs::create_dir_all(out).expect("create the output directory"); + let mut names: Vec<_> = std::fs::read_dir(dir) + .expect("read the directory") + .filter_map(|e| e.ok()) + .map(|e| e.path()) + .collect(); + names.sort(); + for p in names { + let name = p + .file_name() + .unwrap_or_default() + .to_string_lossy() + .to_string(); + let Ok(bytes) = std::fs::read(&p) else { + continue; + }; + let t = Instant::now(); + let r = std::panic::catch_unwind(|| convert(&bytes, fmt, &Limits::default())); + let us = t.elapsed().as_micros(); + match r { + Ok(Ok(c)) => { + let stem = name.rsplit_once('.').map(|s| s.0).unwrap_or(&name); + std::fs::write(format!("{out}/{stem}.pptx"), &c.pptx).expect("write"); + let w: Vec = c.warnings.iter().map(|w| json(w)).collect(); + println!( + "{{\"name\":{},\"ok\":true,\"us\":{us},\"size\":{},\"slides\":{},\"warnings\":[{}]}}", + json(&name), + c.pptx.len(), + c.slides, + w.join(",") + ); + } + Ok(Err(e)) => println!( + "{{\"name\":{},\"ok\":false,\"kind\":\"{}\",\"error\":{},\"us\":{us}}}", + json(&name), + e.kind(), + json(&e.to_string()) + ), + Err(_) => println!( + "{{\"name\":{},\"ok\":false,\"kind\":\"panic\",\"error\":\"panic\",\"us\":{us}}}", + json(&name) + ), + } + } + } + _ => { + eprintln!("usage: one | batch "); + std::process::exit(2); + } + } +} diff --git a/crates/exav-render/examples/office_text.rs b/crates/exav-render/examples/office_text.rs new file mode 100644 index 0000000..5493b8f --- /dev/null +++ b/crates/exav-render/examples/office_text.rs @@ -0,0 +1,87 @@ +//! The text of office documents, as the scanner and `exav-grep --text` read it: +//! `cargo run --release -p exav-render --features text-office --example office_text -- `. +//! +//! `one ` prints the file's sections and its text, and the links. +//! `bench ` reads every file of a directory (not recursively) and prints +//! one JSON line each, the name, the outcome, the microseconds and the text's +//! bytes, then the totals. + +use exav_render::text::visible_text; +use std::time::Instant; + +fn main() { + let args: Vec = std::env::args().skip(1).collect(); + let limits = exav_unpack::Limits::default(); + match args.iter().map(String::as_str).collect::>()[..] { + ["one", file] => { + let data = std::fs::read(file).expect("read the file"); + let name = file.rsplit('/').next().unwrap_or(file); + match visible_text(name, &data, 1 << 24, &limits) { + None => println!("no text view"), + Some(v) => { + if let Some(why) = &v.unreadable { + println!("unreadable: {why}"); + } + for (label, range) in &v.sections { + println!("--- {label} ({} bytes)", range.len()); + } + print!("{}", v.text); + for (label, target) in &v.links { + println!("link: {label} -> {target}"); + } + } + } + } + ["bench", dir] => { + let mut names: Vec<_> = std::fs::read_dir(dir) + .expect("read the directory") + .filter_map(|e| e.ok()) + .map(|e| e.path()) + .filter(|p| p.is_file()) + .collect(); + names.sort(); + let (mut bytes, mut micros, mut read) = (0u64, 0u128, 0u32); + for p in names { + let Ok(data) = std::fs::read(&p) else { + continue; + }; + let name = p + .file_name() + .unwrap_or_default() + .to_string_lossy() + .to_string(); + let t = Instant::now(); + let r = std::panic::catch_unwind(|| { + visible_text(&name, &data, 1 << 24, &exav_unpack::Limits::default()) + }); + let us = t.elapsed().as_micros(); + let outcome = match &r { + Ok(Some(v)) if v.unreadable.is_some() => "unreadable", + Ok(Some(_)) => "text", + Ok(None) => "none", + Err(_) => "panic", + }; + let text = match &r { + Ok(Some(v)) => v.text.len(), + _ => 0, + }; + if outcome == "text" { + bytes += data.len() as u64; + micros += us; + read += 1; + } + println!( + "{{\"name\":{name:?},\"outcome\":\"{outcome}\",\"us\":{us},\"text\":{text}}}" + ); + } + println!( + "{{\"documents\":{read},\"input_bytes\":{bytes},\"us\":{micros},\"mb_per_s\":{:.1}}}", + bytes as f64 / micros.max(1) as f64 + ); + } + _ => { + eprintln!("usage: one | bench "); + std::process::exit(2); + } + } +} diff --git a/crates/exav-render/examples/raw_preview.rs b/crates/exav-render/examples/raw_preview.rs new file mode 100644 index 0000000..a1385fb --- /dev/null +++ b/crates/exav-render/examples/raw_preview.rs @@ -0,0 +1,73 @@ +//! Print what the RAW reader makes of each file given: its family, the +//! preview chosen, and how long it took, one tab-separated line a file. With +//! `--png DIR`, the preview is also saved there as `.png`. +//! +//! cargo run --release -p exav-render --example raw_preview -- \ +//! [--png DIR] [--budget BYTES] ... + +use std::time::Instant; + +use exav_render::image::raw; +use exav_render::image::DECODE_MAX; + +fn main() { + let mut args = std::env::args().skip(1).peekable(); + let (mut png_dir, mut budget) = (None, DECODE_MAX); + let mut files = Vec::new(); + while let Some(a) = args.next() { + match a.as_str() { + "--png" => png_dir = args.next(), + "--budget" => budget = args.next().and_then(|v| v.parse().ok()).unwrap_or(budget), + _ => files.push(a), + } + } + for f in files { + let data = match std::fs::read(&f) { + Ok(d) => d, + Err(e) => { + println!("{f}\tERR\tread: {e}"); + continue; + } + }; + let name = std::path::Path::new(&f) + .file_name() + .map_or_else(String::new, |n| n.to_string_lossy().into_owned()); + let started = Instant::now(); + let result = raw::preview(&data, budget); + let ms = started.elapsed().as_millis(); + match result { + Ok((pixels, info)) => { + println!( + "{name}\t{}\t{}x{}\to{}\t{}\tfound {}\tout {}x{}\t{ms} ms", + info.kind.name(), + info.width, + info.height, + info.orientation, + if info.jpeg { "jpeg" } else { "samples" }, + info.found, + pixels.width, + pixels.height, + ); + if let Some(dir) = &png_dir { + let rgba = pixels.to_rgba8(); + if let Some(img) = image::RgbaImage::from_raw(pixels.width, pixels.height, rgba) + { + let _ = img.save(format!("{dir}/{name}.png")); + } + } + } + // Not a RAW file for the reader: `decode_any` reads it as the + // image it may be (a plain TIFF). + Err(exav_render::image::Error::Unsupported) => { + match exav_render::image::decode_any(&data, budget) { + Ok(p) => println!("{name}\tOTHER\t{}x{}\t{ms} ms", p.width, p.height), + Err(e) => println!("{name}\t-\tERR\t{e}\t{ms} ms"), + } + } + Err(e) => match raw::detect(&data) { + Some(kind) => println!("{name}\t{}\tERR\t{e}\t{ms} ms", kind.name()), + None => println!("{name}\t-\tERR\t{e}\t{ms} ms"), + }, + } + } +} diff --git a/crates/exav-render/examples/scene_stats.rs b/crates/exav-render/examples/scene_stats.rs index 61d471b..4f07970 100644 --- a/crates/exav-render/examples/scene_stats.rs +++ b/crates/exav-render/examples/scene_stats.rs @@ -222,9 +222,11 @@ fn summarise(out: &mut String, d: &Drawing) { .map(|b| String::from_utf8_lossy(b).into_owned()) .unwrap_or_default(); texts.push(format!( - "{s}|h={}|rot={}|align={},{}|face={}|rgba={:08x}", + "{s}|u={},{}|v={},{}|align={},{}|face={}|rgba={:08x}", sig(f32_at(r, 8)), sig(f32_at(r, 12)), + sig(f32_at(r, 16)), + sig(f32_at(r, 20)), r[38], r[39], r[44], diff --git a/crates/exav-render/scripts/font-tables.py b/crates/exav-render/scripts/font-tables.py index f42c1f8..ff9b503 100644 --- a/crates/exav-render/scripts/font-tables.py +++ b/crates/exav-render/scripts/font-tables.py @@ -44,8 +44,14 @@ 0x2206, 0x2300, # increment, diameter 0x2264, 0x2265, 0x2260, # <=, >=, != 0x00B0, 0x00B1, 0x00B2, 0x00B3, # already dense, listed to assert - 0x03A9, 0x03BC, # ohm, micro + 0x2200, 0x2203, 0x220B, 0x2217, # Symbol's for all, exists, contains, star + 0x2212, 0x2234, 0x223C, 0x2245, # minus, therefore, tilde, congruent + 0x22A5, # perpendicular } + # Greek, with Symbol's theta, phi and pi symbols, and basic Cyrillic: + # what Greek and Russian notes on a sheet are written in. + | set(range(0x0384, 0x03D7)) + | set(range(0x0400, 0x0460)) ) # Fixed-point divisor for a stored advance, in em units. An advance is under diff --git a/crates/exav-render/scripts/office/common/codepages.py b/crates/exav-render/scripts/office/common/codepages.py new file mode 100644 index 0000000..668206c --- /dev/null +++ b/crates/exav-render/scripts/office/common/codepages.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""Writes src/formats/office/common/codepage_tables.rs: the single-byte DOS and +Mac code pages that encoding_rs does not have, as tables of 256 UTF-16 code +units, from Python's own codecs. Undefined bytes map to U+FFFD. + +usage, from crates/exav-render: +python3 -I scripts/office/common/codepages.py > src/formats/office/common/codepage_tables.rs +""" + +PAGES = [ + (437, "cp437"), + (720, "cp720"), + (737, "cp737"), + (775, "cp775"), + (850, "cp850"), + (852, "cp852"), + (855, "cp855"), + (857, "cp857"), + (858, "cp858"), + (860, "cp860"), + (861, "cp861"), + (862, "cp862"), + (863, "cp863"), + (864, "cp864"), + (865, "cp865"), + (869, "cp869"), + (10006, "mac_greek"), + (10029, "mac_latin2"), + (10079, "mac_iceland"), + (10081, "mac_turkish"), +] + + +def table(codec): + out = [] + for b in range(256): + try: + s = bytes([b]).decode(codec) + except UnicodeDecodeError: + s = "�" + cp = ord(s) if len(s) == 1 else 0xFFFD + if cp > 0xFFFF: + cp = 0xFFFD + out.append(cp) + return out + + +print("// Generated by scripts/office/common/codepages.py from Python's codecs. Do not edit.") +print() +print("/// (code page, its 256 characters).") +print("#[rustfmt::skip]") +print("pub(crate) static TABLES: &[(u16, [u16; 256])] = &[") +for cp, codec in PAGES: + t = table(codec) + print(f" // {codec}") + print(f" ({cp}, [") + for i in range(0, 256, 16): + print(" " + ", ".join(f"0x{x:04X}" for x in t[i:i + 16]) + ",") + print(" ]),") +print("];") diff --git a/crates/exav-render/scripts/office/sheets/ftab.json b/crates/exav-render/scripts/office/sheets/ftab.json new file mode 100644 index 0000000..0de7e7f --- /dev/null +++ b/crates/exav-render/scripts/office/sheets/ftab.json @@ -0,0 +1,375 @@ +[ +[0, "COUNT", -1], +[1, "IF", -1], +[2, "ISNA", 1], +[3, "ISERROR", 1], +[4, "SUM", -1], +[5, "AVERAGE", -1], +[6, "MIN", -1], +[7, "MAX", -1], +[8, "ROW", -1], +[9, "COLUMN", -1], +[10, "NA", 0], +[11, "NPV", -1], +[12, "STDEV", -1], +[13, "DOLLAR", -1], +[14, "FIXED", -1], +[15, "SIN", 1], +[16, "COS", 1], +[17, "TAN", 1], +[18, "ATAN", 1], +[19, "PI", 0], +[20, "SQRT", 1], +[21, "EXP", 1], +[22, "LN", 1], +[23, "LOG10", 1], +[24, "ABS", 1], +[25, "INT", 1], +[26, "SIGN", 1], +[27, "ROUND", 2], +[28, "LOOKUP", -1], +[29, "INDEX", -1], +[30, "REPT", 2], +[31, "MID", 3], +[32, "LEN", 1], +[33, "VALUE", 1], +[34, "TRUE", 0], +[35, "FALSE", 0], +[36, "AND", -1], +[37, "OR", -1], +[38, "NOT", 1], +[39, "MOD", 2], +[40, "DCOUNT", 3], +[41, "DSUM", 3], +[42, "DAVERAGE", 3], +[43, "DMIN", 3], +[44, "DMAX", 3], +[45, "DSTDEV", 3], +[46, "VAR", -1], +[47, "DVAR", 3], +[48, "TEXT", 2], +[49, "LINEST", -1], +[50, "TREND", -1], +[51, "LOGEST", -1], +[52, "GROWTH", -1], +[53, "GOTO", 1], +[54, "HALT", -1], +[55, "RETURN", -1], +[56, "PV", -1], +[57, "FV", -1], +[58, "NPER", -1], +[59, "PMT", -1], +[60, "RATE", -1], +[61, "MIRR", 3], +[62, "IRR", -1], +[63, "RAND", 0], +[64, "MATCH", -1], +[65, "DATE", 3], +[66, "TIME", 3], +[67, "DAY", 1], +[68, "MONTH", 1], +[69, "YEAR", 1], +[70, "WEEKDAY", -1], +[71, "HOUR", 1], +[72, "MINUTE", 1], +[73, "SECOND", 1], +[74, "NOW", 0], +[75, "AREAS", 1], +[76, "ROWS", 1], +[77, "COLUMNS", 1], +[78, "OFFSET", -1], +[79, "ABSREF", 2], +[80, "RELREF", 2], +[81, "ARGUMENT", -1], +[82, "SEARCH", -1], +[83, "TRANSPOSE", 1], +[84, "ERROR", -1], +[85, "STEP", 0], +[86, "TYPE", 1], +[87, "ECHO", -1], +[88, "SET.NAME", -1], +[89, "CALLER", 0], +[90, "DEREF", 1], +[91, "WINDOWS", -1], +[92, "SERIES", -1], +[93, "DOCUMENTS", -1], +[94, "ACTIVE.CELL", 0], +[95, "SELECTION", 0], +[96, "RESULT", -1], +[97, "ATAN2", 2], +[98, "ASIN", 1], +[99, "ACOS", 1], +[100, "CHOOSE", -1], +[101, "HLOOKUP", -1], +[102, "VLOOKUP", -1], +[103, "LINKS", -1], +[104, "INPUT", -1], +[105, "ISREF", 1], +[106, "GET.FORMULA", 1], +[107, "GET.NAME", -1], +[108, "SET.VALUE", 2], +[109, "LOG", -1], +[110, "EXEC", -1], +[111, "CHAR", 1], +[112, "LOWER", 1], +[113, "UPPER", 1], +[114, "PROPER", 1], +[115, "LEFT", -1], +[116, "RIGHT", -1], +[117, "EXACT", 2], +[118, "TRIM", 1], +[119, "REPLACE", 4], +[120, "SUBSTITUTE", -1], +[121, "CODE", 1], +[122, "NAMES", -1], +[123, "DIRECTORY", -1], +[124, "FIND", -1], +[125, "CELL", -1], +[126, "ISERR", 1], +[127, "ISTEXT", 1], +[128, "ISNUMBER", 1], +[129, "ISBLANK", 1], +[130, "T", 1], +[131, "N", 1], +[132, "FOPEN", -1], +[133, "FCLOSE", 1], +[134, "FSIZE", 1], +[135, "FREADLN", 1], +[136, "FREAD", 2], +[137, "FWRITELN", 2], +[138, "FWRITE", 2], +[139, "FPOS", -1], +[140, "DATEVALUE", 1], +[141, "TIMEVALUE", 1], +[142, "SLN", 3], +[143, "SYD", 4], +[144, "DDB", -1], +[145, "GET.DEF", -1], +[146, "REFTEXT", -1], +[147, "TEXTREF", -1], +[148, "INDIRECT", -1], +[149, "REGISTER", -1], +[150, "CALL", -1], +[151, "ADD.BAR", -1], +[152, "ADD.MENU", -1], +[153, "ADD.COMMAND", -1], +[154, "ENABLE.COMMAND", -1], +[155, "CHECK.COMMAND", -1], +[156, "RENAME.COMMAND", -1], +[157, "SHOW.BAR", -1], +[158, "DELETE.MENU", -1], +[159, "DELETE.COMMAND", -1], +[160, "GET.CHART.ITEM", -1], +[161, "DIALOG.BOX", 1], +[162, "CLEAN", 1], +[163, "MDETERM", 1], +[164, "MINVERSE", 1], +[165, "MMULT", 2], +[166, "FILES", -1], +[167, "IPMT", -1], +[168, "PPMT", -1], +[169, "COUNTA", -1], +[170, "CANCEL.KEY", -1], +[171, "FOR", -1], +[172, "WHILE", 1], +[173, "BREAK", 0], +[174, "NEXT", 0], +[175, "INITIATE", 2], +[176, "REQUEST", 2], +[177, "POKE", 3], +[178, "EXECUTE", 2], +[179, "TERMINATE", 1], +[180, "RESTART", -1], +[181, "HELP", -1], +[182, "GET.BAR", -1], +[183, "PRODUCT", -1], +[184, "FACT", 1], +[185, "GET.CELL", -1], +[186, "GET.WORKSPACE", 1], +[187, "GET.WINDOW", -1], +[188, "GET.DOCUMENT", -1], +[189, "DPRODUCT", 3], +[190, "ISNONTEXT", 1], +[191, "GET.NOTE", -1], +[192, "NOTE", -1], +[193, "STDEVP", -1], +[194, "VARP", -1], +[195, "DSTDEVP", 3], +[196, "DVARP", 3], +[197, "TRUNC", -1], +[198, "ISLOGICAL", 1], +[199, "DCOUNTA", 3], +[200, "DELETE.BAR", 1], +[201, "UNREGISTER", 1], +[204, "USDOLLAR", -1], +[205, "FINDB", -1], +[206, "SEARCHB", -1], +[207, "REPLACEB", 4], +[208, "LEFTB", -1], +[209, "RIGHTB", -1], +[210, "MIDB", 3], +[211, "LENB", 1], +[212, "ROUNDUP", 2], +[213, "ROUNDDOWN", 2], +[214, "ASC", 1], +[215, "DBCS", 1], +[216, "RANK", -1], +[219, "ADDRESS", -1], +[220, "DAYS360", -1], +[221, "TODAY", 0], +[222, "VDB", -1], +[223, "ELSE", 0], +[224, "ELSE.IF", 1], +[225, "END.IF", 0], +[226, "FOR.CELL", -1], +[227, "MEDIAN", -1], +[228, "SUMPRODUCT", -1], +[229, "SINH", 1], +[230, "COSH", 1], +[231, "TANH", 1], +[232, "ASINH", 1], +[233, "ACOSH", 1], +[234, "ATANH", 1], +[235, "DGET", 3], +[236, "CREATE.OBJECT", -1], +[237, "VOLATILE", -1], +[238, "LAST.ERROR", 0], +[239, "CUSTOM.UNDO", -1], +[240, "CUSTOM.REPEAT", -1], +[241, "FORMULA.CONVERT", -1], +[242, "GET.LINK.INFO", -1], +[243, "TEXT.BOX", -1], +[244, "INFO", 1], +[245, "GROUP", 0], +[246, "GET.OBJECT", -1], +[247, "DB", -1], +[248, "PAUSE", -1], +[251, "RESUME", -1], +[252, "FREQUENCY", 2], +[253, "ADD.TOOLBAR", -1], +[254, "DELETE.TOOLBAR", 1], +[255, "User Defined Function", -1], +[256, "RESET.TOOLBAR", 1], +[257, "EVALUATE", 1], +[258, "GET.TOOLBAR", -1], +[259, "GET.TOOL", -1], +[260, "SPELLING.CHECK", -1], +[261, "ERROR.TYPE", 1], +[262, "APP.TITLE", -1], +[263, "WINDOW.TITLE", -1], +[264, "SAVE.TOOLBAR", -1], +[265, "ENABLE.TOOL", 3], +[266, "PRESS.TOOL", 3], +[267, "REGISTER.ID", -1], +[268, "GET.WORKBOOK", -1], +[269, "AVEDEV", -1], +[270, "BETADIST", -1], +[271, "GAMMALN", 1], +[272, "BETAINV", -1], +[273, "BINOMDIST", 4], +[274, "CHIDIST", 2], +[275, "CHIINV", 2], +[276, "COMBIN", 2], +[277, "CONFIDENCE", 3], +[278, "CRITBINOM", 3], +[279, "EVEN", 1], +[280, "EXPONDIST", 3], +[281, "FDIST", 3], +[282, "FINV", 3], +[283, "FISHER", 1], +[284, "FISHERINV", 1], +[285, "FLOOR", 2], +[286, "GAMMADIST", 4], +[287, "GAMMAINV", 3], +[288, "CEILING", 2], +[289, "HYPGEOMDIST", 4], +[290, "LOGNORMDIST", 3], +[291, "LOGINV", 3], +[292, "NEGBINOMDIST", 3], +[293, "NORMDIST", 4], +[294, "NORMSDIST", 1], +[295, "NORMINV", 3], +[296, "NORMSINV", 1], +[297, "STANDARDIZE", 3], +[298, "ODD", 1], +[299, "PERMUT", 2], +[300, "POISSON", 3], +[301, "TDIST", 3], +[302, "WEIBULL", 4], +[303, "SUMXMY2", 2], +[304, "SUMX2MY2", 2], +[305, "SUMX2PY2", 2], +[306, "CHITEST", 2], +[307, "CORREL", 2], +[308, "COVAR", 2], +[309, "FORECAST", 3], +[310, "FTEST", 2], +[311, "INTERCEPT", 2], +[312, "PEARSON", 2], +[313, "RSQ", 2], +[314, "STEYX", 2], +[315, "SLOPE", 2], +[316, "TTEST", 4], +[317, "PROB", -1], +[318, "DEVSQ", -1], +[319, "GEOMEAN", -1], +[320, "HARMEAN", -1], +[321, "SUMSQ", -1], +[322, "KURT", -1], +[323, "SKEW", -1], +[324, "ZTEST", -1], +[325, "LARGE", 2], +[326, "SMALL", 2], +[327, "QUARTILE", 2], +[328, "PERCENTILE", 2], +[329, "PERCENTRANK", -1], +[330, "MODE", -1], +[331, "TRIMMEAN", 2], +[332, "TINV", 2], +[334, "MOVIE.COMMAND", -1], +[335, "GET.MOVIE", -1], +[336, "CONCATENATE", -1], +[337, "POWER", 2], +[338, "PIVOT.ADD.DATA", -1], +[339, "GET.PIVOT.TABLE", -1], +[340, "GET.PIVOT.FIELD", -1], +[341, "GET.PIVOT.ITEM", -1], +[342, "RADIANS", 1], +[343, "DEGREES", 1], +[344, "SUBTOTAL", -1], +[345, "SUMIF", -1], +[346, "COUNTIF", 2], +[347, "COUNTBLANK", 1], +[348, "SCENARIO.GET", -1], +[349, "OPTIONS.LISTS.GET", 1], +[350, "ISPMT", 4], +[351, "DATEDIF", 3], +[352, "DATESTRING", 1], +[353, "NUMBERSTRING", 2], +[354, "ROMAN", -1], +[355, "OPEN.DIALOG", -1], +[356, "SAVE.DIALOG", -1], +[357, "VIEW.GET", -1], +[358, "GETPIVOTDATA", -1], +[359, "HYPERLINK", -1], +[360, "PHONETIC", 1], +[361, "AVERAGEA", -1], +[362, "MAXA", -1], +[363, "MINA", -1], +[364, "STDEVPA", -1], +[365, "VARPA", -1], +[366, "STDEVA", -1], +[367, "VARA", -1], +[368, "BAHTTEXT", 1], +[369, "THAIDAYOFWEEK", 1], +[370, "THAIDIGIT", 1], +[371, "THAIMONTHOFYEAR", 1], +[372, "THAINUMSOUND", 1], +[373, "THAINUMSTRING", 1], +[374, "THAISTRINGLENGTH", 1], +[375, "ISTHAIDIGIT", 1], +[376, "ROUNDBAHTDOWN", 1], +[377, "ROUNDBAHTUP", 1], +[378, "THAIYEAR", 1], +[379, "RTD", -1] +] diff --git a/crates/exav-render/scripts/office/sheets/ftab.py b/crates/exav-render/scripts/office/sheets/ftab.py new file mode 100644 index 0000000..a9875a4 --- /dev/null +++ b/crates/exav-render/scripts/office/sheets/ftab.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""Writes src/formats/office/sheets/xls/ftab.rs, the table of Excel's built-in +functions by their BIFF index, from scripts/office/sheets/ftab.json: rows of +[index, name, fixed argument count or -1], with the names of [MS-XLS] +2.5.198.17 Ftab and the argument counts of OpenOffice.org's Excel file format +documentation, 3.11. + +usage, from crates/exav-render: +python3 -I scripts/office/sheets/ftab.py scripts/office/sheets/ftab.json > src/formats/office/sheets/xls/ftab.rs +""" +import json +import sys + +rows = sorted(json.load(open(sys.argv[1])), key=lambda r: r[0]) +print("// Generated by scripts/office/sheets/ftab.py from ftab.json. Do not edit.") +print() +print("/// (BIFF function index, name, fixed argument count or -1), by index.") +print("#[rustfmt::skip]") +print("pub(crate) const FTAB: &[(u16, &str, i8)] = &[") +for i, name, n in rows: + print(f' ({i}, "{name}", {n}),') +print("];") diff --git a/crates/exav-render/scripts/office/sheets/numbers_fonts.py b/crates/exav-render/scripts/office/sheets/numbers_fonts.py new file mode 100644 index 0000000..476e46b --- /dev/null +++ b/crates/exav-render/scripts/office/sheets/numbers_fonts.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +"""Writes src/formats/office/sheets/numbers/fonts.rs: the PostScript names of +macOS fonts whose family the rule in style::family (split at '-', drop an MT +or PSMT suffix, a space before each capital that follows a lower-case letter) +gets wrong, from numbers-parser's src/numbers_parser/generated/fontmap.py +(MIT, Jon Connell). + +usage, from crates/exav-render: +python3 -I scripts/office/sheets/numbers_fonts.py fontmap.py > src/formats/office/sheets/numbers/fonts.rs +""" +import ast +import sys + +text = open(sys.argv[1]).read() +fonts = ast.literal_eval(text[text.index("{"):]) + + +def rule(ps): + base = ps.split("-", 1)[0] + for suffix in ("PSMT", "MT"): + if base.endswith(suffix): + base = base[: -len(suffix)] + break + out = "" + prev_lower = False + for c in base: + if c.isupper() and prev_lower: + out += " " + prev_lower = c.islower() + out += c + return out + + +rows = sorted((ps, v["family"]) for ps, v in fonts.items() if rule(ps) != v["family"]) +print("// Generated by scripts/office/sheets/numbers_fonts.py from numbers-parser's") +print("// fontmap.py (MIT, Jon Connell). Do not edit.") +print() +print("/// (PostScript name, family), by name.") +print("#[rustfmt::skip]") +print("pub(crate) const FAMILIES: &[(&str, &str)] = &[") +for ps, fam in rows: + print(f' ({ps!r}, {fam!r}),'.replace("'", '"')) +print("];") diff --git a/crates/exav-render/scripts/office/sheets/numbers_functions.py b/crates/exav-render/scripts/office/sheets/numbers_functions.py new file mode 100644 index 0000000..25d91af --- /dev/null +++ b/crates/exav-render/scripts/office/sheets/numbers_functions.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +"""Writes src/formats/office/sheets/numbers/functions.rs, Numbers' function +indexes (the AST_function_node_index of TSCE formula nodes) to their names, +from numbers-parser's src/numbers_parser/generated/functionmap.py (MIT, Jon +Connell), which maps them from the iWork applications. + +usage, from crates/exav-render: +python3 -I scripts/office/sheets/numbers_functions.py functionmap.py > src/formats/office/sheets/numbers/functions.rs +""" +import re +import sys + +text = open(sys.argv[1]).read() +rows = sorted((int(k), v) for k, v in re.findall(r'^\s*(\d+):\s*"([A-Z0-9.]+)"', text, re.M)) +print("// Generated by scripts/office/sheets/numbers_functions.py from numbers-parser's") +print("// functionmap.py (MIT, Jon Connell). Do not edit.") +print() +print("/// (function index, name), by index.") +print("#[rustfmt::skip]") +print("pub(crate) const FUNCTIONS: &[(u32, &str)] = &[") +for k, v in rows: + print(f' ({k}, "{v}"),') +print("];") diff --git a/crates/exav-render/src/formats/cad/dwg/blocks.rs b/crates/exav-render/src/formats/cad/dwg/blocks.rs index 2b3da90..c66d6a1 100644 --- a/crates/exav-render/src/formats/cad/dwg/blocks.rs +++ b/crates/exav-render/src/formats/cad/dwg/blocks.rs @@ -74,12 +74,19 @@ pub(crate) fn read(ctx: &mut Ctx<'_, '_>, vars: &Vars) -> Vec { } } } - ctx.names.insert(h, block.name.clone()); if block.end_handle.0 != 0 { let _ = typed(ctx, block.end_handle.0, ENDBLK, "ENDBLK"); } - records.push(rec); + records.push((h, rec)); } + number_anonymous(&mut records); + let records: Vec = records + .into_iter() + .map(|(h, rec)| { + ctx.names.insert(h, rec.block.name.clone()); + rec + }) + .collect(); let mut out = Vec::new(); for rec in records { let mut block = rec.block; @@ -112,6 +119,33 @@ pub(crate) fn read(ctx: &mut Ctx<'_, '_>, vars: &Vars) -> Vec { out } +/// AutoCAD's files can keep an anonymous block's name without its number in +/// both its record and its BLOCK entity: several `*U` blocks, each named by +/// its inserts, and found by that name. Each gets a number past the highest +/// one the drawing has, as AutoCAD numbers them when it loads the file. +fn number_anonymous(records: &mut [(u64, Record)]) { + let bare = |n: &str| matches!(n.as_bytes(), [b'*', c] if c.is_ascii_alphabetic()); + let mut next = records + .iter() + .filter_map(|(_, r)| { + let n = &r.block.name; + let digits = n + .trim_start_matches('*') + .trim_start_matches(|c: char| c.is_ascii_alphabetic()); + (n.starts_with('*') && !digits.is_empty()) + .then(|| digits.parse::().ok()) + .flatten() + }) + .max() + .unwrap_or(0); + for (_, r) in records.iter_mut() { + if bare(&r.block.name) { + next = next.saturating_add(1); + r.block.name = format!("{}{next}", r.block.name); + } + } +} + /// A layout's viewports have no number or status in DWG (spec 20.4.38), /// which DXF has (69, 68). As the converter writes them: an on viewport's /// number is its place among the layout's viewports from 1 and its status @@ -556,6 +590,52 @@ fn common(ctx: &mut Ctx<'_, '_>, vars: &Vars, o: &Object<'_>, record: Handle) -> mod tests { use super::*; + /// Inserts find their block by name, so two blocks named `*U` drew the + /// first one for both (AutoCAD's blocks_and_tables sample). + #[test] + fn bare_anonymous_names_are_numbered_past_the_highest() { + let mut records: Vec<(u64, Record)> = [ + "*Model_Space", + "*Paper_Space0", + "*U2", + "*U", + "*U", + "*D", + "*B12", + ] + .iter() + .map(|n| { + let block = Block { + name: (*n).to_string(), + ..Block::default() + }; + ( + 0, + Record { + block, + first: 0, + last: 0, + owned: Vec::new(), + }, + ) + }) + .collect(); + number_anonymous(&mut records); + let names: Vec<&str> = records.iter().map(|(_, r)| r.block.name.as_str()).collect(); + assert_eq!( + names, + [ + "*Model_Space", + "*Paper_Space0", + "*U2", + "*U13", + "*U14", + "*D15", + "*B12" + ] + ); + } + #[test] fn the_spaces_have_their_names_whatever_the_release_wrote() { for (written, read) in [ diff --git a/crates/exav-render/src/formats/cad/dwg/entities.rs b/crates/exav-render/src/formats/cad/dwg/entities.rs index 4ea60c1..d325efd 100644 --- a/crates/exav-render/src/formats/cad/dwg/entities.rs +++ b/crates/exav-render/src/formats/cad/dwg/entities.rs @@ -153,6 +153,7 @@ pub(crate) fn read( 0x29 => return none(EntityKind::XLine(ray(o)?)), 0x2C => return none(EntityKind::MText(Box::new(mtext(ctx, o)?))), 0x2D => return none(EntityKind::Leader(Box::new(leader(ctx, o)?))), + 0x2E => return none(EntityKind::Tolerance(Box::new(tolerance(ctx, o)?))), 0x2F => return none(EntityKind::MLine(Box::new(mline(ctx, o)?))), _ => {} } @@ -169,6 +170,7 @@ pub(crate) fn read( } "MULTILEADER" => none(EntityKind::MultiLeader(Box::new(multileader(ctx, o)?))), "HELIX" => none(EntityKind::Helix(Box::new(helix(ctx, o)?))), + "MESH" => none(EntityKind::Mesh(Box::new(mesh(ctx, o)?))), "ACAD_TABLE" => none(EntityKind::Table(Box::new(table(ctx, o)?))), "PDFUNDERLAY" => none(EntityKind::Underlay(Box::new(underlay( ctx, @@ -401,6 +403,60 @@ fn quad(o: &mut Object<'_>, v: Version) -> BitResult { }) } +/// TOLERANCE: R13 and R14 a BS, the height and the gap (BD each), not +/// kept; then the +/// insertion, direction and extrusion (3BD each), the text (TV), and the +/// dimension style in the handle stream. +fn tolerance(ctx: &mut Ctx<'_, '_>, o: &mut Object<'_>) -> BitResult { + let b = &mut o.data; + if ctx.version < Version::R2000 { + b.bs()?; + b.bd()?; + b.bd()?; + } + let mut t = Tolerance { + insertion: v3(b.bd3()?), + x_direction: v3(b.bd3()?), + extrusion: v3(b.bd3()?), + ..Tolerance::default() + }; + t.text = string(ctx, o)?; + t.dimstyle = entry(ctx, o, "dimension style")?; + Ok(t) +} + +/// MESH: BS version, B blend crease, BL subdivision level, BL vertex count +/// and the vertices (3BD), BL face list length and the list (BL each), each +/// face its count then its corners; the edges and creases after it are not +/// read. +fn mesh(ctx: &mut Ctx<'_, '_>, o: &mut Object<'_>) -> BitResult { + let b = &mut o.data; + b.bs()?; + b.b()?; + b.bl()?; + let n = i64::from(b.bl()?); + let n = count(b, n, 6)?; + let mut m = Mesh::default(); + for _ in 0..n { + let p = v3(o.data.bd3()?); + if ctx.room(m.vertices.len()) { + m.vertices.push(p); + } + } + let b = &mut o.data; + let n = i64::from(b.bl()?); + let n = count(b, n, 2)?; + let mut list = Vec::new(); + for _ in 0..n { + let k = i64::from(o.data.bl()?); + if ctx.room(list.len()) { + list.push(k); + } + } + m.faces = Mesh::faces_from_list(&list, m.vertices.len()); + Ok(m) +} + fn face3d(o: &mut Object<'_>, v: Version) -> BitResult { let b = &mut o.data; let mut f = Face3D::default(); @@ -599,6 +655,9 @@ fn insert( let block = o.handle_ref()?; i.block_name = ctx.name(block).unwrap_or_default().to_string(); let f = followers(o, v, has_attribs, n)?; + if o.xdictionary != 0 { + i.clip = super::objects::insert_clip(ctx, o.xdictionary); + } Ok((i, f)) } @@ -1662,8 +1721,12 @@ fn viewport(ctx: &mut Ctx<'_, '_>, o: &mut Object<'_>) -> BitResult { } let frozen = count(&o.handles, frozen, 8)?; for _ in 0..frozen { + // AutoCAD's files can hold null references here, which name no + // layer and which DXF leaves out. let h = o.handle_ref()?; - push(ctx, &mut p.frozen_layers, Handle(h)); + if h != 0 { + push(ctx, &mut p.frozen_layers, Handle(h)); + } } p.clip_boundary = Handle(o.handle_ref()?); Ok(p) diff --git a/crates/exav-render/src/formats/cad/dwg/header.rs b/crates/exav-render/src/formats/cad/dwg/header.rs index 7bb0fdf..28283a9 100644 --- a/crates/exav-render/src/formats/cad/dwg/header.rs +++ b/crates/exav-render/src/formats/cad/dwg/header.rs @@ -438,8 +438,11 @@ fn variables(s: &mut HeaderStreams<'_>, v: Version, vars: &mut Vars) -> BitResul } if r2004 { // SORTENTS, INDEXCTL, HIDETEXT, XCLIPFRAME, DIMASSOC, HALOGAP - for _ in 0..6 { - s.data.rc()?; + for i in 0..6 { + let x = s.data.rc()?; + if i == 3 { + vars.header.xclipframe = i16::from(x); + } } // OBSCUREDCOLOR, INTERSECTIONCOLOR skip_bs(s, 2)?; diff --git a/crates/exav-render/src/formats/cad/dwg/objects.rs b/crates/exav-render/src/formats/cad/dwg/objects.rs index bdcce72..de47821 100644 --- a/crates/exav-render/src/formats/cad/dwg/objects.rs +++ b/crates/exav-render/src/formats/cad/dwg/objects.rs @@ -243,6 +243,67 @@ pub(crate) fn annotative_columns(ctx: &mut Ctx<'_, '_>, xdictionary: u64) -> Opt first.flatten() } +/// An insert's XCLIP boundary: its extension dictionary's ACAD_FILTER +/// dictionary, whose SPATIAL entry is a SPATIAL_FILTER: BS +/// count (70), 2RD points (10), 3BD extrusion (210), 3BD origin (11), BS +/// display boundary (71), BS front clip on (72) and BD distance (40) when +/// set, the same for the back (73, 41), then the inverse insert matrix and +/// the clip boundary's, 12BD each (40). +pub(crate) fn insert_clip(ctx: &mut Ctx<'_, '_>, xdictionary: u64) -> Option { + let entry = |entries: Vec<(String, Handle)>, name: &str| { + entries + .into_iter() + .find(|(n, _)| n.eq_ignore_ascii_case(name)) + .map(|(_, h)| h) + }; + let acad = entry(entries_of(ctx, xdictionary), "ACAD_FILTER")?; + let spatial = entry(entries_of(ctx, acad.0), "SPATIAL")?; + let mut o = ctx.object(spatial.0, "spatial filter")?; + if ctx.dwg.type_name(o.type_code).as_deref() != Some("SPATIAL_FILTER") { + return None; + } + match spatial_filter(ctx, &mut o) { + Ok(c) => c, + Err(e) => { + ctx.warn( + WarningKind::Malformed, + format!("spatial filter {:X} could not be read: {e}", spatial.0), + ); + None + } + } +} + +fn spatial_filter(ctx: &mut Ctx<'_, '_>, o: &mut Object<'_>) -> BitResult> { + let b = &mut o.data; + let n = i64::from(b.bs()?); + let n = count(n, b.remaining(), 128)?; + let mut points = Vec::new(); + for _ in 0..n { + let p = v2(b.rd2()?); + if ctx.room(points.len()) { + points.push(p); + } + } + b.bd3()?; // extrusion + b.bd3()?; // origin + let enabled = b.bs()? != 0; + if b.bs()? != 0 { + b.bd()?; // front distance + } + if b.bs()? != 0 { + b.bd()?; // back distance + } + let mut inverse = [0.0; 12]; + for m in &mut inverse { + *m = b.bd()?; + } + if points.len() < 2 { + return Ok(None); + } + Ok(Some(InsertClip::from_filter(&points, &inverse, enabled))) +} + /// An ACDB_MTEXTOBJECTCONTEXTDATA_CLASS object: whether it is the default /// context, and its columns. fn mtext_context( diff --git a/crates/exav-render/src/formats/cad/dwg/tables.rs b/crates/exav-render/src/formats/cad/dwg/tables.rs index 2c46cff..aeb3bcf 100644 --- a/crates/exav-render/src/formats/cad/dwg/tables.rs +++ b/crates/exav-render/src/formats/cad/dwg/tables.rs @@ -421,9 +421,8 @@ fn dim_style(ctx: &mut Ctx<'_, '_>, o: &mut Object<'_>) -> BitResult { for _ in 0..11 { b.b()?; } - // DIMALTD, DIMZIN - b.rc()?; - b.rc()?; + b.rc()?; // DIMALTD + s.dimzin = i16::from(b.rc()?); // DIMSD1, DIMSD2 b.b()?; b.b()?; @@ -432,12 +431,17 @@ fn dim_style(ctx: &mut Ctx<'_, '_>, o: &mut Object<'_>) -> BitResult { b.rc()?; } b.b()?; // DIMUPT - // DIMTZIN, DIMALTZ, DIMALTTZ, DIMTAD - for _ in 0..4 { + // DIMTZIN, DIMALTZ, DIMALTTZ + for _ in 0..3 { b.rc()?; } - // DIMUNIT, DIMAUNIT, DIMDEC, DIMTDEC, DIMALTU, DIMALTTD - for _ in 0..6 { + s.dimtad = i16::from(b.rc()?); + // DIMUNIT, DIMAUNIT + b.bs()?; + b.bs()?; + s.dimdec = b.bs()?; + // DIMTDEC, DIMALTU, DIMALTTD + for _ in 0..3 { b.bs()?; } s.dimscale = b.bd()?; @@ -453,10 +457,11 @@ fn dim_style(ctx: &mut Ctx<'_, '_>, o: &mut Object<'_>) -> BitResult { s.dimtxt = b.bd()?; b.bd()?; // DIMCEN s.dimtsz = b.bd()?; - // DIMALTF, DIMLFAC, DIMTVP, DIMTFAC - for _ in 0..4 { - b.bd()?; - } + b.bd()?; // DIMALTF + s.dimlfac = b.bd()?; + // DIMTVP, DIMTFAC + b.bd()?; + b.bd()?; s.dimgap = b.bd()?; // DIMPOST, DIMAPOST, DIMBLK, DIMBLK1, DIMBLK2 for _ in 0..5 { @@ -497,20 +502,20 @@ fn dim_style(ctx: &mut Ctx<'_, '_>, o: &mut Object<'_>) -> BitResult { for _ in 0..6 { b.b()?; } - // DIMTAD, DIMZIN, DIMAZIN - for _ in 0..3 { - b.bs()?; - } + s.dimtad = b.bs()?; + s.dimzin = b.bs()?; + b.bs()?; // DIMAZIN if ctx.version >= Version::R2007 { b.bs()?; // DIMARCSYM } s.dimtxt = b.bd()?; b.bd()?; // DIMCEN s.dimtsz = b.bd()?; - // DIMALTF, DIMLFAC, DIMTVP, DIMTFAC - for _ in 0..4 { - b.bd()?; - } + b.bd()?; // DIMALTF + s.dimlfac = b.bd()?; + // DIMTVP, DIMTFAC + b.bd()?; + b.bd()?; s.dimgap = b.bd()?; b.bd()?; // DIMALTRND b.b()?; // DIMALT @@ -523,11 +528,16 @@ fn dim_style(ctx: &mut Ctx<'_, '_>, o: &mut Object<'_>) -> BitResult { s.dimclre = cmc(o, ctx.version)?.0; s.dimclrt = cmc(o, ctx.version)?.0; let b = &mut o.data; - // DIMADEC, DIMDEC, DIMTDEC, DIMALTU, DIMALTTD, DIMAUNIT, DIMFRAC, - // DIMLUNIT, DIMDSEP, DIMTMOVE, DIMJUST - for _ in 0..11 { + s.dimadec = b.bs()?; + s.dimdec = b.bs()?; + // DIMTDEC, DIMALTU, DIMALTTD, DIMAUNIT, DIMFRAC, DIMLUNIT + for _ in 0..6 { b.bs()?; } + s.dimdsep = b.bs()?; + // DIMTMOVE, DIMJUST + b.bs()?; + b.bs()?; // DIMSD1, DIMSD2 b.b()?; b.b()?; diff --git a/crates/exav-render/src/formats/cad/dxf/build.rs b/crates/exav-render/src/formats/cad/dxf/build.rs index 69a8fe8..0c58263 100644 --- a/crates/exav-render/src/formats/cad/dxf/build.rs +++ b/crates/exav-render/src/formats/cad/dxf/build.rs @@ -317,6 +317,27 @@ pub(crate) fn build(mut raw: Raw, ctx: Ctx<'_>) -> Drawing { } } + // An insert's clipping boundary: its extension dictionary's ACAD_FILTER + // dictionary, whose SPATIAL entry is the filter. + if !ctx.insert_dictionaries.is_empty() { + let dictionaries: HashMap = + raw.dictionaries.iter().map(|d| (d.handle, d)).collect(); + let filter_of = |xdict: u64| -> Option { + let acad = dictionaries.get(&Handle(xdict))?.get("ACAD_FILTER")?; + let spatial = dictionaries.get(&acad)?.get("SPATIAL")?; + ctx.spatial_filters.get(&spatial.0).cloned() + }; + for b in &mut blocks { + for e in &mut b.entities { + if let EntityKind::Insert(ins) = &mut e.kind { + if let Some(&x) = ctx.insert_dictionaries.get(&e.handle.0) { + ins.clip = filter_of(x); + } + } + } + } + } + Drawing { header: raw.header, layers: raw.layers, diff --git a/crates/exav-render/src/formats/cad/dxf/entities.rs b/crates/exav-render/src/formats/cad/dxf/entities.rs index 2950ef6..3c9cef0 100644 --- a/crates/exav-render/src/formats/cad/dxf/entities.rs +++ b/crates/exav-render/src/formats/cad/dxf/entities.rs @@ -92,6 +92,20 @@ fn plane(p: &mut Plane, t: &Tag<'_>) -> bool { p3(&mut p.extrusion, t, 210) } +/// A record's extension dictionary: group 360 of its `{ACAD_XDICTIONARY` +/// application group, which `Parts` sets aside. +fn xdictionary(tags: &[Tag<'_>]) -> Option { + let start = tags + .iter() + .position(|t| t.code == 102 && t.is("{ACAD_XDICTIONARY"))?; + tags.get(start + 1..)? + .iter() + .take_while(|t| t.code != 102) + .find(|t| t.code == 360) + .map(|t| t.handle()) + .filter(|h| *h != 0) +} + pub(crate) fn entity(rec: &Record<'_>, ctx: &mut Ctx<'_>) -> Entity { let parts = Parts::new(&rec.tags, false); let mut e = Entity { @@ -114,10 +128,17 @@ pub(crate) fn entity(rec: &Record<'_>, ctx: &mut Ctx<'_>) -> Entity { "SOLID" => EntityKind::Solid(quad(data)), "TRACE" => EntityKind::Trace(quad(data)), "3DFACE" => EntityKind::Face3D(face3d(data)), + "MESH" => EntityKind::Mesh(Box::new(mesh(data, ctx))), + "TOLERANCE" => EntityKind::Tolerance(Box::new(tolerance(data, ctx))), "TEXT" => EntityKind::Text(Box::new(text(data, false, ctx).0)), "ATTRIB" => EntityKind::Attribute(Box::new(attribute(&parts, data, ctx))), "ATTDEF" => EntityKind::AttributeDefinition(Box::new(attribute(&parts, data, ctx))), - "INSERT" => EntityKind::Insert(Box::new(insert(data, ctx))), + "INSERT" => { + if let Some(d) = xdictionary(&rec.tags) { + ctx.insert_dictionaries.insert(e.handle.0, d); + } + EntityKind::Insert(Box::new(insert(data, ctx))) + } "MTEXT" => { let mut m = mtext(data, ctx); if m.columns.is_none() { @@ -436,6 +457,81 @@ fn quad(data: &[Tag<'_>]) -> Quad { q } +/// MESH: its level 0 cage, 92 vertices (10, 20, 30) and a face list of 93 +/// values (90), each face its corner count then its corners; the edges +/// (94), creases (95) and overrides after it are not read. +fn mesh(data: &[Tag<'_>], ctx: &mut Ctx<'_>) -> Mesh { + #[derive(PartialEq)] + enum At { + Head, + Vertices, + Faces(usize), + Tail, + } + let mut m = Mesh::default(); + let mut list: Vec = Vec::new(); + let mut at = At::Head; + for t in data { + match (&at, t.code) { + (At::Head, 92) => at = At::Vertices, + (At::Vertices, 10) => { + if ctx.room(m.vertices.len()) { + m.vertices.push(Vec3::new(t.f64(), 0.0, 0.0)); + } + } + (At::Vertices, 20) => { + if let Some(v) = m.vertices.last_mut() { + v.y = t.f64(); + } + } + (At::Vertices, 30) => { + if let Some(v) = m.vertices.last_mut() { + v.z = t.f64(); + } + } + (At::Head | At::Vertices, 93) => { + let n = usize::try_from(t.int()).unwrap_or(0); + at = if n > 0 { At::Faces(n) } else { At::Tail }; + } + (At::Faces(left), 90) => { + let left = *left; + if ctx.room(list.len()) { + list.push(t.int()); + } + at = if left > 1 { + At::Faces(left - 1) + } else { + At::Tail + }; + } + (_, 94) => at = At::Tail, + _ => {} + } + } + m.faces = Mesh::faces_from_list(&list, m.vertices.len()); + m +} + +/// TOLERANCE: insertion (10), direction (11), extrusion (210), text (1), +/// dimension style (3). +fn tolerance(data: &[Tag<'_>], ctx: &mut Ctx<'_>) -> Tolerance { + let mut x = Tolerance::default(); + for t in data { + if p3(&mut x.insertion, t, 10) + || p3(&mut x.x_direction, t, 11) + || p3(&mut x.extrusion, t, 210) + { + continue; + } + match t.code { + 1 => x.text = ctx.text(t), + 3 => x.dimstyle = ctx.text(t), + _ => {} + } + } + x +} + fn face3d(data: &[Tag<'_>]) -> Face3D { let mut f = Face3D::default(); let mut fourth = false; diff --git a/crates/exav-render/src/formats/cad/dxf/header.rs b/crates/exav-render/src/formats/cad/dxf/header.rs index 18aa11d..ceabc72 100644 --- a/crates/exav-render/src/formats/cad/dxf/header.rs +++ b/crates/exav-render/src/formats/cad/dxf/header.rs @@ -106,6 +106,7 @@ pub(crate) fn read(tags: &[Tag<'_>], raw: &mut Raw, ctx: &mut Ctx<'_>) { "$LWDISPLAY" => h.lwdisplay = v.bool(), "$FILLMODE" => h.fillmode = v.bool(), "$MIRRTEXT" => h.mirrtext = v.bool(), + "$XCLIPFRAME" => h.xclipframe = v.i16(), _ => {} } } diff --git a/crates/exav-render/src/formats/cad/dxf/mod.rs b/crates/exav-render/src/formats/cad/dxf/mod.rs index 9f750e6..87a1f04 100644 --- a/crates/exav-render/src/formats/cad/dxf/mod.rs +++ b/crates/exav-render/src/formats/cad/dxf/mod.rs @@ -64,6 +64,11 @@ pub(crate) struct Ctx<'l> { /// Layer names and handles, once the tables are read: R12 viewports /// name their frozen layers. pub layer_handles: Vec<(String, Handle)>, + /// Each INSERT's extension dictionary, by the insert's handle: where its + /// clipping boundary is found once the objects are read. + pub insert_dictionaries: std::collections::HashMap, + /// SPATIAL_FILTER objects, by handle. + pub spatial_filters: std::collections::HashMap, } impl<'l> Ctx<'l> { @@ -79,6 +84,8 @@ impl<'l> Ctx<'l> { entity_limit_hit: false, item_limit_hit: false, layer_handles: Vec::new(), + insert_dictionaries: Default::default(), + spatial_filters: Default::default(), } } diff --git a/crates/exav-render/src/formats/cad/dxf/objects.rs b/crates/exav-render/src/formats/cad/dxf/objects.rs index 26c1083..3f83164 100644 --- a/crates/exav-render/src/formats/cad/dxf/objects.rs +++ b/crates/exav-render/src/formats/cad/dxf/objects.rs @@ -46,6 +46,42 @@ pub(crate) fn object(rec: &Record<'_>, raw: &mut Raw, ctx: &mut Ctx<'_>) { raw.dictionaries.push(d); } "LAYOUT" => raw.layouts.push(layout(&parts, handle, ctx)), + // An XCLIP boundary: its points (10), clipping on (71), then two + // matrices of 12 (40), the inverse insert matrix and the clip + // boundary's; the front and back distances are 40 and 41 before + // them, so the matrices are the last 24 of the 40s. + "SPATIAL_FILTER" => { + let mut points: Vec = Vec::new(); + let mut forties: Vec = Vec::new(); + let mut enabled = true; + for t in class(&parts, "AcDbSpatialFilter") { + match t.code { + 10 => { + if ctx.room(points.len()) { + points.push(Vec2::new(t.f64(), 0.0)); + } + } + 20 => { + if let Some(p) = points.last_mut() { + p.y = t.f64(); + } + } + 71 => enabled = t.bool(), + 40 if ctx.room(forties.len()) => forties.push(t.f64()), + _ => {} + } + } + let at = forties.len().saturating_sub(24); + let inverse = forties + .get(at..at + 12) + .and_then(|m| <[f64; 12]>::try_from(m).ok()); + if let (Some(inverse), true) = (inverse, forties.len() >= 24 && points.len() >= 2) { + ctx.spatial_filters.insert( + handle.0, + InsertClip::from_filter(&points, &inverse, enabled), + ); + } + } "SORTENTSTABLE" => { let mut s = SortEntsTable { handle, diff --git a/crates/exav-render/src/formats/cad/dxf/tables.rs b/crates/exav-render/src/formats/cad/dxf/tables.rs index b6cbca8..fc26f30 100644 --- a/crates/exav-render/src/formats/cad/dxf/tables.rs +++ b/crates/exav-render/src/formats/cad/dxf/tables.rs @@ -195,6 +195,12 @@ fn dim_style(parts: &Parts<'_>, handle: Handle, ctx: &mut Ctx<'_>) -> DimStyle { 140 => d.dimtxt = t.f64(), 142 => d.dimtsz = t.f64(), 147 => d.dimgap = t.f64(), + 77 => d.dimtad = t.i16(), + 78 => d.dimzin = t.i16(), + 144 => d.dimlfac = t.f64(), + 271 => d.dimdec = t.i16(), + 179 => d.dimadec = t.i16(), + 278 => d.dimdsep = t.i16(), 176 => d.dimclrd = Color::from_aci(t.int()), 177 => d.dimclre = Color::from_aci(t.int()), 178 => d.dimclrt = Color::from_aci(t.int()), diff --git a/crates/exav-render/src/formats/cad/json.rs b/crates/exav-render/src/formats/cad/json.rs index f29aad5..ed42bb0 100644 --- a/crates/exav-render/src/formats/cad/json.rs +++ b/crates/exav-render/src/formats/cad/json.rs @@ -340,6 +340,7 @@ fn header(o: &mut Obj<'_>, h: &Header) { o.b("lwdisplay", h.lwdisplay); o.b("fillmode", h.fillmode); o.b("mirrtext", h.mirrtext); + o.i("xclipframe", h.xclipframe); } fn layer(o: &mut Obj<'_>, l: &Layer) { @@ -401,6 +402,12 @@ fn dim_style(o: &mut Obj<'_>, d: &DimStyle) { o.f("dimtsz", d.dimtsz); o.f("dimtxt", d.dimtxt); o.f("dimgap", d.dimgap); + o.i("dimtad", d.dimtad); + o.i("dimzin", d.dimzin); + o.f("dimlfac", d.dimlfac); + o.i("dimdec", d.dimdec); + o.i("dimadec", d.dimadec); + o.i("dimdsep", d.dimdsep); o.color("dimclrd", d.dimclrd); o.color("dimclre", d.dimclre); o.color("dimclrt", d.dimclrt); @@ -947,6 +954,26 @@ fn kind(o: &mut Obj<'_>, k: &EntityKind) { o.v3s("corners", &f.corners); o.i("invisible_edges", f.invisible_edges); } + EntityKind::Mesh(m) => { + o.v3s("vertices", &m.vertices); + o.list("faces", &m.faces, |s, f| { + s.push('['); + for (n, i) in f.iter().enumerate() { + if n > 0 { + s.push(','); + } + let _ = write!(s, "{i}"); + } + s.push(']'); + }); + } + EntityKind::Tolerance(t) => { + o.v3("insertion", t.insertion); + o.v3("x_direction", t.x_direction); + o.v3("extrusion", t.extrusion); + o.str("text", &t.text); + o.str("dimstyle", &t.dimstyle); + } EntityKind::Text(t) => text(o, t), EntityKind::Attribute(a) | EntityKind::AttributeDefinition(a) => attribute(o, a), EntityKind::Insert(i) => { @@ -960,6 +987,13 @@ fn kind(o: &mut Obj<'_>, k: &EntityKind) { o.f("row_spacing", i.row_spacing); o.v3("extrusion", i.extrusion); o.objects("attributes", &i.attributes, entity); + match &i.clip { + Some(c) => o.object("clip", |o| { + o.v2s("boundary", &c.boundary); + o.b("enabled", c.enabled); + }), + None => o.null("clip"), + } } EntityKind::MText(m) => mtext(o, m), EntityKind::Dimension(d) => { diff --git a/crates/exav-render/src/formats/cad/model.rs b/crates/exav-render/src/formats/cad/model.rs index 136633a..c2b8d24 100644 --- a/crates/exav-render/src/formats/cad/model.rs +++ b/crates/exav-render/src/formats/cad/model.rs @@ -244,6 +244,8 @@ pub struct Header { pub lwdisplay: bool, pub fillmode: bool, pub mirrtext: bool, + /// `$XCLIPFRAME`: 0 hidden, 1 shown and plotted, 2 shown only. + pub xclipframe: i16, } impl Default for Header { @@ -286,6 +288,7 @@ impl Default for Header { lwdisplay: false, fillmode: true, mirrtext: false, + xclipframe: 2, } } } diff --git a/crates/exav-render/src/formats/cad/model/entity.rs b/crates/exav-render/src/formats/cad/model/entity.rs index 60ed8f8..5fd3d84 100644 --- a/crates/exav-render/src/formats/cad/model/entity.rs +++ b/crates/exav-render/src/formats/cad/model/entity.rs @@ -68,6 +68,7 @@ pub enum EntityKind { Leader(Box), Line(Line), LwPolyline(LwPolyline), + Mesh(Box), MLine(Box), MText(Box), MultiLeader(Box), @@ -80,6 +81,7 @@ pub enum EntityKind { Spline(Box), Table(Box), Text(Box), + Tolerance(Box), Trace(Quad), Underlay(Box), Viewport(Box), @@ -106,6 +108,7 @@ impl EntityKind { EntityKind::Leader(_) => "LEADER", EntityKind::Line(_) => "LINE", EntityKind::LwPolyline(_) => "LWPOLYLINE", + EntityKind::Mesh(_) => "MESH", EntityKind::MLine(_) => "MLINE", EntityKind::MText(_) => "MTEXT", EntityKind::MultiLeader(_) => "MULTILEADER", @@ -118,6 +121,7 @@ impl EntityKind { EntityKind::Spline(_) => "SPLINE", EntityKind::Table(_) => "ACAD_TABLE", EntityKind::Text(_) => "TEXT", + EntityKind::Tolerance(_) => "TOLERANCE", EntityKind::Trace(_) => "TRACE", EntityKind::Underlay(u) => match u.kind { UnderlayKind::Pdf => "PDFUNDERLAY", @@ -412,6 +416,63 @@ pub struct Quad { pub plane: Plane, } +/// MESH (2010 on): a subdivision mesh's control cage, in world +/// coordinates; its smoothed levels are not stored. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct Mesh { + pub vertices: Vec, + /// Each face's vertex indices, from 0. + pub faces: Vec>, +} + +impl Mesh { + /// The faces of a stored face list (each its corner count, then its + /// corners), those naming a vertex the mesh does not have left out. + pub fn faces_from_list(list: &[i64], vertices: usize) -> Vec> { + let mut faces = Vec::new(); + let mut i = 0; + while let Some(&n) = list.get(i) { + let Ok(n) = usize::try_from(n) else { break }; + let Some(ids) = list.get(i + 1..i + 1 + n) else { + break; + }; + let face: Option> = ids + .iter() + .map(|&k| u32::try_from(k).ok().filter(|&k| (k as usize) < vertices)) + .collect(); + if let Some(face) = face.filter(|f| f.len() >= 2) { + faces.push(face); + } + i += n + 1; + } + faces + } +} + +/// TOLERANCE: a feature control frame, its text in the GD&T font's codes +/// (`{\Fgdt;j}`), `%%v` between its boxes and `^J` between its rows. +#[derive(Clone, Debug, PartialEq)] +pub struct Tolerance { + pub insertion: Vec3, + pub x_direction: Vec3, + pub extrusion: Vec3, + pub text: String, + /// The dimension style: its text height, gap and colours. + pub dimstyle: String, +} + +impl Default for Tolerance { + fn default() -> Self { + Tolerance { + insertion: Vec3::default(), + x_direction: Vec3::new(1.0, 0.0, 0.0), + extrusion: Vec3::Z, + text: String::new(), + dimstyle: String::new(), + } + } +} + /// 3DFACE, in world coordinates. #[derive(Clone, Debug, Default, PartialEq)] pub struct Face3D { @@ -548,6 +609,39 @@ pub struct Insert { pub extrusion: Vec3, /// The ATTRIB entities that follow it. pub attributes: Vec, + /// Its clipping boundary (XCLIP), when it has one. + pub clip: Option, +} + +/// An insert's clipping boundary: the SPATIAL_FILTER its extension +/// dictionary names under ACAD_FILTER, then SPATIAL. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct InsertClip { + /// In the block's coordinates: the filter's points through its inverse + /// insert matrix. Two points are a rectangle's opposite corners. + pub boundary: Vec, + /// Group 71: clipping is on. + pub enabled: bool, +} + +impl InsertClip { + /// The boundary from a filter's points and its inverse insert matrix, + /// 12 numbers by rows of 4 (x' = m0 x + m1 y + m2 z + m3, ...). + pub fn from_filter(points: &[Vec2], inverse: &[f64; 12], enabled: bool) -> InsertClip { + let m = inverse; + InsertClip { + boundary: points + .iter() + .map(|p| { + Vec2::new( + m[0] * p.x + m[1] * p.y + m[3], + m[4] * p.x + m[5] * p.y + m[7], + ) + }) + .collect(), + enabled, + } + } } impl Default for Insert { @@ -563,6 +657,7 @@ impl Default for Insert { row_spacing: 0.0, extrusion: Vec3::Z, attributes: Vec::new(), + clip: None, } } } diff --git a/crates/exav-render/src/formats/cad/model/tables.rs b/crates/exav-render/src/formats/cad/model/tables.rs index bdafbfa..f0bb4da 100644 --- a/crates/exav-render/src/formats/cad/model/tables.rs +++ b/crates/exav-render/src/formats/cad/model/tables.rs @@ -162,6 +162,17 @@ pub struct DimStyle { pub dimtsz: f64, pub dimtxt: f64, pub dimgap: f64, + /// Text above the dimension line (1 and up) or centred on it (0). + pub dimtad: i16, + /// Zero suppression: 4 leading, 8 trailing. + pub dimzin: i16, + /// Scale applied to linear measurements. + pub dimlfac: f64, + /// Decimal places of linear and of angular measurements. + pub dimdec: i16, + pub dimadec: i16, + /// The decimal separator's character code. + pub dimdsep: i16, pub dimclrd: Color, pub dimclre: Color, pub dimclrt: Color, @@ -190,6 +201,12 @@ impl Default for DimStyle { dimtsz: 0.0, dimtxt: 0.18, dimgap: 0.09, + dimtad: 0, + dimzin: 0, + dimlfac: 1.0, + dimdec: 4, + dimadec: 0, + dimdsep: 46, dimclrd: Color::ByBlock, dimclre: Color::ByBlock, dimclrt: Color::ByBlock, diff --git a/crates/exav-render/src/formats/dwg/DESIGN.md b/crates/exav-render/src/formats/dwg/DESIGN.md index b23e304..5fa28d8 100644 --- a/crates/exav-render/src/formats/dwg/DESIGN.md +++ b/crates/exav-render/src/formats/dwg/DESIGN.md @@ -71,11 +71,26 @@ entities. | Fills | Hatch, Solid, Face3D, gradients | triangles: colour, layer id | | Glyphs | Text, MText, Attribute in an outline face | instanced quads into a Canvas-built atlas | -Curves are flattened at a tolerance chosen from the drawing's extents. Both +Circles, arcs and bulged polyline segments are strokes too, when nothing +dashes them and the transform keeps circles round: each carries a bulge, at +most a quarter turn's, and the fragment shader measures the distance to the +arc itself, so a curve is exact at any zoom. Other curves (ellipses, +splines, dashed arcs, arcs in a block scaled unevenly) are flattened at a +fixed sagitta of a thousandth of their radius, and an arc crossing a clip +boundary is cut as its flattened pieces. Both the stroke and fill buffers are sorted into spatial buckets recording the true -box of their contents, so a view draws only the buckets it touches. Buckets -are built within the opaque and the translucent halves, which are two passes -(only the first writes depth). +box of their contents, so a view draws only the buckets it touches. Only the +opaque half is bucketed. The translucent half follows it in draw order, cut +into tiles of consecutive entities, and is drawn after all opaque geometry, +fills and strokes interleaved by draw order (`translucent_runs`). Both passes +write depth, so an entity's overlaps with itself blend once. Text under +translucent geometry is drawn in two parts: the glyphs' solid cores before +the translucent pass, their edges after it. + +The context has no multisampling: strokes measure their own coverage. An +opaque fill of one colour is outlined by strokes of no width (`FILL_EDGE`), +whose fringe is the coverage of the pixels just outside it; drawn at the +fill's depth, they are hidden wherever the fill is. ### 3.3 Layer show and hide without re-uploading @@ -125,19 +140,28 @@ it into the view matrix. |---|---| | Lines, arcs, circles, ellipses, polylines, splines | Drawn | | Blocks and inserts, nested, scaled, rotated, MINSERT arrays | Drawn, with a cycle guard | -| Dimensions | Drawn from the anonymous block AutoCAD bakes | +| Dimensions | Drawn from the anonymous block AutoCAD bakes; one saved without it from its definition points and style (`dimension.rs`: no DIMTIH, feet and inches, tolerances or alternate units) | | MLINE, HELIX | Drawn | | Layers: colour, on/off, freeze, transparency | From the file | | Lineweight | Instanced quads, zoom-aware | | Solid and gradient hatch, islands | Even-odd, holes bridged into the outer ring | | Pattern hatch | Line families clipped to the region, with dash phase | | Linetypes | Dashed in drawing units, phase carried along a polyline; LTSCALE, per-entity and block scale | +| Complex linetypes | Their text; the shapes of ltypeshp.shx (AutoCAD's own TRACKS, ZIGZAG, FENCELINE1 and 2, BATTING), redrawn; other shape files' shapes left out | | Extrusion (OCS) | Arbitrary Axis Algorithm, for the entity types stored in object coordinates | -| TrueType text | Bundled faces, glyph atlas | +| TrueType text | Bundled faces, glyph atlas sized to the view; distance fields when the character set is too large for that size | | SHX text | Substituted, see 5.3 | -| MTEXT formatting | Colour, height, font, the three rules, indents and tabs kept; stacked fractions as `a/b` | +| MTEXT formatting | Colour, height, font, width factor, oblique, tracking, the three rules, indents, tabs, justification, stacks, background masks and frames | +| Text placement | Mirrored and stretched with its block, TEXT's backward and upside-down flags, Bottom and Middle on the face's descender | +| Symbol fonts | symbol.ttf, greeks/greekc.shx and gdt.shx as the characters they draw | +| Characters the stroke font lacks (CJK) | The run drawn in the outline face, completed from the browser's fonts | | Paper-space layouts and viewports | Drawn | -| External references, images, OLE | Frame only; counted in the warnings | +| External references, images, OLE | Xrefs: their path at the insertion point; images, underlays, OLE: frame only; all counted, with the files they name, in the warnings | +| XCLIP | The block cut to its boundary, the frame as `$XCLIPFRAME` says | +| Points | `$PDMODE` shapes, `$PDSIZE` (a share of the drawing's height when not in units) | +| 3DFACE, polyface and polygon meshes, MESH | Their visible edges, in plan | +| TOLERANCE | Feature control frame, GD&T symbols | +| Leader arrowheads | The style's arrow block, else AutoCAD's built-in shape of that name | | Custom objects (proxy graphics) | Drawn from the graphics saved with them, see 5.4; those saved without are counted in the warnings | | Plot styles (CTB/STB) | Not planned | diff --git a/crates/exav-render/src/formats/dwg/clip.rs b/crates/exav-render/src/formats/dwg/clip.rs index 9d42dea..a7beb78 100644 --- a/crates/exav-render/src/formats/dwg/clip.rs +++ b/crates/exav-render/src/formats/dwg/clip.rs @@ -65,6 +65,17 @@ impl ClipShape { }) } + /// The region as triangles. + pub fn triangles(&self) -> Vec<[[f64; 2]; 3]> { + match self { + ClipShape::Rect { min, max } => vec![ + [[min[0], min[1]], [max[0], min[1]], [max[0], max[1]]], + [[min[0], min[1]], [max[0], max[1]], [min[0], max[1]]], + ], + ClipShape::Poly { pieces, .. } => pieces.clone(), + } + } + pub fn bounds(&self) -> ([f64; 2], [f64; 2]) { match self { ClipShape::Rect { min, max } => (*min, *max), diff --git a/crates/exav-render/src/formats/dwg/curves.rs b/crates/exav-render/src/formats/dwg/curves.rs index e43b56e..ba09271 100644 --- a/crates/exav-render/src/formats/dwg/curves.rs +++ b/crates/exav-render/src/formats/dwg/curves.rs @@ -4,8 +4,9 @@ use std::f64::consts::TAU; /// Sagitta error target as a fraction of radius. 0.001 gives ~70 segments for a -/// full circle, which holds up past the zoom levels a viewer reaches before -/// re-tessellation would kick in. +/// full circle. The curves that reach here are flattened once and never +/// refined at a closer zoom; a circle, arc or bulge that nothing prevents is +/// not flattened at all (see DESIGN.md). const SAGITTA_RATIO: f64 = 0.001; const MIN_SEGMENTS: usize = 8; const MAX_SEGMENTS: usize = 512; @@ -31,6 +32,58 @@ fn ccw_sweep(sweep: f64) -> Option { Some(if s > 0.0 { s } else { TAU }) } +/// The centre, radius and angles of the arc from `a` to `b` with this +/// bulge: (cx, cy, r, start, signed sweep). None for a straight one. +pub fn bulge_arc(a: [f64; 2], b: [f64; 2], bulge: f64) -> Option<(f64, f64, f64, f64, f64)> { + let chord = (b[0] - a[0]).hypot(b[1] - a[1]); + if bulge == 0.0 || !bulge.is_finite() || chord < 1e-12 { + return None; + } + let sweep = 4.0 * bulge.atan(); + let r = chord / (2.0 * (sweep / 2.0).sin().abs()); + // The centre lies off the chord's middle, to its left for a + // counter-clockwise arc under half a turn. + let (mx, my) = ((a[0] + b[0]) / 2.0, (a[1] + b[1]) / 2.0); + let (ux, uy) = ((b[0] - a[0]) / chord, (b[1] - a[1]) / chord); + let d = chord / 2.0 / (sweep / 2.0).tan(); + let (cx, cy) = (mx - uy * d, my + ux * d); + let start = (a[1] - cy).atan2(a[0] - cx); + Some((cx, cy, r, start, sweep)) +} + +/// `n` + 1 points along the arc from `a` to `b` with this bulge. +pub fn bulge_points(a: [f64; 2], b: [f64; 2], bulge: f64, n: usize) -> Vec<[f64; 2]> { + let Some((cx, cy, r, start, sweep)) = bulge_arc(a, b, bulge) else { + return vec![a, b]; + }; + let n = n.max(1); + let mut out: Vec<[f64; 2]> = (0..=n) + .map(|i| { + let t = start + sweep * i as f64 / n as f64; + [cx + r * t.cos(), cy + r * t.sin()] + }) + .collect(); + // The ends exactly where they were. + out[0] = a; + out[n] = b; + out +} + +/// Sample a circular arc from `start` over a signed `sweep` (radians, +/// positive counter-clockwise). +pub fn arc_points(cx: f64, cy: f64, r: f64, start: f64, sweep: f64) -> Vec<[f64; 2]> { + if !r.is_finite() || r <= 0.0 || !sweep.is_finite() || !start.is_finite() { + return Vec::new(); + } + let n = segments_for_sweep(sweep); + (0..=n) + .map(|i| { + let a = start + sweep * (i as f64 / n as f64); + [cx + r * a.cos(), cy + r * a.sin()] + }) + .collect() +} + /// Sample a circular arc counter-clockwise from `start` to `end` (radians). pub fn flatten_arc(cx: f64, cy: f64, r: f64, start: f64, end: f64) -> Vec<[f64; 2]> { if !r.is_finite() || r <= 0.0 { @@ -529,6 +582,25 @@ mod tests { ((a[0] - b[0]).powi(2) + (a[1] - b[1]).powi(2)).sqrt() } + #[test] + fn a_bulge_is_its_arc() { + let quarter = (PI / 8.0).tan(); + // Counter-clockwise from (1,0) to (0,1): about the origin, radius 1. + let (cx, cy, r, start, sweep) = bulge_arc([1.0, 0.0], [0.0, 1.0], quarter).unwrap(); + assert!(cx.abs() < 1e-12 && cy.abs() < 1e-12 && (r - 1.0).abs() < 1e-12); + assert!(start.abs() < 1e-12 && (sweep - PI / 2.0).abs() < 1e-12); + // Clockwise the other way round: about (1,1). + let (cx, cy, _, _, sweep) = bulge_arc([1.0, 0.0], [0.0, 1.0], -quarter).unwrap(); + assert!((cx - 1.0).abs() < 1e-12 && (cy - 1.0).abs() < 1e-12 && sweep < 0.0); + // Three quarters of a turn: its middle point on the far side. + let pts = bulge_points([1.0, 0.0], [0.0, -1.0], (3.0 * PI / 8.0).tan(), 2); + assert!( + dist(pts[1], [-(0.5f64.sqrt()), 0.5f64.sqrt()]) < 1e-12, + "{pts:?}" + ); + assert!(bulge_arc([1.0, 0.0], [0.0, 1.0], 0.0).is_none()); + } + /// `f`'s result, or a failure if it has not returned within five seconds /// (the thread is left spinning; the test binary exits anyway). fn finishes(f: impl FnOnce() -> T + Send + 'static) -> T { diff --git a/crates/exav-render/src/formats/dwg/dimension.rs b/crates/exav-render/src/formats/dwg/dimension.rs new file mode 100644 index 0000000..6801a41 --- /dev/null +++ b/crates/exav-render/src/formats/dwg/dimension.rs @@ -0,0 +1,471 @@ +//! A dimension's graphics, for one saved without the anonymous block AutoCAD +//! draws it from: generators often leave the block out. The geometry follows +//! the definition points and the style's sizes; what this leaves to the +//! block (DIMTIH, DIMLUNIT's feet and inches, tolerances, alternate units, +//! arrows flipped outside a short dimension) is not drawn. + +use crate::cad::{DimStyle, Dimension, DimensionKind, Vec3}; + +/// A style's sizes in drawing units (DIMSCALE applied) and how it writes +/// numbers. +pub struct Style { + pub asz: f64, + pub exo: f64, + pub exe: f64, + pub dle: f64, + pub tsz: f64, + pub txt: f64, + pub gap: f64, + /// Text above the dimension line, else centred on it, the line broken. + pub above: bool, + pub zin: i16, + pub lfac: f64, + pub dec: usize, + pub adec: usize, + pub dsep: char, +} + +impl Style { + pub fn new(s: &DimStyle) -> Style { + let scale = if s.dimscale > 0.0 && s.dimscale.is_finite() { + s.dimscale + } else { + 1.0 + }; + let size = |v: f64| if v.is_finite() { v.abs() * scale } else { 0.0 }; + let places = |v: i16| usize::from(v.clamp(0, 8) as u8); + Style { + asz: size(s.dimasz), + exo: size(s.dimexo), + exe: size(s.dimexe), + dle: size(s.dimdle), + tsz: size(s.dimtsz), + txt: size(s.dimtxt), + gap: size(s.dimgap), + above: s.dimtad != 0, + zin: s.dimzin, + lfac: if s.dimlfac.is_finite() && s.dimlfac != 0.0 { + s.dimlfac.abs() + } else { + 1.0 + }, + dec: places(s.dimdec), + adec: places(s.dimadec), + dsep: char::from_u32(u32::from(s.dimdsep.max(0) as u16)) + .filter(|c| !c.is_control()) + .unwrap_or('.'), + } + } +} + +/// The text, its middle at `at`, turned by `rotation` (radians). +pub struct Label { + pub text: String, + pub at: [f64; 2], + pub rotation: f64, +} + +#[derive(Default)] +pub struct Graphics { + pub lines: Vec<[[f64; 2]; 2]>, + /// Centre, radius, start angle and signed sweep (radians). + pub arcs: Vec<([f64; 2], f64, f64, f64)>, + /// An arrowhead's tip, and a point it points away from. + pub arrows: Vec<([f64; 2], [f64; 2])>, + pub label: Option
Facts
one
two
x
y
"; + let wb = read_str(page); + let s = &wb.sheets[0]; + assert_eq!(value(s, 0, 0), &Value::text("Facts")); + assert_eq!(value(s, 1, 0), &Value::text("one")); + assert_eq!(value(s, 2, 0), &Value::text("two")); + assert_eq!(value(s, 2, 1), &Value::text("y")); + assert_eq!(style(&wb, s, 1, 1).border.left.style, Some("thin")); + // Excel's style sheet keeps it in the cell. + let wb = read_str("
one
two
"); + assert_eq!(value(&wb.sheets[0], 0, 0), &Value::text("one\ntwo")); +} + +#[test] +fn encodings() { + let page = b"
\xcf\xf0\xe8\xe2\xe5\xf2
"; + let wb = read(page, &mut Budget::new(Limits::default())).unwrap(); + assert_eq!(value(&wb.sheets[0], 0, 0), &Value::text("Привет")); + let utf16: Vec = [0xFF, 0xFE] + .into_iter() + .chain( + "
é
" + .encode_utf16() + .flat_map(u16::to_le_bytes), + ) + .collect(); + let wb = read(&utf16, &mut Budget::new(Limits::default())).unwrap(); + assert_eq!(value(&wb.sheets[0], 0, 0), &Value::text("é")); +} + +#[test] +fn refusals_and_limits() { + let b = || Budget::new(Limits::default()); + assert!(matches!( + read(b"just text, a < b", &mut b()), + Err(Error::NotFormat(_)) + )); + assert!(matches!( + read(b"

no table

", &mut b()), + Err(Error::NotFormat(_)) + )); + // A workbook's frameset: its sheets are other files, not read. + let frames = b""; + assert!(matches!(read(frames, &mut b()), Err(Error::Unsupported(_)))); + let few = Limits::default().with_max_cells(5); + assert_eq!( + read(EXCEL.as_bytes(), &mut Budget::new(few)).unwrap_err(), + Error::TooLarge("cells") + ); +} + +#[test] +fn hostile_pages() { + let b = EXCEL.as_bytes(); + for cut in (0..b.len()).step_by(37) { + let _ = read(&b[..cut], &mut Budget::new(Limits::default())); + } + let deep = "", + "
".repeat(300); + assert!(read(deep.as_bytes(), &mut Budget::new(Limits::default())).is_err()); + for page in [ + "
x
", + "
���&bogus;&
", + "
1e9991,2,3
", + "
x
x", + "vbscript:msgbox(1)", + "file:///etc/passwd", + "ftp://example.com/x", + "blob:https://example.com/1", + "about:blank", + "/relative/path", + "../up", + "page.html", + "#anchor", + "//evil.example/x", + "https://user:pass@example.com/", + "https://google.com@evil.example/", + "https://google.com\\@evil.example/", + "https://", + "https:///x", + "http://?x", + "mailto:", + "tel:+123", + "https://exa\u{202e}mple.com/", + "https://example.com/a\u{2028}b", + "https://example.com/a\u{85}b", + "https://example.com/a b", + "https://example.com/\u{7f}", + &long, + ]; + for target in refused { + // In angle brackets, which allow spaces, and bare, for a target with none. + let inside = target.replace(['<', '>', '\n'], " "); + let mut forms = vec![format!("[click me](<{inside}>)")]; + if !target + .contains(|c: char| c.is_whitespace() || c == '(' || c == ')' || c == '<' || c == '>') + { + forms.push(format!("[click me]({target})")); + } + for md in forms { + let d = doc(&md); + assert!(links(&d).is_empty(), "{md:?} -> {:?}", d.blocks); + assert!(paras(&d.blocks).concat().contains("click me"), "{md:?}"); + } + } +} + +#[test] +fn a_target_of_the_longest_size_is_kept_and_one_byte_more_is_not() { + let base = "https://example.com/"; + let fits = format!("{base}{}", "a".repeat(MAX_TARGET - base.len())); + assert_eq!(one(&format!("[x](<{fits}>)")).len(), 1); + assert!(one(&format!("[x](<{fits}a>)")).is_empty()); +} + +#[test] +fn an_image_is_its_alt_text_and_loads_nothing() { + let d = doc("![a diagram](https://example.com/d.png) ![](https://example.com/e.png) ![x *y* `z`](data:image/png;base64,AAAA)"); + let alts: Vec<_> = all_inlines(&d) + .into_iter() + .filter_map(|n| { + if let Inline::Image { alt } = n { + Some(alt) + } else { + None + } + }) + .collect(); + assert_eq!(alts, ["a diagram", "", "x y z"]); + assert!(links(&d).is_empty()); + let json = d.to_json(); + assert!( + !json.contains("example.com") && !json.contains("base64"), + "{json}" + ); +} + +#[test] +fn an_image_inside_a_link_keeps_the_link() { + let d = doc("[![logo](https://example.com/l.png)](https://example.com/home)"); + assert_eq!(links(&d), [pair("https://example.com/home", "logo")]); +} + +// ── raw HTML ───────────────────────────────────────────────────────────────── + +const HOSTILE_HTML: &[&str] = &[ + "", + "", + "", + "", + "x", + "", + "
", + "
", + "bold", + "", + "", + "", + "", + "

", +]; + +#[test] +fn raw_html_is_text_exactly_as_written() { + for html in HOSTILE_HTML { + let d = doc(html); + // A block of HTML, or a paragraph that has tags in it: the characters are all there is. + let shown = match d.blocks.as_slice() { + [Block::Raw(s)] => s.clone(), + [Block::Para(c)] => text(c), + other => panic!("{html}: {other:?}"), + }; + assert_eq!(shown, *html); + assert!( + all_inlines(&d).iter().all(|n| matches!(n, Inline::Text(_))), + "{html}" + ); + } +} + +#[test] +fn raw_html_is_text_inside_every_construct() { + let html = ""; + let wrapped = [ + format!("# {html}"), + format!("> {html}"), + format!("- {html}"), + format!("1. {html}"), + format!("*{html}*"), + format!("**{html}**"), + format!("[{html}](https://example.com)"), + format!("![{html}](https://example.com/i.png)"), + format!("| {html} |\n|---|\n| {html} |"), + format!("`{html}`"), + format!("```\n{html}\n```"), + format!(" {html}"), + format!("a {html} b"), + ]; + for md in wrapped { + let d = doc(&md); + // Whatever the shape, the tag's characters are somewhere as text, + // and nothing but the node kinds of this tree exists. + let json = d.to_json(); + assert!( + json.contains("") || json.contains(" { + if let Some(t) = m.get("t") { + assert!(KINDS.contains(&t.as_str().unwrap()), "{t}"); + assert!(m.keys().all(|k| KEYS.contains(&k.as_str())), "{m:?}"); + } + m.values().for_each(assert_kinds); + } + serde_json::Value::Array(a) => a.iter().for_each(assert_kinds), + _ => {} + } +} + +// ── the JSON the page reads ────────────────────────────────────────────────── + +#[test] +fn the_json_is_valid_and_has_the_shape_the_page_reads() { + let d = doc("# H\n\ntext **b** [l](https://example.com/\"q\")\n\n- a\n- b\n\n| x | y |\n|:-|-:|\n| 1 | 2 |\n\n> q\n\n```\ncode\n```\n\n---\n\n
raw
\n"); + let v: serde_json::Value = serde_json::from_str(&d.to_json()).unwrap(); + assert_eq!(v["truncated"], false); + let kinds: Vec<_> = v["blocks"] + .as_array() + .unwrap() + .iter() + .map(|b| b["t"].as_str().unwrap()) + .collect(); + assert_eq!( + kinds, + ["h", "p", "list", "table", "quote", "code", "hr", "raw"] + ); + assert_eq!( + v["blocks"][0], + serde_json::json!({"t": "h", "level": 1, "c": [{"t": "text", "s": "H"}]}) + ); + assert_eq!(v["blocks"][2]["tight"], true); + assert_eq!(v["blocks"][2]["start"], 1); + assert_eq!( + v["blocks"][3]["align"], + serde_json::json!(["left", "right"]) + ); + assert_eq!(v["blocks"][3]["head"][0][0]["s"], "x"); + // The quotes in the target are the link's own, not a break out of the string. + assert_eq!(v["blocks"][1]["c"][3]["url"], "https://example.com/\"q\""); + assert_eq!(v["blocks"][7]["s"], "
raw
"); + assert_kinds(&v); +} + +#[test] +fn strings_survive_the_json() { + let nasty = + "quote \" slash \\ tab \t nul \u{0} bell \u{7} sep \u{2028} emoji \u{1F600} close ]}"; + let d = doc(&format!("```\n{nasty}\n```")); + let v: serde_json::Value = serde_json::from_str(&d.to_json()).unwrap(); + assert_eq!(v["blocks"][0]["s"], nasty); +} + +// ── limits ─────────────────────────────────────────────────────────────────── + +fn depth(blocks: &[Block]) -> usize { + blocks + .iter() + .map(|b| match b { + Block::Quote(c) => 1 + depth(c), + Block::List { items, .. } => 1 + items.iter().map(|i| depth(i)).max().unwrap_or(0), + _ => 0, + }) + .max() + .unwrap_or(0) +} + +fn inline_depth(c: &[Inline]) -> usize { + c.iter() + .map(|n| match n { + Inline::Em(c) + | Inline::Strong(c) + | Inline::Del(c) + | Inline::Link { children: c, .. } => 1 + inline_depth(c), + _ => 0, + }) + .max() + .unwrap_or(0) +} + +fn raws(blocks: &[Block], out: &mut String) { + for b in blocks { + match b { + Block::Raw(s) => out.push_str(s), + Block::Quote(c) => raws(c, out), + Block::List { items, .. } => items.iter().for_each(|i| raws(i, out)), + _ => {} + } + } +} + +#[test] +fn quotes_stop_nesting_at_the_limit_and_the_rest_is_text() { + let d = doc(&format!("{}deep text", "> ".repeat(50))); + assert_eq!(depth(&d.blocks), MAX_BLOCK_DEPTH); + let mut raw = String::new(); + raws(&d.blocks, &mut raw); + assert!(raw.contains("deep text"), "{:?}", d.blocks); +} + +#[test] +fn lists_stop_nesting_at_the_limit_and_the_rest_is_text() { + let md: Vec = (0..50) + .map(|i| format!("{}- level{i}", " ".repeat(i))) + .collect(); + let d = doc(&md.join("\n")); + assert_eq!(depth(&d.blocks), MAX_BLOCK_DEPTH); + let mut raw = String::new(); + raws(&d.blocks, &mut raw); + assert!(raw.contains("level49"), "{raw:?}"); + assert!( + raw.contains("level10") && !raw.contains("level9"), + "{raw:?}" + ); +} + +#[test] +fn quotes_and_lists_count_toward_one_limit() { + let d = doc(&format!("{}x", "> - ".repeat(30))); + assert_eq!(depth(&d.blocks), MAX_BLOCK_DEPTH); +} + +#[test] +fn inlines_stop_nesting_at_the_limit_and_keep_their_text() { + let d = doc(&format!("{}x{}", "*a **b ".repeat(60), "** b* ".repeat(60))); + let Block::Para(c) = &d.blocks[0] else { + panic!("{:?}", d.blocks) + }; + assert!(inline_depth(c) <= MAX_INLINE_DEPTH, "{}", inline_depth(c)); + assert!(text(c).contains('x')); + // And links nested in emphasis nested in links. + let d = doc(&format!( + "{}x{}", + "*[a ".repeat(100), + "](https://example.com)*".repeat(100) + )); + let Block::Para(c) = &d.blocks[0] else { + panic!("{:?}", d.blocks) + }; + assert!(inline_depth(c) <= MAX_INLINE_DEPTH); +} + +#[test] +fn a_document_stops_at_the_node_limit_and_says_so() { + let d = doc(&"x *y*\n\n".repeat(150_000)); + assert!(d.truncated); + assert!(d.blocks.len() < 150_000 && d.blocks.len() > 1000); + assert!(d.to_json().ends_with("\"truncated\":true}")); + assert!(!doc("# small").truncated); +} + +#[test] +fn what_was_open_at_the_node_limit_is_kept() { + let d = doc(&"- a *b*\n".repeat(200_000)); + assert!(d.truncated); + let Block::List { items, .. } = &d.blocks[0] else { + panic!("{} blocks", d.blocks.len()) + }; + assert!( + items.len() > 1000 && items.len() < 200_000, + "{}", + items.len() + ); +} + +#[test] +fn the_node_limit_counts_table_cells_and_the_padding_of_short_rows() { + let head = format!( + "|{}\n|{}\n", + "a|".repeat(MAX_COLUMNS), + "-|".repeat(MAX_COLUMNS) + ); + let d = doc(&format!("{head}{}", "|1|\n".repeat(20_000))); + assert!(d.truncated); + let Block::Table { rows, .. } = &d.blocks[0] else { + panic!("{:?}", d.blocks.len()) + }; + assert!( + rows.len() * MAX_COLUMNS <= MAX_NODES + MAX_COLUMNS, + "{}", + rows.len() + ); +} + +#[test] +fn a_table_keeps_at_most_the_column_limit() { + let n = MAX_COLUMNS + 40; + let md = format!( + "|{}\n|{}\n|{}\n", + "a|".repeat(n), + "-|".repeat(n), + "b|".repeat(n) + ); + let d = doc(&md); + let Block::Table { align, head, rows } = &d.blocks[0] else { + panic!("{:?}", d.blocks) + }; + assert_eq!( + (align.len(), head.len(), rows[0].len()), + (MAX_COLUMNS, MAX_COLUMNS, MAX_COLUMNS) + ); +} + +#[test] +fn a_list_start_is_nine_digits_at_most() { + let d = doc("999999999. a\n\n1234567890. b"); + assert!(matches!( + d.blocks[0], + Block::List { + start: 999_999_999, + .. + } + )); + assert!(d + .blocks + .iter() + .all(|b| !matches!(b, Block::List { start, .. } if *start > 999_999_999))); +} + +fn rep(n: usize, s: &str) -> String { + s.repeat(n) +} + +fn hostile() -> Vec<(&'static str, String)> { + let lines = + |n: usize, f: &dyn Fn(usize) -> String| (0..n).map(f).collect::>().join("\n"); + vec![ + ("100k stars", rep(100_000, "*")), + ("100k stars and letters", rep(50_000, "*a ")), + ("100k underscores", rep(100_000, "_")), + ("closers only", rep(40, &format!("{}\n", rep(3000, "a* ")))), + ( + "closers that fail the rule of three", + rep(40, &format!("{}\n", rep(1500, "a** b* "))), + ), + ( + "underscore closers", + rep(40, &format!("{}\n", rep(3000, "a_ "))), + ), + ("alternating emphasis", rep(50_000, "*a_b")), + ("100k open brackets", rep(100_000, "[")), + ("100k link openers", rep(100_000, "[](")), + ( + "link openers filling the limit", + rep(200, &format!("{}\n", rep(3333, "[]("))), + ), + ("100k image openers", rep(100_000, "![")), + ( + "brackets then parens", + rep(50_000, "[a]") + &rep(50_000, "("), + ), + ("nested links", rep(20_000, "[a](") + &rep(20_000, ")")), + ("100k backticks", rep(100_000, "`")), + ( + "ascending backtick runs", + (0..1500) + .map(|i| "`".repeat(i + 1)) + .collect::>() + .join(" "), + ), + ("100k angle brackets", rep(100_000, "<")), + ("autolink openers", rep(30_000, "")), + ("10k nested quotes", rep(10_000, "> ") + "deep"), + ( + "quote staircase", + lines(2000, &|i| format!("{}x", "> ".repeat(i % 40))), + ), + ("nested list on one line", rep(10_000, "- ") + "deep"), + ( + "list staircase", + lines(3000, &|i| format!("{}- item", " ".repeat(2 * (i % 60)))), + ), + ( + "ordered list staircase", + lines(3000, &|i| format!("{}1. item", " ".repeat(3 * (i % 60)))), + ), + ("20k tiny items", rep(20_000, "- a\n")), + ("20k blank-separated items", rep(20_000, "- a\n\n")), + ("50k headings", rep(50_000, "# h\n")), + ("50k hr", rep(50_000, "---\n")), + ( + "wide table", + format!( + "|{}\n|{}\n{}", + rep(5000, "a|"), + rep(5000, "-|"), + rep(2000, &format!("|{}\n", rep(100, "x|"))) + ), + ), + ( + "long table", + format!("|a|b|\n|-|-|\n{}", rep(50_000, "|1|2|\n")), + ), + ("fence storms", rep(30_000, "```\n")), + ("setext storms", rep(30_000, "a\n===\n")), + ("html storm", rep(30_000, "
bc"), + "abc\n" + ); + // A raw-text element ends at its own end tag only. + assert_eq!(html("z"), "z\n"); + assert_eq!(html("yes"), "yes\n"); + // A script that opens a comment and another script ends at the second end tag. + assert_eq!(html("z"), "z\n"); +} + +#[test] +fn entities_are_decoded_whatever_their_name() { + assert_eq!( + html("& <b> ♥ A B  x &zzzz; ∳"), + "& \u{2665} A B x &zzzz; \u{2233}\n" + ); + // The specification's legacy names need no semicolon. + assert_eq!(html("¬it"), "\u{ac}it\n"); +} + +#[test] +fn a_link_is_its_label_and_where_it_leads() { + assert_eq!( + html("Click here now"), + "Click here (https://evil.example/x?a=1&b=2) now\n" + ); + // The label that is the target says it once; a fragment leads nowhere. + assert_eq!( + html("https://a.example/ top"), + "https://a.example/ top\n" + ); + // Whatever the target is. + assert_eq!( + html("run"), + "run (javascript:alert(1))\n" + ); + // A label naming one site over a target on another is all there to see. + let t = html("https://www.paypal.com/login"); + assert!( + t.contains("paypal.com/login") && t.contains("(https://evil.example/steal)"), + "{t}" + ); + // An unclosed link ends with the document. + assert_eq!(html("y"), "y (x)\n"); +} + +#[test] +fn an_image_is_its_alt_text() { + assert_eq!(html("a\"ab"), "a a diagram b\n"); +} + +#[test] +fn title_and_textarea_are_text_as_written() { + assert_eq!( + html("T & U"), + "T & U\nx\n" + ); +} + +#[test] +fn a_greater_than_in_a_quoted_attribute_does_not_end_the_tag() { + assert_eq!(html(" b\" href=\"u\">t"), "t (u)\n"); +} + +#[test] +fn bytes_that_are_not_utf8_are_read_as_windows_1252() { + let t = extract( + Kind::Html, + b"

caf\xe9 \x80

", + 1 << 20, + &Limits::default(), + ) + .text; + assert_eq!(t, "caf\u{e9} \u{20ac}\n"); + let utf16: Vec = [0xff, 0xfe] + .into_iter() + .chain("

hi

".encode_utf16().flat_map(u16::to_le_bytes)) + .collect(); + assert_eq!( + extract(Kind::Html, &utf16, 1 << 20, &Limits::default()).text, + "hi\n" + ); +} + +#[test] +fn the_text_is_cut_at_the_cap_and_says_so() { + let e = extract( + Kind::Html, + "

word

".repeat(1000).as_bytes(), + 100, + &Limits::default(), + ); + assert!(e.truncated); + assert!(e.text.len() <= 101, "{}", e.text.len()); + assert!(!extract(Kind::Html, b"

a

", 100, &Limits::default()).truncated); +} + +#[test] +fn hostile_html_is_bounded_in_time_and_stack() { + let inputs = [ + "".repeat(300_000), + "PDF, images, DWG and DXF drawings, Word, Excel, PowerPoint and CSV, text (Markdown, JSON, XML, source code), IFC, STL, OBJ, PLY and glTF models, video, audio, and what is inside an archive; and, converted in the browser, RTF, the 1997 Office +formats and OpenDocument. One package; each format's engine is +loaded only when a file of that format is opened, and only the engines a +host lists are ever bundled. **[Live demo](https://exav.org/viewer/demo/)** · **[Documentation](https://exav.org/viewer/)** @@ -14,8 +13,9 @@ bundled. checks every message the frame sends. See [Security](https://exav.org/viewer/security/). - Formats browsers do not draw (TIFF, BMP variants, ICO, PNM, QOI, DDS, - farbfeld, HDR, JPEG 2000, JBIG2), DWG/DXF and IFC/STL models are decoded - by exav's own Rust decoders, compiled to WebAssembly and run in workers. So are the + farbfeld, HDR, JPEG 2000, JBIG2, JPEG XL, camera RAW files, shown by the + preview they embed), DWG/DXF drawings and IFC, STL, OBJ, PLY and glTF + models are decoded by exav's own Rust decoders, compiled to WebAssembly and run in workers. So are the JPEG 2000, JBIG2 and fax images of PDFs: pdf.js is given them in place of its OpenJPEG and PDFium decoders (C and C++), which are not copied. The modules import nothing but wasm-bindgen's plumbing: no network, no global @@ -25,6 +25,15 @@ bundled. Content-Security-Policy and offline. - Archives open in place, an archive inside an archive included, with the same plugins. +- Whatever draws something can be exported as a picture: a page, a region of + it in the format's own coordinates (a fraction of a page, pixels of an + image, drawing units, a 3D camera), or what the user sees now + (`controllers.viewport`), drawn again from the document's data at the size + asked for, as an `ImageBitmap` or an image file (`pictures.raster`, + `pictures.toBlob`), in the sandboxed frame too. See + [Pictures of pages](https://exav.org/viewer/api/#pictures-of-pages). +- A session keeps its zoom and place when the same document comes again with + other bytes (`session.replace`), in the sandboxed frame too. - A framework-free core with a plugin contract, and a default React UI on top of it whose every piece can be restyled or replaced. @@ -39,17 +48,96 @@ then the engines of the formats you open (all optional peer dependencies): | Format | Plugin | Install beside it | |---|---|---| | PDF | `pdf()` from `@exav/viewer/pdf` | `pdfjs-dist` (5 or 6) | -| Images | `image({ wasmDecoders: true })` from `@exav/viewer/image` | nothing | +| Images, SVG, camera RAW (DNG, CR2, CR3, NEF, ARW, ORF, RW2, RAF, PEF, SRW, 3FR, IIQ, X3F and more: the largest embedded preview) | `image({ wasmDecoders: true })` from `@exav/viewer/image` | nothing | | DWG, DXF | `dwg()`, `dxf()` from `@exav/viewer/cad` | nothing | | Word, Excel, PowerPoint, CSV | `docx()`, `xlsx()`, `pptx()`, `csv()` from `@exav/viewer/office` | `@silurus/ooxml` | +| RTF, DOC, ODT | `rtf()`, `doc()`, `odt()` from `@exav/viewer/office`, beside `docx()` | `@silurus/ooxml` (read by exav-render's `docs`, a prototype; an external converter and `pdf()` do better) | +| XLS, ODS, Numbers | `xls()`, `ods()`, `numbers()` from `@exav/viewer/office`, beside `xlsx()` | `@silurus/ooxml` (an external converter for the files exav-render's `sheets` does not recognise) | +| PPT, ODP, Keynote, ODG, Visio (VSDX) | `ppt()`, `odp()`, `keynote()`, `odg()`, `visio()` from `@exav/viewer/office`, beside `pptx()` | `@silurus/ooxml` (an external converter and `pdf()` for the files exav-render's `slides` does not recognise, such as the binary .vsd) | +| Binary Visio (VSD), CorelDRAW, Publisher, PageMaker, FreeHand, QuarkXPress, Zoner Draw, WPG | `visio()`, `coreldraw()`, `publisher()`, `pagemaker()`, `freehand()`, `quarkxpress()`, `zonerdraw()`, `wpg()` from `@exav/viewer/office`, beside `pdf()` | an external converter (see below) | +| Text, Markdown, JSON, XML, source code | `text()` from `@exav/viewer/text` | nothing (Markdown is read by a small wasm module, loaded when one is opened) | | IFC | `ifc()` from `@exav/viewer/ifc` | `three` | -| STL | `stl()` from `@exav/viewer/model` | `three` | +| STL, OBJ, PLY, glTF | `stl()`, `obj()`, `ply()`, `gltf()` from `@exav/viewer/model` | `three` | | Video, audio | `video()`, `audio()` from `@exav/viewer/media` | nothing | | Archives | `archive()` from `@exav/viewer/archive` | `@exav/unpack-wasm` | | Default UI | `@exav/viewer/react` | `react`, `react-dom` (19) | IFC models (IFC2X3, IFC4, IFC4X3) are read and meshed by exav's own engine -(exav-render), and three.js draws them. +(exav-render), and three.js draws them. Categories and building storeys +(`controllers.storeys`, for a model with two or more) can be hidden. + +XLS, ODS and Numbers are converted to XLSX, shown by `xlsx()` as a +workbook; PPT, ODP, Keynote, ODG and VSDX (a page to a slide) to PPTX, shown +by `pptx()`; RTF, DOC and ODT to DOCX, shown by `docx()`. All by exav-render, +which the package ships as WebAssembly modules +(`wasm/exav_viewer_sheets_bg.wasm`, `..._slides_...`, `..._docs_...`): no +install is needed, and nothing is fetched besides the module. What no +converter of the package reads (binary Visio, CorelDRAW, Publisher, +PageMaker, FreeHand, QuarkXPress, Zoner Draw and WordPerfect Graphics +files, a CSV or a DIF saved as .xls) goes to an external converter if the +host set one, and ends in the "needs_converter" error, with the format's +name, if not. Each plugin also takes its templates (.dot, .pps, .pot, .xlt, +.ott, .otp, .ots, .otg, Visio's), the flat XML OpenDocument files (.fodt, +.fodp, .fods, .fodg), and Word 6.0/95 and Excel 2.1 to 95 files. What the +bytes are decides, within each kind: an RTF saved as .doc is read as RTF, +an XLSX named .xls is shown unconverted. The sandboxed viewer opens these +formats only when named in `formats` (`BUILTIN_ORDER` names every one). + +A file a converter of the package recognises and cannot convert (encrypted +with a password, too large, damaged, of a version it does not read) ends in +the Office error, whose cause is a `SheetConversionError`, +`SlideConversionError` or `DocConversionError` naming the reason in its +`kind`; it is never handed to the external converter, which gets only what +the package's converters do not recognise. exav-render reads PowerPoint 95 +and 97 to 2003 (2 to 4 are recognised and reported as unsupported), Excel 2 +to 2003, the text formats Excel opens from a .xls file (XML Spreadsheet +2003, HTML tables, SYLK), OpenDocument drawings (a page to a slide, in the +largest page's size) and Keynote and Numbers of every version. Text +documents (DOC, ODT, RTF) are read by `docs`, a prototype, where no external +converter is set; with one, text documents go to it. + +### The external converter + +`rtf({ externalConverter })` and the other plugins take `converter` and +`externalConverter` (a plugin's options, or `conversion` in the sandboxed +viewer's): + +- `converter: "exav"` (the default): the converters of the package, then the + external one for what they do not read. For text documents, the external + converter first when there is one. +- `converter: "external"`: the external converter alone, for every format. +- `externalConverter`: where the converter is. A URL (absolute, rooted, or + relative to the page) of an ES module, or the name of a package copied + beside the viewer's assets, which `exavViewer({ externalConverter: + "" })` of `@exav/viewer/vite` (or `exav-viewer-assets + --external-converter `) copies: its published files go under + `assetBase`, and `manifest.json` names its entry. Default: none. + +The module exports `convert`, and may export `prefetch`: + +```ts +export function convert(bytes: Uint8Array, options: { + hint: string; // what the viewer took the file for: "rtf", "doc", "odt", "ppt", + // "odp", "keynote", "xls", "ods", "numbers", "odg", "visio", + // "coreldraw", "publisher", "pagemaker", "freehand", "quarkxpress", + // "zonerdraw" or "wpg": a hint, the bytes decide + maxMemory?: number; // bytes, when the host set the `maxMemory` option + signal?: AbortSignal; // aborted when the file is closed or `timeoutMs` passes: reject + onProgress?: (p: ConvertProgress) => void; +}): Promise<{ format: "pdf" | "xlsx"; bytes: Uint8Array }>; + +export function prefetch?(hint: string): string[] | Promise; // URLs, relative to the module +``` + +`ConvertProgress` is `{ stage: "download"; loaded; total }` (the module's +code and data arriving, `total` 0 when not known), `{ stage: "start" }`, and +`{ stage: "load" | "export"; done; total }`; the viewer shows them as its +loading and converting steps. A PDF is shown by `pdf()`, an XLSX by +`xlsx()`: register them. A rejection ends in the Office error, its cause an +`ExternalConversionError` (`kind` "failed", with the module's error as its +cause, or "timeout": the viewer stops waiting after `timeoutMs` whether or +not the module looks at its signal). `e2e/fixtures/fake-converter.js` is a +minimal module that implements it. ## Use @@ -103,6 +191,12 @@ import { SandboxedViewerProvider } from "@exav/viewer/react/sandbox"; ``` +The converted formats in the frame: name them, `sandbox={{ url, formats: +BUILTIN_ORDER }}`. For an external converter, install it where the frame +is built and give `exavViewer({ frameDir, externalConverter: "" })` +its name (it is copied beside the frame app, and the frame's +`conversion.externalConverter` names it). + The host reads each file for the frame: a PDF or a ZIP by HTTP range requests, as the frame asks for parts, the rest whole. Video, audio and images can go to the frame by URL instead, from origins written into its @@ -121,11 +215,20 @@ import { pdf } from "@exav/viewer/pdf"; const viewer = createViewer({ plugins: [pdf()] }); const session = viewer.mount(element, { id: "1", name: "report.pdf", source: { url: "/files/report.pdf" } }); -session.status.subscribe((s) => console.log(s.phase)); +// While loading: what it is doing (`step`: "file", "engine", "convert"...) and how far (`progress`, 0 to 1) +session.status.subscribe((s) => console.log(s.phase, "step" in s && s.step, "progress" in s && s.progress)); // later session.destroy(); ``` +`createSandboxedViewer` from `@exav/viewer/frame` gives the same sessions +for files in the frame. A host can draw every control itself from their +controllers (pages, zoom, sheets, a player's controls, thumbnails, +printing) with no React and no stylesheet in its page; the frame takes the +page's colours and hands back the arrow keys and Escape. See +[Integration](https://exav.org/viewer/integration/#a-host-that-draws-its-own-ui) +and `demo/headless.html`. + Other bundlers: copy the assets with the command the package installs, and serve the directory as the viewer's `assetBase` (default `/exav-viewer/`): @@ -136,7 +239,9 @@ npx exav-viewer-assets public/exav-viewer --frame public/exav-frame --frame-orig ``` The files are under versioned directories, so `assetBase` can be served -`Cache-Control: immutable`. The package's own wasm, workers and fonts are +`Cache-Control: immutable`. With an `externalConverter` they include that +package's published files under `converters///`. The +package's own wasm, workers and fonts are referenced with `new URL("...", import.meta.url)`, which Vite, webpack 5 and Parcel follow and emit; Rollup and esbuild need a plugin for it. @@ -159,6 +264,8 @@ MIT. The DWG module contains the NewStroke font (CC0-1.0) and encoding_rs, whose WHATWG data is BSD-3-Clause; the bundled fonts are under the SIL Open Font License. See NOTICE and LICENSES/. The engines installed beside the package keep their own licences: pdf.js is Apache-2.0 (and its ICC engine, -qcms, MIT), the others MIT. The sandboxed frame app +qcms, MIT), the others MIT; an external converter you install keeps its +own. +The sandboxed frame app (`dist/frame/app/`) bundles them, with their licence files in its `licenses/`. diff --git a/crates/exav-viewer/demo/examples/NOTICE.md b/crates/exav-viewer/demo/examples/NOTICE.md new file mode 100644 index 0000000..722c822 --- /dev/null +++ b/crates/exav-viewer/demo/examples/NOTICE.md @@ -0,0 +1,2912 @@ +# Notices of the example files + +The demo of `@exav/viewer` lists the files of this directory's `examples.json`. Each has a free licence +that was read at the page named under "Evidence", or is made by a script of this repository and +given to the public domain (CC0-1.0). This file is written by `generate/make-attributions.mjs`; do not edit it. + +235 files: 145 are committed under `files/` (5.6 MB); 90 are downloaded by `npm run demo:examples` (83.0 MB). + +To rebuild: run the scripts of `generate/` (each lists what it needs; `python3 -I generate/make-images.py`, `make-cad.py`, +`make-models.py`, `make-ifc.py`, `make-text.py`, `make-archives.py`, `make-media.py`, `make-pdf.py`, `make-office.py`), then +`node generate/make-manifest.mjs` and `node generate/make-attributions.mjs`. `node check.mjs` checks the manifest and the +files, `node verify-open.mjs` opens every example with the viewer's own engines, and `node generate/verify-evidence.mjs` +reads the licence pages again. `catalog.json` is where each example is described by hand. + +Where the pictures made here hold text, it is set in Aileron, the font Pillow bundles, which its author gives to the +public domain (CC0-1.0, "No Rights Reserved": https://dotcolon.net/font/aileron/). Drawings name their fonts and +embed none; documents that embed fonts embed the Liberation fonts (SIL OFL 1.1, which lets documents embed them). + +## PDF + +### field-report.pdf + +- What: Field report, six pages (pdf, 104 KB) +- Shows: a table of contents whose lines are links, a two-level outline, roman and arabic page labels, internal and external links, a table, bar, line and pie charts as vectors, a JPEG, standard and embedded fonts (Latin, Greek, Cyrillic), document information +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-pdf.py` +- SHA-256: 75b7649d62fb12034d56478c98baa92beba3c0a2117ce0cfcfffa9233d060a5b + +### application-form.pdf + +- What: Berth application form (AcroForm) (pdf-form, 19 KB) +- Shows: text fields (multiline, maximum length, password, read-only), check boxes, radio buttons, a drop-down list, a list box, some filled in +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-pdf.py` +- SHA-256: 883dff8626a2a95d66d74bd8876ceee621197902de671b7c036d39e21774c50b + +### annotations.pdf + +- What: Annotations without appearance streams (pdf-annotations, 6.1 KB) +- Shows: links to a URL, a page and a named destination, highlight, underline, strike-out, squiggly, note, free text, square, circle, line with arrows, polygon, polyline, ink, stamp, file attachment, an outline and a named destination +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-pdf.py` +- SHA-256: 212ea14f43e151d2d477b73659ef4fdb50735ee337eb76283d065ba9ec1701e9 + +### scan-mixed.pdf + +- What: Scanned letters, one page for each scanner image filter (pdf-scan, 201 KB) +- Shows: four pages: DCTDecode (JPEG), CCITTFaxDecode (Group 4), JBIG2Decode and JPXDecode (JPEG 2000), each with an invisible OCR text layer; the viewer decodes the last three with its own decoders +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-pdf.py` (with opj_compress, jbig2, tiffcp) +- SHA-256: daeb8cab36d82d4e5391041effc7d37dddf2421a87c3853c4b763e4a4d534776 + +### vector-art.pdf + +- What: Vector art (pdf, 4.3 KB) +- Shows: axial and radial shadings, transparency, a clipping path, dashes, caps and joins, Bezier curves, an even-odd fill, text with render modes, rotated and scaled text +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-pdf.py` +- SHA-256: fad466f385e89bc008128072d0b16544144c8a42983afd5d444079e59519e08e + +### handbook-tagged.pdf + +- What: Harbour handbook as a tagged PDF/A-2 (pdf, 188 KB) +- Shows: bookmarks from the headings, hyperlinks, tags, footnotes, a landscape section, embedded Liberation fonts +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: c88a1434c1cbf8a8af467325bb413463276bbe70c84b5f88760638ff5975773d + +### arxiv-rational-cherednik-torus-knots.pdf + +- What: Rational Cherednik Algebras and Torus Knot Invariants (arXiv:2402.18770) (pdf, 421 KB) +- Shows: 28 pages of mathematics, 24 outline entries, 256 links, set in LaTeX +- Author: Xinchun Ma +- Source: https://arxiv.org/abs/2402.18770v1 +- Licence: CC-BY-4.0 +- Evidence: https://arxiv.org/abs/2402.18770v1 +- Words read there: "href="http://creativecommons.org/licenses/by/4.0/" title="Rights to this article"" +- Attribution: Xinchun Ma, Rational Cherednik Algebras and Torus Knot Invariants, arXiv:2402.18770v1, CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Not modified. +- Origin: downloaded from https://arxiv.org/pdf/2402.18770v1 +- SHA-256: 2b22841d8a64b271d7def6fa15aa0b5b98f533ae259e4108eb7104320f07cf10 + +### nist-sp-800-63-4-digital-identity.pdf + +- What: NIST SP 800-63-4, Digital Identity Guidelines (pdf, 838 KB) +- Shows: 96 tagged pages, 54 outline entries, 227 links +- Author: David Temoshok, Diana Proud-Madruga, Yee-Yin Choong et al., NIST +- Source: https://csrc.nist.gov/pubs/sp/800/63/4/final +- Licence: public-domain (US federal government work, 17 U.S.C. 105; the PDF says so itself) +- Evidence: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-63-4.pdf +- Words read there: "is not subject to copyright in the United States." +- Origin: downloaded from https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-63-4.pdf +- SHA-256: 2f5b107de218a0fc3fe7f7e91b2ece5babb001eda5745b7c568a3cc876002f2d + +### scan-cfa-minutes-1971.pdf + +- What: Minutes of the U.S. Commission of Fine Arts, 1970 to 1972 (scan) (pdf-scan, 1.1 MB) +- Shows: 40 scanned pages: JPEG 2000 pictures and JBIG2 masks, an OCR text layer, PDF/A-2B +- Author: U.S. Commission of Fine Arts; scanned by the Internet Archive +- Source: https://archive.org/details/cfaminutes21april1971 +- Licence: public-domain (US federal government work, 17 U.S.C. 105) +- Evidence: https://commons.wikimedia.org/wiki/File:July_8_1970_to_May_19_1972_(IA_cfaminutes21april1971).pdf +- Words read there: "This work is in the public domain in the United States because it is a work prepared by an officer o" +- Origin: downloaded from https://archive.org/download/cfaminutes21april1971/cfaminutes21april1971.pdf +- SHA-256: 2fc5edb8a4f303b89449443dcb5a32249c79b2a8d67253348025d0e7eea5f94b + +### scan-blm-land-survey-records.pdf + +- What: Land and survey records, Bureau of Land Management (scan) (pdf-scan, 2.1 MB) +- Shows: 40 pages scanned at about 500 ppi: JPEG 2000 and JBIG2 images, an OCR text layer, PDF/A-2B +- Author: United States Bureau of Land Management; scanned by the Internet Archive +- Source: https://archive.org/details/landsurveyrecord00unit +- Licence: public-domain (US federal government work, 17 U.S.C. 105) +- Evidence: https://commons.wikimedia.org/wiki/File:Land_%26_survey_records_-_record_preservation_%26_service_through_microfilm_(IA_landsurveyrecord00unit).pdf +- Words read there: "This work is in the public domain in the United States because it is a work prepared by an officer o" +- Origin: downloaded from https://archive.org/download/landsurveyrecord00unit/landsurveyrecord00unit.pdf +- SHA-256: d9a9e6583d0afb1688a043ef59a8d2e236e20c58d4ba76ff625d7c11a181c16c + +### form-uscis-i9.pdf + +- What: USCIS Form I-9, Employment Eligibility Verification (pdf-form, 512 KB) +- Shows: 115 text fields, 5 drop-down lists, 8 check boxes, links; a tagged government form +- Author: U.S. Citizenship and Immigration Services (DHS) +- Source: https://www.uscis.gov/i-9 +- Licence: public-domain (US federal government work, 17 U.S.C. 105) +- Evidence: https://www.uscis.gov/website-policies +- Words read there: "Information presented on this WWW site is considered public information and may be distributed or co" +- Origin: downloaded from https://www.uscis.gov/sites/default/files/document/forms/i-9.pdf +- SHA-256: 780f348c34df694bb0b4dbbfaf9f22b99b9757b80d16a37ba89aadf069597281 + +### map-nps-canyonlands.pdf + +- What: Canyonlands National Park, Island in the Sky: roads and trails (pdf-map, 341 KB) +- Shows: two tagged pages of vector map +- Author: National Park Service +- Source: https://home.nps.gov/cany/planyourvisit/maps.htm +- Licence: public-domain (US federal government work, 17 U.S.C. 105) +- Evidence: https://www.nps.gov/aboutus/disclaimer.htm +- Words read there: "material created by the National Park Service and presented on this website, unless otherwise indica" +- Origin: downloaded from https://home.nps.gov/cany/planyourvisit/upload/IslandRoadsandTrailsUpdated24-508forweb.pdf +- SHA-256: b29a639d9bc0d2e37ca41b68c21bcddba7637b1727dce86980c3373715610d55 + +### slides-unige-open-access.pdf + +- What: Open Access publishing at no cost thanks to UNIGE agreements (slides) (pdf, 782 KB) +- Shows: ten slides with outline, links, tags and pictures +- Author: Floriane Muller, Anouk Santos (University of Geneva) +- Source: https://zenodo.org/records/23478694 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/records/23478694 +- Words read there: "Creative Commons Attribution 4.0 International" +- Attribution: Floriane Muller and Anouk Santos, Open Access publishing at no cost thanks to UNIGE agreements, in 15 minutes, Zenodo, https://doi.org/10.5281/zenodo.23478694, CC BY 4.0. Not modified. +- Origin: downloaded from https://zenodo.org/api/records/23478694/files/2026-10-20_Read_and_publish_en15min_EN_zenodo.pdf/content +- SHA-256: 03356ed569a80f7d7dc1d96fcbfd75a2fbc663c63f6d74f4e89eb2390bb5ee64 + +### paper-ja-labor-law.pdf + +- What: A paper in Japanese on labour law and the constitution (pdf, 860 KB) +- Shows: 25 pages with embedded MS Mincho fonts +- Author: Takashi Fujiki (藤木 è²´å�²) +- Source: https://zenodo.org/records/23469422 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/records/23469422 +- Words read there: "Creative Commons Attribution 4.0 International" +- Attribution: 藤木 è²´å�², アメリカ労åƒ�法ã�‹ã‚‰ã�¿ã�Ÿæ†²æ³•ã�®å½±éŸ¿, アメリカ憲法ã�®ç�†è«–ã�¨å®Ÿè·µ 創刊å�·, Zenodo, https://doi.org/10.5281/zenodo.23469422, CC BY 4.0. Not modified. +- Origin: downloaded from https://zenodo.org/api/records/23469422/files/%E3%82%A2%E3%83%A1%E3%83%AA%E3%82%AB%E5%8A%B4%E5%83%8D%E6%B3%95%E3%81%8B%E3%82%89%E3%81%BF%E3%81%9F%E6%86%B2%E6%B3%95%E3%81%AE%E5%BD%B1%E9%9F%BF.pdf/content +- SHA-256: 08b2be3ebc781107f71003344ccf8b230229079e978687f1e0da2329bef1cbe9 + +## Word, Excel, PowerPoint + +### handbook.docx + +- What: Harbour handbook (Word) (docx, 25 KB) +- Shows: title page, table of contents with links, outline numbering, character and paragraph styles, bulleted and numbered lists of three levels, tables with merged cells and a repeated header, two pictures (one floating with wrapped text), a shape, footnotes, hyperlinks, bookmarks, fields, a comment, tracked changes, a two-column section, a landscape section with a wide table, headers and footers with page numbers +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: 46c4fb53949dbd25cfc8b1fecbbd282d470b767d16c1fea426394872fcffc95d + +### workbook.xlsx + +- What: Harbour workbook (Excel) (xlsx, 23 KB) +- Shows: three sheets: a budget with formulas (SUM, AVERAGE, INDEX, MATCH, COUNTIF, IF, VLOOKUP, ROUND), currency, percent and date formats, merged title, frozen header rows, a validation list, a comment, a hyperlink and named ranges; 120 rows of sales with an autofilter; a bar, a line and a pie chart +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: 3e3e0247bde87b6fa1c6f9b06f0561f2eae8bc326925b4b28ba2d7d3b8c12792 + +### deck.pptx + +- What: Harbour review (PowerPoint) (pptx, 30 KB) +- Shows: five slides: a gradient title slide, nested bullets, a native bar chart with a callout, a table, a picture with shapes, gradients and arrows; a master with footer and slide number; speaker notes (not shown) and transitions +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: 160962428c7f1d15c8865d51fef7e74ebc8ccc6782f60ea4bf08ed0a805a7edb + +### docx4j-getting-started.docx + +- What: docx4j Getting Started (Word) (docx, 153 KB) +- Shows: a manual with styles, tables, pictures and links +- Author: Jason Harrop and the docx4j contributors +- Source: https://github.com/plutext/docx4j/blob/c95b55be6832ff716131ffdbd7006755db92f696/docs/Docx4j_GettingStarted.docx +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/plutext/docx4j/c95b55be6832ff716131ffdbd7006755db92f696/legals/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: docx4j, Jason Harrop / Plutext, https://github.com/plutext/docx4j, Apache-2.0. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/plutext/docx4j/c95b55be6832ff716131ffdbd7006755db92f696/docs/Docx4j_GettingStarted.docx +- SHA-256: a518cffcbef0b60cf5c95930acd9af9a56484e47376c5f0c4d6e3a15a0799941 + +### docx4j-two-charts.docx + +- What: docx4j chart test: two charts (Word) (docx, 41 KB) +- Shows: two native charts in a document +- Author: Jason Harrop and the docx4j contributors +- Source: https://github.com/plutext/docx4j/blob/c95b55be6832ff716131ffdbd7006755db92f696/docx4j-chart-render/src/test/resources/charts/render/office/p3-two-charts.docx +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/plutext/docx4j/c95b55be6832ff716131ffdbd7006755db92f696/legals/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: docx4j, Jason Harrop / Plutext, https://github.com/plutext/docx4j, Apache-2.0. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/plutext/docx4j/c95b55be6832ff716131ffdbd7006755db92f696/docx4j-chart-render/src/test/resources/charts/render/office/p3-two-charts.docx +- SHA-256: e0bc29916de415c53c03dcee14817bbd1e3eeea8f54a2b76629fe6754e6c641e + +### gsa-policy-review-template.xlsx + +- What: Section508.gov Policy Review Template (Excel) (xlsx, 217 KB) +- Shows: a government workbook with formatted tables +- Author: U.S. General Services Administration and the agencies that wrote the documents (Section508.gov) +- Source: https://github.com/GSA/Assets.Section508.gov/blob/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Policy%20Review%20Template.xlsx +- Licence: CC0-1.0 +- Evidence: https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/LICENSE.md +- Words read there: "this project is in the public domain within the United States of America. Additionally, we waive copyright and" +- Origin: downloaded from https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Policy%20Review%20Template.xlsx +- SHA-256: 840661eba4653879dca24f209bca1619f7b168ef1232b595df5713741b2465bd + +### closedxml-pivot-tables.xlsx + +- What: ClosedXML example: pivot tables (Excel) (xlsx, 30 KB) +- Shows: pivot tables over a data sheet +- Author: ClosedXML contributors +- Source: https://github.com/ClosedXML/ClosedXML/blob/09f2f21a60e821ce7fb18ca3576b272e5dd6d921/ClosedXML.Tests/Resource/Examples/PivotTables/PivotTables.xlsx +- Licence: MIT +- Evidence: https://raw.githubusercontent.com/ClosedXML/ClosedXML/09f2f21a60e821ce7fb18ca3576b272e5dd6d921/LICENSE +- Words read there: "MIT License Copyright (c) 2016 ClosedXML" +- Attribution: Copyright (c) 2016 ClosedXML, MIT, https://github.com/ClosedXML/ClosedXML. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/ClosedXML/ClosedXML/09f2f21a60e821ce7fb18ca3576b272e5dd6d921/ClosedXML.Tests/Resource/Examples/PivotTables/PivotTables.xlsx +- SHA-256: d13f149091c804cfe9b02c81301ea7ce13d20d1f3311cac799151541d0467d02 + +### xlsxwriter-bar-chart.xlsx + +- What: XlsxWriter test file: a bar chart (Excel) (xlsx, 14 KB) +- Shows: a native bar chart saved in Excel +- Author: John McNamara (XlsxWriter) +- Source: https://github.com/jmcnamara/XlsxWriter/blob/5d4606d89a955226d2d0825a0f44309043ae7251/xlsxwriter/test/comparison/xlsx_files/chart_bar14.xlsx +- Licence: BSD-2-Clause +- Evidence: https://raw.githubusercontent.com/jmcnamara/XlsxWriter/5d4606d89a955226d2d0825a0f44309043ae7251/LICENSE.txt +- Words read there: "BSD 2-Clause License Copyright (c) 2013-2025, John McNamara" +- Attribution: Copyright (c) 2013-2025, John McNamara, BSD-2-Clause, https://github.com/jmcnamara/XlsxWriter. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/jmcnamara/XlsxWriter/5d4606d89a955226d2d0825a0f44309043ae7251/xlsxwriter/test/comparison/xlsx_files/chart_bar14.xlsx +- SHA-256: c4ed1e8117b4a0e014b95f42361c7e060728b398d4ea650395d902557429cdd2 + +### python-pptx-chart-types.pptx + +- What: python-pptx test file: one slide for each chart type (PowerPoint) (pptx, 1.3 MB) +- Shows: many native chart types +- Author: Steve Canny (python-pptx) +- Source: https://github.com/scanny/python-pptx/blob/278b47b1dedd5b46ee84c286e77cdfb0bf4594be/features/steps/test_files/cht-chart-type.pptx +- Licence: MIT +- Evidence: https://raw.githubusercontent.com/scanny/python-pptx/278b47b1dedd5b46ee84c286e77cdfb0bf4594be/LICENSE +- Words read there: "The MIT License (MIT) Copyright (c) 2013 Steve Canny" +- Attribution: Copyright (c) 2013 Steve Canny, MIT, https://github.com/scanny/python-pptx. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/scanny/python-pptx/278b47b1dedd5b46ee84c286e77cdfb0bf4594be/features/steps/test_files/cht-chart-type.pptx +- SHA-256: d0a7979d05970aa83fd8406f0829cd0019853a7bc4e16f8cda814586fc2eaccc + +### cdc-lifecycle-508.pptx + +- What: Integrating Section 508 Requirements in the Development Lifecycle (PowerPoint) (pptx, 598 KB) +- Shows: a government deck with pictures and diagrams +- Author: Mark D. Urban, CDC Section 508 Coordinator (US federal government) +- Source: https://github.com/GSA/Assets.Section508.gov/blob/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Integrating%20Section%20508%20Requirements%20in%20the%20Development%20Lifecycle.pptx +- Licence: CC0-1.0 +- Evidence: https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/LICENSE.md +- Words read there: "this project is in the public domain within the United States of America. Additionally, we waive copyright and" +- Origin: downloaded from https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Integrating%20Section%20508%20Requirements%20in%20the%20Development%20Lifecycle.pptx +- SHA-256: 51c7d6af2e6682e5ee66204b813a45488e62b0e6e13cecc9207a982fdeb1720a + +## Other office formats + +### handbook.doc + +- What: Harbour handbook (Word 97 to 2003) (doc, 66 KB) +- Shows: the handbook as a binary .doc +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: 807c9b812188d73b3558ea8b91360d7a39eb637a18172295f206612da92cce39 + +### handbook.odt + +- What: Harbour handbook (OpenDocument text) (odt, 41 KB) +- Shows: the handbook as .odt +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: d28f2667008ebd0e9456f7900eb4af8dbbd10b5af7490a059d6868d468c475ce + +### handbook.fodt + +- What: Harbour handbook (flat OpenDocument text) (fodt, 76 KB) +- Shows: one XML file, pictures in base64; written by hand, not converted +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with ) +- SHA-256: 7c9f74181b5c9ad2b4766d5e3c82d9edf2c1cdd370417d0f8592d00ec71beec9 + +### handbook.rtf + +- What: Harbour handbook (Rich Text Format) (rtf, 94 KB) +- Shows: the handbook as .rtf +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: 04eea9909d09ed87fb621459f1ac6e024b094eb767c1d0f7d536dd76f0b82e43 + +### workbook.xls + +- What: Harbour workbook (Excel 97 to 2003) (xls, 29 KB) +- Shows: the workbook as a binary .xls +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: 8552c433665e927723ecb747c5a0e1696076964f1bfd20ddd30bc3b95cc97e19 + +### workbook.ods + +- What: Harbour workbook (OpenDocument spreadsheet) (ods, 45 KB) +- Shows: the workbook as .ods +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: 32b0cf2984ddef9c2209d4cdb874866a65217d0b6bcdd3417264982ef07d660a + +### workbook.fods + +- What: Harbour workbook (flat OpenDocument spreadsheet) (fods, 118 KB) +- Shows: one XML file; written by hand, not converted +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with ) +- SHA-256: 80f5ad00faf7555d5aab526226204658880127a91f0af62a439d106c7a52e1be + +### deck.ppt + +- What: Harbour review (PowerPoint 97 to 2003) (ppt, 480 KB) +- Shows: the deck as a binary .ppt (its thumbnail makes it large) +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: 8a6285ae02086db5ddb3246c75ef08a3508f672a91ba38b30efae291e119fb1e + +### deck.odp + +- What: Harbour review (OpenDocument presentation) (odp, 71 KB) +- Shows: the deck as .odp +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: e194842a5abfb245477c00eee30736ef7f8460606b62b887bf8392283b41dd07 + +### deck.fodp + +- What: Harbour review (flat OpenDocument presentation) (fodp, 31 KB) +- Shows: one XML file; written by hand, not converted +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with ) +- SHA-256: 07da109d15eceb65d7a0601998ed9508ecd140d5aef311301c96e7aad6faa236 + +### diagram.odg + +- What: Flowchart (OpenDocument drawing) (odg, 26 KB) +- Shows: two pages, layers (one hidden), connectors glued to shapes, groups, gradients, a curve and a polyline, shadows, dashes +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with soffice) +- SHA-256: 8c80d0ef2e536db14a7e5a92fc0092ab4f0976c87a091875899d3a7655f5b56e + +### diagram.fodg + +- What: Flowchart (flat OpenDocument drawing) (fodg, 14 KB) +- Shows: one XML file; written by hand, not converted +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-office.py` (with ) +- SHA-256: 52ed359ccb0acec09a2d7401129021ff3f0ad69e35c770eab33986f063924203 + +### poi-sample.doc + +- What: Apache POI test document (Word 97) (doc, 27 KB) +- Shows: a binary .doc +- Author: Apache POI committers +- Source: https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/SampleDoc.doc +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/SampleDoc.doc +- SHA-256: 717585c0a88f20862c86220163dd03da87cd743970354c6b29add32725f2e833 + +### poi-word95.doc + +- What: Apache POI test document (Word 6 and 95 format) (doc, 100 KB) +- Shows: the pre-1997 Word format +- Author: Nick Burch (Apache POI) +- Source: https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/Word95.doc +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/Word95.doc +- SHA-256: a7b9557e917daf29cfee6baaa90226fbfa7900ffa05cc35bdc03aafdefef5789 + +### dhs-directive-139-02.doc + +- What: DHS Directive 139-02 (Word 97) (doc, 81 KB) +- Shows: a government directive in the binary .doc format +- Author: U.S. Department of Homeland Security +- Source: https://github.com/GSA/Assets.Section508.gov/blob/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Directive_139.2_Final_10-28-2008.doc +- Licence: CC0-1.0 +- Evidence: https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/LICENSE.md +- Words read there: "this project is in the public domain within the United States of America. Additionally, we waive copyright and" +- Origin: downloaded from https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Directive_139.2_Final_10-28-2008.doc +- SHA-256: 48d1c85456d6b515ce8e3db6b43024f90bac69be86a3e78c1ae08406d4cad493 + +### poi-formula-eval.xls + +- What: Apache POI test workbook of formulas (Excel 97) (xls, 174 KB) +- Shows: hundreds of formula cases +- Author: Apache POI committers +- Source: https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/FormulaEvalTestData.xls +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/FormulaEvalTestData.xls +- SHA-256: c2040c1fac1088f1e112abef197ae1f9bcb03547861783b89c1d4281a42049d1 + +### poi-conditional-formats.xls + +- What: Apache POI test workbook of conditional formats (Excel 97) (xls, 44 KB) +- Shows: colour scales, icon sets and data bars +- Author: Nick Burch (Apache POI) +- Source: https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/NewStyleConditionalFormattings.xls +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/NewStyleConditionalFormattings.xls +- SHA-256: 899a29aa6ce35fee0268847ff8b5d9459e6ce34d5e2ff462fd42ee9b80837b87 + +### poi-excel5.xls + +- What: Apache POI test workbook (Excel 5 and 95 format) (xls, 7.5 KB) +- Shows: the BIFF5 format of 1993 to 1995 +- Author: Apache POI committers +- Source: https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/testEXCEL_5.xls +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/testEXCEL_5.xls +- SHA-256: ac0ce3a2eff43e32e56d6b789df6aaa1645ae846d22fa3a2fe3057391d0f1cae + +### poi-sample-show.ppt + +- What: Apache POI test presentation (PowerPoint 97) (ppt, 123 KB) +- Shows: a binary .ppt +- Author: Apache POI committers +- Source: https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/slideshow/SampleShow.ppt +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/slideshow/SampleShow.ppt +- SHA-256: 64275a6685b8f267827178037dcc59de927475e56385725916f4c6039c7ce7f6 + +### tika-rtf-various.rtf + +- What: Apache Tika test document: various RTF features (rtf, 64 KB) +- Shows: fonts, colours, tables and lists in RTF +- Author: Michael McCandless (Apache Tika) +- Source: https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/resources/test-documents/testRTFVarious.rtf +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/resources/test-documents/testRTFVarious.rtf +- SHA-256: cf00c56fe7099d14b820a0d751324e415f2c09af580f2c96f08614a2aec42c1e + +### tdf-thesis-template.odt + +- What: Thesis template in Spanish (OpenDocument text) (odt, 66 KB) +- Shows: styles, a table of contents, headers +- Author: Phorious (Document Foundation wiki user) +- Source: https://wiki.documentfoundation.org/File:Tesis-v1.0.4.odt +- Licence: CC0-1.0 +- Evidence: https://wiki.documentfoundation.org/File:Tesis-v1.0.4.odt +- Words read there: "This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Ded" +- Origin: downloaded from https://wiki.documentfoundation.org/images/5/54/Tesis-v1.0.4.odt +- SHA-256: ec323e9fde67103a7f0039d8a59625bd7e2c5afa9e057563f5064c6b68d442a1 + +### tika-odt-ooo3.odt + +- What: Apache Tika test document written with OpenOffice 3 (OpenDocument text) (odt, 24 KB) +- Shows: an .odt of 2009 +- Author: Apache Tika committers +- Source: https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/test/resources/test-documents/testODFwithOOo3.odt +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/test/resources/test-documents/testODFwithOOo3.odt +- SHA-256: b6cd74b570a98fcb6d838dd85ab869604e0711812d9533d5ecde0000b24ba7ef + +### tdf-household-budget.ods + +- What: Household budget book (OpenDocument spreadsheet) (ods, 21 KB) +- Shows: formulas, charts and several sheets +- Author: Hrbrgr (Document Foundation wiki user) +- Source: https://wiki.documentfoundation.org/File:Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods +- Licence: CC-BY-3.0 +- Evidence: https://wiki.documentfoundation.org/File:Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods +- Words read there: "This work is licensed under the Attribution 3.0 Unported License" +- Attribution: Hrbrgr (Document Foundation wiki user), Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods, https://wiki.documentfoundation.org/File:Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods, CC BY 3.0. No changes. +- Origin: downloaded from https://wiki.documentfoundation.org/images/b/bc/Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods +- SHA-256: aacd76666860f7bf879e1518a07b90d535815ce92d076ea26c835061b8aff854 + +### odfdo-flat.fods + +- What: odfdo test sample (flat OpenDocument spreadsheet) (fods, 32 KB) +- Shows: one XML file +- Author: Jérôme Dumonteil (odfdo) +- Source: https://github.com/jdum/odfdo/blob/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/test_flat_lo.fods +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: Copyright Jérôme Dumonteil, odfdo, Apache-2.0, https://github.com/jdum/odfdo. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/test_flat_lo.fods +- SHA-256: 4966023bf427dbc9c975dc9b11816b4a90158f7dab452c59104b8800fb27ec36 + +### tdf-presentation-template.odp + +- What: Presentation template (OpenDocument presentation) (odp, 403 KB) +- Shows: master slides, pictures and layouts +- Author: Phorious (Document Foundation wiki user) +- Source: https://wiki.documentfoundation.org/File:Presenta.odp +- Licence: CC0-1.0 +- Evidence: https://wiki.documentfoundation.org/File:Presenta.odp +- Words read there: "This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Ded" +- Origin: downloaded from https://wiki.documentfoundation.org/images/5/51/Presenta.odp +- SHA-256: 147ca9c6dbcdd45470627b84c04824c7f3e07de57485a8190018eea5f23c64b3 + +### odfdo-example.odp + +- What: odfdo test sample (OpenDocument presentation) (odp, 54 KB) +- Shows: slides with text and shapes +- Author: Jérôme Dumonteil (odfdo) +- Source: https://github.com/jdum/odfdo/blob/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/example.odp +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: Copyright Jérôme Dumonteil, odfdo, Apache-2.0, https://github.com/jdum/odfdo. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/example.odp +- SHA-256: 9075b87e36bb4618bdc9a8a6138bcaaf31b2b81e089e9006ac906e66a94f912b + +### tdf-diagram-gallery.odg + +- What: A gallery of diagrams (OpenDocument drawing) (odg, 89 KB) +- Shows: several diagram types +- Author: Hrbrgr (Document Foundation wiki user) +- Source: https://wiki.documentfoundation.org/File:Diagramme.odg +- Licence: CC-BY-3.0 +- Evidence: https://wiki.documentfoundation.org/File:Diagramme.odg +- Words read there: "This work is licensed under the Attribution 3.0 Unported License" +- Attribution: Hrbrgr (Document Foundation wiki user), Diagramme.odg, https://wiki.documentfoundation.org/File:Diagramme.odg, CC BY 3.0. No changes. +- Origin: downloaded from https://wiki.documentfoundation.org/images/0/07/Diagramme.odg +- SHA-256: 2e5f43734db7c600256e0670f6ec9da9428eb6b7a074c4742fd506e32c833a5a + +### odfdo-shapes.odg + +- What: odfdo test sample: basic shapes (OpenDocument drawing) (odg, 10 KB) +- Shows: rectangles, ellipses, lines and polygons +- Author: Jérôme Dumonteil (odfdo) +- Source: https://github.com/jdum/odfdo/blob/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/base_shapes.odg +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: Copyright Jérôme Dumonteil, odfdo, Apache-2.0, https://github.com/jdum/odfdo. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/base_shapes.odg +- SHA-256: dfe6a6c83ba5caec340889d6c77a899e420060d55f4b08fd9a1fb7b36e0b799f + +### tika-keynote09.key + +- What: Apache Tika test presentation (Keynote '09) (keynote, 217 KB) +- Shows: an XML Keynote document (index.apxl) +- Author: Jukka Zitting (Apache Tika) +- Source: https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote.key +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote.key +- SHA-256: 4a270c2427f11d77f82fae696e3fd6eda945bae0422ae87c5fac6cf2bd06015c + +### tika-keynote2013.key + +- What: Apache Tika test presentation (Keynote 2013, IWA format) (keynote, 268 KB) +- Shows: a Keynote document in the iWork archive format +- Author: Tim Allison (Apache Tika) +- Source: https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote2013.key +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote2013.key +- SHA-256: 8da93f6b566bc9eb22f4791bbfd5f2179162f39bf80968187b164c33d31824db + +### tika-numbers09-charts.numbers + +- What: Apache Tika test spreadsheet with charts (Numbers '09) (numbers, 102 KB) +- Shows: an XML Numbers document with charts +- Author: Michael McCandless (Apache Tika) +- Source: https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testNumbersCharts.numbers +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testNumbersCharts.numbers +- SHA-256: f4430f2aa0ddab186e7e32f15552b58b7b03abada7a978dfbcd51e5548757789 + +### numbers-formulas.numbers + +- What: numbers-parser test spreadsheet of formulas (Numbers) (numbers, 323 KB) +- Shows: formulas across tables +- Author: Jon Connell (numbers-parser) +- Source: https://github.com/masaccio/numbers-parser/blob/a6affe5599c8373f575192ac5777d0c6426da696/tests/data/create-formulas.numbers +- Licence: MIT +- Evidence: https://raw.githubusercontent.com/masaccio/numbers-parser/a6affe5599c8373f575192ac5777d0c6426da696/LICENSE.rst +- Words read there: "Permission is hereby granted, free of charge, to any person obtaining a copy of this softw" +- Attribution: Copyright 2021 Jon Connell, numbers-parser, MIT, https://github.com/masaccio/numbers-parser. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/masaccio/numbers-parser/a6affe5599c8373f575192ac5777d0c6426da696/tests/data/create-formulas.numbers +- SHA-256: 9371c5b1d6ee4dfa17569097f064eba9c67f804d88b48638efbbeeb459d07dd4 + +### poi-network.vsdx + +- What: Apache POI test diagram (Visio): a network (visio, 43 KB) +- Shows: a use-case diagram: actors, ovals and connecting lines +- Author: A reporter of Apache POI bug 60489 (committed by Tim Allison) +- Source: https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/diagram/60489.vsdx +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/diagram/60489.vsdx +- SHA-256: 15494702ecb5554c1dfaee2c09ac35e2ea656e2eed7ba4ba0cf1039e6125fbe1 + +### vsdx-house.vsdx + +- What: vsdx library test drawing (Visio): a house (visio, 20 KB) +- Shows: boxes and house shapes with text +- Author: Dave Howard (vsdx library) +- Source: https://github.com/dave-howard/vsdx/blob/6703e6c2c906bea4051f43525ec9af9dcf735c13/tests/test3_house.vsdx +- Licence: BSD-3-Clause +- Evidence: https://raw.githubusercontent.com/dave-howard/vsdx/6703e6c2c906bea4051f43525ec9af9dcf735c13/LICENSE +- Words read there: "BSD 3-Clause License Copyright (c) 2020, Dave Howard" +- Attribution: Copyright (c) 2020, Dave Howard, BSD-3-Clause, https://github.com/dave-howard/vsdx. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/dave-howard/vsdx/6703e6c2c906bea4051f43525ec9af9dcf735c13/tests/test3_house.vsdx +- SHA-256: e454217e49d1ec2aaa7c9b8f38b148ffc0d028ce44ba096fe3386e9894b1775f + +## Text and code + +### field-guide.md + +- What: Field guide to Markdown (markdown, 2.3 KB) +- Shows: headings of six levels, nested and task lists, quotes, an aligned table, fenced code with languages, footnotes, links and references, inline HTML, Unicode +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 0f65f0bb537b18b6d5b1ec88da73686350e31d6529bb78a682aaa93d755e9f49 + +### field-notes.txt + +- What: Plain text with tabs, a long line and pangrams in nine scripts (text, 1.6 KB) +- Shows: Latin, Greek, Cyrillic, Japanese, Arabic and Hebrew text, box drawing, symbols, no final newline +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 12054040d6aef17fff17a18adf238fee6fd4158eeefd1d1230108fbd0f03df11 + +### recipes.json + +- What: A small recipe book as JSON (json, 2.4 KB) +- Shows: nested objects and arrays, numbers of every kind, null, booleans, escapes, empty values +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 9662568867ec0629cb9c18897f1bff96f2b837cc7f89f0840f25f1e1f3e8f69c + +### config.yaml + +- What: Configuration file, YAML (yaml, 585 B) +- Shows: mappings, lists, block scalars, anchors and aliases, comments +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 398192bf091eeedd240dca6116180ef291ea95d7ee1c20e2e9853505d62854c9 + +### pyproject.toml + +- What: Project file, TOML (toml, 440 B) +- Shows: tables, arrays of tables, inline values +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: abcdc7dd5ef4d56589629b5c88d8b9a7931a84ddebd60c6b19f9f3b45349fb03 + +### feed.xml + +- What: Atom feed (xml, 1.3 KB) +- Shows: namespaces, CDATA, an XHTML content element, entities, comments +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 6cddabc37cc985205a2c04b4863fe3514695a5ef437e710463d15a597eb54560 + +### route.gpx + +- What: Coastal walk, GPX track (xml, 6.3 KB) +- Shows: 60 track points with elevation and time, two waypoints +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: fcafdec4e3a6819fa406e98590dd7ede302bf76cbc6a2080f08542438d08524e + +### places.kml + +- What: Places, KML (xml, 1.0 KB) +- Shows: a point, a line and a polygon, a shared style, HTML in CDATA +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 9bb4a018a5c1f00843e61af1c475c1a735898f73950689b9ce36f9bdeb7879b8 + +### harbour-log.csv + +- What: Harbour log, 300 rows of CSV (csv, 19 KB) +- Shows: nine columns, quoted fields with commas, quotes and line breaks, accents +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: d4e07a9e0b1aec65f189c8897fa27e1daf24189c3c204fb9527f2bf75d22e314 + +### tides.tsv + +- What: Tide table, tab-separated values (csv, 833 B) +- Shows: 28 rows, six columns +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: eff347351015e329e7904aebc8f334de5ab16cfda7a6b4c6b2575d25ac06fd68 + +### prix.csv + +- What: Price list in the European style (csv, 255 B) +- Shows: semicolon separator, decimal commas, accented headers +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: d490f1d9c26d7218e9937591baf5688d9846303fb6942a5e3c60417c1647b91d + +### life.py + +- What: Conway's Game of Life, Python (source, 1.0 KB) +- Shows: docstrings, comprehensions, f-strings, a main guard +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 2cfc1e34f435d1ee59d3b01e5567bf61034df38a7257e9fed4f1fbdf9436e19e + +### lru.rs + +- What: A least-recently-used cache, Rust (source, 1.6 KB) +- Shows: generics, trait bounds, closures, a test module +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 1e2181c4c51e88e4255f391fce16a9d657560408b728df079274804674ab1acb + +### tokens.ts + +- What: Arithmetic tokenizer and evaluator, TypeScript (source, 2.2 KB) +- Shows: union types, a sticky regular expression, the shunting-yard algorithm +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 3587b167a990c8ec02b14477721b4259431f39b432556a6cd86afc8cd2f525c2 + +### bits.c + +- What: Bit tricks on 32-bit words, C (source, 1.4 KB) +- Shows: static functions, hexadecimal literals, printf formats +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: dc7eab8de40430eb6ed22610c37fd2b13df11e69cc70f6d9e2718514e589a6d5 + +### report.sql + +- What: Monthly report with window functions, SQL (source, 1.3 KB) +- Shows: DDL, a CTE, lag, rank and sum over windows, joins +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 99688fcab08ea4876cee7a5d3352abbbd23d230c8c17bc4bbebeea276cf2bd9a + +### deploy.sh + +- What: Build and deploy script, Bash (source, 989 B) +- Shows: strict mode, traps, functions, process substitution, a case statement +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: a304fad73e5636d1caf340cfeca167e01905df2a31fc7abca661e8b8131375c7 + +### style.css + +- What: A small stylesheet, CSS (source, 1.1 KB) +- Shows: custom properties, grid, clamp, color-mix, a dark mode and a media query +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 7918765d12e41edd33e5a0eb2b7dba28c5429c3a517f086fcc8722f0306920c0 + +### page.html + +- What: A page, shown as its source, HTML (html, 1.1 KB) +- Shows: semantic elements, a table, a form, a style and a script that do not run +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: 82dd9087ee3afdb2c5443f2a9fb8100500a1633f2e0bdffc2630a8be8387c678 + +### changes.diff + +- What: A unified diff of two files (diff, 879 B) +- Shows: two files, three hunks, added and removed lines +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: e0d7a274666b4f411cd8a5b7318736c37ad7993db25b884c4c9100e13a1391d6 + +### subtitles.srt + +- What: Subtitles, SubRip (text, 338 B) +- Shows: six cues with a tag +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: b4e25a1b12f662df624ae81c2c8bd89a8951e338688d2ea2cce55134c5de3161 + +### server.log + +- What: A server log of 120 lines (text, 8.9 KB) +- Shows: INFO, WARN and ERROR lines +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-text.py` +- SHA-256: d7e982445e5d36a398533f671c0e7d0f758b47ff406798631924b037a64f6d95 + +## Images + +### scene.png + +- What: Dusk landscape, PNG (png, 26 KB) +- Shows: 8-bit RGB, optimised +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 4a0f00c07bb229932be134ede00f78851c8b1c4d3fa3eaa32164bb97c424f3fe + +### scene-alpha.png + +- What: Landscape fading to transparent, PNG (png, 48 KB) +- Shows: RGBA: the viewer shows its chequerboard through the alpha +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: c06a1651cfa68c3c729ba2a94eb0e6a3ccb306a24b3e4029d909a0da3e705a69 + +### scene-indexed.png + +- What: Landscape in 32 colours, PNG (png, 5.0 KB) +- Shows: palette (indexed) PNG +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: ebd709f812945dd233203f4dbea12c22af3450bd67be52dbc6668f35f55a0e58 + +### gradient-grey16.png + +- What: Grey ramp, 16-bit PNG (png, 47 KB) +- Shows: 16-bit greyscale +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 594a376de8d26c143d65c012f82aafd3775e8bd6698cd168ce957638c636379d + +### bounce.png + +- What: Bouncing ball, animated PNG (apng, 40 KB) +- Shows: 24 frames, APNG +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: dbe78676dee3a09eb44aafd14980b8999f11bf576e1152d2183193a9c18ff131 + +### scene.jpg + +- What: Dusk landscape, JPEG (jpeg, 24 KB) +- Shows: baseline 4:2:0 with EXIF description and copyright +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 42f3881913d6401dc2df511f6a975caeb834f965299c152f5535aa3ae6a5e02e + +### scene-progressive.jpg + +- What: Dusk landscape, progressive JPEG (jpeg, 20 KB) +- Shows: progressive scans, optimised Huffman tables +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 70c6c3352c093ac5da448706cb7873dc1fa991f84119d37f80acf63550078f65 + +### scene-orientation6.jpg + +- What: JPEG stored on its side with EXIF orientation 6 (jpeg, 22 KB) +- Shows: shown upright through the EXIF orientation +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 02e8b993e435a3de434c7efbe688757efa2fef452b1747c7382732b63e8e971b + +### scene-grey.jpg + +- What: Landscape in grey, JPEG (jpeg, 17 KB) +- Shows: single-component JPEG +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 546838a80bc5b7b042fdc593b8e95fbaaf39165347dcba32c45d341f2f5dabea + +### scene-cmyk.jpg + +- What: Landscape as a CMYK JPEG (jpeg, 51 KB) +- Shows: four components (Adobe inverted CMYK) +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 2c85449ef1574bc35fc3f54cf8aa724e518180aa86488ecef2be603816bfac01 + +### bounce.gif + +- What: Bouncing ball, animated GIF (gif, 100 KB) +- Shows: 24 frames with a palette each +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 386425b57344417f2205ac176a3a72eaed208ad67e57f7cd304ab845bf27d83b + +### scene.gif + +- What: Dusk landscape, dithered GIF (gif, 25 KB) +- Shows: 256 colours, Floyd-Steinberg dithering +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 9680147c7fabe6ba25e464c9cd41fe6e45b73502e68e811ea7037922f8c33255 + +### scene.webp + +- What: Dusk landscape, lossy WebP (webp, 8.8 KB) +- Shows: VP8 +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: c5a026e0341b0952e99af9ff4fa34de68e7ecc2da3326421e79a66639fef4787 + +### scene-lossless.webp + +- What: Dusk landscape, lossless WebP (webp, 18 KB) +- Shows: VP8L +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 7455a0e9ae36e7e9fb3f5b6ee094fcbece393dd9444d37cee3db785e36b01e79 + +### scene-alpha.webp + +- What: Landscape fading to transparent, WebP (webp, 18 KB) +- Shows: lossy colour with an alpha plane (VP8X, ALPH) +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: d62a7a8f0b2655221b84eec04c8adfd3d5f37a59425a706fa0eea900cc05b525 + +### bounce.webp + +- What: Bouncing ball, animated WebP (webp, 20 KB) +- Shows: 24 frames +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: edb4905dd92651bd42dbc3c15873913ec6bdca9a04afe83740565e082d90b84c + +### scene-lzw.tif + +- What: Dusk landscape, TIFF with LZW (tiff, 94 KB) +- Shows: RGB, LZW, 300 dpi +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: b3a41a6e8e4644e2b2291a50e499fd9988b735932c6c27def20587c1f565bcaa + +### scene-jpeg.tif + +- What: Dusk landscape, TIFF with JPEG compression (tiff, 56 KB) +- Shows: JPEG in TIFF (compression 7) +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: c5add42f305af0ca4dcf2cd554dc973611ce1334e5e91ba2b38ec2c58a35e89b + +### scene-cmyk-packbits.tif + +- What: Landscape as a CMYK TIFF (tiff, 49 KB) +- Shows: four inks, PackBits +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 57d7dbd0c807d1bcd7064367051ff75cdedddc4109e85cf67450c6601ec48fbc + +### gradient-grey16.tif + +- What: Grey ramp, 16-bit TIFF (tiff, 91 KB) +- Shows: 16-bit greyscale, Deflate +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 94c41cab542120478f4a7b97e694e8ddddd2520b022f9266a59bcf0e727baeea + +### scene-pages.tif + +- What: Three-page TIFF (tiff, 83 KB) +- Shows: pages of 512, 256 and 128 pixels, the last in grey, Deflate +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 9a8267875af78208d587777b341eb152d166b6acc10aede6d198d8e788ebd7a6 + +### fax-g4.tif + +- What: Fax cover sheet and register, CCITT Group 4 TIFF (tiff-fax, 22 KB) +- Shows: 1-bit, 1728 by 2200 at 204 by 196 dpi, T.6 +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: c4efa355dc63ce59863446b62b960397f34ab3d3c04a212450d0c2bca5f3904a + +### fax-g4-3pages.tif + +- What: Three-page fax, CCITT Group 4 TIFF (tiff-fax, 66 KB) +- Shows: three pages, T.6 +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: a94bc11060a7f2553803580c0feb779d1e59b032fd9f4406fbd4972765842cbb + +### scene-24.bmp + +- What: Dusk landscape, 24-bit BMP (bmp, 56 KB) +- Shows: BI_RGB, bottom-up +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: f3281d18d1f2944c7cb5f60eac3593facfbb3b77a0e5505e1ac88a9fdbefbfaa + +### scene-8.bmp + +- What: Dusk landscape, 8-bit BMP (bmp, 20 KB) +- Shows: 256-colour palette +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: d8ac5f35b9b76cd509191ec7f5c4a48f8236c5ca4dcc88197810060b16f47ad2 + +### scene-32.bmp + +- What: Dusk landscape, 32-bit BMP (bmp, 75 KB) +- Shows: four channels +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 1d99799f83adc1486eb1072502893ed39d91220d9e132a0716d56d9e05285d94 + +### scene-1bit.bmp + +- What: Dusk landscape, 1-bit BMP (bmp, 24 KB) +- Shows: two-colour palette +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: cc5152076963ba9beca3d0a5ed8a4ebd5f082c127e780ef68a955ce4b71e8786 + +### scene-rle8.bmp + +- What: Dusk landscape, 8-bit BMP with RLE compression (bmp, 11 KB) +- Shows: BI_RLE8 with encoded and absolute runs +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 2b1c69a7597006677e38cd8e32ad11f85acb0602ef228ec5c080d03350fc7936 + +### icon.ico + +- What: Icon with seven sizes (ico, 25 KB) +- Shows: 16 to 256 pixels, PNG-coded images +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 436e2c802c34d1c83b4492308ca660d4944eeb44fe32f6de87d3869e1c9e89ea + +### icon-legacy.ico + +- What: Icon in the legacy bitmap coding (ico, 14 KB) +- Shows: 32-bit and 8-bit DIBs with AND masks, and one PNG image +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 0ded5b411cd2cf1ebd15cdecfa12a1e9f4a53b74da39fa263f935329efe399ec + +### scene.ppm + +- What: Dusk landscape, PPM (P6) (pnm, 36 KB) +- Shows: binary pixmap with a comment +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 43949e7d7636ed5a7d552ad6fac28eb72487a70a1f63db7d944fb7e587612b40 + +### scene-ascii.ppm + +- What: Dusk landscape, ASCII PPM (P3) (pnm, 17 KB) +- Shows: text pixmap, 48 by 36 +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 996f21e5c7c05ed1c586b9dc9882ad6fba9f1153ba23c49844c640eef647bf8a + +### scene-grey16.pgm + +- What: Landscape in grey, 16-bit PGM (P5) (pnm, 24 KB) +- Shows: maxval 65535 +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 059c3e7b9e22b0aa4247552139886564f9b36d66051ffc7957efd972f557b52c + +### scene.pbm + +- What: Landscape as a bitmap, PBM (P4) (pnm, 6.0 KB) +- Shows: 1 bit a pixel +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 648c9687dc2c226306c64aa945bf81170bbff5d8c9f88b0630b07b294d4e2edb + +### scene-alpha.pam + +- What: Landscape with alpha, PAM (P7) (pnm, 48 KB) +- Shows: RGB_ALPHA tuples +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 806cee6e77cbd0226f6ec3ab18de4259612a89c1df5ff5e27e37d4d5c932c515 + +### scene.qoi + +- What: Dusk landscape, QOI (qoi, 38 KB) +- Shows: three channels +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: d04c2ff91df0173bf20c495eb19555dc4bc9342b9ec7b61f653a4742c00b6188 + +### scene-alpha.qoi + +- What: Landscape with alpha, QOI (qoi, 89 KB) +- Shows: four channels +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 16a53b8756ab8dd663400cfa04dde6a598b6c608d345efd131c0d714cde8affb + +### scene.ff + +- What: Landscape with alpha, farbfeld (farbfeld, 54 KB) +- Shows: 16-bit RGBA, big-endian +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: b6d250a92f39b7183b42191933d84da7e6ef1a33a971c8e7c2f8ccc85ad060d0 + +### sunset.hdr + +- What: Sunset with a sun far brighter than the sky, Radiance HDR (hdr, 54 KB) +- Shows: RGBE with run-length scanlines; the sun is 60 times white +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: f65ffee0666792f829c6692ca1ef4a0a553304d06e28682f18a47de5efed7e9b + +### sunset-flat.hdr + +- What: Sunset, uncompressed Radiance HDR (hdr, 48 KB) +- Shows: flat RGBE scanlines +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: a401df61e76cfdf88731294a4ba5ce1ba607ee294b5010a1312925240f5d2131 + +### scene-bc1.dds + +- What: Dusk landscape, DDS with BC1 (DXT1) (dds, 32 KB) +- Shows: full mipmap chain +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 77d26e97cc0f532481e3e585321305aca44efd7694307f312d75b1c4bfecf8f8 + +### scene-bc3.dds + +- What: Landscape with alpha, DDS with BC3 (DXT5) (dds, 64 KB) +- Shows: full mipmap chain, alpha blocks +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 9028c95d163d7283b357e3beb6a531a192087fcb76e7aeb1aead81195e4f4a92 + +### scene.jp2 + +- What: Dusk landscape, JPEG 2000 (JP2) (jpeg2000, 80 KB) +- Shows: lossy, 3 quality layers, 5 resolutions, 256-pixel tiles, RPCL progression +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: f90f58bb1e3ef0bfd48b9b55bffc293ee4f1fe506a6717f0052319a34621bf9a + +### scene.j2k + +- What: Dusk landscape, bare JPEG 2000 codestream (jpeg2000, 48 KB) +- Shows: no JP2 boxes +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 949564fa2b811a1987a12989095289d673c2a4937f5014b0b9c1d7bfbe660b9c + +### scene-grey.jp2 + +- What: Landscape in grey, JPEG 2000 (jpeg2000, 19 KB) +- Shows: one component +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: eb50ae4528e774c7ab9c427509faee07473249a89d35403c33afb2e5e9abf983 + +### scene-alpha.jp2 + +- What: Landscape with alpha, JPEG 2000 (jpeg2000, 77 KB) +- Shows: four components with an alpha channel +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: bc1adbddf1bd608b71b1cac9dd1a47f47cde2c046a4202f1642cd15efa647825 + +### page-generic.jb2 + +- What: Fax page as a JBIG2 file, generic region (jbig2, 8.4 KB) +- Shows: 1-bit page of 1240 by 1579, arithmetic coding +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 1447cbbc1ebab320062a78fa40f81ccf768aed3d9aea2cfa0583ebce2fb3e088 + +### page-symbol.jb2 + +- What: Fax page as a JBIG2 file, symbol coding (jbig2, 5.4 KB) +- Shows: text region over a symbol dictionary +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 8fba2e640c71101dd5ab376008ea177ee0e8f2070c49250d31186c198991da9e + +### scene-lossy.jxl + +- What: Dusk landscape, JPEG XL, lossy (jpeg-xl, 23 KB) +- Shows: VarDCT at distance 1 +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: dc1e17bd77c26a49a3c61fcd8b299c79b71395550a4e1d42bc69af6aa33a200f + +### scene-lossless.jxl + +- What: Dusk landscape, JPEG XL, lossless (jpeg-xl, 26 KB) +- Shows: modular mode +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 5f2ce3702bb3fe54bb31feb6f1a9e92347a9acd290a6a7730a3074fe5fb088fe + +### scene-alpha.jxl + +- What: Landscape with alpha, JPEG XL (jpeg-xl, 35 KB) +- Shows: lossless with an extra alpha channel +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: d18698258dcc59292483265284a96099bc2c1f23f53f4893d778062070588166 + +### bounce.jxl + +- What: Bouncing ball, animated JPEG XL (jpeg-xl, 60 KB) +- Shows: 24 frames +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: 679c04f1bec63d699c6baeb1d42dfa4ff205a40327f208f650115f7292e27f89 + +### monet-gardeners-house-antibes.jpg + +- What: Claude Monet, The Gardener's House at Antibes (1888) (jpeg, 395 KB) +- Shows: a painting, JPEG from the museum's web size +- Author: Claude Monet, Cleveland Museum of Art (open access) +- Source: https://clevelandart.org/art/1916.1044 +- Licence: CC0-1.0 +- Evidence: https://clevelandart.org/art/1916.1044 +- Words read there: ""share_license_status":"CC0"" +- Origin: downloaded from https://openaccess-cdn.clevelandart.org/1916.1044/1916.1044_web.jpg +- SHA-256: 95142eba48d54f01352eb4ef6f04260cb3df3bcb1d9c86000c1284a7817674ca + +### queen-mab-cave.jpg + +- What: Queen Mab's Cave, in the manner of Turner (jpeg, 213 KB) +- Shows: a painting +- Author: Imitator of J. M. W. Turner, Cleveland Museum of Art (open access) +- Source: https://clevelandart.org/art/1916.1036 +- Licence: CC0-1.0 +- Evidence: https://clevelandart.org/art/1916.1036 +- Words read there: ""share_license_status":"CC0"" +- Origin: downloaded from https://openaccess-cdn.clevelandart.org/1916.1036/1916.1036_web.jpg +- SHA-256: b84e005332288229d808172a7610b501d9977c0b4668e333faea5ff780157223 + +### rembrandt-st-francis.jpg + +- What: Rembrandt, Saint Francis Beneath a Tree Praying (etching) (jpeg, 362 KB) +- Shows: an etching, fine line work +- Author: Rembrandt van Rijn, Cleveland Museum of Art (open access) +- Source: https://clevelandart.org/art/2024.64 +- Licence: CC0-1.0 +- Evidence: https://clevelandart.org/art/2024.64 +- Words read there: ""share_license_status":"CC0"" +- Origin: downloaded from https://openaccess-cdn.clevelandart.org/2024.64/2024.64_web.jpg +- SHA-256: 74b37aa3738914dd66c07533b3758f7694fefbaa918d2f23c263205cf987db7b + +### nolli-rome-plate.jpg + +- What: Nolli's map of Rome (1748), a plate (jpeg, 315 KB) +- Shows: an engraved city plan +- Author: Giovanni Battista Nolli et al., Cleveland Museum of Art (open access) +- Source: https://clevelandart.org/art/2020.276.3 +- Licence: CC0-1.0 +- Evidence: https://clevelandart.org/art/2020.276.3 +- Words read there: ""share_license_status":"CC0"" +- Origin: downloaded from https://openaccess-cdn.clevelandart.org/2020.276.3/2020.276.3_web.jpg +- SHA-256: 7643c9e59f7706ebe62518a51daf7d72129acc8092dde7afc65516d3d11b6c77 + +### pallid-swift.jpg + +- What: Pallid swift in flight (photograph) (jpeg, 348 KB) +- Shows: a camera JPEG with EXIF data (Canon EOS R6 Mark II) +- Author: Hobbyfotowiki +- Source: https://commons.wikimedia.org/wiki/File:Pallid_swift_(in_flight).jpg +- Licence: CC0-1.0 +- Evidence: https://commons.wikimedia.org/wiki/File:Pallid_swift_(in_flight).jpg +- Words read there: "This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Dedication." +- Origin: downloaded from https://upload.wikimedia.org/wikipedia/commons/d/df/Pallid_swift_%28in_flight%29.jpg +- SHA-256: 9d0f79f12dcc236f549cdefb66dc468f25335d444ebd26e98805efdd94afecbd + +### cyclotron-patent.png + +- What: Drawing from Lawrence's cyclotron patent (png, 202 KB) +- Shows: a black and white technical drawing +- Author: Ernest O. Lawrence (US Patent Office) +- Source: https://commons.wikimedia.org/wiki/File:Cyclotron_patent_p1.png +- Licence: public-domain (US patent text and drawings published before 1989) +- Evidence: https://commons.wikimedia.org/wiki/File:Cyclotron_patent_p1.png +- Words read there: "The text and illustrations of US patents published before March 1, 1989 are in the public domain unl" +- Origin: downloaded from https://upload.wikimedia.org/wikipedia/commons/4/42/Cyclotron_patent_p1.png +- SHA-256: 0be9b59ae21bbadeb8a13fafde5e0bcfb6d470ba516244eab0ec1c74afd7394f + +### mature-flower-diagram.svg + +- What: Diagram of a mature flower (svg, 121 KB) +- Shows: 85 texts, about 90 gradient references, many paths +- Author: Mariana Ruiz Villarreal (LadyofHats) +- Source: https://commons.wikimedia.org/wiki/File:Mature_flower_diagram.svg +- Licence: public-domain (released by its author) +- Evidence: https://commons.wikimedia.org/wiki/File:Mature_flower_diagram.svg +- Words read there: "This work has been released into the public domain by its author, LadyofHats." +- Origin: downloaded from https://upload.wikimedia.org/wikipedia/commons/7/7f/Mature_flower_diagram.svg +- SHA-256: b40bd4e188c0a99e51e994b4f39f931d3fca28093ecb6454aa2bd93c575ea999 + +### entamoeba-life-cycle.svg + +- What: Life cycle of Entamoeba histolytica (svg, 267 KB) +- Shows: 547 paths, text and arrows +- Author: Mariana Ruiz Villarreal (LadyofHats) +- Source: https://commons.wikimedia.org/wiki/File:Entamoeba_histolytica_life_cycle-en.svg +- Licence: public-domain (released by its author) +- Evidence: https://commons.wikimedia.org/wiki/File:Entamoeba_histolytica_life_cycle-en.svg +- Words read there: "This work has been released into the public domain by its author, LadyofHats." +- Origin: downloaded from https://upload.wikimedia.org/wikipedia/commons/a/a1/Entamoeba_histolytica_life_cycle-en.svg +- SHA-256: 68a4a92289d81f0e7e9361abbba2da9a8c8b4e440e3ad9de5c420646eb133eaa + +### sieve-of-eratosthenes.svg + +- What: Sieve of Eratosthenes, animated (svg, 22 KB) +- Shows: SMIL animation with 179 animate elements +- Author: Ricordisamoa, with later edits by Jc86035, HereToHelp and Glrx +- Source: https://commons.wikimedia.org/wiki/File:Sieve_of_Eratosthenes_animation.svg +- Licence: public-domain (ineligible for copyright, Wikimedia Commons PD-ineligible) +- Evidence: https://commons.wikimedia.org/wiki/File:Sieve_of_Eratosthenes_animation.svg +- Words read there: "This work is ineligible for copyright and therefore in the public domain because it consists entirel" +- Origin: downloaded from https://upload.wikimedia.org/wikipedia/commons/0/0b/Sieve_of_Eratosthenes_animation.svg +- SHA-256: d8f1d6d0a4b5710ebe1e7766eab30b766b10dc9380c1058ccb39baccd7d51586 + +### muybridge-horse.gif + +- What: Muybridge's horse in motion, animated GIF (gif, 555 KB) +- Shows: 15 frames +- Author: Eadweard Muybridge (photographs, 1887); animation by Waugsberg +- Source: https://commons.wikimedia.org/wiki/File:Muybridge_race_horse_animated.gif +- Licence: public-domain (the author died in 1904) +- Evidence: https://commons.wikimedia.org/wiki/File:Muybridge_race_horse_animated.gif +- Words read there: "The author died in 1904, so this work is in the public domain in its country of origin and other cou" +- Origin: downloaded from https://upload.wikimedia.org/wikipedia/commons/d/dd/Muybridge_race_horse_animated.gif +- SHA-256: eb40bebc1f039e7c2a121673c3b55d4aa73582f858053dbbcca9ebce9e2b479d + +### geneva-mechanism.gif + +- What: Geneva mechanism with six spokes, animated GIF (gif, 224 KB) +- Shows: 101 frames +- Author: Mike1024 +- Source: https://commons.wikimedia.org/wiki/File:Geneva_mechanism_6spoke_animation.gif +- Licence: public-domain (released by its author) +- Evidence: https://commons.wikimedia.org/wiki/File:Geneva_mechanism_6spoke_animation.gif +- Words read there: "I, the copyright holder of this work, release this work into the public domain." +- Origin: downloaded from https://upload.wikimedia.org/wikipedia/commons/9/9b/Geneva_mechanism_6spoke_animation.gif +- SHA-256: d7df5c9984109c2ca60f7aab1a51db1f0b578cddcdede5d43be9f67536e2a1ee + +### abundance-nemo-g4-6pages.tif + +- What: Les grans et merveilleux faictz du seigneur Nemo (scan, six pages, CCITT Group 4) (tiff-fax, 323 KB) +- Shows: a multi-page bilevel TIFF scanned from a 16th-century book +- Author: Jean d'Abundance (16th century); scanned by the Bibliothèque nationale de France +- Source: https://commons.wikimedia.org/wiki/File:Abundance_-_Les_grans_et_merveilleux_faictz_du_seigneur_Nemo%2C_avec_les_privil%C3%A8ges_qu%E2%80%99il_a.tif +- Licence: public-domain (a mechanical scan of a public domain book, Wikimedia Commons PD-scan) +- Evidence: https://commons.wikimedia.org/wiki/File:Abundance_-_Les_grans_et_merveilleux_faictz_du_seigneur_Nemo%2C_avec_les_privil%C3%A8ges_qu%E2%80%99il_a.tif +- Words read there: "This file is in the public domain because it is a mere mechanical scan or photocopy of a public doma" +- Origin: downloaded from https://upload.wikimedia.org/wikipedia/commons/b/b5/Abundance_-_Les_grans_et_merveilleux_faictz_du_seigneur_Nemo%2C_avec_les_privil%C3%A8ges_qu%E2%80%99il_a.tif +- SHA-256: 38bab27c6d559e11468d6c7e4222f0bb1bee4ba0044540adcebfc012930e00d1 + +## Camera RAW + +### canon-eos-40d-sraw.cr2 + +- What: Canon EOS 40D, sRAW (CR2) (raw-cr2, 5.5 MB) +- Shows: TIFF-based CR2 with a 1936 by 1288 JPEG preview +- Author: Uploader to raw.pixls.us (the site gives no name) +- Source: https://raw.pixls.us/#repo +- Licence: CC0-1.0 +- Evidence: https://raw.pixls.us/json/getrepository.php?set=all +- Words read there: "Creative Commons 0 - Public Domain" +- Origin: downloaded from https://raw.pixls.us/getfile.php/2102/nice/Canon%20-%20EOS%2040D%20-%20sRAW2%20%28sRAW%29%20%283%3A2%29.CR2 +- SHA-256: ba644e7dd2abe74eca260e67f0206ff113bf0f62e710f8130611e964d6be5bf1 + +### canon-eos-r6.cr3 + +- What: Canon EOS R6, C-RAW (CR3) (raw-cr3, 5.0 MB) +- Shows: ISO base media CR3 with a 3408 by 2272 JPEG in its second track; its EXIF names Johannes Kimmel as artist and states CC0 +- Author: Uploader to raw.pixls.us; EXIF artist Johannes Kimmel +- Source: https://raw.pixls.us/#repo +- Licence: CC0-1.0 +- Evidence: https://raw.pixls.us/json/getrepository.php?set=all +- Words read there: "Creative Commons 0 - Public Domain" +- Origin: downloaded from https://raw.pixls.us/getfile.php/4659/nice/Canon%20-%20EOS%20R6%20-%203%3A2.CR3 +- SHA-256: 74abb0a113d075ad9887a058082f40dd2a938c4813a08474d82356f11a027778 + +### canon-powershot-g1.crw + +- What: Canon PowerShot G1 (CRW) (raw-crw, 2.2 MB) +- Shows: the 2000 CIFF/HEAP container with a 640 by 480 JPEG +- Author: Uploader to raw.pixls.us (the site gives no name) +- Source: https://raw.pixls.us/#repo +- Licence: CC0-1.0 +- Evidence: https://raw.pixls.us/json/getrepository.php?set=all +- Words read there: "Creative Commons 0 - Public Domain" +- Origin: downloaded from https://raw.pixls.us/getfile.php/2073/nice/Canon%20-%20PowerShot%20G1%20-%20RAW%20%284%3A3%29.crw +- SHA-256: f39be5acf14057ce04527fd8d0574e57ec8ed5fed082d7bfaff763075a44ee8a + +### nikon-d70s.nef + +- What: Nikon D70s (NEF) (raw-nef, 5.0 MB) +- Shows: TIFF-based NEF with a 3008 by 2000 JPEG in a SubIFD +- Author: Uploader to raw.pixls.us (the site gives no name) +- Source: https://raw.pixls.us/#repo +- Licence: CC0-1.0 +- Evidence: https://raw.pixls.us/json/getrepository.php?set=all +- Words read there: "Creative Commons 0 - Public Domain" +- Origin: downloaded from https://raw.pixls.us/getfile.php/1117/nice/Nikon%20-%20D70s%20-%2012bit%2012bit%20compressed%20%28Lossy%20%28type%201%29%29%20%283%3A2%29.NEF +- SHA-256: 6c46f9854033e7623ebbb5de8c951df6762ca44f05d45035ccc5cb7e9f4e5692 + +### sony-ilce-7s.arw + +- What: Sony A7S (ARW) (raw-arw, 5.9 MB) +- Shows: TIFF-based ARW with a 1616 by 1080 JPEG preview +- Author: Uploader to raw.pixls.us (the site gives no name) +- Source: https://raw.pixls.us/#repo +- Licence: CC0-1.0 +- Evidence: https://raw.pixls.us/json/getrepository.php?set=all +- Words read there: "Creative Commons 0 - Public Domain" +- Origin: downloaded from https://raw.pixls.us/getfile.php/1582/nice/Sony%20-%20ILCE-7S%20-%2014bit%2014bit%20compressed%20%283%3A2%29.ARW +- SHA-256: a35ebb2fbec929daa5beb20d1ce5c15a8aac7b1a7a231455387f3df8a7442e07 + +### olympus-c5060wz.orf + +- What: Olympus C5060WZ (ORF) (raw-orf, 7.3 MB) +- Shows: the only picture inside is a 160 by 120 thumbnail +- Author: Uploader to raw.pixls.us (the site gives no name) +- Source: https://raw.pixls.us/#repo +- Licence: CC0-1.0 +- Evidence: https://raw.pixls.us/json/getrepository.php?set=all +- Words read there: "Creative Commons 0 - Public Domain" +- Origin: downloaded from https://raw.pixls.us/getfile.php/1799/nice/Olympus%20-%20C5060WZ%20-%2012bit%20%284%3A3%29.ORF +- SHA-256: 3fc12bc3f6320cfab456111d7805b446e329fdd1907680be55e2e163e5e084bd + +### panasonic-dmc-lx7.rw2 + +- What: Panasonic Lumix DMC-LX7 (RW2) (raw-rw2, 3.2 MB) +- Shows: RW2 with a 1920 by 1280 JPEG +- Author: Uploader to raw.pixls.us (the site gives no name) +- Source: https://raw.pixls.us/#repo +- Licence: CC0-1.0 +- Evidence: https://raw.pixls.us/json/getrepository.php?set=all +- Words read there: "Creative Commons 0 - Public Domain" +- Origin: downloaded from https://raw.pixls.us/getfile.php/7010/nice/Panasonic%20-%20DMC-LX7%20-%203%3A2.RW2 +- SHA-256: 18dfc3877e944020299635a8c2fad61fca2485b1c9b67645a495ee870a86e599 + +### fujifilm-finepix-s5000.raf + +- What: Fujifilm FinePix S5000 (RAF) (raw-raf, 6.5 MB) +- Shows: RAF container with a 1280 by 960 JPEG +- Author: Uploader to raw.pixls.us (the site gives no name) +- Source: https://raw.pixls.us/#repo +- Licence: CC0-1.0 +- Evidence: https://raw.pixls.us/json/getrepository.php?set=all +- Words read there: "Creative Commons 0 - Public Domain" +- Origin: downloaded from https://raw.pixls.us/getfile.php/2726/nice/Fujifilm%20-%20FinePix%20S5000%20-%204%3A3.RAF +- SHA-256: dabd5e74521a6980156be9fd4b88d0c37b0fe4d0e0e6f5c12db8cffff1b76297 + +### adobe-dng-canon-5d3.dng + +- What: Canon EOS 5D Mark III converted to DNG (lossy JPEG) (raw-dng, 2.4 MB) +- Shows: DNG with previews of 256, 1024 and 3960 pixels; converted by Adobe DNG Converter, not straight from a camera +- Author: Uploader to raw.pixls.us; EXIF artist Simon Harhues +- Source: https://raw.pixls.us/#repo +- Licence: CC0-1.0 +- Evidence: https://raw.pixls.us/json/getrepository.php?set=all +- Words read there: "Creative Commons 0 - Public Domain" +- Origin: downloaded from https://raw.pixls.us/getfile.php/1033/nice/Adobe%20DNG%20Converter%20-%20Canon%20EOS%205D%20Mark%20III%20-%20Lossy%20JPEG%20compression%2C%20rgb%20%283%3A2%29.DNG +- SHA-256: b22f1e36331f679abb8b13e433b9bbde3988723adf10fee7aa0dda6381016a98 + +## CAD + +### house-plan.dxf + +- What: House, ground floor plan (DXF 2018) (dxf, 85 KB) +- Shows: walls cut at openings with pattern hatches, door blocks with attributes, window and furniture blocks, axes with bubbles, room labels, linear, aligned, radius and angular dimensions, stair, north arrow, 17 layers, paper-space sheet with a viewport and a title block +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-cad.py` +- SHA-256: ad78cc54ad3c52483040b71dcb5cafda6f3660bdc9f229e21b22ece2cc773815 + +### house-plan-r2000.dxf + +- What: House, ground floor plan (DXF 2000) (dxf, 82 KB) +- Shows: the same plan written as an AutoCAD 2000 file +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-cad.py` +- SHA-256: eabe480065538e478a22424b5d3b0427efd321e098f7e9cabe4ad332984ab033 + +### house-elevations.dxf + +- What: House, four elevations and a section in 2D (dxf, 95 KB) +- Shows: gabled roofs with roof-tile hatches, plaster hatches, ground hatching, windows with transparent glass, steps, level marks, height dimensions, a hatched section with a stair +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-cad.py` +- SHA-256: 4ddb32c976e6709e39a4184a09c772ecff99324dcefd03e40a2cf7d89f62661f + +### hatch-gallery.dxf + +- What: Hatch gallery (dxf, 142 KB) +- Shows: about a hundred predefined patterns, nine gradient types, islands in the three hatch styles, boundaries of lines, arcs, ellipses and splines, pattern angle and scale +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-cad.py` +- SHA-256: 0d9978ab422cfea65f91149502727f7132a3192450eedf52f90c9075f36b8cf4 + +### dimensions.dxf + +- What: Dimension types (dxf, 55 KB) +- Shows: linear, aligned, diameter, radius, arc length, angular (two lines and three points), ordinate, leaders, a multileader, tolerances, text override, three dimension styles +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-cad.py` +- SHA-256: 515ccb26e3d707c2dc12192f147a4003dc44118d17da04d6f162250aa5935d87 + +### linetypes.dxf + +- What: Linetypes, line weights and polylines (dxf, 35 KB) +- Shows: the standard linetypes, custom ones with text inside, 12 line weights, per-entity scale, linetype generation, polylines with widths, circles, arcs, ellipses and splines in dashed styles +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-cad.py` +- SHA-256: 0c8f9b53c105c230bad51a7fbad1af8972725fea449d638015c94467229c7cc0 + +### text-styles.dxf + +- What: Text styles and MTEXT (dxf, 30 KB) +- Shows: ten text styles (width and oblique factors, mirrored, upside down), justifications, rotation, special codes, Unicode, MTEXT colours, fonts, stacked fractions, underline, columns, background, nine attachment points +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-cad.py` +- SHA-256: e2c312052780d94fd25ad4205370645b143ceecde87d57dac2d471582cddeb3e + +### blocks.dxf + +- What: Blocks, nested inserts and arrays (dxf, 30 KB) +- Shows: a block inside a block inside a block with attributes, mirrored, scaled and rotated inserts, a 3 by 8 array, BYBLOCK colours +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-cad.py` +- SHA-256: 419ffd35c1dd1d4ded3d70039dfa49852fa85cce935911b10a7a00557b967844 + +### bracket.dxf + +- What: Mechanical part: an L bracket in three views (dxf, 42 KB) +- Shows: centre and hidden lines, a section with hatching, dimensions with tolerances, diameter and radius dimensions, a leader, an A4 sheet with a title block +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-cad.py` +- SHA-256: cd5d9676a8bb77c0702757674e17723202e3a614c38ca96ae8bd8f9c2ad1cfa9 + +### site-plan.dxf + +- What: Site plan with contour lines (dxf, 84 KB) +- Shows: closed spline contours, wide polyline roads, parcels with areas, hatched buildings, a gradient pond, spot heights, trees, scale bar, legend and north arrow +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-cad.py` +- SHA-256: c5bb9b26f9dbd785754d18854c1faef18fd360a8411f2244c3553d4c75a8baeb + +### legacy-r12.dxf + +- What: Gear in the R12 format (dxf, 14 KB) +- Shows: POLYLINE, CIRCLE, ARC, TEXT, SOLID, 3DFACE and INSERT entities of the 1992 format +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-cad.py` +- SHA-256: 926e991c1389fcdf73d8aff413eb8b0c122943bf95f1667b31ba78b7db2a0723 + +### barraca-valenciana-0100-r2010.dwg + +- What: Barraca Valenciana, ground floor plan (DWG 2010, Revit export) (dwg, 278 KB) +- Shows: walls, doors, glazing, stairs, furniture, hatches, areas, 24 layers, 56 blocks, extra layouts with title block and viewports +- Author: Ã’scar Selfa +- Source: https://zenodo.org/records/14293897 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/records/14293897 +- Words read there: "Creative Commons Attribution 4.0 International" +- Attribution: Ã’scar Selfa, Barraca Valenciana de Llauradors: Model BIM i Estudi de la Tipologia Arquitectònica, Zenodo, doi:10.5281/zenodo.14293897, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/records/14293897/files/BRC-OSP-XXX-P00-PLA-ARQ-0100-tipologiaGen%C3%A8rica-A1-P2.dwg?download=1 +- SHA-256: fcd3eef78cbd568e3f8a8262378670495a3ea6b8e091cb162fe8ef9c3c9add13 + +### barraca-valenciana-0300-r2010.dwg + +- What: Barraca Valenciana, elevations (DWG 2010, Revit export) (dwg, 1.0 MB) +- Shows: elevations drawn as 2D linework with hatches, topography and planting, no 3D +- Author: Ã’scar Selfa +- Source: https://zenodo.org/records/14293897 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/records/14293897 +- Words read there: "Creative Commons Attribution 4.0 International" +- Attribution: Ã’scar Selfa, Barraca Valenciana de Llauradors: Model BIM i Estudi de la Tipologia Arquitectònica, Zenodo, doi:10.5281/zenodo.14293897, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/records/14293897/files/BRC-OSP-XXX-ZZZ-PLA-ARQ-0300-tipologiaGen%C3%A8rica-A1-P2.dwg?download=1 +- SHA-256: 93a211cfb797525a94b5b41aeae3ecf33e61442eea07cadae056463cc400a3e5 + +### barraca-valenciana-0400-r2010.dwg + +- What: Barraca Valenciana, sections and details (DWG 2010, Revit export) (dwg, 499 KB) +- Shows: 42 layers, hatches, arcs, splines, ellipses, 61 blocks +- Author: Ã’scar Selfa +- Source: https://zenodo.org/records/14293897 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/records/14293897 +- Words read there: "Creative Commons Attribution 4.0 International" +- Attribution: Ã’scar Selfa, Barraca Valenciana de Llauradors: Model BIM i Estudi de la Tipologia Arquitectònica, Zenodo, doi:10.5281/zenodo.14293897, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/records/14293897/files/BRC-OSP-XXX-ZZZ-PLA-ARQ-0400-tipologiaGen%C3%A8rica-A1-P2.dwg?download=1 +- SHA-256: a09c492dc34ead8df619d6d618049298afffb050a8436c470055923a90f4b61c + +### building-survey-plans-r2000.dwg + +- What: Survey of a small building: plans, elevations and details (DWG 2000) (dwg, 2.0 MB) +- Shows: Italian drawing with room names and areas, over 120 layers, 890 blocks, 567 dimensions, 492 hatches +- Author: Giovanni De Gasperis, Sante Dino Facchini, Asif Saeed +- Source: https://zenodo.org/records/15076037 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/records/15076037 +- Words read there: "Creative Commons Attribution 4.0 International" +- Attribution: De Gasperis, G., Facchini, S. D., Saeed, A., Building Ledger Dossier: Seismic Prevention and Building Documentation Tracking through a Digital Twin Approach (4_Architectural_Building_Survey.dwg), Zenodo, doi:10.5281/zenodo.15076037, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/records/15076037/files/4_Architectural_Building_Survey.dwg?download=1 +- SHA-256: 2f096b44cd5b60ded2ad8b12c2f46116db8b1fda1c980f7bb02660a85782ab1d + +### golden-tile-palace-r2004.dwg + +- What: Golden Tile Palace: front elevation and section (DWG 2004) (dwg, 746 KB) +- Shows: elevation and section with level marks and Chinese titles, 4393 polylines, 841 arcs, 328 splines, 26 dimensions, 24 hatches +- Author: Jing Zhang, Yunying Ren, Xiaofan An +- Source: https://figshare.com/articles/dataset/Figure_of_surveying_and_mapping_of_Golden_Tile_Palace_/21374221 +- Licence: CC-BY-4.0 +- Evidence: https://api.figshare.com/v2/articles/21374221 +- Words read there: ""name": "CC BY 4.0"" +- Attribution: Jing Zhang, Yunying Ren, Xiaofan An, Figure of surveying and mapping of Golden Tile Palace, supplementary file S1 of PLOS ONE doi:10.1371/journal.pone.0262155, figshare, CC BY 4.0. No changes. +- Origin: downloaded from https://ndownloader.figshare.com/files/37930432 +- SHA-256: 14d128397f89c1af652b2cd3c9d523db98ae539b1bc061d4f06fba6d21501ae9 + +### residential-site-plan-r2007.dwg + +- What: Site plan of an old residential community in Beijing (DWG 2007) (dwg, 926 KB) +- Shows: 58 layers, 79 blocks, buildings, roads, 2865 polylines, 656 texts, 125 hatches, 39 dimensions +- Author: Yijun Fan +- Source: https://figshare.com/articles/dataset/Drainage_System_Layout_of_Old_Urban_Residential_Communities_In_Beijing/28188725 +- Licence: CC-BY-4.0 +- Evidence: https://api.figshare.com/v2/articles/28188725 +- Words read there: ""name": "CC BY 4.0"" +- Attribution: Yijun Fan, Drainage System Layout of Old Urban Residential Communities In Beijing (Site Plan.dwg), figshare, doi:10.6084/m9.figshare.28188725.v1, CC BY 4.0. No changes. +- Origin: downloaded from https://ndownloader.figshare.com/files/51611078 +- SHA-256: 37b03757172e5360a03cc26da473cde84e85dbd61914b67741c94a40f7f0db2f + +### hospital-floor-plan-r2013.dwg + +- What: Furnished hospital floor plan (DWG 2013) (dwg, 1.2 MB) +- Shows: section and level marks, 109 dimensions, 429 block definitions of furniture and plants, 19 layers +- Author: Toka Ehab +- Source: https://zenodo.org/records/10520508 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/records/10520508 +- Words read there: "Creative Commons Attribution 4.0 International" +- Attribution: Toka Ehab, Nanotechnology Applications in Interior Design of hospitals to enhance thermal comfort and decrease the infection spread for the occupants (Elite hospital plan.dwg), Zenodo, doi:10.5281/zenodo.10520508, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/records/10520508/files/Elite%20hospital%20plan.dwg?download=1 +- SHA-256: b618207b01a1759142e038e1edf762ab8efbe11804bb2e84fc6f472e7e040fb9 + +### commercial-building-hvac-plans-r2018.dwg + +- What: Air-conditioning plans of a commercial building (DWG 2018) (dwg, 495 KB) +- Shows: 48 layers, 320 blocks, 316 dimensions, 125 hatches, 112 wipeouts +- Author: Kevin Anthony do Bem +- Source: https://zenodo.org/records/10407941 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/records/10407941 +- Words read there: "Creative Commons Attribution 4.0 International" +- Attribution: Kevin Anthony do Bem, Projeto de Climatização de um Edifício de Comércio e Serviços (F04 Plantas- Rede aerolica.dwg), Zenodo, doi:10.5281/zenodo.10407941, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/records/10407941/files/F04%20Plantas-%20Rede%20aerolica.dwg?download=1 +- SHA-256: bcf3b92e0afdf29bb75e7632e8193f881918ddabb4de67a1331b5eda34ee9be2 + +### ezdxf-dim-linear-tutorial-r2013.dwg + +- What: ezdxf documentation: linear dimension tutorial (DWG 2013) (dwg, 36 KB) +- Shows: 16 dimensions, 16 multileaders, 13 dimension styles, 27 text styles +- Author: Manfred Moitzi (ezdxf) +- Source: https://github.com/mozman/ezdxf/blob/748e211c9a0b977b9e15845a6bcad8e1b9743e26/docs/graphics/dim_linear_tutorial.dwg +- Licence: MIT +- Evidence: https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/LICENSE +- Words read there: "Copyright (c) 2020 Manfred Moitzi" +- Attribution: Copyright (c) 2020 Manfred Moitzi, ezdxf, MIT License. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/docs/graphics/dim_linear_tutorial.dwg +- SHA-256: 88037b595bd46d81c5c98ce7aa428ce6b8506d1aa4602e976811cfb154005155 + +### hospital-ward-wing-plan-section.dxf + +- What: Hospital ward wing, plan and section (DXF 2010) (dxf, 300 KB) +- Shows: 542 polylines, 17 layers of the A-* scheme, 3 blocks, a paper-space viewport +- Author: Innerscene (original model) +- Source: https://www.innerscene.com/tools/library/drawings/hospital-ward-wing-1200-square-metres-plan-and-section-73a3f4dd +- Licence: CC0-1.0 +- Evidence: https://www.innerscene.com/tools/library/drawings/hospital-ward-wing-1200-square-metres-plan-and-section-73a3f4dd +- Words read there: "Original Innerscene model, released CC0." +- Origin: downloaded from https://www.innerscene.com/api/library/hospital-ward-wing-1200-square-metres-plan-and-section-73a3f4dd/download +- SHA-256: 4fabf62d6d7bbc7c8bdc5f3c9d292d4980c3ec504281b0bd77f487d3c6bb9ba3 + +### grocery-store-plan-section.dxf + +- What: Grocery store, plan and section (DXF 2010) (dxf, 128 KB) +- Shows: 234 lines, 150 polylines, 17 layers, 3 blocks, a viewport +- Author: Innerscene (original model) +- Source: https://www.innerscene.com/tools/library/drawings/grocery-store-600-square-metres-plan-and-section-2a67d041 +- Licence: CC0-1.0 +- Evidence: https://www.innerscene.com/tools/library/drawings/grocery-store-600-square-metres-plan-and-section-2a67d041 +- Words read there: "Original Innerscene model, released CC0." +- Origin: downloaded from https://www.innerscene.com/api/library/grocery-store-600-square-metres-plan-and-section-2a67d041/download +- SHA-256: 0b875304e1769e0f7c9377abf270f1fb4d103547cc27a3795a57c34fb4619d30 + +### ezdxf-uncommon-entities.dxf + +- What: ezdxf example: uncommon entities (DXF 2018) (dxf, 335 KB) +- Shows: 13 dimensions, 2 multileaders, large radial dimensions, rays, construction lines, splines, 33 blocks, 2 extra layouts +- Author: Manfred Moitzi (ezdxf) +- Source: https://github.com/mozman/ezdxf/blob/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/uncommon.dxf +- Licence: MIT +- Evidence: https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/LICENSE +- Words read there: "Copyright (c) 2020 Manfred Moitzi" +- Attribution: Copyright (c) 2020 Manfred Moitzi, ezdxf, MIT License. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/uncommon.dxf +- SHA-256: 5efdd671e3b6d8c45bd0688b1d6479d523f2290f0b390f1584348bf46e34c965 + +### ezdxf-hatches-1.dxf + +- What: ezdxf example: solid hatches (DXF 2018) (dxf, 127 KB) +- Shows: ten solid hatches over polylines and arcs +- Author: Manfred Moitzi (ezdxf) +- Source: https://github.com/mozman/ezdxf/blob/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/hatches_1.dxf +- Licence: MIT +- Evidence: https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/LICENSE +- Words read there: "Copyright (c) 2020 Manfred Moitzi" +- Attribution: Copyright (c) 2020 Manfred Moitzi, ezdxf, MIT License. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/hatches_1.dxf +- SHA-256: 2dc2930b4f7d5fb16698437e4f6972986e580a81b2b5d36a780b4311f85fb326 + +## 3D + +### gear.stl + +- What: Spur gear, binary STL with facet colours (stl, 42 KB) +- Shows: 864 facets, orange teeth and blue hub through the VisCAM colour attribute +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-models.py` +- SHA-256: aac8dd0d87fed7b77061d32a5bbe61ac90cbfef16130b7c35730cdc1e77e93c9 + +### bracket-ascii.stl + +- What: L bracket, ASCII STL (stl, 8.8 KB) +- Shows: text STL, three overlapping boxes +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-models.py` +- SHA-256: dd4b8c55140214fe71a8200d4fe2ae7b51f53e6ab6184e82e79b3d2d12c708f9 + +### knot.obj + +- What: Trefoil knot and base, OBJ with vertex colours (obj, 98 KB) +- Shows: two objects (knot, base), a colour and a normal per vertex, quads, a rainbow along the knot +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-models.py` +- SHA-256: a2eaba271264d700edc372eaaa6944d342fe9b823c98e698b1445846bded3bf1 + +### terrain.ply + +- What: Height field, binary PLY with colours (ply, 117 KB) +- Shows: 2304 vertices with normals and a hypsometric colour each, 4418 triangles +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-models.py` +- SHA-256: 22c2f25d47c43841c1ed1327c6fb9e75725925ca1e3c61dc413c23319dcfde52 + +### icosphere-ascii.ply + +- What: Icosphere, ASCII PLY with colours (ply, 14 KB) +- Shows: text PLY with normals and RGBA per vertex +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-models.py` +- SHA-256: dbe5ae97077d8177503d5bab7d83fbc3f0a943181384fbffc68db7a4930f19be + +### arm.glb + +- What: Articulated arm in a glass dome, GLB (glb, 28 KB) +- Shows: node tree with rotations and scales, five materials, a metallic and a transparent one, vertex colours on the floor +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-models.py` +- SHA-256: 146ba6e29d9b8bf4ec57c72bde686a5119b80cfe4365f05f0f0b7004b066a7b7 + +### table.gltf + +- What: Table and two chairs, glTF with an embedded buffer (gltf, 7.6 KB) +- Shows: 17 nodes, a data URI buffer, shared meshes instanced under several nodes +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-models.py` +- SHA-256: ae656d2f656968fa44870ffc539d2383b85725289feb90e658881c5825bb7ef4 + +### house.ifc + +- What: Two-storey house (IFC4) (ifc, 65 KB) +- Shows: walls with openings filled by windows and doors, slabs, a gable roof, porch columns, a stair of eleven steps, a table and chairs sharing a mapped representation, spaces, a property set, a material and colours +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-ifc.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-ifc.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-ifc.py` +- SHA-256: d65c93ae607a5b03316662719f5995f9de3bfd94366383ab683838bbccfa4731 + +### bsi-building-architecture-ifc2x3.ifc + +- What: buildingSMART Simple-Scene Building-Architecture (IFC2X3) (ifc, 90 KB) +- Shows: a small SketchUp house: walls, slabs, a roof, spaces, materials with colours, quantity and property sets; faceted breps +- Author: buildingSMART International Ltd. +- Source: https://github.com/buildingSMART/Sample-Test-Files +- Licence: CC-BY-4.0 +- Evidence: https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/LICENSE +- Words read there: "This work is licensed under the Creative Commons Attribution 4.0 International License." +- Attribution: buildingSMART International, Sample-Test-Files, https://github.com/buildingSMART/Sample-Test-Files, licensed CC BY 4.0. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/IFC%202.3.0.1%20%28IFC%202x3%20TC1%29/Simple-Scene/Building-Architecture.ifc +- SHA-256: c4db65ba847f6b369a95d6c54fa11f4750cbe6d59f021934e8923d8d578e5885 + +### bsi-building-architecture-ifc4x3.ifc + +- What: buildingSMART Simple-Scene Building-Architecture (IFC4X3_ADD2) (ifc, 139 KB) +- Shows: the same house in IFC 4.3, with triangulated faces +- Author: buildingSMART International Ltd. +- Source: https://github.com/buildingSMART/Sample-Test-Files +- Licence: CC-BY-4.0 +- Evidence: https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/LICENSE +- Words read there: "This work is licensed under the Creative Commons Attribution 4.0 International License." +- Attribution: buildingSMART International, Sample-Test-Files, https://github.com/buildingSMART/Sample-Test-Files, licensed CC BY 4.0. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/IFC%204.3.2.0%20%28IFC%204.3%20ADD2%29/Simple-Scene/Building-Architecture.ifc +- SHA-256: 96e7103812b15b65eb1fd7802d36b9962833485dce5ead4f440bbf529530881d + +### bsi-wall-with-opening-and-window-ifc4.ifc + +- What: buildingSMART reference view: a wall with an opening and a window (IFC4) (ifc, 12 KB) +- Shows: a wall with a material layer set, an opening element and a window with its type +- Author: Peter Bonsma, RDF Ltd. (file header), distributed by buildingSMART International Ltd. +- Source: https://github.com/buildingSMART/Sample-Test-Files +- Licence: CC-BY-4.0 +- Evidence: https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/LICENSE +- Words read there: "This work is licensed under the Creative Commons Attribution 4.0 International License." +- Attribution: buildingSMART International, Sample-Test-Files, https://github.com/buildingSMART/Sample-Test-Files, licensed CC BY 4.0. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/IFC%204.0.2.1%20%28IFC%204%20ADD2%20TC1%29/ISO%20Spec%20-%20ReferenceView_V1.2/wall-with-opening-and-window.ifc +- SHA-256: 73b0e45d931d5dc13bfee5fdc7bd80f796526445458b2de74c4168d209097832 + +### duplex-apartment-ifc2x3.ifc + +- What: Duplex Apartment (IFC2X3, Revit export) (ifc, 2.3 MB) +- Shows: four storeys: 57 walls, 24 windows, 14 doors, 2 stairs, 21 spaces, furniture, 18 materials +- Author: Provided to the US Army Construction Engineering Research Laboratory, republished by buildingSMART International +- Source: https://github.com/buildingsmart-community/Community-Sample-Test-Files/tree/7ddf57a201f88a0c213d5322b02ed15e94a60a40/IFC%202.3.0.1%20(IFC%202x3)/Duplex%20Apartment +- Licence: CC-BY-4.0 +- Evidence: https://raw.githubusercontent.com/buildingsmart-community/Community-Sample-Test-Files/7ddf57a201f88a0c213d5322b02ed15e94a60a40/IFC%202.3.0.1%20%28IFC%202x3%29/Duplex%20Apartment/README.md +- Words read there: "Creative Commons (CC BY 4.0). You are free (1) to copy and resitribute this material any way you like" +- Attribution: BSI (2020) Duplex Apartment Test Files, buildingSMART International, https://github.com/buildingsmart-community/Community-Sample-Test-Files, CC BY 4.0. No changes. +- Origin: downloaded from https://media.githubusercontent.com/media/buildingsmart-community/Community-Sample-Test-Files/7ddf57a201f88a0c213d5322b02ed15e94a60a40/IFC%202.3.0.1%20%28IFC%202x3%29/Duplex%20Apartment/Duplex_A_20110907.ifc +- SHA-256: b347a2c8aa8fff6db896a4417a9c50c22ac0ccd7c5cfc22b99b8d29336c606ed + +### barraca-valenciana-ifc4.ifc + +- What: Barraca Valenciana de Llauradors, BIM model (IFC4, Revit export) (ifc, 1.5 MB) +- Shows: a traditional farmhouse: 2 storeys, 16 walls, 5 slabs, 2 roofs, a stair, 27 beams, 28 materials +- Author: Ã’scar Selfa +- Source: https://zenodo.org/records/14293897 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/records/14293897 +- Words read there: "Creative Commons Attribution 4.0 International" +- Attribution: Ã’scar Selfa, Barraca Valenciana de Llauradors: Model BIM i Estudi de la Tipologia Arquitectònica, Zenodo, doi:10.5281/zenodo.14293897, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/records/14293897/files/BRC-OSP-XXX-ZZZ-M3D-ARQ-0001-tipologiaGen%C3%A8rica-S3-0001.ifc?download=1 +- SHA-256: b6f8828e9bd2491dc452b2ab78f9f9e28f39bd81a5f2f4e2cdb2d81668287193 + +### office-archetype-1970-ifc4x3.ifc + +- What: Office archetype of 1970 (IFC4X3_ADD2) (ifc, 1.4 MB) +- Shows: four storeys: 88 walls, 167 windows, 49 doors, 16 curtain walls, 48 spaces +- Author: Verena Dannapfel, Moritz Müller, Rita Streblow, Dirk Müller et al., RWTH Aachen University +- Source: https://zenodo.org/records/21820756 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/records/21820756 +- Words read there: "Creative Commons Attribution 4.0 International" +- Attribution: Dannapfel, V., Müller, M., Streblow, R., Müller, D. et al., Archetypes for German Office Buildings of Construction Years 1970, 1998 and 2026, Zenodo, doi:10.5281/zenodo.21820756, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/records/21820756/files/2026-07_Klassiqua_Office_Archetype_Construction_Year_1970.ifc?download=1 +- SHA-256: a5f12304d33fe5da9174c8ea9827d2f322706646b3da2766dff0ab278c65df3c + +### fox.glb + +- What: Fox, skinned and animated (GLB) (glb, 159 KB) +- Shows: a low-poly fox with a skin, three animations and a texture +- Author: PixelMannen (model, CC0), tomkranis (rigging and animation, CC BY 4.0), glTF conversion by Asobo Studio and the Khronos Group +- Source: https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/Fox +- Licence: CC-BY-4.0 +- Evidence: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/Fox/README.md +- Words read there: "© 2014, tomkranis. [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/legalcode)" +- Attribution: Fox: model by PixelMannen (CC0, https://opengameart.org/content/fox-and-shiba), rigging and animation by tomkranis (CC BY 4.0, https://sketchfab.com/3d-models/low-poly-fox-by-pixelmannen-animated-371dea88d7e04a76af5763f2a36866bc), glTF conversion by Asobo Studio and the Khronos Group. Unmodified. +- Origin: downloaded from https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/Fox/glTF-Binary/Fox.glb +- SHA-256: d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7 + +### riggedfigure.gltf + +- What: Rigged Figure (glTF with an embedded buffer) (gltf, 98 KB) +- Shows: a skinned figure, a data URI buffer +- Author: Cesium +- Source: https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/RiggedFigure +- Licence: CC-BY-4.0 +- Evidence: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/RiggedFigure/README.md +- Words read there: "© 2017, Cesium. [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/legalcode)" +- Attribution: Rigged Figure by Cesium, CC BY 4.0, https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main/Models/RiggedFigure. Unmodified. +- Origin: downloaded from https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/RiggedFigure/glTF-Embedded/RiggedFigure.gltf +- SHA-256: 354572cfef17b136b437ac9749da0fa316fd6e42ee7d62fe50a696b25f5047e9 + +### vertexcolortest.glb + +- What: Vertex Color Test (GLB) (glb, 26 KB) +- Shows: COLOR_0 vertex colours, tangents, two textures +- Author: Ed Mackey, Analytical Graphics, Inc. (Cesium) +- Source: https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/VertexColorTest +- Licence: CC-BY-4.0 +- Evidence: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/VertexColorTest/README.md +- Words read there: "© 2018, Analytical Graphics, Inc.. [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/legalcode)" +- Attribution: Vertex Color Test by Ed Mackey, Copyright 2018 Analytical Graphics, Inc., CC BY 4.0, https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main/Models/VertexColorTest. Unmodified. +- Origin: downloaded from https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/VertexColorTest/glTF-Binary/VertexColorTest.glb +- SHA-256: 58006bdcff8084339da0f6e24400160890638c16dbcb83c362ccaf150e8c6e10 + +### metalroughspheres.glb + +- What: Metal-Rough spheres (GLB) (glb, 284 KB) +- Shows: 119 nodes and 98 materials of growing metalness and roughness +- Author: Krill Gavrilov / Draw Harness script (Open CASCADE Technology) +- Source: https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/MetalRoughSpheresNoTextures +- Licence: CC0-1.0 +- Evidence: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/MetalRoughSpheresNoTextures/README.md +- Words read there: "© 2019, Public. [Creative Commons Zero v1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/legalcode)" +- Origin: downloaded from https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/MetalRoughSpheresNoTextures/glTF-Binary/MetalRoughSpheresNoTextures.glb +- SHA-256: 5e677f260ec0f366967a6e9545de2f3dab2a160e307b9bcb9d050cd2028f63f8 + +### iridescencesuzanne.glb + +- What: Iridescence Suzanne (GLB) (glb, 496 KB) +- Shows: Suzanne with the iridescence, transmission and volume extensions +- Author: Mathias Kanzler (UX3D), Pascal Schoen +- Source: https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/IridescenceSuzanne +- Licence: CC0-1.0 +- Evidence: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/IridescenceSuzanne/README.md +- Words read there: "© 2022, UX3D. [Creative Commons Zero v1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/legalcode)" +- Origin: downloaded from https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/IridescenceSuzanne/glTF-Binary/IridescenceSuzanne.glb +- SHA-256: 866762602d60a0942b7608bfabf4e8686a29033636224f4b55c5e56abe8abf8f + +### ratchet-cam.stl + +- What: Apollo 11 hatch, stationary ratchet cam (binary STL) (stl, 75 KB) +- Shows: 1536 triangles, a mechanical part +- Author: NASA Johnson Space Center, transferred to the Smithsonian Institution; model published on Wikimedia Commons +- Source: https://commons.wikimedia.org/wiki/File:Stationary_Ratchet_Cam_v11_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl +- Licence: CC0-1.0 +- Evidence: https://commons.wikimedia.org/wiki/File:Stationary_Ratchet_Cam_v11_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl +- Words read there: "CC0 1.0 Universal Public Domain Dedication" +- Origin: downloaded from https://upload.wikimedia.org/wikipedia/commons/e/e0/Stationary_Ratchet_Cam_v11_%28Hatch%2C_Crew%2C_Apollo_11_by_NASA_and_Smithsonian_Institution%29.stl +- SHA-256: b42d79fb357413b118b973f3fa40b76ae2999451537cd991bebce18b486c581f + +### ratchet-spur-gear.stl + +- What: Apollo 11 hatch, stationary ratchet spur gear (binary STL) (stl, 148 KB) +- Shows: 3026 triangles, a gear with 19 teeth +- Author: NASA Johnson Space Center, transferred to the Smithsonian Institution; model published on Wikimedia Commons +- Source: https://commons.wikimedia.org/wiki/File:N=19,_P=28_-_Stat._Ratchet_Spur_Gear_v13_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl +- Licence: CC0-1.0 +- Evidence: https://commons.wikimedia.org/wiki/File:N=19,_P=28_-_Stat._Ratchet_Spur_Gear_v13_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl +- Words read there: "CC0 1.0 Universal Public Domain Dedication" +- Origin: downloaded from https://upload.wikimedia.org/wikipedia/commons/c/cb/N%3D19%2C_P%3D28_-_Stat._Ratchet_Spur_Gear_v13_%28Hatch%2C_Crew%2C_Apollo_11_by_NASA_and_Smithsonian_Institution%29.stl +- SHA-256: c99eca56ab40ed6b2e9dfc49b88c23c6fbef982ff18813ba593d3e138ef1f51d + +### petri-dish-holder-base.stl + +- What: Petri dish holder base of a spore capture device (ASCII STL) (stl, 148 KB) +- Shows: 566 facets as text +- Author: Kevin A. Adkins, Kaiyu Li, M. N. Blasko, J. L. Cabrera, B. H. Neal, James et al. +- Source: https://zenodo.org/records/12193898 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/api/records/12193898 +- Words read there: ""license": {"id": "cc-by-4.0"}" +- Attribution: Components of the spore capture device in A simple mechanism for uncrewed aircraft bioaerosol sampling in the lower atmosphere (Inspire1Petri_Dish_Holder_Base.stl), Kevin A. Adkins et al., Zenodo 2024, doi:10.5281/zenodo.12193898, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/api/records/12193898/files/Inspire1Petri_Dish_Holder_Base.stl/content +- SHA-256: d654bf60064e79675acd9694726282c70251905d77391ad45c29d3ba3ecaf93e + +### chickpea-mesh.ply + +- What: Photogrammetric mesh of a chickpea plant (binary PLY with colours) (ply, 198 KB) +- Shows: 8788 triangles, RGBA per vertex +- Author: William T. Salter, Arjina Shrestha, Margaret M. Barbour +- Source: https://zenodo.org/records/4018242 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/api/records/4018242 +- Words read there: ""license": {"id": "cc-by-4.0"}" +- Attribution: 3D photogrammetric reconstructions of individual chickpea plants (PBASlasher_S3s_Wk1_meshed.ply), William T. Salter, Arjina Shrestha and Margaret M. Barbour, Zenodo 2020, doi:10.5281/zenodo.4018242, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/api/records/4018242/files/PBASlasher_S3s_Wk1_meshed.ply/content +- SHA-256: ef9cd2141897781c8e3e6a72ac316056b991d4d0fae99e053c4695fceea8cb75 + +### ruthwell-lamb-of-god.ply + +- What: Lamb of God panel of the Ruthwell Cross (binary PLY with normals and colours) (ply, 873 KB) +- Shows: 33020 triangles, a scanned stone carving +- Author: Gurpreet Singh +- Source: https://zenodo.org/records/3348342 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/api/records/3348342 +- Words read there: ""license": {"id": "cc-by-4.0"}" +- Attribution: Small Panel PLY (Lamb of God panel from the Ruthwell Cross), Gurpreet Singh, Zenodo 2019, doi:10.5281/zenodo.3348342, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/api/records/3348342/files/Small_Lamb_Of_God_North_Ruthwell_Cross.ply/content +- SHA-256: 0d40a4305885932596afce091891a8f4b212b0c012b742db10d4487351c2457a + +## Audio and video + +### canon.wav + +- What: A four-voice canon, WAV (wav, 131 KB) +- Shows: 8 kHz mono 16-bit, 8.4 seconds, synthesised +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-media.py` (with ffmpeg) +- SHA-256: c26b3aa385a70bb6785c7eb36b0bf3fe04a379fe46294d77d29ad153d0cc1028 + +### canon.mp3 + +- What: The canon as MP3 (mp3, 25 KB) +- Shows: 24 kbit/s +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-media.py` (with ffmpeg) +- SHA-256: c9f569a2833d11af90232c2f950c865f02bfbcc5822fc35cccb7466dd9c46c49 + +### canon.flac + +- What: The canon as FLAC (flac, 73 KB) +- Shows: lossless, level 8 +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-media.py` (with ffmpeg) +- SHA-256: c3dd10ace8ccaacb09f74ca73619e0d991ff94ce3d25fdc20ee9fb4597bc8a63 + +### canon.ogg + +- What: The canon as Ogg Vorbis (ogg, 14 KB) +- Shows: quality 2 +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-media.py` (with ffmpeg) +- SHA-256: 39c1dabbcadc817bfa1fc76839b1ee6940bab7187dffd4c495a5f61362cb91ad + +### canon.opus + +- What: The canon as Opus (opus, 16 KB) +- Shows: 16 kbit/s +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-media.py` (with ffmpeg) +- SHA-256: e18075a4586929741c6bf264c92e8f7f35086f5e4ab2f3be58845835556bc9ae + +### canon.m4a + +- What: The canon as AAC in MP4 (m4a, 24 KB) +- Shows: 24 kbit/s +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-media.py` (with ffmpeg) +- SHA-256: edd56750fd23edd327a46ea907c9d34d53fcff6e04f2d0516a1083ea2c7306e5 + +### testcard.mp4 + +- What: Test card with a clock, H.264 and AAC in MP4 (mp4, 41 KB) +- Shows: 256 by 192, 12 frames a second, 4 seconds, with the canon as sound +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-media.py` (with ffmpeg) +- SHA-256: ad088934ae59962bafc0b9b56a57556623d5e2b7821869e2dc91047573213a12 + +### testcard.webm + +- What: Test card with a clock, VP9 and Opus in WebM (webm, 41 KB) +- Shows: 256 by 192, 12 frames a second, 4 seconds, with the canon as sound +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-media.py` (with ffmpeg) +- SHA-256: dca14e93bb8e3448a5d9a61fbbe402a7cf2b0c8f476a13b98f5649d079a1b7b8 + +## Archives + +### sample.zip + +- What: Zip with folders, stored and deflated members, Unicode names and a comment (zip, 15 KB) +- Shows: 9 files in 5 folders, an empty folder +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ) +- SHA-256: ad98593f9dc85d5dad309140ce703f96b36da749e48ea6648ce10c53a418250d + +### sample.tar + +- What: Tar (ustar) with folders and a symbolic link (tar, 50 KB) +- Shows: 16 entries +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ) +- SHA-256: b31804242af3545fd922934e81a2aade8fd09a7e2648fe26b41cd32dc37e1fb8 + +### sample.tar.gz + +- What: Tar compressed with gzip (tar.gz, 15 KB) +- Shows: the tar opens inside the gzip +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ) +- SHA-256: 5c423a4e7e0d96e025bb871034a88308f1d32861f60826074c29aa121fcdecca + +### sample.tar.bz2 + +- What: Tar compressed with bzip2 (tar.bz2, 14 KB) +- Shows: the tar opens inside the bzip2 stream +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ) +- SHA-256: 99b6742b5c54a36261f06a24032c22c11ed84b01e40e2267ef338b15ca181fcf + +### sample.tar.xz + +- What: Tar compressed with xz (tar.xz, 13 KB) +- Shows: the tar opens inside the xz stream +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ) +- SHA-256: 762ce440ee2dfd2f4d22a6d29f2535e7079ad21d461d7fce3167cd62a9f356bf + +### sample.tar.zst + +- What: Tar compressed with Zstandard (tar.zst, 14 KB) +- Shows: level 19 +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with zstd) +- SHA-256: d134793d16db00229eb192be488ef248a7c3e1226d9d27b67d8a763cd9b0641d + +### server.log.gz + +- What: A log compressed with gzip (gz, 1.3 KB) +- Shows: one member, no tar +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ) +- SHA-256: 9f80faaae63eb4ae0a3a68c1346966049cb6ad5eba17e9c8600eb404ced75922 + +### server.log.bz2 + +- What: A log compressed with bzip2 (bz2, 1.1 KB) +- Shows: one member, no tar +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ) +- SHA-256: 4b235dc9fc1a2840be3dd7ed792c7e4bc373851130e7122de3e798e7061b39c4 + +### server.log.xz + +- What: A log compressed with xz (xz, 820 B) +- Shows: one member, no tar +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ) +- SHA-256: 7dec383660d188a36f28cae361ebb809914849ddf10a508fc47503f367c1e86c + +### sample.7z + +- What: 7z with LZMA2 (7z, 13 KB) +- Shows: a solid archive of 9 files +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with 7z) +- SHA-256: 7a2df3dd03ae207f3be0175190e3795662753e701d36555cd06e7295a72483c9 + +### sample.rar + +- What: RAR 5 with stored members (rar, 34 KB) +- Shows: folders, CRC32 and Unix modes, written by the script from the format's documentation (no RAR program) +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ) +- SHA-256: 71aa4939bc7f2e4a98cc484e7353b829ad8a5019b1dee3911e8df3548e317c90 + +### sample.iso + +- What: ISO 9660 image with Joliet and Rock Ridge (iso, 130 KB) +- Shows: volume EXAV_EXAMPLE, long and Unicode names +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with genisoimage) +- SHA-256: baa0c331dc2f1f8e3f04c171282faf7753a38d380e82e0ca894c70a04f08d4c0 + +### matryoshka.zip + +- What: Nested archives: a zip holding a tar.gz holding a 7z holding a zip (zip, 7.1 KB) +- Shows: four levels, opened in place one after the other +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with 7z) +- SHA-256: 0c4d4171bd6cd565a17ff675763cebf6c8d8c9408ebd6c738d436feab6cb42e9 + +### encrypted-aes.zip + +- What: Zip encrypted with AES-256, password: exav (zip, 16 KB) +- Shows: names are listed, each member says it is encrypted +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with 7z) +- SHA-256: e6cd983b8b1694a5df2c2f7d7790a249e4e9c529cb0d796e6d05de7a4bb03bd0 + +### encrypted-zipcrypto.zip + +- What: Zip encrypted with the traditional ZipCrypto, password: exav (zip, 16 KB) +- Shows: names are listed, each member says it is encrypted +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with 7z) +- SHA-256: 21053827c2871cda2d2f6259dc1d3848e318b40c0e71858220d601fc3c90767c + +### encrypted.7z + +- What: 7z encrypted with AES-256, password: exav (7z, 13 KB) +- Shows: file names visible, contents encrypted +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with 7z) +- SHA-256: c2606ee4ee72de0d9ba1461ba976c5ac20de157b6b17771372bd6acf221cc6ce + +### example.jar + +- What: A jar (a zip with a manifest) (jar, 793 B) +- Shows: META-INF/MANIFEST.MF, a source file, a properties file +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ) +- SHA-256: 44aeabd990d5a5c75f88846f5310ad44a9b56deadde592ec3d932cf13476ff45 + +### pages.cbz + +- What: Comic book archive (zip of pages) (cbz, 10 KB) +- Shows: two page images and ComicInfo.xml +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ) +- SHA-256: 82dc884486eec4ca4fbeb3c016d6431848d0a2ccd843ab6e65972503524b0723 + +### sample.cab + +- What: Microsoft cabinet (cab, 6.1 KB) +- Shows: four files, MSZIP +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with gcab) +- SHA-256: 5f12d6c186b5cc81f70dc4b3d4a4d7b4b7bdebb74f002ada9067b4738589de00 + +### exav-example.deb + +- What: Debian package (deb, 2.2 KB) +- Shows: an ar archive of debian-binary, control.tar.xz and data.tar.xz +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with dpkg-deb) +- SHA-256: d73cac532f34c9948bc596e1241189b66d4d4497af030d766bbb451b4ab1adea + +### libexample.a + +- What: Unix ar archive (ar, 1.9 KB) +- Shows: two members +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with ar) +- SHA-256: 59396e78830b3119a01419e202810446dc15c312cf4b91727170b181d0afaf3e + +### sample.cpio + +- What: cpio archive (newc) (cpio, 7.0 KB) +- Shows: four files +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-archives.py` (with cpio) +- SHA-256: aab3c3fdd392a978d0a516e5a420bbed6b97c203966c1ed275d7246a93ab9827 + +## Unsupported + +### fax-g3-1d.tif + +- What: Fax page, CCITT Group 3 (T.4, one-dimensional) TIFF (tiff-fax, 60 KB) +- Shows: kept to show the error: the TIFF decoder reads Group 4 only +- Author: exav project +- Source: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Licence: CC0-1.0 +- Evidence: https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py +- Words read there: "Output: CC0-1.0, a public domain dedication by the exav project." +- Origin: generated by `generate/make-images.py` +- SHA-256: ee3c004c31ac0c49f045db053347a219bcce795a074931ad15463fc86fd208ed + +### minolta-dimage-5.mrw + +- What: Minolta DiMAGE 5 (MRW) (raw-mrw, 6.1 MB) +- Shows: MRW with a 640 by 480 preview whose first byte is stored as zero: the viewer finds no preview in it (kept to show the message) +- Author: Uploader to raw.pixls.us (the site gives no name) +- Source: https://raw.pixls.us/#repo +- Licence: CC0-1.0 +- Evidence: https://raw.pixls.us/json/getrepository.php?set=all +- Words read there: "Creative Commons 0 - Public Domain" +- Origin: downloaded from https://raw.pixls.us/getfile.php/7795/nice/Minolta%20-%20DiMAGE%205%20-%204%3A3.MRW +- SHA-256: d60bfd80bcb1f7b9c88b14a5e46ea27885bbf92d990ab30b3939288678fea0d9 + +### chickpea-pointcloud-ascii.ply + +- What: Point cloud of a chickpea plant (ASCII PLY without faces) (ply, 3.3 MB) +- Shows: 53195 coloured points and no faces: kept to show what the viewer says about a point cloud +- Author: William T. Salter, Arjina Shrestha, Margaret M. Barbour +- Source: https://zenodo.org/records/4018242 +- Licence: CC-BY-4.0 +- Evidence: https://zenodo.org/api/records/4018242 +- Words read there: ""license": {"id": "cc-by-4.0"}" +- Attribution: 3D photogrammetric reconstructions of individual chickpea plants (SonSla_3_groundtruth_pointcloud.ply), William T. Salter, Arjina Shrestha and Margaret M. Barbour, Zenodo 2020, doi:10.5281/zenodo.4018242, CC BY 4.0. No changes. +- Origin: downloaded from https://zenodo.org/api/records/4018242/files/SonSla_3_groundtruth_pointcloud.ply/content +- SHA-256: 53a08f6e1c831ac58c42342ee257c97730bcf6997e246c88198478f9aeba4fe0 + +### tika-pages09-layout.pages + +- What: Apache Tika test document (Pages '09) (pages, 65 KB) +- Shows: kept to show what the viewer says about Pages files, which it does not list yet +- Author: Michael McCandless (Apache Tika) +- Source: https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testPagesLayout.pages +- Licence: Apache-2.0 +- Evidence: https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt +- Words read there: "Version 2.0, January 2004" +- Attribution: Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes. +- Origin: downloaded from https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testPagesLayout.pages +- SHA-256: 6157fe7a95f7bc7d42251872f990d2f2d589f7f5e25a52b58e25c14cc447a4b2 + diff --git a/crates/exav-viewer/demo/examples/check.mjs b/crates/exav-viewer/demo/examples/check.mjs new file mode 100644 index 0000000..4faf29e --- /dev/null +++ b/crates/exav-viewer/demo/examples/check.mjs @@ -0,0 +1,114 @@ +#!/usr/bin/env node +// Checks demo/examples/examples.json against the files: +// +// node demo/examples/check.mjs # the manifest and files/ +// node demo/examples/check.mjs --public # also demo/public/examples/ (after `npm run demo:examples`) +// +// Fails (exit 1) on a missing field, a licence that is not allowed, a missing +// attribution, a file whose size or SHA-256 differs, a file in files/ that the +// manifest does not list, a group the demo does not know, or a script that is +// not there. +import crypto from "node:crypto"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const here = path.dirname(fileURLToPath(import.meta.url)); +const pkg = path.join(here, "..", ".."); +const repo = path.join(pkg, "..", ".."); +const withPublic = process.argv.includes("--public"); + +const manifest = JSON.parse(fs.readFileSync(path.join(here, "examples.json"), "utf8")); +const problems = []; +const bad = (file, msg) => problems.push(`${file}: ${msg}`); + +// Public domain, CC0, CC-BY, and MIT, BSD and Apache test files. No share-alike or copyleft licence. +const SPDX = /^(CC0-1\.0|CC-BY-(1\.0|2\.0|2\.5|3\.0|4\.0)|MIT|BSD-2-Clause|BSD-3-Clause|Apache-2\.0)$/; +const NEEDS_ATTRIBUTION = /^(CC-BY|MIT|BSD|Apache)/; +const REFUSED = /\b(GPL|LGPL|AGPL|MPL|NC|ND|non-?commercial|no derivatives)\b/i; + +const groups = new Set([...fs.readFileSync(path.join(pkg, "demo", "src", "showcase.ts"), "utf8").matchAll(/^\s+(?:"([\w-]+)"|(\w+)): \{ en: /gm)].map((m) => m[1] ?? m[2])); + +const sha256 = (data) => crypto.createHash("sha256").update(data).digest("hex"); +const isUrl = (s) => typeof s === "string" && /^https:\/\/[^\s]+$/.test(s); +const names = new Set(); +const paths = new Set(); +let committedBytes = 0; +let fetchedBytes = 0; + +for (const e of manifest.examples) { + const f = e.file ?? "(no file)"; + for (const k of ["file", "group", "family", "title", "author", "source", "evidence", "evidence_quote", "licence", "sha256"]) { + if (typeof e[k] !== "string" || !e[k].trim()) bad(f, `no ${k}`); + } + if (typeof e.attribution !== "string") bad(f, "no attribution (use \"\" when the licence asks for none)"); + if (!Number.isInteger(e.bytes) || e.bytes <= 0) bad(f, "no bytes"); + if (typeof e.committed !== "boolean") bad(f, "no committed flag"); + if (names.has(e.file)) bad(f, "listed twice"); + names.add(e.file); + if (e.file && e.file !== path.basename(e.file)) bad(f, "not a plain file name"); + if (e.group && !groups.has(e.group)) bad(f, `group ${e.group} is not in demo/src/showcase.ts`); + if (!isUrl(e.source)) bad(f, "source is not an https URL"); + if (!isUrl(e.evidence)) bad(f, "evidence is not an https URL"); + if (e.sha256 && !/^[0-9a-f]{64}$/.test(e.sha256)) bad(f, "sha256 is not 64 hex digits"); + + const lic = e.licence ?? ""; + if (!SPDX.test(lic) && !/^public-domain \(.{8,}\)$/.test(lic)) bad(f, `licence "${lic}" is not allowed (use an SPDX id of the list, or "public-domain (reason)")`); + if (REFUSED.test(lic)) bad(f, `licence "${lic}" is refused`); + if (NEEDS_ATTRIBUTION.test(lic) && !(e.attribution ?? "").trim()) bad(f, `${lic} needs an attribution line`); + if (e.attribution && /—|load-bearing|genuinely/i.test(e.attribution + e.title)) bad(f, "dash or AI wording in the credit"); + + const origins = ["generated", "fetched", "fixture"].filter((k) => e[k] !== undefined); + if (!origins.length) bad(f, "none of generated, fetched, fixture"); + if (e.generated) { + if (typeof e.generated.script !== "string" || !Array.isArray(e.generated.args)) bad(f, "generated needs a script and its args"); + else if (!fs.existsSync(path.join(here, e.generated.script))) bad(f, `script ${e.generated.script} is missing`); + } + if (e.fetched !== undefined && !isUrl(e.fetched)) bad(f, "fetched is not an https URL"); + if (e.fixture !== undefined && !fs.existsSync(path.join(repo, e.fixture))) bad(f, `fixture ${e.fixture} is not in the repository`); + if (!e.committed && !isUrl(e.fetched)) bad(f, "not committed and not fetched: nothing to serve"); + + if (e.committed) { + if (!e.path) { + bad(f, "committed without a path"); + continue; + } + paths.add(path.normalize(e.path)); + const p = path.join(here, "files", e.path); + if (!fs.existsSync(p)) { + bad(f, `files/${e.path} is missing`); + continue; + } + const data = fs.readFileSync(p); + if (data.length !== e.bytes) bad(f, `files/${e.path} is ${data.length} bytes, the manifest says ${e.bytes}`); + if (sha256(data) !== e.sha256) bad(f, `files/${e.path} has sha256 ${sha256(data)}, the manifest says ${e.sha256}`); + if (path.basename(e.path) !== e.file) bad(f, "path and file name differ"); + if (data.length > 1_000_000) bad(f, `committed file of ${data.length} bytes: over 1 MB goes by download`); + committedBytes += data.length; + } else { + if (e.bytes > 12_000_000) bad(f, `fetched file of ${e.bytes} bytes is too large`); + fetchedBytes += e.bytes; + } + + if (withPublic) { + const p = path.join(pkg, "demo", "public", "examples", e.file); + if (fs.existsSync(p)) { + const data = fs.readFileSync(p); + if (data.length !== e.bytes || sha256(data) !== e.sha256) bad(f, `demo/public/examples/${e.file} does not match the manifest`); + } else if (e.committed) { + bad(f, `demo/public/examples/${e.file} is missing: run npm run demo:examples`); + } + } +} + +// Every file under files/ is listed. +const listed = (dir, base = "") => + fs.readdirSync(path.join(dir, base), { withFileTypes: true }).flatMap((d) => (d.isDirectory() ? listed(dir, path.join(base, d.name)) : [path.join(base, d.name)])); +const filesDir = path.join(here, "files"); +if (fs.existsSync(filesDir)) for (const p of listed(filesDir)) if (!paths.has(path.normalize(p))) bad(p, "in files/ but not in the manifest"); + +if (problems.length) { + console.error(`${problems.length} problem${problems.length === 1 ? "" : "s"} in demo/examples/examples.json:\n ${problems.join("\n ")}`); + process.exit(1); +} +console.log(`${manifest.examples.length} examples ok: ${committedBytes} bytes committed, ${fetchedBytes} bytes fetched`); diff --git a/crates/exav-viewer/demo/examples/examples.json b/crates/exav-viewer/demo/examples/examples.json new file mode 100644 index 0000000..846e6b2 --- /dev/null +++ b/crates/exav-viewer/demo/examples/examples.json @@ -0,0 +1,4703 @@ +{ + "version": 1, + "examples": [ + { + "file": "scene.png", + "group": "images", + "family": "png", + "title": "Dusk landscape, PNG", + "features": "8-bit RGB, optimised", + "path": "images/scene.png", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 26756, + "sha256": "4a0f00c07bb229932be134ede00f78851c8b1c4d3fa3eaa32164bb97c424f3fe" + }, + { + "file": "scene-alpha.png", + "group": "images", + "family": "png", + "title": "Landscape fading to transparent, PNG", + "features": "RGBA: the viewer shows its chequerboard through the alpha", + "path": "images/scene-alpha.png", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 48816, + "sha256": "c06a1651cfa68c3c729ba2a94eb0e6a3ccb306a24b3e4029d909a0da3e705a69" + }, + { + "file": "scene-indexed.png", + "group": "images", + "family": "png", + "title": "Landscape in 32 colours, PNG", + "features": "palette (indexed) PNG", + "path": "images/scene-indexed.png", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 5152, + "sha256": "ebd709f812945dd233203f4dbea12c22af3450bd67be52dbc6668f35f55a0e58" + }, + { + "file": "gradient-grey16.png", + "group": "images", + "family": "png", + "title": "Grey ramp, 16-bit PNG", + "features": "16-bit greyscale", + "path": "images/gradient-grey16.png", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 48383, + "sha256": "594a376de8d26c143d65c012f82aafd3775e8bd6698cd168ce957638c636379d" + }, + { + "file": "bounce.png", + "group": "images", + "family": "apng", + "title": "Bouncing ball, animated PNG", + "features": "24 frames, APNG", + "path": "images/bounce.png", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 41428, + "sha256": "dbe78676dee3a09eb44aafd14980b8999f11bf576e1152d2183193a9c18ff131" + }, + { + "file": "scene.jpg", + "group": "images", + "family": "jpeg", + "title": "Dusk landscape, JPEG", + "features": "baseline 4:2:0 with EXIF description and copyright", + "path": "images/scene.jpg", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 24631, + "sha256": "42f3881913d6401dc2df511f6a975caeb834f965299c152f5535aa3ae6a5e02e" + }, + { + "file": "scene-progressive.jpg", + "group": "images", + "family": "jpeg", + "title": "Dusk landscape, progressive JPEG", + "features": "progressive scans, optimised Huffman tables", + "path": "images/scene-progressive.jpg", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 20456, + "sha256": "70c6c3352c093ac5da448706cb7873dc1fa991f84119d37f80acf63550078f65" + }, + { + "file": "scene-orientation6.jpg", + "group": "images", + "family": "jpeg", + "title": "JPEG stored on its side with EXIF orientation 6", + "features": "shown upright through the EXIF orientation", + "path": "images/scene-orientation6.jpg", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 22193, + "sha256": "02e8b993e435a3de434c7efbe688757efa2fef452b1747c7382732b63e8e971b" + }, + { + "file": "scene-grey.jpg", + "group": "images", + "family": "jpeg", + "title": "Landscape in grey, JPEG", + "features": "single-component JPEG", + "path": "images/scene-grey.jpg", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 17273, + "sha256": "546838a80bc5b7b042fdc593b8e95fbaaf39165347dcba32c45d341f2f5dabea" + }, + { + "file": "scene-cmyk.jpg", + "group": "images", + "family": "jpeg", + "title": "Landscape as a CMYK JPEG", + "features": "four components (Adobe inverted CMYK)", + "path": "images/scene-cmyk.jpg", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 52705, + "sha256": "2c85449ef1574bc35fc3f54cf8aa724e518180aa86488ecef2be603816bfac01" + }, + { + "file": "bounce.gif", + "group": "images", + "family": "gif", + "title": "Bouncing ball, animated GIF", + "features": "24 frames with a palette each", + "path": "images/bounce.gif", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 102524, + "sha256": "386425b57344417f2205ac176a3a72eaed208ad67e57f7cd304ab845bf27d83b" + }, + { + "file": "scene.gif", + "group": "images", + "family": "gif", + "title": "Dusk landscape, dithered GIF", + "features": "256 colours, Floyd-Steinberg dithering", + "path": "images/scene.gif", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 25539, + "sha256": "9680147c7fabe6ba25e464c9cd41fe6e45b73502e68e811ea7037922f8c33255" + }, + { + "file": "scene.webp", + "group": "images", + "family": "webp", + "title": "Dusk landscape, lossy WebP", + "features": "VP8", + "path": "images/scene.webp", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 9040, + "sha256": "c5a026e0341b0952e99af9ff4fa34de68e7ecc2da3326421e79a66639fef4787" + }, + { + "file": "scene-lossless.webp", + "group": "images", + "family": "webp", + "title": "Dusk landscape, lossless WebP", + "features": "VP8L", + "path": "images/scene-lossless.webp", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 18644, + "sha256": "7455a0e9ae36e7e9fb3f5b6ee094fcbece393dd9444d37cee3db785e36b01e79" + }, + { + "file": "scene-alpha.webp", + "group": "images", + "family": "webp", + "title": "Landscape fading to transparent, WebP", + "features": "lossy colour with an alpha plane (VP8X, ALPH)", + "path": "images/scene-alpha.webp", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 18784, + "sha256": "d62a7a8f0b2655221b84eec04c8adfd3d5f37a59425a706fa0eea900cc05b525" + }, + { + "file": "bounce.webp", + "group": "images", + "family": "webp", + "title": "Bouncing ball, animated WebP", + "features": "24 frames", + "path": "images/bounce.webp", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 20748, + "sha256": "edb4905dd92651bd42dbc3c15873913ec6bdca9a04afe83740565e082d90b84c" + }, + { + "file": "scene-lzw.tif", + "group": "images", + "family": "tiff", + "title": "Dusk landscape, TIFF with LZW", + "features": "RGB, LZW, 300 dpi", + "path": "images/scene-lzw.tif", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 96668, + "sha256": "b3a41a6e8e4644e2b2291a50e499fd9988b735932c6c27def20587c1f565bcaa" + }, + { + "file": "scene-jpeg.tif", + "group": "images", + "family": "tiff", + "title": "Dusk landscape, TIFF with JPEG compression", + "features": "JPEG in TIFF (compression 7)", + "path": "images/scene-jpeg.tif", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 57205, + "sha256": "c5add42f305af0ca4dcf2cd554dc973611ce1334e5e91ba2b38ec2c58a35e89b" + }, + { + "file": "scene-cmyk-packbits.tif", + "group": "images", + "family": "tiff", + "title": "Landscape as a CMYK TIFF", + "features": "four inks, PackBits", + "path": "images/scene-cmyk-packbits.tif", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 49730, + "sha256": "57d7dbd0c807d1bcd7064367051ff75cdedddc4109e85cf67450c6601ec48fbc" + }, + { + "file": "gradient-grey16.tif", + "group": "images", + "family": "tiff", + "title": "Grey ramp, 16-bit TIFF", + "features": "16-bit greyscale, Deflate", + "path": "images/gradient-grey16.tif", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 93424, + "sha256": "94c41cab542120478f4a7b97e694e8ddddd2520b022f9266a59bcf0e727baeea" + }, + { + "file": "scene-pages.tif", + "group": "images", + "family": "tiff", + "title": "Three-page TIFF", + "features": "pages of 512, 256 and 128 pixels, the last in grey, Deflate", + "path": "images/scene-pages.tif", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 84896, + "sha256": "9a8267875af78208d587777b341eb152d166b6acc10aede6d198d8e788ebd7a6" + }, + { + "file": "fax-g4.tif", + "group": "images", + "family": "tiff-fax", + "title": "Fax cover sheet and register, CCITT Group 4 TIFF", + "features": "1-bit, 1728 by 2200 at 204 by 196 dpi, T.6", + "path": "images/fax-g4.tif", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 22702, + "sha256": "c4efa355dc63ce59863446b62b960397f34ab3d3c04a212450d0c2bca5f3904a" + }, + { + "file": "fax-g4-3pages.tif", + "group": "images", + "family": "tiff-fax", + "title": "Three-page fax, CCITT Group 4 TIFF", + "features": "three pages, T.6", + "path": "images/fax-g4-3pages.tif", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 68092, + "sha256": "a94bc11060a7f2553803580c0feb779d1e59b032fd9f4406fbd4972765842cbb" + }, + { + "file": "fax-g3-1d.tif", + "group": "unsupported", + "family": "tiff-fax", + "title": "Fax page, CCITT Group 3 (T.4, one-dimensional) TIFF", + "features": "kept to show the error: the TIFF decoder reads Group 4 only", + "path": "images/fax-g3-1d.tif", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 61464, + "sha256": "ee3c004c31ac0c49f045db053347a219bcce795a074931ad15463fc86fd208ed" + }, + { + "file": "scene-24.bmp", + "group": "images", + "family": "bmp", + "title": "Dusk landscape, 24-bit BMP", + "features": "BI_RGB, bottom-up", + "path": "images/scene-24.bmp", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 57654, + "sha256": "f3281d18d1f2944c7cb5f60eac3593facfbb3b77a0e5505e1ac88a9fdbefbfaa" + }, + { + "file": "scene-8.bmp", + "group": "images", + "family": "bmp", + "title": "Dusk landscape, 8-bit BMP", + "features": "256-colour palette", + "path": "images/scene-8.bmp", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 20278, + "sha256": "d8ac5f35b9b76cd509191ec7f5c4a48f8236c5ca4dcc88197810060b16f47ad2" + }, + { + "file": "scene-32.bmp", + "group": "images", + "family": "bmp", + "title": "Dusk landscape, 32-bit BMP", + "features": "four channels", + "path": "images/scene-32.bmp", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 76854, + "sha256": "1d99799f83adc1486eb1072502893ed39d91220d9e132a0716d56d9e05285d94" + }, + { + "file": "scene-1bit.bmp", + "group": "images", + "family": "bmp", + "title": "Dusk landscape, 1-bit BMP", + "features": "two-colour palette", + "path": "images/scene-1bit.bmp", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 24638, + "sha256": "cc5152076963ba9beca3d0a5ed8a4ebd5f082c127e780ef68a955ce4b71e8786" + }, + { + "file": "scene-rle8.bmp", + "group": "images", + "family": "bmp", + "title": "Dusk landscape, 8-bit BMP with RLE compression", + "features": "BI_RLE8 with encoded and absolute runs", + "path": "images/scene-rle8.bmp", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 10838, + "sha256": "2b1c69a7597006677e38cd8e32ad11f85acb0602ef228ec5c080d03350fc7936" + }, + { + "file": "icon.ico", + "group": "images", + "family": "ico", + "title": "Icon with seven sizes", + "features": "16 to 256 pixels, PNG-coded images", + "path": "images/icon.ico", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 25530, + "sha256": "436e2c802c34d1c83b4492308ca660d4944eeb44fe32f6de87d3869e1c9e89ea" + }, + { + "file": "icon-legacy.ico", + "group": "images", + "family": "ico", + "title": "Icon in the legacy bitmap coding", + "features": "32-bit and 8-bit DIBs with AND masks, and one PNG image", + "path": "images/icon-legacy.ico", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 14193, + "sha256": "0ded5b411cd2cf1ebd15cdecfa12a1e9f4a53b74da39fa263f935329efe399ec" + }, + { + "file": "scene.ppm", + "group": "images", + "family": "pnm", + "title": "Dusk landscape, PPM (P6)", + "features": "binary pixmap with a comment", + "path": "images/scene.ppm", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 36893, + "sha256": "43949e7d7636ed5a7d552ad6fac28eb72487a70a1f63db7d944fb7e587612b40" + }, + { + "file": "scene-ascii.ppm", + "group": "images", + "family": "pnm", + "title": "Dusk landscape, ASCII PPM (P3)", + "features": "text pixmap, 48 by 36", + "path": "images/scene-ascii.ppm", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 17916, + "sha256": "996f21e5c7c05ed1c586b9dc9882ad6fba9f1153ba23c49844c640eef647bf8a" + }, + { + "file": "scene-grey16.pgm", + "group": "images", + "family": "pnm", + "title": "Landscape in grey, 16-bit PGM (P5)", + "features": "maxval 65535", + "path": "images/scene-grey16.pgm", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 24592, + "sha256": "059c3e7b9e22b0aa4247552139886564f9b36d66051ffc7957efd972f557b52c" + }, + { + "file": "scene.pbm", + "group": "images", + "family": "pnm", + "title": "Landscape as a bitmap, PBM (P4)", + "features": "1 bit a pixel", + "path": "images/scene.pbm", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 6155, + "sha256": "648c9687dc2c226306c64aa945bf81170bbff5d8c9f88b0630b07b294d4e2edb" + }, + { + "file": "scene-alpha.pam", + "group": "images", + "family": "pnm", + "title": "Landscape with alpha, PAM (P7)", + "features": "RGB_ALPHA tuples", + "path": "images/scene-alpha.pam", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 49220, + "sha256": "806cee6e77cbd0226f6ec3ab18de4259612a89c1df5ff5e27e37d4d5c932c515" + }, + { + "file": "scene.qoi", + "group": "images", + "family": "qoi", + "title": "Dusk landscape, QOI", + "features": "three channels", + "path": "images/scene.qoi", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 38960, + "sha256": "d04c2ff91df0173bf20c495eb19555dc4bc9342b9ec7b61f653a4742c00b6188" + }, + { + "file": "scene-alpha.qoi", + "group": "images", + "family": "qoi", + "title": "Landscape with alpha, QOI", + "features": "four channels", + "path": "images/scene-alpha.qoi", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 90838, + "sha256": "16a53b8756ab8dd663400cfa04dde6a598b6c608d345efd131c0d714cde8affb" + }, + { + "file": "scene.ff", + "group": "images", + "family": "farbfeld", + "title": "Landscape with alpha, farbfeld", + "features": "16-bit RGBA, big-endian", + "path": "images/scene.ff", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 55312, + "sha256": "b6d250a92f39b7183b42191933d84da7e6ef1a33a971c8e7c2f8ccc85ad060d0" + }, + { + "file": "sunset.hdr", + "group": "images", + "family": "hdr", + "title": "Sunset with a sun far brighter than the sky, Radiance HDR", + "features": "RGBE with run-length scanlines; the sun is 60 times white", + "path": "images/sunset.hdr", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 55026, + "sha256": "f65ffee0666792f829c6692ca1ef4a0a553304d06e28682f18a47de5efed7e9b" + }, + { + "file": "sunset-flat.hdr", + "group": "images", + "family": "hdr", + "title": "Sunset, uncompressed Radiance HDR", + "features": "flat RGBE scanlines", + "path": "images/sunset-flat.hdr", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 49248, + "sha256": "a401df61e76cfdf88731294a4ba5ce1ba607ee294b5010a1312925240f5d2131" + }, + { + "file": "scene-bc1.dds", + "group": "images", + "family": "dds", + "title": "Dusk landscape, DDS with BC1 (DXT1)", + "features": "full mipmap chain", + "path": "images/scene-bc1.dds", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 32904, + "sha256": "77d26e97cc0f532481e3e585321305aca44efd7694307f312d75b1c4bfecf8f8" + }, + { + "file": "scene-bc3.dds", + "group": "images", + "family": "dds", + "title": "Landscape with alpha, DDS with BC3 (DXT5)", + "features": "full mipmap chain, alpha blocks", + "path": "images/scene-bc3.dds", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 65680, + "sha256": "9028c95d163d7283b357e3beb6a531a192087fcb76e7aeb1aead81195e4f4a92" + }, + { + "file": "scene.jp2", + "group": "images", + "family": "jpeg2000", + "title": "Dusk landscape, JPEG 2000 (JP2)", + "features": "lossy, 3 quality layers, 5 resolutions, 256-pixel tiles, RPCL progression", + "path": "images/scene.jp2", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 81825, + "sha256": "f90f58bb1e3ef0bfd48b9b55bffc293ee4f1fe506a6717f0052319a34621bf9a" + }, + { + "file": "scene.j2k", + "group": "images", + "family": "jpeg2000", + "title": "Dusk landscape, bare JPEG 2000 codestream", + "features": "no JP2 boxes", + "path": "images/scene.j2k", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 49050, + "sha256": "949564fa2b811a1987a12989095289d673c2a4937f5014b0b9c1d7bfbe660b9c" + }, + { + "file": "scene-grey.jp2", + "group": "images", + "family": "jpeg2000", + "title": "Landscape in grey, JPEG 2000", + "features": "one component", + "path": "images/scene-grey.jp2", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 19629, + "sha256": "eb50ae4528e774c7ab9c427509faee07473249a89d35403c33afb2e5e9abf983" + }, + { + "file": "scene-alpha.jp2", + "group": "images", + "family": "jpeg2000", + "title": "Landscape with alpha, JPEG 2000", + "features": "four components with an alpha channel", + "path": "images/scene-alpha.jp2", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 78619, + "sha256": "bc1adbddf1bd608b71b1cac9dd1a47f47cde2c046a4202f1642cd15efa647825" + }, + { + "file": "page-generic.jb2", + "group": "images", + "family": "jbig2", + "title": "Fax page as a JBIG2 file, generic region", + "features": "1-bit page of 1240 by 1579, arithmetic coding", + "path": "images/page-generic.jb2", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 8595, + "sha256": "1447cbbc1ebab320062a78fa40f81ccf768aed3d9aea2cfa0583ebce2fb3e088" + }, + { + "file": "page-symbol.jb2", + "group": "images", + "family": "jbig2", + "title": "Fax page as a JBIG2 file, symbol coding", + "features": "text region over a symbol dictionary", + "path": "images/page-symbol.jb2", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 5577, + "sha256": "8fba2e640c71101dd5ab376008ea177ee0e8f2070c49250d31186c198991da9e" + }, + { + "file": "scene-lossy.jxl", + "group": "images", + "family": "jpeg-xl", + "title": "Dusk landscape, JPEG XL, lossy", + "features": "VarDCT at distance 1", + "path": "images/scene-lossy.jxl", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 23664, + "sha256": "dc1e17bd77c26a49a3c61fcd8b299c79b71395550a4e1d42bc69af6aa33a200f" + }, + { + "file": "scene-lossless.jxl", + "group": "images", + "family": "jpeg-xl", + "title": "Dusk landscape, JPEG XL, lossless", + "features": "modular mode", + "path": "images/scene-lossless.jxl", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 26223, + "sha256": "5f2ce3702bb3fe54bb31feb6f1a9e92347a9acd290a6a7730a3074fe5fb088fe" + }, + { + "file": "scene-alpha.jxl", + "group": "images", + "family": "jpeg-xl", + "title": "Landscape with alpha, JPEG XL", + "features": "lossless with an extra alpha channel", + "path": "images/scene-alpha.jxl", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 35576, + "sha256": "d18698258dcc59292483265284a96099bc2c1f23f53f4893d778062070588166" + }, + { + "file": "bounce.jxl", + "group": "images", + "family": "jpeg-xl", + "title": "Bouncing ball, animated JPEG XL", + "features": "24 frames", + "path": "images/bounce.jxl", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-images.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-images.py", + "args": [] + }, + "bytes": 61211, + "sha256": "679c04f1bec63d699c6baeb1d42dfa4ff205a40327f208f650115f7292e27f89" + }, + { + "file": "house-plan.dxf", + "group": "cad", + "family": "dxf", + "title": "House, ground floor plan (DXF 2018)", + "features": "walls cut at openings with pattern hatches, door blocks with attributes, window and furniture blocks, axes with bubbles, room labels, linear, aligned, radius and angular dimensions, stair, north arrow, 17 layers, paper-space sheet with a viewport and a title block", + "path": "cad/house-plan.dxf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-cad.py", + "args": [] + }, + "bytes": 86949, + "sha256": "ad78cc54ad3c52483040b71dcb5cafda6f3660bdc9f229e21b22ece2cc773815" + }, + { + "file": "house-plan-r2000.dxf", + "group": "cad", + "family": "dxf", + "title": "House, ground floor plan (DXF 2000)", + "features": "the same plan written as an AutoCAD 2000 file", + "path": "cad/house-plan-r2000.dxf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-cad.py", + "args": [] + }, + "bytes": 84233, + "sha256": "eabe480065538e478a22424b5d3b0427efd321e098f7e9cabe4ad332984ab033" + }, + { + "file": "house-elevations.dxf", + "group": "cad", + "family": "dxf", + "title": "House, four elevations and a section in 2D", + "features": "gabled roofs with roof-tile hatches, plaster hatches, ground hatching, windows with transparent glass, steps, level marks, height dimensions, a hatched section with a stair", + "path": "cad/house-elevations.dxf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-cad.py", + "args": [] + }, + "bytes": 97170, + "sha256": "4ddb32c976e6709e39a4184a09c772ecff99324dcefd03e40a2cf7d89f62661f" + }, + { + "file": "hatch-gallery.dxf", + "group": "cad", + "family": "dxf", + "title": "Hatch gallery", + "features": "about a hundred predefined patterns, nine gradient types, islands in the three hatch styles, boundaries of lines, arcs, ellipses and splines, pattern angle and scale", + "path": "cad/hatch-gallery.dxf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-cad.py", + "args": [] + }, + "bytes": 145226, + "sha256": "0d9978ab422cfea65f91149502727f7132a3192450eedf52f90c9075f36b8cf4" + }, + { + "file": "dimensions.dxf", + "group": "cad", + "family": "dxf", + "title": "Dimension types", + "features": "linear, aligned, diameter, radius, arc length, angular (two lines and three points), ordinate, leaders, a multileader, tolerances, text override, three dimension styles", + "path": "cad/dimensions.dxf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-cad.py", + "args": [] + }, + "bytes": 56099, + "sha256": "515ccb26e3d707c2dc12192f147a4003dc44118d17da04d6f162250aa5935d87" + }, + { + "file": "linetypes.dxf", + "group": "cad", + "family": "dxf", + "title": "Linetypes, line weights and polylines", + "features": "the standard linetypes, custom ones with text inside, 12 line weights, per-entity scale, linetype generation, polylines with widths, circles, arcs, ellipses and splines in dashed styles", + "path": "cad/linetypes.dxf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-cad.py", + "args": [] + }, + "bytes": 36080, + "sha256": "0c8f9b53c105c230bad51a7fbad1af8972725fea449d638015c94467229c7cc0" + }, + { + "file": "text-styles.dxf", + "group": "cad", + "family": "dxf", + "title": "Text styles and MTEXT", + "features": "ten text styles (width and oblique factors, mirrored, upside down), justifications, rotation, special codes, Unicode, MTEXT colours, fonts, stacked fractions, underline, columns, background, nine attachment points", + "path": "cad/text-styles.dxf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-cad.py", + "args": [] + }, + "bytes": 30737, + "sha256": "e2c312052780d94fd25ad4205370645b143ceecde87d57dac2d471582cddeb3e" + }, + { + "file": "blocks.dxf", + "group": "cad", + "family": "dxf", + "title": "Blocks, nested inserts and arrays", + "features": "a block inside a block inside a block with attributes, mirrored, scaled and rotated inserts, a 3 by 8 array, BYBLOCK colours", + "path": "cad/blocks.dxf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-cad.py", + "args": [] + }, + "bytes": 30901, + "sha256": "419ffd35c1dd1d4ded3d70039dfa49852fa85cce935911b10a7a00557b967844" + }, + { + "file": "bracket.dxf", + "group": "cad", + "family": "dxf", + "title": "Mechanical part: an L bracket in three views", + "features": "centre and hidden lines, a section with hatching, dimensions with tolerances, diameter and radius dimensions, a leader, an A4 sheet with a title block", + "path": "cad/bracket.dxf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-cad.py", + "args": [] + }, + "bytes": 42633, + "sha256": "cd5d9676a8bb77c0702757674e17723202e3a614c38ca96ae8bd8f9c2ad1cfa9" + }, + { + "file": "site-plan.dxf", + "group": "cad", + "family": "dxf", + "title": "Site plan with contour lines", + "features": "closed spline contours, wide polyline roads, parcels with areas, hatched buildings, a gradient pond, spot heights, trees, scale bar, legend and north arrow", + "path": "cad/site-plan.dxf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-cad.py", + "args": [] + }, + "bytes": 85531, + "sha256": "c5bb9b26f9dbd785754d18854c1faef18fd360a8411f2244c3553d4c75a8baeb" + }, + { + "file": "legacy-r12.dxf", + "group": "cad", + "family": "dxf", + "title": "Gear in the R12 format", + "features": "POLYLINE, CIRCLE, ARC, TEXT, SOLID, 3DFACE and INSERT entities of the 1992 format", + "path": "cad/legacy-r12.dxf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-cad.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-cad.py", + "args": [] + }, + "bytes": 13965, + "sha256": "926e991c1389fcdf73d8aff413eb8b0c122943bf95f1667b31ba78b7db2a0723" + }, + { + "file": "gear.stl", + "group": "3d", + "family": "stl", + "title": "Spur gear, binary STL with facet colours", + "features": "864 facets, orange teeth and blue hub through the VisCAM colour attribute", + "path": "models/gear.stl", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-models.py", + "args": [] + }, + "bytes": 43284, + "sha256": "aac8dd0d87fed7b77061d32a5bbe61ac90cbfef16130b7c35730cdc1e77e93c9" + }, + { + "file": "bracket-ascii.stl", + "group": "3d", + "family": "stl", + "title": "L bracket, ASCII STL", + "features": "text STL, three overlapping boxes", + "path": "models/bracket-ascii.stl", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-models.py", + "args": [] + }, + "bytes": 8980, + "sha256": "dd4b8c55140214fe71a8200d4fe2ae7b51f53e6ab6184e82e79b3d2d12c708f9" + }, + { + "file": "knot.obj", + "group": "3d", + "family": "obj", + "title": "Trefoil knot and base, OBJ with vertex colours", + "features": "two objects (knot, base), a colour and a normal per vertex, quads, a rainbow along the knot", + "path": "models/knot.obj", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-models.py", + "args": [] + }, + "bytes": 100272, + "sha256": "a2eaba271264d700edc372eaaa6944d342fe9b823c98e698b1445846bded3bf1" + }, + { + "file": "terrain.ply", + "group": "3d", + "family": "ply", + "title": "Height field, binary PLY with colours", + "features": "2304 vertices with normals and a hypsometric colour each, 4418 triangles", + "path": "models/terrain.ply", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-models.py", + "args": [] + }, + "bytes": 119979, + "sha256": "22c2f25d47c43841c1ed1327c6fb9e75725925ca1e3c61dc413c23319dcfde52" + }, + { + "file": "icosphere-ascii.ply", + "group": "3d", + "family": "ply", + "title": "Icosphere, ASCII PLY with colours", + "features": "text PLY with normals and RGBA per vertex", + "path": "models/icosphere-ascii.ply", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-models.py", + "args": [] + }, + "bytes": 14774, + "sha256": "dbe5ae97077d8177503d5bab7d83fbc3f0a943181384fbffc68db7a4930f19be" + }, + { + "file": "arm.glb", + "group": "3d", + "family": "glb", + "title": "Articulated arm in a glass dome, GLB", + "features": "node tree with rotations and scales, five materials, a metallic and a transparent one, vertex colours on the floor", + "path": "models/arm.glb", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-models.py", + "args": [] + }, + "bytes": 29036, + "sha256": "146ba6e29d9b8bf4ec57c72bde686a5119b80cfe4365f05f0f0b7004b066a7b7" + }, + { + "file": "table.gltf", + "group": "3d", + "family": "gltf", + "title": "Table and two chairs, glTF with an embedded buffer", + "features": "17 nodes, a data URI buffer, shared meshes instanced under several nodes", + "path": "models/table.gltf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-models.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-models.py", + "args": [] + }, + "bytes": 7768, + "sha256": "ae656d2f656968fa44870ffc539d2383b85725289feb90e658881c5825bb7ef4" + }, + { + "file": "field-report.pdf", + "group": "pdf", + "family": "pdf", + "title": "Field report, six pages", + "features": "a table of contents whose lines are links, a two-level outline, roman and arabic page labels, internal and external links, a table, bar, line and pie charts as vectors, a JPEG, standard and embedded fonts (Latin, Greek, Cyrillic), document information", + "path": "pdf/field-report.pdf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-pdf.py", + "args": [] + }, + "bytes": 107001, + "sha256": "75b7649d62fb12034d56478c98baa92beba3c0a2117ce0cfcfffa9233d060a5b" + }, + { + "file": "application-form.pdf", + "group": "pdf", + "family": "pdf-form", + "title": "Berth application form (AcroForm)", + "features": "text fields (multiline, maximum length, password, read-only), check boxes, radio buttons, a drop-down list, a list box, some filled in", + "path": "pdf/application-form.pdf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-pdf.py", + "args": [] + }, + "bytes": 19127, + "sha256": "883dff8626a2a95d66d74bd8876ceee621197902de671b7c036d39e21774c50b" + }, + { + "file": "annotations.pdf", + "group": "pdf", + "family": "pdf-annotations", + "title": "Annotations without appearance streams", + "features": "links to a URL, a page and a named destination, highlight, underline, strike-out, squiggly, note, free text, square, circle, line with arrows, polygon, polyline, ink, stamp, file attachment, an outline and a named destination", + "path": "pdf/annotations.pdf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-pdf.py", + "args": [] + }, + "bytes": 6245, + "sha256": "212ea14f43e151d2d477b73659ef4fdb50735ee337eb76283d065ba9ec1701e9" + }, + { + "file": "scan-mixed.pdf", + "group": "pdf", + "family": "pdf-scan", + "title": "Scanned letters, one page for each scanner image filter", + "features": "four pages: DCTDecode (JPEG), CCITTFaxDecode (Group 4), JBIG2Decode and JPXDecode (JPEG 2000), each with an invisible OCR text layer; the viewer decodes the last three with its own decoders", + "path": "pdf/scan-mixed.pdf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-pdf.py", + "args": [], + "tools": [ + "opj_compress", + "jbig2", + "tiffcp" + ] + }, + "bytes": 206092, + "sha256": "daeb8cab36d82d4e5391041effc7d37dddf2421a87c3853c4b763e4a4d534776" + }, + { + "file": "vector-art.pdf", + "group": "pdf", + "family": "pdf", + "title": "Vector art", + "features": "axial and radial shadings, transparency, a clipping path, dashes, caps and joins, Bezier curves, an even-odd fill, text with render modes, rotated and scaled text", + "path": "pdf/vector-art.pdf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-pdf.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-pdf.py", + "args": [] + }, + "bytes": 4368, + "sha256": "fad466f385e89bc008128072d0b16544144c8a42983afd5d444079e59519e08e" + }, + { + "file": "handbook.docx", + "group": "office", + "family": "docx", + "title": "Harbour handbook (Word)", + "features": "title page, table of contents with links, outline numbering, character and paragraph styles, bulleted and numbered lists of three levels, tables with merged cells and a repeated header, two pictures (one floating with wrapped text), a shape, footnotes, hyperlinks, bookmarks, fields, a comment, tracked changes, a two-column section, a landscape section with a wide table, headers and footers with page numbers", + "path": "office/handbook.docx", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 25180, + "sha256": "46c4fb53949dbd25cfc8b1fecbbd282d470b767d16c1fea426394872fcffc95d" + }, + { + "file": "workbook.xlsx", + "group": "office", + "family": "xlsx", + "title": "Harbour workbook (Excel)", + "features": "three sheets: a budget with formulas (SUM, AVERAGE, INDEX, MATCH, COUNTIF, IF, VLOOKUP, ROUND), currency, percent and date formats, merged title, frozen header rows, a validation list, a comment, a hyperlink and named ranges; 120 rows of sales with an autofilter; a bar, a line and a pie chart", + "path": "office/workbook.xlsx", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 23363, + "sha256": "3e3e0247bde87b6fa1c6f9b06f0561f2eae8bc326925b4b28ba2d7d3b8c12792" + }, + { + "file": "deck.pptx", + "group": "office", + "family": "pptx", + "title": "Harbour review (PowerPoint)", + "features": "five slides: a gradient title slide, nested bullets, a native bar chart with a callout, a table, a picture with shapes, gradients and arrows; a master with footer and slide number; speaker notes (not shown) and transitions", + "path": "office/deck.pptx", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 30490, + "sha256": "160962428c7f1d15c8865d51fef7e74ebc8ccc6782f60ea4bf08ed0a805a7edb" + }, + { + "file": "handbook-tagged.pdf", + "group": "pdf", + "family": "pdf", + "title": "Harbour handbook as a tagged PDF/A-2", + "features": "bookmarks from the headings, hyperlinks, tags, footnotes, a landscape section, embedded Liberation fonts", + "path": "pdf/handbook-tagged.pdf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 192239, + "sha256": "c88a1434c1cbf8a8af467325bb413463276bbe70c84b5f88760638ff5975773d" + }, + { + "file": "handbook.doc", + "group": "converted", + "family": "doc", + "title": "Harbour handbook (Word 97 to 2003)", + "features": "the handbook as a binary .doc", + "path": "converted/handbook.doc", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 67584, + "sha256": "807c9b812188d73b3558ea8b91360d7a39eb637a18172295f206612da92cce39" + }, + { + "file": "handbook.odt", + "group": "converted", + "family": "odt", + "title": "Harbour handbook (OpenDocument text)", + "features": "the handbook as .odt", + "path": "converted/handbook.odt", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 42008, + "sha256": "d28f2667008ebd0e9456f7900eb4af8dbbd10b5af7490a059d6868d468c475ce" + }, + { + "file": "handbook.fodt", + "group": "converted", + "family": "fodt", + "title": "Harbour handbook (flat OpenDocument text)", + "features": "one XML file, pictures in base64; written by hand, not converted", + "path": "converted/handbook.fodt", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [] + }, + "bytes": 78095, + "sha256": "7c9f74181b5c9ad2b4766d5e3c82d9edf2c1cdd370417d0f8592d00ec71beec9" + }, + { + "file": "handbook.rtf", + "group": "converted", + "family": "rtf", + "title": "Harbour handbook (Rich Text Format)", + "features": "the handbook as .rtf", + "path": "converted/handbook.rtf", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 95772, + "sha256": "04eea9909d09ed87fb621459f1ac6e024b094eb767c1d0f7d536dd76f0b82e43" + }, + { + "file": "workbook.xls", + "group": "converted", + "family": "xls", + "title": "Harbour workbook (Excel 97 to 2003)", + "features": "the workbook as a binary .xls", + "path": "converted/workbook.xls", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 29696, + "sha256": "8552c433665e927723ecb747c5a0e1696076964f1bfd20ddd30bc3b95cc97e19" + }, + { + "file": "workbook.ods", + "group": "converted", + "family": "ods", + "title": "Harbour workbook (OpenDocument spreadsheet)", + "features": "the workbook as .ods", + "path": "converted/workbook.ods", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 45583, + "sha256": "32b0cf2984ddef9c2209d4cdb874866a65217d0b6bcdd3417264982ef07d660a" + }, + { + "file": "workbook.fods", + "group": "converted", + "family": "fods", + "title": "Harbour workbook (flat OpenDocument spreadsheet)", + "features": "one XML file; written by hand, not converted", + "path": "converted/workbook.fods", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [] + }, + "bytes": 120795, + "sha256": "80f5ad00faf7555d5aab526226204658880127a91f0af62a439d106c7a52e1be" + }, + { + "file": "deck.ppt", + "group": "converted", + "family": "ppt", + "title": "Harbour review (PowerPoint 97 to 2003)", + "features": "the deck as a binary .ppt (its thumbnail makes it large)", + "path": "converted/deck.ppt", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 491520, + "sha256": "8a6285ae02086db5ddb3246c75ef08a3508f672a91ba38b30efae291e119fb1e" + }, + { + "file": "deck.odp", + "group": "converted", + "family": "odp", + "title": "Harbour review (OpenDocument presentation)", + "features": "the deck as .odp", + "path": "converted/deck.odp", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 72325, + "sha256": "e194842a5abfb245477c00eee30736ef7f8460606b62b887bf8392283b41dd07" + }, + { + "file": "deck.fodp", + "group": "converted", + "family": "fodp", + "title": "Harbour review (flat OpenDocument presentation)", + "features": "one XML file; written by hand, not converted", + "path": "converted/deck.fodp", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [] + }, + "bytes": 31777, + "sha256": "07da109d15eceb65d7a0601998ed9508ecd140d5aef311301c96e7aad6faa236" + }, + { + "file": "diagram.odg", + "group": "converted", + "family": "odg", + "title": "Flowchart (OpenDocument drawing)", + "features": "two pages, layers (one hidden), connectors glued to shapes, groups, gradients, a curve and a polyline, shadows, dashes", + "path": "converted/diagram.odg", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [ + "soffice" + ] + }, + "bytes": 26758, + "sha256": "8c80d0ef2e536db14a7e5a92fc0092ab4f0976c87a091875899d3a7655f5b56e" + }, + { + "file": "diagram.fodg", + "group": "converted", + "family": "fodg", + "title": "Flowchart (flat OpenDocument drawing)", + "features": "one XML file; written by hand, not converted", + "path": "converted/diagram.fodg", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-office.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-office.py", + "args": [], + "tools": [] + }, + "bytes": 14205, + "sha256": "52ed359ccb0acec09a2d7401129021ff3f0ad69e35c770eab33986f063924203" + }, + { + "file": "field-guide.md", + "group": "text", + "family": "markdown", + "title": "Field guide to Markdown", + "features": "headings of six levels, nested and task lists, quotes, an aligned table, fenced code with languages, footnotes, links and references, inline HTML, Unicode", + "path": "text/field-guide.md", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 2368, + "sha256": "0f65f0bb537b18b6d5b1ec88da73686350e31d6529bb78a682aaa93d755e9f49" + }, + { + "file": "field-notes.txt", + "group": "text", + "family": "text", + "title": "Plain text with tabs, a long line and pangrams in nine scripts", + "features": "Latin, Greek, Cyrillic, Japanese, Arabic and Hebrew text, box drawing, symbols, no final newline", + "path": "text/field-notes.txt", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 1632, + "sha256": "12054040d6aef17fff17a18adf238fee6fd4158eeefd1d1230108fbd0f03df11" + }, + { + "file": "recipes.json", + "group": "text", + "family": "json", + "title": "A small recipe book as JSON", + "features": "nested objects and arrays, numbers of every kind, null, booleans, escapes, empty values", + "path": "text/recipes.json", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 2457, + "sha256": "9662568867ec0629cb9c18897f1bff96f2b837cc7f89f0840f25f1e1f3e8f69c" + }, + { + "file": "config.yaml", + "group": "text", + "family": "yaml", + "title": "Configuration file, YAML", + "features": "mappings, lists, block scalars, anchors and aliases, comments", + "path": "text/config.yaml", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 585, + "sha256": "398192bf091eeedd240dca6116180ef291ea95d7ee1c20e2e9853505d62854c9" + }, + { + "file": "pyproject.toml", + "group": "text", + "family": "toml", + "title": "Project file, TOML", + "features": "tables, arrays of tables, inline values", + "path": "text/pyproject.toml", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 440, + "sha256": "abcdc7dd5ef4d56589629b5c88d8b9a7931a84ddebd60c6b19f9f3b45349fb03" + }, + { + "file": "feed.xml", + "group": "text", + "family": "xml", + "title": "Atom feed", + "features": "namespaces, CDATA, an XHTML content element, entities, comments", + "path": "text/feed.xml", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 1330, + "sha256": "6cddabc37cc985205a2c04b4863fe3514695a5ef437e710463d15a597eb54560" + }, + { + "file": "route.gpx", + "group": "text", + "family": "xml", + "title": "Coastal walk, GPX track", + "features": "60 track points with elevation and time, two waypoints", + "path": "text/route.gpx", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 6491, + "sha256": "fcafdec4e3a6819fa406e98590dd7ede302bf76cbc6a2080f08542438d08524e" + }, + { + "file": "places.kml", + "group": "text", + "family": "xml", + "title": "Places, KML", + "features": "a point, a line and a polygon, a shared style, HTML in CDATA", + "path": "text/places.kml", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 1035, + "sha256": "9bb4a018a5c1f00843e61af1c475c1a735898f73950689b9ce36f9bdeb7879b8" + }, + { + "file": "harbour-log.csv", + "group": "text", + "family": "csv", + "title": "Harbour log, 300 rows of CSV", + "features": "nine columns, quoted fields with commas, quotes and line breaks, accents", + "path": "text/harbour-log.csv", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 19962, + "sha256": "d4e07a9e0b1aec65f189c8897fa27e1daf24189c3c204fb9527f2bf75d22e314" + }, + { + "file": "tides.tsv", + "group": "text", + "family": "csv", + "title": "Tide table, tab-separated values", + "features": "28 rows, six columns", + "path": "text/tides.tsv", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 833, + "sha256": "eff347351015e329e7904aebc8f334de5ab16cfda7a6b4c6b2575d25ac06fd68" + }, + { + "file": "prix.csv", + "group": "text", + "family": "csv", + "title": "Price list in the European style", + "features": "semicolon separator, decimal commas, accented headers", + "path": "text/prix.csv", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 255, + "sha256": "d490f1d9c26d7218e9937591baf5688d9846303fb6942a5e3c60417c1647b91d" + }, + { + "file": "life.py", + "group": "text", + "family": "source", + "title": "Conway's Game of Life, Python", + "features": "docstrings, comprehensions, f-strings, a main guard", + "path": "text/life.py", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 1069, + "sha256": "2cfc1e34f435d1ee59d3b01e5567bf61034df38a7257e9fed4f1fbdf9436e19e" + }, + { + "file": "lru.rs", + "group": "text", + "family": "source", + "title": "A least-recently-used cache, Rust", + "features": "generics, trait bounds, closures, a test module", + "path": "text/lru.rs", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 1592, + "sha256": "1e2181c4c51e88e4255f391fce16a9d657560408b728df079274804674ab1acb" + }, + { + "file": "tokens.ts", + "group": "text", + "family": "source", + "title": "Arithmetic tokenizer and evaluator, TypeScript", + "features": "union types, a sticky regular expression, the shunting-yard algorithm", + "path": "text/tokens.ts", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 2262, + "sha256": "3587b167a990c8ec02b14477721b4259431f39b432556a6cd86afc8cd2f525c2" + }, + { + "file": "bits.c", + "group": "text", + "family": "source", + "title": "Bit tricks on 32-bit words, C", + "features": "static functions, hexadecimal literals, printf formats", + "path": "text/bits.c", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 1463, + "sha256": "dc7eab8de40430eb6ed22610c37fd2b13df11e69cc70f6d9e2718514e589a6d5" + }, + { + "file": "report.sql", + "group": "text", + "family": "source", + "title": "Monthly report with window functions, SQL", + "features": "DDL, a CTE, lag, rank and sum over windows, joins", + "path": "text/report.sql", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 1287, + "sha256": "99688fcab08ea4876cee7a5d3352abbbd23d230c8c17bc4bbebeea276cf2bd9a" + }, + { + "file": "deploy.sh", + "group": "text", + "family": "source", + "title": "Build and deploy script, Bash", + "features": "strict mode, traps, functions, process substitution, a case statement", + "path": "text/deploy.sh", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 989, + "sha256": "a304fad73e5636d1caf340cfeca167e01905df2a31fc7abca661e8b8131375c7" + }, + { + "file": "style.css", + "group": "text", + "family": "source", + "title": "A small stylesheet, CSS", + "features": "custom properties, grid, clamp, color-mix, a dark mode and a media query", + "path": "text/style.css", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 1165, + "sha256": "7918765d12e41edd33e5a0eb2b7dba28c5429c3a517f086fcc8722f0306920c0" + }, + { + "file": "page.html", + "group": "text", + "family": "html", + "title": "A page, shown as its source, HTML", + "features": "semantic elements, a table, a form, a style and a script that do not run", + "path": "text/page.html", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 1116, + "sha256": "82dd9087ee3afdb2c5443f2a9fb8100500a1633f2e0bdffc2630a8be8387c678" + }, + { + "file": "changes.diff", + "group": "text", + "family": "diff", + "title": "A unified diff of two files", + "features": "two files, three hunks, added and removed lines", + "path": "text/changes.diff", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 879, + "sha256": "e0d7a274666b4f411cd8a5b7318736c37ad7993db25b884c4c9100e13a1391d6" + }, + { + "file": "subtitles.srt", + "group": "text", + "family": "text", + "title": "Subtitles, SubRip", + "features": "six cues with a tag", + "path": "text/subtitles.srt", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 338, + "sha256": "b4e25a1b12f662df624ae81c2c8bd89a8951e338688d2ea2cce55134c5de3161" + }, + { + "file": "server.log", + "group": "text", + "family": "text", + "title": "A server log of 120 lines", + "features": "INFO, WARN and ERROR lines", + "path": "text/server.log", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-text.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-text.py", + "args": [] + }, + "bytes": 9084, + "sha256": "d7e982445e5d36a398533f671c0e7d0f758b47ff406798631924b037a64f6d95" + }, + { + "file": "sample.zip", + "group": "archives", + "family": "zip", + "title": "Zip with folders, stored and deflated members, Unicode names and a comment", + "features": "9 files in 5 folders, an empty folder", + "path": "archives/sample.zip", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [] + }, + "bytes": 15824, + "sha256": "ad98593f9dc85d5dad309140ce703f96b36da749e48ea6648ce10c53a418250d" + }, + { + "file": "sample.tar", + "group": "archives", + "family": "tar", + "title": "Tar (ustar) with folders and a symbolic link", + "features": "16 entries", + "path": "archives/sample.tar", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [] + }, + "bytes": 51200, + "sha256": "b31804242af3545fd922934e81a2aade8fd09a7e2648fe26b41cd32dc37e1fb8" + }, + { + "file": "sample.tar.gz", + "group": "archives", + "family": "tar.gz", + "title": "Tar compressed with gzip", + "features": "the tar opens inside the gzip", + "path": "archives/sample.tar.gz", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [] + }, + "bytes": 15648, + "sha256": "5c423a4e7e0d96e025bb871034a88308f1d32861f60826074c29aa121fcdecca" + }, + { + "file": "sample.tar.bz2", + "group": "archives", + "family": "tar.bz2", + "title": "Tar compressed with bzip2", + "features": "the tar opens inside the bzip2 stream", + "path": "archives/sample.tar.bz2", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [] + }, + "bytes": 14648, + "sha256": "99b6742b5c54a36261f06a24032c22c11ed84b01e40e2267ef338b15ca181fcf" + }, + { + "file": "sample.tar.xz", + "group": "archives", + "family": "tar.xz", + "title": "Tar compressed with xz", + "features": "the tar opens inside the xz stream", + "path": "archives/sample.tar.xz", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [] + }, + "bytes": 13772, + "sha256": "762ce440ee2dfd2f4d22a6d29f2535e7079ad21d461d7fce3167cd62a9f356bf" + }, + { + "file": "sample.tar.zst", + "group": "archives", + "family": "tar.zst", + "title": "Tar compressed with Zstandard", + "features": "level 19", + "path": "archives/sample.tar.zst", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [ + "zstd" + ] + }, + "bytes": 14331, + "sha256": "d134793d16db00229eb192be488ef248a7c3e1226d9d27b67d8a763cd9b0641d" + }, + { + "file": "server.log.gz", + "group": "archives", + "family": "gz", + "title": "A log compressed with gzip", + "features": "one member, no tar", + "path": "archives/server.log.gz", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [] + }, + "bytes": 1331, + "sha256": "9f80faaae63eb4ae0a3a68c1346966049cb6ad5eba17e9c8600eb404ced75922" + }, + { + "file": "server.log.bz2", + "group": "archives", + "family": "bz2", + "title": "A log compressed with bzip2", + "features": "one member, no tar", + "path": "archives/server.log.bz2", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [] + }, + "bytes": 1155, + "sha256": "4b235dc9fc1a2840be3dd7ed792c7e4bc373851130e7122de3e798e7061b39c4" + }, + { + "file": "server.log.xz", + "group": "archives", + "family": "xz", + "title": "A log compressed with xz", + "features": "one member, no tar", + "path": "archives/server.log.xz", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [] + }, + "bytes": 820, + "sha256": "7dec383660d188a36f28cae361ebb809914849ddf10a508fc47503f367c1e86c" + }, + { + "file": "sample.7z", + "group": "archives", + "family": "7z", + "title": "7z with LZMA2", + "features": "a solid archive of 9 files", + "path": "archives/sample.7z", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [ + "7z" + ] + }, + "bytes": 13642, + "sha256": "7a2df3dd03ae207f3be0175190e3795662753e701d36555cd06e7295a72483c9" + }, + { + "file": "sample.rar", + "group": "archives", + "family": "rar", + "title": "RAR 5 with stored members", + "features": "folders, CRC32 and Unix modes, written by the script from the format's documentation (no RAR program)", + "path": "archives/sample.rar", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [] + }, + "bytes": 35056, + "sha256": "71aa4939bc7f2e4a98cc484e7353b829ad8a5019b1dee3911e8df3548e317c90" + }, + { + "file": "sample.iso", + "group": "archives", + "family": "iso", + "title": "ISO 9660 image with Joliet and Rock Ridge", + "features": "volume EXAV_EXAMPLE, long and Unicode names", + "path": "archives/sample.iso", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [ + "genisoimage" + ] + }, + "bytes": 133120, + "sha256": "baa0c331dc2f1f8e3f04c171282faf7753a38d380e82e0ca894c70a04f08d4c0" + }, + { + "file": "matryoshka.zip", + "group": "archives", + "family": "zip", + "title": "Nested archives: a zip holding a tar.gz holding a 7z holding a zip", + "features": "four levels, opened in place one after the other", + "path": "archives/matryoshka.zip", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [ + "7z" + ] + }, + "bytes": 7232, + "sha256": "0c4d4171bd6cd565a17ff675763cebf6c8d8c9408ebd6c738d436feab6cb42e9" + }, + { + "file": "encrypted-aes.zip", + "group": "archives", + "family": "zip", + "title": "Zip encrypted with AES-256, password: exav", + "features": "names are listed, each member says it is encrypted", + "path": "archives/encrypted-aes.zip", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [ + "7z" + ] + }, + "bytes": 16604, + "sha256": "e6cd983b8b1694a5df2c2f7d7790a249e4e9c529cb0d796e6d05de7a4bb03bd0" + }, + { + "file": "encrypted-zipcrypto.zip", + "group": "archives", + "family": "zip", + "title": "Zip encrypted with the traditional ZipCrypto, password: exav", + "features": "names are listed, each member says it is encrypted", + "path": "archives/encrypted-zipcrypto.zip", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [ + "7z" + ] + }, + "bytes": 16262, + "sha256": "21053827c2871cda2d2f6259dc1d3848e318b40c0e71858220d601fc3c90767c" + }, + { + "file": "encrypted.7z", + "group": "archives", + "family": "7z", + "title": "7z encrypted with AES-256, password: exav", + "features": "file names visible, contents encrypted", + "path": "archives/encrypted.7z", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [ + "7z" + ] + }, + "bytes": 13726, + "sha256": "c2606ee4ee72de0d9ba1461ba976c5ac20de157b6b17771372bd6acf221cc6ce" + }, + { + "file": "example.jar", + "group": "archives", + "family": "jar", + "title": "A jar (a zip with a manifest)", + "features": "META-INF/MANIFEST.MF, a source file, a properties file", + "path": "archives/example.jar", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [] + }, + "bytes": 793, + "sha256": "44aeabd990d5a5c75f88846f5310ad44a9b56deadde592ec3d932cf13476ff45" + }, + { + "file": "pages.cbz", + "group": "archives", + "family": "cbz", + "title": "Comic book archive (zip of pages)", + "features": "two page images and ComicInfo.xml", + "path": "archives/pages.cbz", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [] + }, + "bytes": 10720, + "sha256": "82dc884486eec4ca4fbeb3c016d6431848d0a2ccd843ab6e65972503524b0723" + }, + { + "file": "sample.cab", + "group": "archives", + "family": "cab", + "title": "Microsoft cabinet", + "features": "four files, MSZIP", + "path": "archives/sample.cab", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [ + "gcab" + ] + }, + "bytes": 6284, + "sha256": "5f12d6c186b5cc81f70dc4b3d4a4d7b4b7bdebb74f002ada9067b4738589de00" + }, + { + "file": "exav-example.deb", + "group": "archives", + "family": "deb", + "title": "Debian package", + "features": "an ar archive of debian-binary, control.tar.xz and data.tar.xz", + "path": "archives/exav-example.deb", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [ + "dpkg-deb" + ] + }, + "bytes": 2256, + "sha256": "d73cac532f34c9948bc596e1241189b66d4d4497af030d766bbb451b4ab1adea" + }, + { + "file": "libexample.a", + "group": "archives", + "family": "ar", + "title": "Unix ar archive", + "features": "two members", + "path": "archives/libexample.a", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [ + "ar" + ] + }, + "bytes": 1988, + "sha256": "59396e78830b3119a01419e202810446dc15c312cf4b91727170b181d0afaf3e" + }, + { + "file": "sample.cpio", + "group": "archives", + "family": "cpio", + "title": "cpio archive (newc)", + "features": "four files", + "path": "archives/sample.cpio", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-archives.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-archives.py", + "args": [], + "tools": [ + "cpio" + ] + }, + "bytes": 7168, + "sha256": "aab3c3fdd392a978d0a516e5a420bbed6b97c203966c1ed275d7246a93ab9827" + }, + { + "file": "canon.wav", + "group": "media", + "family": "wav", + "title": "A four-voice canon, WAV", + "features": "8 kHz mono 16-bit, 8.4 seconds, synthesised", + "path": "media/canon.wav", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-media.py", + "args": [], + "tools": [ + "ffmpeg" + ] + }, + "bytes": 134444, + "sha256": "c26b3aa385a70bb6785c7eb36b0bf3fe04a379fe46294d77d29ad153d0cc1028" + }, + { + "file": "canon.mp3", + "group": "media", + "family": "mp3", + "title": "The canon as MP3", + "features": "24 kbit/s", + "path": "media/canon.mp3", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-media.py", + "args": [], + "tools": [ + "ffmpeg" + ] + }, + "bytes": 25920, + "sha256": "c9f569a2833d11af90232c2f950c865f02bfbcc5822fc35cccb7466dd9c46c49" + }, + { + "file": "canon.flac", + "group": "media", + "family": "flac", + "title": "The canon as FLAC", + "features": "lossless, level 8", + "path": "media/canon.flac", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-media.py", + "args": [], + "tools": [ + "ffmpeg" + ] + }, + "bytes": 74904, + "sha256": "c3dd10ace8ccaacb09f74ca73619e0d991ff94ce3d25fdc20ee9fb4597bc8a63" + }, + { + "file": "canon.ogg", + "group": "media", + "family": "ogg", + "title": "The canon as Ogg Vorbis", + "features": "quality 2", + "path": "media/canon.ogg", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-media.py", + "args": [], + "tools": [ + "ffmpeg" + ] + }, + "bytes": 14618, + "sha256": "39c1dabbcadc817bfa1fc76839b1ee6940bab7187dffd4c495a5f61362cb91ad" + }, + { + "file": "canon.opus", + "group": "media", + "family": "opus", + "title": "The canon as Opus", + "features": "16 kbit/s", + "path": "media/canon.opus", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-media.py", + "args": [], + "tools": [ + "ffmpeg" + ] + }, + "bytes": 16274, + "sha256": "e18075a4586929741c6bf264c92e8f7f35086f5e4ab2f3be58845835556bc9ae" + }, + { + "file": "canon.m4a", + "group": "media", + "family": "m4a", + "title": "The canon as AAC in MP4", + "features": "24 kbit/s", + "path": "media/canon.m4a", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-media.py", + "args": [], + "tools": [ + "ffmpeg" + ] + }, + "bytes": 25066, + "sha256": "edd56750fd23edd327a46ea907c9d34d53fcff6e04f2d0516a1083ea2c7306e5" + }, + { + "file": "testcard.mp4", + "group": "media", + "family": "mp4", + "title": "Test card with a clock, H.264 and AAC in MP4", + "features": "256 by 192, 12 frames a second, 4 seconds, with the canon as sound", + "path": "media/testcard.mp4", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-media.py", + "args": [], + "tools": [ + "ffmpeg" + ] + }, + "bytes": 41946, + "sha256": "ad088934ae59962bafc0b9b56a57556623d5e2b7821869e2dc91047573213a12" + }, + { + "file": "testcard.webm", + "group": "media", + "family": "webm", + "title": "Test card with a clock, VP9 and Opus in WebM", + "features": "256 by 192, 12 frames a second, 4 seconds, with the canon as sound", + "path": "media/testcard.webm", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-media.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-media.py", + "args": [], + "tools": [ + "ffmpeg" + ] + }, + "bytes": 42004, + "sha256": "dca14e93bb8e3448a5d9a61fbbe402a7cf2b0c8f476a13b98f5649d079a1b7b8" + }, + { + "file": "house.ifc", + "group": "3d", + "family": "ifc", + "title": "Two-storey house (IFC4)", + "features": "walls with openings filled by windows and doors, slabs, a gable roof, porch columns, a stair of eleven steps, a table and chairs sharing a mapped representation, spaces, a property set, a material and colours", + "path": "ifc/house.ifc", + "committed": true, + "author": "exav project", + "source": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-ifc.py", + "evidence": "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/generate/make-ifc.py", + "evidence_quote": "Output: CC0-1.0, a public domain dedication by the exav project.", + "licence": "CC0-1.0", + "attribution": "", + "generated": { + "script": "generate/make-ifc.py", + "args": [] + }, + "bytes": 66945, + "sha256": "d65c93ae607a5b03316662719f5995f9de3bfd94366383ab683838bbccfa4731" + }, + { + "file": "canon-eos-40d-sraw.cr2", + "group": "raw", + "family": "raw-cr2", + "title": "Canon EOS 40D, sRAW (CR2)", + "features": "TIFF-based CR2 with a 1936 by 1288 JPEG preview", + "author": "Uploader to raw.pixls.us (the site gives no name)", + "source": "https://raw.pixls.us/#repo", + "evidence": "https://raw.pixls.us/json/getrepository.php?set=all", + "evidence_quote": "Creative Commons 0 - Public Domain", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.pixls.us/getfile.php/2102/nice/Canon%20-%20EOS%2040D%20-%20sRAW2%20%28sRAW%29%20%283%3A2%29.CR2", + "evidence_row": "sha256", + "committed": false, + "bytes": 5805950, + "sha256": "ba644e7dd2abe74eca260e67f0206ff113bf0f62e710f8130611e964d6be5bf1" + }, + { + "file": "canon-eos-r6.cr3", + "group": "raw", + "family": "raw-cr3", + "title": "Canon EOS R6, C-RAW (CR3)", + "features": "ISO base media CR3 with a 3408 by 2272 JPEG in its second track; its EXIF names Johannes Kimmel as artist and states CC0", + "author": "Uploader to raw.pixls.us; EXIF artist Johannes Kimmel", + "source": "https://raw.pixls.us/#repo", + "evidence": "https://raw.pixls.us/json/getrepository.php?set=all", + "evidence_quote": "Creative Commons 0 - Public Domain", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.pixls.us/getfile.php/4659/nice/Canon%20-%20EOS%20R6%20-%203%3A2.CR3", + "evidence_row": "sha256", + "committed": false, + "bytes": 5273174, + "sha256": "74abb0a113d075ad9887a058082f40dd2a938c4813a08474d82356f11a027778" + }, + { + "file": "canon-powershot-g1.crw", + "group": "raw", + "family": "raw-crw", + "title": "Canon PowerShot G1 (CRW)", + "features": "the 2000 CIFF/HEAP container with a 640 by 480 JPEG", + "author": "Uploader to raw.pixls.us (the site gives no name)", + "source": "https://raw.pixls.us/#repo", + "evidence": "https://raw.pixls.us/json/getrepository.php?set=all", + "evidence_quote": "Creative Commons 0 - Public Domain", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.pixls.us/getfile.php/2073/nice/Canon%20-%20PowerShot%20G1%20-%20RAW%20%284%3A3%29.crw", + "evidence_row": "sha256", + "committed": false, + "bytes": 2300702, + "sha256": "f39be5acf14057ce04527fd8d0574e57ec8ed5fed082d7bfaff763075a44ee8a" + }, + { + "file": "nikon-d70s.nef", + "group": "raw", + "family": "raw-nef", + "title": "Nikon D70s (NEF)", + "features": "TIFF-based NEF with a 3008 by 2000 JPEG in a SubIFD", + "author": "Uploader to raw.pixls.us (the site gives no name)", + "source": "https://raw.pixls.us/#repo", + "evidence": "https://raw.pixls.us/json/getrepository.php?set=all", + "evidence_quote": "Creative Commons 0 - Public Domain", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.pixls.us/getfile.php/1117/nice/Nikon%20-%20D70s%20-%2012bit%2012bit%20compressed%20%28Lossy%20%28type%201%29%29%20%283%3A2%29.NEF", + "evidence_row": "sha256", + "committed": false, + "bytes": 5193213, + "sha256": "6c46f9854033e7623ebbb5de8c951df6762ca44f05d45035ccc5cb7e9f4e5692" + }, + { + "file": "sony-ilce-7s.arw", + "group": "raw", + "family": "raw-arw", + "title": "Sony A7S (ARW)", + "features": "TIFF-based ARW with a 1616 by 1080 JPEG preview", + "author": "Uploader to raw.pixls.us (the site gives no name)", + "source": "https://raw.pixls.us/#repo", + "evidence": "https://raw.pixls.us/json/getrepository.php?set=all", + "evidence_quote": "Creative Commons 0 - Public Domain", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.pixls.us/getfile.php/1582/nice/Sony%20-%20ILCE-7S%20-%2014bit%2014bit%20compressed%20%283%3A2%29.ARW", + "evidence_row": "sha256", + "committed": false, + "bytes": 6160384, + "sha256": "a35ebb2fbec929daa5beb20d1ce5c15a8aac7b1a7a231455387f3df8a7442e07" + }, + { + "file": "olympus-c5060wz.orf", + "group": "raw", + "family": "raw-orf", + "title": "Olympus C5060WZ (ORF)", + "features": "the only picture inside is a 160 by 120 thumbnail", + "author": "Uploader to raw.pixls.us (the site gives no name)", + "source": "https://raw.pixls.us/#repo", + "evidence": "https://raw.pixls.us/json/getrepository.php?set=all", + "evidence_quote": "Creative Commons 0 - Public Domain", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.pixls.us/getfile.php/1799/nice/Olympus%20-%20C5060WZ%20-%2012bit%20%284%3A3%29.ORF", + "evidence_row": "sha256", + "committed": false, + "bytes": 7646208, + "sha256": "3fc12bc3f6320cfab456111d7805b446e329fdd1907680be55e2e163e5e084bd" + }, + { + "file": "panasonic-dmc-lx7.rw2", + "group": "raw", + "family": "raw-rw2", + "title": "Panasonic Lumix DMC-LX7 (RW2)", + "features": "RW2 with a 1920 by 1280 JPEG", + "author": "Uploader to raw.pixls.us (the site gives no name)", + "source": "https://raw.pixls.us/#repo", + "evidence": "https://raw.pixls.us/json/getrepository.php?set=all", + "evidence_quote": "Creative Commons 0 - Public Domain", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.pixls.us/getfile.php/7010/nice/Panasonic%20-%20DMC-LX7%20-%203%3A2.RW2", + "evidence_row": "sha256", + "committed": false, + "bytes": 3394560, + "sha256": "18dfc3877e944020299635a8c2fad61fca2485b1c9b67645a495ee870a86e599" + }, + { + "file": "fujifilm-finepix-s5000.raf", + "group": "raw", + "family": "raw-raf", + "title": "Fujifilm FinePix S5000 (RAF)", + "features": "RAF container with a 1280 by 960 JPEG", + "author": "Uploader to raw.pixls.us (the site gives no name)", + "source": "https://raw.pixls.us/#repo", + "evidence": "https://raw.pixls.us/json/getrepository.php?set=all", + "evidence_quote": "Creative Commons 0 - Public Domain", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.pixls.us/getfile.php/2726/nice/Fujifilm%20-%20FinePix%20S5000%20-%204%3A3.RAF", + "evidence_row": "sha256", + "committed": false, + "bytes": 6851240, + "sha256": "dabd5e74521a6980156be9fd4b88d0c37b0fe4d0e0e6f5c12db8cffff1b76297" + }, + { + "file": "minolta-dimage-5.mrw", + "group": "unsupported", + "family": "raw-mrw", + "title": "Minolta DiMAGE 5 (MRW)", + "features": "MRW with a 640 by 480 preview whose first byte is stored as zero: the viewer finds no preview in it (kept to show the message)", + "author": "Uploader to raw.pixls.us (the site gives no name)", + "source": "https://raw.pixls.us/#repo", + "evidence": "https://raw.pixls.us/json/getrepository.php?set=all", + "evidence_quote": "Creative Commons 0 - Public Domain", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.pixls.us/getfile.php/7795/nice/Minolta%20-%20DiMAGE%205%20-%204%3A3.MRW", + "evidence_row": "sha256", + "committed": false, + "bytes": 6422144, + "sha256": "d60bfd80bcb1f7b9c88b14a5e46ea27885bbf92d990ab30b3939288678fea0d9" + }, + { + "file": "adobe-dng-canon-5d3.dng", + "group": "raw", + "family": "raw-dng", + "title": "Canon EOS 5D Mark III converted to DNG (lossy JPEG)", + "features": "DNG with previews of 256, 1024 and 3960 pixels; converted by Adobe DNG Converter, not straight from a camera", + "author": "Uploader to raw.pixls.us; EXIF artist Simon Harhues", + "source": "https://raw.pixls.us/#repo", + "evidence": "https://raw.pixls.us/json/getrepository.php?set=all", + "evidence_quote": "Creative Commons 0 - Public Domain", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.pixls.us/getfile.php/1033/nice/Adobe%20DNG%20Converter%20-%20Canon%20EOS%205D%20Mark%20III%20-%20Lossy%20JPEG%20compression%2C%20rgb%20%283%3A2%29.DNG", + "evidence_row": "sha256", + "committed": false, + "bytes": 2484836, + "sha256": "b22f1e36331f679abb8b13e433b9bbde3988723adf10fee7aa0dda6381016a98" + }, + { + "file": "barraca-valenciana-0100-r2010.dwg", + "group": "cad", + "family": "dwg", + "title": "Barraca Valenciana, ground floor plan (DWG 2010, Revit export)", + "features": "walls, doors, glazing, stairs, furniture, hatches, areas, 24 layers, 56 blocks, extra layouts with title block and viewports", + "author": "Ã’scar Selfa", + "source": "https://zenodo.org/records/14293897", + "evidence": "https://zenodo.org/records/14293897", + "evidence_quote": "Creative Commons Attribution 4.0 International", + "licence": "CC-BY-4.0", + "attribution": "Ã’scar Selfa, Barraca Valenciana de Llauradors: Model BIM i Estudi de la Tipologia Arquitectònica, Zenodo, doi:10.5281/zenodo.14293897, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/records/14293897/files/BRC-OSP-XXX-P00-PLA-ARQ-0100-tipologiaGen%C3%A8rica-A1-P2.dwg?download=1", + "committed": false, + "bytes": 284266, + "sha256": "fcd3eef78cbd568e3f8a8262378670495a3ea6b8e091cb162fe8ef9c3c9add13" + }, + { + "file": "barraca-valenciana-0300-r2010.dwg", + "group": "cad", + "family": "dwg", + "title": "Barraca Valenciana, elevations (DWG 2010, Revit export)", + "features": "elevations drawn as 2D linework with hatches, topography and planting, no 3D", + "author": "Ã’scar Selfa", + "source": "https://zenodo.org/records/14293897", + "evidence": "https://zenodo.org/records/14293897", + "evidence_quote": "Creative Commons Attribution 4.0 International", + "licence": "CC-BY-4.0", + "attribution": "Ã’scar Selfa, Barraca Valenciana de Llauradors: Model BIM i Estudi de la Tipologia Arquitectònica, Zenodo, doi:10.5281/zenodo.14293897, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/records/14293897/files/BRC-OSP-XXX-ZZZ-PLA-ARQ-0300-tipologiaGen%C3%A8rica-A1-P2.dwg?download=1", + "committed": false, + "bytes": 1069565, + "sha256": "93a211cfb797525a94b5b41aeae3ecf33e61442eea07cadae056463cc400a3e5" + }, + { + "file": "barraca-valenciana-0400-r2010.dwg", + "group": "cad", + "family": "dwg", + "title": "Barraca Valenciana, sections and details (DWG 2010, Revit export)", + "features": "42 layers, hatches, arcs, splines, ellipses, 61 blocks", + "author": "Ã’scar Selfa", + "source": "https://zenodo.org/records/14293897", + "evidence": "https://zenodo.org/records/14293897", + "evidence_quote": "Creative Commons Attribution 4.0 International", + "licence": "CC-BY-4.0", + "attribution": "Ã’scar Selfa, Barraca Valenciana de Llauradors: Model BIM i Estudi de la Tipologia Arquitectònica, Zenodo, doi:10.5281/zenodo.14293897, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/records/14293897/files/BRC-OSP-XXX-ZZZ-PLA-ARQ-0400-tipologiaGen%C3%A8rica-A1-P2.dwg?download=1", + "committed": false, + "bytes": 511114, + "sha256": "a09c492dc34ead8df619d6d618049298afffb050a8436c470055923a90f4b61c" + }, + { + "file": "building-survey-plans-r2000.dwg", + "group": "cad", + "family": "dwg", + "title": "Survey of a small building: plans, elevations and details (DWG 2000)", + "features": "Italian drawing with room names and areas, over 120 layers, 890 blocks, 567 dimensions, 492 hatches", + "author": "Giovanni De Gasperis, Sante Dino Facchini, Asif Saeed", + "source": "https://zenodo.org/records/15076037", + "evidence": "https://zenodo.org/records/15076037", + "evidence_quote": "Creative Commons Attribution 4.0 International", + "licence": "CC-BY-4.0", + "attribution": "De Gasperis, G., Facchini, S. D., Saeed, A., Building Ledger Dossier: Seismic Prevention and Building Documentation Tracking through a Digital Twin Approach (4_Architectural_Building_Survey.dwg), Zenodo, doi:10.5281/zenodo.15076037, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/records/15076037/files/4_Architectural_Building_Survey.dwg?download=1", + "committed": false, + "bytes": 2097350, + "sha256": "2f096b44cd5b60ded2ad8b12c2f46116db8b1fda1c980f7bb02660a85782ab1d" + }, + { + "file": "golden-tile-palace-r2004.dwg", + "group": "cad", + "family": "dwg", + "title": "Golden Tile Palace: front elevation and section (DWG 2004)", + "features": "elevation and section with level marks and Chinese titles, 4393 polylines, 841 arcs, 328 splines, 26 dimensions, 24 hatches", + "author": "Jing Zhang, Yunying Ren, Xiaofan An", + "source": "https://figshare.com/articles/dataset/Figure_of_surveying_and_mapping_of_Golden_Tile_Palace_/21374221", + "evidence": "https://api.figshare.com/v2/articles/21374221", + "evidence_quote": "\"name\": \"CC BY 4.0\"", + "licence": "CC-BY-4.0", + "attribution": "Jing Zhang, Yunying Ren, Xiaofan An, Figure of surveying and mapping of Golden Tile Palace, supplementary file S1 of PLOS ONE doi:10.1371/journal.pone.0262155, figshare, CC BY 4.0. No changes.", + "fetched": "https://ndownloader.figshare.com/files/37930432", + "committed": false, + "bytes": 763903, + "sha256": "14d128397f89c1af652b2cd3c9d523db98ae539b1bc061d4f06fba6d21501ae9" + }, + { + "file": "residential-site-plan-r2007.dwg", + "group": "cad", + "family": "dwg", + "title": "Site plan of an old residential community in Beijing (DWG 2007)", + "features": "58 layers, 79 blocks, buildings, roads, 2865 polylines, 656 texts, 125 hatches, 39 dimensions", + "author": "Yijun Fan", + "source": "https://figshare.com/articles/dataset/Drainage_System_Layout_of_Old_Urban_Residential_Communities_In_Beijing/28188725", + "evidence": "https://api.figshare.com/v2/articles/28188725", + "evidence_quote": "\"name\": \"CC BY 4.0\"", + "licence": "CC-BY-4.0", + "attribution": "Yijun Fan, Drainage System Layout of Old Urban Residential Communities In Beijing (Site Plan.dwg), figshare, doi:10.6084/m9.figshare.28188725.v1, CC BY 4.0. No changes.", + "fetched": "https://ndownloader.figshare.com/files/51611078", + "committed": false, + "bytes": 948192, + "sha256": "37b03757172e5360a03cc26da473cde84e85dbd61914b67741c94a40f7f0db2f" + }, + { + "file": "hospital-floor-plan-r2013.dwg", + "group": "cad", + "family": "dwg", + "title": "Furnished hospital floor plan (DWG 2013)", + "features": "section and level marks, 109 dimensions, 429 block definitions of furniture and plants, 19 layers", + "author": "Toka Ehab", + "source": "https://zenodo.org/records/10520508", + "evidence": "https://zenodo.org/records/10520508", + "evidence_quote": "Creative Commons Attribution 4.0 International", + "licence": "CC-BY-4.0", + "attribution": "Toka Ehab, Nanotechnology Applications in Interior Design of hospitals to enhance thermal comfort and decrease the infection spread for the occupants (Elite hospital plan.dwg), Zenodo, doi:10.5281/zenodo.10520508, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/records/10520508/files/Elite%20hospital%20plan.dwg?download=1", + "committed": false, + "bytes": 1249695, + "sha256": "b618207b01a1759142e038e1edf762ab8efbe11804bb2e84fc6f472e7e040fb9" + }, + { + "file": "commercial-building-hvac-plans-r2018.dwg", + "group": "cad", + "family": "dwg", + "title": "Air-conditioning plans of a commercial building (DWG 2018)", + "features": "48 layers, 320 blocks, 316 dimensions, 125 hatches, 112 wipeouts", + "author": "Kevin Anthony do Bem", + "source": "https://zenodo.org/records/10407941", + "evidence": "https://zenodo.org/records/10407941", + "evidence_quote": "Creative Commons Attribution 4.0 International", + "licence": "CC-BY-4.0", + "attribution": "Kevin Anthony do Bem, Projeto de Climatização de um Edifício de Comércio e Serviços (F04 Plantas- Rede aerolica.dwg), Zenodo, doi:10.5281/zenodo.10407941, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/records/10407941/files/F04%20Plantas-%20Rede%20aerolica.dwg?download=1", + "committed": false, + "bytes": 506884, + "sha256": "bcf3b92e0afdf29bb75e7632e8193f881918ddabb4de67a1331b5eda34ee9be2" + }, + { + "file": "ezdxf-dim-linear-tutorial-r2013.dwg", + "group": "cad", + "family": "dwg", + "title": "ezdxf documentation: linear dimension tutorial (DWG 2013)", + "features": "16 dimensions, 16 multileaders, 13 dimension styles, 27 text styles", + "author": "Manfred Moitzi (ezdxf)", + "source": "https://github.com/mozman/ezdxf/blob/748e211c9a0b977b9e15845a6bcad8e1b9743e26/docs/graphics/dim_linear_tutorial.dwg", + "evidence": "https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/LICENSE", + "evidence_quote": "Copyright (c) 2020 Manfred Moitzi", + "licence": "MIT", + "attribution": "Copyright (c) 2020 Manfred Moitzi, ezdxf, MIT License. No changes.", + "fetched": "https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/docs/graphics/dim_linear_tutorial.dwg", + "committed": false, + "bytes": 36391, + "sha256": "88037b595bd46d81c5c98ce7aa428ce6b8506d1aa4602e976811cfb154005155" + }, + { + "file": "hospital-ward-wing-plan-section.dxf", + "group": "cad", + "family": "dxf", + "title": "Hospital ward wing, plan and section (DXF 2010)", + "features": "542 polylines, 17 layers of the A-* scheme, 3 blocks, a paper-space viewport", + "author": "Innerscene (original model)", + "source": "https://www.innerscene.com/tools/library/drawings/hospital-ward-wing-1200-square-metres-plan-and-section-73a3f4dd", + "evidence": "https://www.innerscene.com/tools/library/drawings/hospital-ward-wing-1200-square-metres-plan-and-section-73a3f4dd", + "evidence_quote": "Original Innerscene model, released CC0.", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://www.innerscene.com/api/library/hospital-ward-wing-1200-square-metres-plan-and-section-73a3f4dd/download", + "committed": false, + "bytes": 307408, + "sha256": "4fabf62d6d7bbc7c8bdc5f3c9d292d4980c3ec504281b0bd77f487d3c6bb9ba3" + }, + { + "file": "grocery-store-plan-section.dxf", + "group": "cad", + "family": "dxf", + "title": "Grocery store, plan and section (DXF 2010)", + "features": "234 lines, 150 polylines, 17 layers, 3 blocks, a viewport", + "author": "Innerscene (original model)", + "source": "https://www.innerscene.com/tools/library/drawings/grocery-store-600-square-metres-plan-and-section-2a67d041", + "evidence": "https://www.innerscene.com/tools/library/drawings/grocery-store-600-square-metres-plan-and-section-2a67d041", + "evidence_quote": "Original Innerscene model, released CC0.", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://www.innerscene.com/api/library/grocery-store-600-square-metres-plan-and-section-2a67d041/download", + "committed": false, + "bytes": 130840, + "sha256": "0b875304e1769e0f7c9377abf270f1fb4d103547cc27a3795a57c34fb4619d30" + }, + { + "file": "ezdxf-uncommon-entities.dxf", + "group": "cad", + "family": "dxf", + "title": "ezdxf example: uncommon entities (DXF 2018)", + "features": "13 dimensions, 2 multileaders, large radial dimensions, rays, construction lines, splines, 33 blocks, 2 extra layouts", + "author": "Manfred Moitzi (ezdxf)", + "source": "https://github.com/mozman/ezdxf/blob/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/uncommon.dxf", + "evidence": "https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/LICENSE", + "evidence_quote": "Copyright (c) 2020 Manfred Moitzi", + "licence": "MIT", + "attribution": "Copyright (c) 2020 Manfred Moitzi, ezdxf, MIT License. No changes.", + "fetched": "https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/uncommon.dxf", + "committed": false, + "bytes": 343110, + "sha256": "5efdd671e3b6d8c45bd0688b1d6479d523f2290f0b390f1584348bf46e34c965" + }, + { + "file": "ezdxf-hatches-1.dxf", + "group": "cad", + "family": "dxf", + "title": "ezdxf example: solid hatches (DXF 2018)", + "features": "ten solid hatches over polylines and arcs", + "author": "Manfred Moitzi (ezdxf)", + "source": "https://github.com/mozman/ezdxf/blob/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/hatches_1.dxf", + "evidence": "https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/LICENSE", + "evidence_quote": "Copyright (c) 2020 Manfred Moitzi", + "licence": "MIT", + "attribution": "Copyright (c) 2020 Manfred Moitzi, ezdxf, MIT License. No changes.", + "fetched": "https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/hatches_1.dxf", + "committed": false, + "bytes": 130334, + "sha256": "2dc2930b4f7d5fb16698437e4f6972986e580a81b2b5d36a780b4311f85fb326" + }, + { + "file": "bsi-building-architecture-ifc2x3.ifc", + "group": "3d", + "family": "ifc", + "title": "buildingSMART Simple-Scene Building-Architecture (IFC2X3)", + "features": "a small SketchUp house: walls, slabs, a roof, spaces, materials with colours, quantity and property sets; faceted breps", + "author": "buildingSMART International Ltd.", + "source": "https://github.com/buildingSMART/Sample-Test-Files", + "evidence": "https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/LICENSE", + "evidence_quote": "This work is licensed under the Creative Commons Attribution 4.0 International License.", + "licence": "CC-BY-4.0", + "attribution": "buildingSMART International, Sample-Test-Files, https://github.com/buildingSMART/Sample-Test-Files, licensed CC BY 4.0. No changes.", + "fetched": "https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/IFC%202.3.0.1%20%28IFC%202x3%20TC1%29/Simple-Scene/Building-Architecture.ifc", + "committed": false, + "bytes": 92542, + "sha256": "c4db65ba847f6b369a95d6c54fa11f4750cbe6d59f021934e8923d8d578e5885" + }, + { + "file": "bsi-building-architecture-ifc4x3.ifc", + "group": "3d", + "family": "ifc", + "title": "buildingSMART Simple-Scene Building-Architecture (IFC4X3_ADD2)", + "features": "the same house in IFC 4.3, with triangulated faces", + "author": "buildingSMART International Ltd.", + "source": "https://github.com/buildingSMART/Sample-Test-Files", + "evidence": "https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/LICENSE", + "evidence_quote": "This work is licensed under the Creative Commons Attribution 4.0 International License.", + "licence": "CC-BY-4.0", + "attribution": "buildingSMART International, Sample-Test-Files, https://github.com/buildingSMART/Sample-Test-Files, licensed CC BY 4.0. No changes.", + "fetched": "https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/IFC%204.3.2.0%20%28IFC%204.3%20ADD2%29/Simple-Scene/Building-Architecture.ifc", + "committed": false, + "bytes": 141965, + "sha256": "96e7103812b15b65eb1fd7802d36b9962833485dce5ead4f440bbf529530881d" + }, + { + "file": "bsi-wall-with-opening-and-window-ifc4.ifc", + "group": "3d", + "family": "ifc", + "title": "buildingSMART reference view: a wall with an opening and a window (IFC4)", + "features": "a wall with a material layer set, an opening element and a window with its type", + "author": "Peter Bonsma, RDF Ltd. (file header), distributed by buildingSMART International Ltd.", + "source": "https://github.com/buildingSMART/Sample-Test-Files", + "evidence": "https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/LICENSE", + "evidence_quote": "This work is licensed under the Creative Commons Attribution 4.0 International License.", + "licence": "CC-BY-4.0", + "attribution": "buildingSMART International, Sample-Test-Files, https://github.com/buildingSMART/Sample-Test-Files, licensed CC BY 4.0. No changes.", + "fetched": "https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/IFC%204.0.2.1%20%28IFC%204%20ADD2%20TC1%29/ISO%20Spec%20-%20ReferenceView_V1.2/wall-with-opening-and-window.ifc", + "committed": false, + "bytes": 12492, + "sha256": "73b0e45d931d5dc13bfee5fdc7bd80f796526445458b2de74c4168d209097832" + }, + { + "file": "duplex-apartment-ifc2x3.ifc", + "group": "3d", + "family": "ifc", + "title": "Duplex Apartment (IFC2X3, Revit export)", + "features": "four storeys: 57 walls, 24 windows, 14 doors, 2 stairs, 21 spaces, furniture, 18 materials", + "author": "Provided to the US Army Construction Engineering Research Laboratory, republished by buildingSMART International", + "source": "https://github.com/buildingsmart-community/Community-Sample-Test-Files/tree/7ddf57a201f88a0c213d5322b02ed15e94a60a40/IFC%202.3.0.1%20(IFC%202x3)/Duplex%20Apartment", + "evidence": "https://raw.githubusercontent.com/buildingsmart-community/Community-Sample-Test-Files/7ddf57a201f88a0c213d5322b02ed15e94a60a40/IFC%202.3.0.1%20%28IFC%202x3%29/Duplex%20Apartment/README.md", + "evidence_quote": "Creative Commons (CC BY 4.0). You are free (1) to copy and resitribute this material any way you like", + "licence": "CC-BY-4.0", + "attribution": "BSI (2020) Duplex Apartment Test Files, buildingSMART International, https://github.com/buildingsmart-community/Community-Sample-Test-Files, CC BY 4.0. No changes.", + "fetched": "https://media.githubusercontent.com/media/buildingsmart-community/Community-Sample-Test-Files/7ddf57a201f88a0c213d5322b02ed15e94a60a40/IFC%202.3.0.1%20%28IFC%202x3%29/Duplex%20Apartment/Duplex_A_20110907.ifc", + "committed": false, + "bytes": 2380763, + "sha256": "b347a2c8aa8fff6db896a4417a9c50c22ac0ccd7c5cfc22b99b8d29336c606ed" + }, + { + "file": "barraca-valenciana-ifc4.ifc", + "group": "3d", + "family": "ifc", + "title": "Barraca Valenciana de Llauradors, BIM model (IFC4, Revit export)", + "features": "a traditional farmhouse: 2 storeys, 16 walls, 5 slabs, 2 roofs, a stair, 27 beams, 28 materials", + "author": "Ã’scar Selfa", + "source": "https://zenodo.org/records/14293897", + "evidence": "https://zenodo.org/records/14293897", + "evidence_quote": "Creative Commons Attribution 4.0 International", + "licence": "CC-BY-4.0", + "attribution": "Ã’scar Selfa, Barraca Valenciana de Llauradors: Model BIM i Estudi de la Tipologia Arquitectònica, Zenodo, doi:10.5281/zenodo.14293897, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/records/14293897/files/BRC-OSP-XXX-ZZZ-M3D-ARQ-0001-tipologiaGen%C3%A8rica-S3-0001.ifc?download=1", + "committed": false, + "bytes": 1584183, + "sha256": "b6f8828e9bd2491dc452b2ab78f9f9e28f39bd81a5f2f4e2cdb2d81668287193" + }, + { + "file": "office-archetype-1970-ifc4x3.ifc", + "group": "3d", + "family": "ifc", + "title": "Office archetype of 1970 (IFC4X3_ADD2)", + "features": "four storeys: 88 walls, 167 windows, 49 doors, 16 curtain walls, 48 spaces", + "author": "Verena Dannapfel, Moritz Müller, Rita Streblow, Dirk Müller et al., RWTH Aachen University", + "source": "https://zenodo.org/records/21820756", + "evidence": "https://zenodo.org/records/21820756", + "evidence_quote": "Creative Commons Attribution 4.0 International", + "licence": "CC-BY-4.0", + "attribution": "Dannapfel, V., Müller, M., Streblow, R., Müller, D. et al., Archetypes for German Office Buildings of Construction Years 1970, 1998 and 2026, Zenodo, doi:10.5281/zenodo.21820756, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/records/21820756/files/2026-07_Klassiqua_Office_Archetype_Construction_Year_1970.ifc?download=1", + "committed": false, + "bytes": 1471699, + "sha256": "a5f12304d33fe5da9174c8ea9827d2f322706646b3da2766dff0ab278c65df3c" + }, + { + "file": "fox.glb", + "group": "3d", + "family": "glb", + "title": "Fox, skinned and animated (GLB)", + "features": "a low-poly fox with a skin, three animations and a texture", + "author": "PixelMannen (model, CC0), tomkranis (rigging and animation, CC BY 4.0), glTF conversion by Asobo Studio and the Khronos Group", + "source": "https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/Fox", + "evidence": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/Fox/README.md", + "evidence_quote": "© 2014, tomkranis. [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/legalcode)", + "licence": "CC-BY-4.0", + "attribution": "Fox: model by PixelMannen (CC0, https://opengameart.org/content/fox-and-shiba), rigging and animation by tomkranis (CC BY 4.0, https://sketchfab.com/3d-models/low-poly-fox-by-pixelmannen-animated-371dea88d7e04a76af5763f2a36866bc), glTF conversion by Asobo Studio and the Khronos Group. Unmodified.", + "fetched": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/Fox/glTF-Binary/Fox.glb", + "committed": false, + "bytes": 162852, + "sha256": "d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7" + }, + { + "file": "riggedfigure.gltf", + "group": "3d", + "family": "gltf", + "title": "Rigged Figure (glTF with an embedded buffer)", + "features": "a skinned figure, a data URI buffer", + "author": "Cesium", + "source": "https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/RiggedFigure", + "evidence": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/RiggedFigure/README.md", + "evidence_quote": "© 2017, Cesium. [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/legalcode)", + "licence": "CC-BY-4.0", + "attribution": "Rigged Figure by Cesium, CC BY 4.0, https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main/Models/RiggedFigure. Unmodified.", + "fetched": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/RiggedFigure/glTF-Embedded/RiggedFigure.gltf", + "committed": false, + "bytes": 99902, + "sha256": "354572cfef17b136b437ac9749da0fa316fd6e42ee7d62fe50a696b25f5047e9" + }, + { + "file": "vertexcolortest.glb", + "group": "3d", + "family": "glb", + "title": "Vertex Color Test (GLB)", + "features": "COLOR_0 vertex colours, tangents, two textures", + "author": "Ed Mackey, Analytical Graphics, Inc. (Cesium)", + "source": "https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/VertexColorTest", + "evidence": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/VertexColorTest/README.md", + "evidence_quote": "© 2018, Analytical Graphics, Inc.. [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/legalcode)", + "licence": "CC-BY-4.0", + "attribution": "Vertex Color Test by Ed Mackey, Copyright 2018 Analytical Graphics, Inc., CC BY 4.0, https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main/Models/VertexColorTest. Unmodified.", + "fetched": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/VertexColorTest/glTF-Binary/VertexColorTest.glb", + "committed": false, + "bytes": 26220, + "sha256": "58006bdcff8084339da0f6e24400160890638c16dbcb83c362ccaf150e8c6e10" + }, + { + "file": "metalroughspheres.glb", + "group": "3d", + "family": "glb", + "title": "Metal-Rough spheres (GLB)", + "features": "119 nodes and 98 materials of growing metalness and roughness", + "author": "Krill Gavrilov / Draw Harness script (Open CASCADE Technology)", + "source": "https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/MetalRoughSpheresNoTextures", + "evidence": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/MetalRoughSpheresNoTextures/README.md", + "evidence_quote": "© 2019, Public. [Creative Commons Zero v1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/legalcode)", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/MetalRoughSpheresNoTextures/glTF-Binary/MetalRoughSpheresNoTextures.glb", + "committed": false, + "bytes": 291316, + "sha256": "5e677f260ec0f366967a6e9545de2f3dab2a160e307b9bcb9d050cd2028f63f8" + }, + { + "file": "iridescencesuzanne.glb", + "group": "3d", + "family": "glb", + "title": "Iridescence Suzanne (GLB)", + "features": "Suzanne with the iridescence, transmission and volume extensions", + "author": "Mathias Kanzler (UX3D), Pascal Schoen", + "source": "https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/IridescenceSuzanne", + "evidence": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/IridescenceSuzanne/README.md", + "evidence_quote": "© 2022, UX3D. [Creative Commons Zero v1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/legalcode)", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/IridescenceSuzanne/glTF-Binary/IridescenceSuzanne.glb", + "committed": false, + "bytes": 507608, + "sha256": "866762602d60a0942b7608bfabf4e8686a29033636224f4b55c5e56abe8abf8f" + }, + { + "file": "ratchet-cam.stl", + "group": "3d", + "family": "stl", + "title": "Apollo 11 hatch, stationary ratchet cam (binary STL)", + "features": "1536 triangles, a mechanical part", + "author": "NASA Johnson Space Center, transferred to the Smithsonian Institution; model published on Wikimedia Commons", + "source": "https://commons.wikimedia.org/wiki/File:Stationary_Ratchet_Cam_v11_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl", + "evidence": "https://commons.wikimedia.org/wiki/File:Stationary_Ratchet_Cam_v11_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl", + "evidence_quote": "CC0 1.0 Universal Public Domain Dedication", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://upload.wikimedia.org/wikipedia/commons/e/e0/Stationary_Ratchet_Cam_v11_%28Hatch%2C_Crew%2C_Apollo_11_by_NASA_and_Smithsonian_Institution%29.stl", + "committed": false, + "bytes": 76884, + "sha256": "b42d79fb357413b118b973f3fa40b76ae2999451537cd991bebce18b486c581f" + }, + { + "file": "ratchet-spur-gear.stl", + "group": "3d", + "family": "stl", + "title": "Apollo 11 hatch, stationary ratchet spur gear (binary STL)", + "features": "3026 triangles, a gear with 19 teeth", + "author": "NASA Johnson Space Center, transferred to the Smithsonian Institution; model published on Wikimedia Commons", + "source": "https://commons.wikimedia.org/wiki/File:N=19,_P=28_-_Stat._Ratchet_Spur_Gear_v13_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl", + "evidence": "https://commons.wikimedia.org/wiki/File:N=19,_P=28_-_Stat._Ratchet_Spur_Gear_v13_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl", + "evidence_quote": "CC0 1.0 Universal Public Domain Dedication", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://upload.wikimedia.org/wikipedia/commons/c/cb/N%3D19%2C_P%3D28_-_Stat._Ratchet_Spur_Gear_v13_%28Hatch%2C_Crew%2C_Apollo_11_by_NASA_and_Smithsonian_Institution%29.stl", + "committed": false, + "bytes": 151384, + "sha256": "c99eca56ab40ed6b2e9dfc49b88c23c6fbef982ff18813ba593d3e138ef1f51d" + }, + { + "file": "petri-dish-holder-base.stl", + "group": "3d", + "family": "stl", + "title": "Petri dish holder base of a spore capture device (ASCII STL)", + "features": "566 facets as text", + "author": "Kevin A. Adkins, Kaiyu Li, M. N. Blasko, J. L. Cabrera, B. H. Neal, James et al.", + "source": "https://zenodo.org/records/12193898", + "evidence": "https://zenodo.org/api/records/12193898", + "evidence_quote": "\"license\": {\"id\": \"cc-by-4.0\"}", + "licence": "CC-BY-4.0", + "attribution": "Components of the spore capture device in A simple mechanism for uncrewed aircraft bioaerosol sampling in the lower atmosphere (Inspire1Petri_Dish_Holder_Base.stl), Kevin A. Adkins et al., Zenodo 2024, doi:10.5281/zenodo.12193898, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/api/records/12193898/files/Inspire1Petri_Dish_Holder_Base.stl/content", + "committed": false, + "bytes": 151270, + "sha256": "d654bf60064e79675acd9694726282c70251905d77391ad45c29d3ba3ecaf93e" + }, + { + "file": "chickpea-mesh.ply", + "group": "3d", + "family": "ply", + "title": "Photogrammetric mesh of a chickpea plant (binary PLY with colours)", + "features": "8788 triangles, RGBA per vertex", + "author": "William T. Salter, Arjina Shrestha, Margaret M. Barbour", + "source": "https://zenodo.org/records/4018242", + "evidence": "https://zenodo.org/api/records/4018242", + "evidence_quote": "\"license\": {\"id\": \"cc-by-4.0\"}", + "licence": "CC-BY-4.0", + "attribution": "3D photogrammetric reconstructions of individual chickpea plants (PBASlasher_S3s_Wk1_meshed.ply), William T. Salter, Arjina Shrestha and Margaret M. Barbour, Zenodo 2020, doi:10.5281/zenodo.4018242, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/api/records/4018242/files/PBASlasher_S3s_Wk1_meshed.ply/content", + "committed": false, + "bytes": 202701, + "sha256": "ef9cd2141897781c8e3e6a72ac316056b991d4d0fae99e053c4695fceea8cb75" + }, + { + "file": "ruthwell-lamb-of-god.ply", + "group": "3d", + "family": "ply", + "title": "Lamb of God panel of the Ruthwell Cross (binary PLY with normals and colours)", + "features": "33020 triangles, a scanned stone carving", + "author": "Gurpreet Singh", + "source": "https://zenodo.org/records/3348342", + "evidence": "https://zenodo.org/api/records/3348342", + "evidence_quote": "\"license\": {\"id\": \"cc-by-4.0\"}", + "licence": "CC-BY-4.0", + "attribution": "Small Panel PLY (Lamb of God panel from the Ruthwell Cross), Gurpreet Singh, Zenodo 2019, doi:10.5281/zenodo.3348342, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/api/records/3348342/files/Small_Lamb_Of_God_North_Ruthwell_Cross.ply/content", + "committed": false, + "bytes": 893893, + "sha256": "0d40a4305885932596afce091891a8f4b212b0c012b742db10d4487351c2457a" + }, + { + "file": "chickpea-pointcloud-ascii.ply", + "group": "unsupported", + "family": "ply", + "title": "Point cloud of a chickpea plant (ASCII PLY without faces)", + "features": "53195 coloured points and no faces: kept to show what the viewer says about a point cloud", + "author": "William T. Salter, Arjina Shrestha, Margaret M. Barbour", + "source": "https://zenodo.org/records/4018242", + "evidence": "https://zenodo.org/api/records/4018242", + "evidence_quote": "\"license\": {\"id\": \"cc-by-4.0\"}", + "licence": "CC-BY-4.0", + "attribution": "3D photogrammetric reconstructions of individual chickpea plants (SonSla_3_groundtruth_pointcloud.ply), William T. Salter, Arjina Shrestha and Margaret M. Barbour, Zenodo 2020, doi:10.5281/zenodo.4018242, CC BY 4.0. No changes.", + "fetched": "https://zenodo.org/api/records/4018242/files/SonSla_3_groundtruth_pointcloud.ply/content", + "committed": false, + "bytes": 3455582, + "sha256": "53a08f6e1c831ac58c42342ee257c97730bcf6997e246c88198478f9aeba4fe0" + }, + { + "file": "arxiv-rational-cherednik-torus-knots.pdf", + "group": "pdf", + "family": "pdf", + "title": "Rational Cherednik Algebras and Torus Knot Invariants (arXiv:2402.18770)", + "features": "28 pages of mathematics, 24 outline entries, 256 links, set in LaTeX", + "author": "Xinchun Ma", + "source": "https://arxiv.org/abs/2402.18770v1", + "evidence": "https://arxiv.org/abs/2402.18770v1", + "evidence_quote": "href=\"http://creativecommons.org/licenses/by/4.0/\" title=\"Rights to this article\"", + "licence": "CC-BY-4.0", + "attribution": "Xinchun Ma, Rational Cherednik Algebras and Torus Knot Invariants, arXiv:2402.18770v1, CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Not modified.", + "fetched": "https://arxiv.org/pdf/2402.18770v1", + "committed": false, + "bytes": 430745, + "sha256": "2b22841d8a64b271d7def6fa15aa0b5b98f533ae259e4108eb7104320f07cf10" + }, + { + "file": "nist-sp-800-63-4-digital-identity.pdf", + "group": "pdf", + "family": "pdf", + "title": "NIST SP 800-63-4, Digital Identity Guidelines", + "features": "96 tagged pages, 54 outline entries, 227 links", + "author": "David Temoshok, Diana Proud-Madruga, Yee-Yin Choong et al., NIST", + "source": "https://csrc.nist.gov/pubs/sp/800/63/4/final", + "evidence": "https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-63-4.pdf", + "evidence_quote": "is not subject to copyright in the United States.", + "licence": "public-domain (US federal government work, 17 U.S.C. 105; the PDF says so itself)", + "attribution": "", + "fetched": "https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-63-4.pdf", + "committed": false, + "bytes": 858054, + "sha256": "2f5b107de218a0fc3fe7f7e91b2ece5babb001eda5745b7c568a3cc876002f2d" + }, + { + "file": "scan-cfa-minutes-1971.pdf", + "group": "pdf", + "family": "pdf-scan", + "title": "Minutes of the U.S. Commission of Fine Arts, 1970 to 1972 (scan)", + "features": "40 scanned pages: JPEG 2000 pictures and JBIG2 masks, an OCR text layer, PDF/A-2B", + "author": "U.S. Commission of Fine Arts; scanned by the Internet Archive", + "source": "https://archive.org/details/cfaminutes21april1971", + "evidence": "https://commons.wikimedia.org/wiki/File:July_8_1970_to_May_19_1972_(IA_cfaminutes21april1971).pdf", + "evidence_quote": "This work is in the public domain in the United States because it is a work prepared by an officer o", + "licence": "public-domain (US federal government work, 17 U.S.C. 105)", + "attribution": "", + "fetched": "https://archive.org/download/cfaminutes21april1971/cfaminutes21april1971.pdf", + "committed": false, + "bytes": 1104628, + "sha256": "2fc5edb8a4f303b89449443dcb5a32249c79b2a8d67253348025d0e7eea5f94b" + }, + { + "file": "scan-blm-land-survey-records.pdf", + "group": "pdf", + "family": "pdf-scan", + "title": "Land and survey records, Bureau of Land Management (scan)", + "features": "40 pages scanned at about 500 ppi: JPEG 2000 and JBIG2 images, an OCR text layer, PDF/A-2B", + "author": "United States Bureau of Land Management; scanned by the Internet Archive", + "source": "https://archive.org/details/landsurveyrecord00unit", + "evidence": "https://commons.wikimedia.org/wiki/File:Land_%26_survey_records_-_record_preservation_%26_service_through_microfilm_(IA_landsurveyrecord00unit).pdf", + "evidence_quote": "This work is in the public domain in the United States because it is a work prepared by an officer o", + "licence": "public-domain (US federal government work, 17 U.S.C. 105)", + "attribution": "", + "fetched": "https://archive.org/download/landsurveyrecord00unit/landsurveyrecord00unit.pdf", + "committed": false, + "bytes": 2192413, + "sha256": "d9a9e6583d0afb1688a043ef59a8d2e236e20c58d4ba76ff625d7c11a181c16c" + }, + { + "file": "form-uscis-i9.pdf", + "group": "pdf", + "family": "pdf-form", + "title": "USCIS Form I-9, Employment Eligibility Verification", + "features": "115 text fields, 5 drop-down lists, 8 check boxes, links; a tagged government form", + "author": "U.S. Citizenship and Immigration Services (DHS)", + "source": "https://www.uscis.gov/i-9", + "evidence": "https://www.uscis.gov/website-policies", + "evidence_quote": "Information presented on this WWW site is considered public information and may be distributed or co", + "licence": "public-domain (US federal government work, 17 U.S.C. 105)", + "attribution": "", + "fetched": "https://www.uscis.gov/sites/default/files/document/forms/i-9.pdf", + "committed": false, + "bytes": 524095, + "sha256": "780f348c34df694bb0b4dbbfaf9f22b99b9757b80d16a37ba89aadf069597281" + }, + { + "file": "map-nps-canyonlands.pdf", + "group": "pdf", + "family": "pdf-map", + "title": "Canyonlands National Park, Island in the Sky: roads and trails", + "features": "two tagged pages of vector map", + "author": "National Park Service", + "source": "https://home.nps.gov/cany/planyourvisit/maps.htm", + "evidence": "https://www.nps.gov/aboutus/disclaimer.htm", + "evidence_quote": "material created by the National Park Service and presented on this website, unless otherwise indica", + "licence": "public-domain (US federal government work, 17 U.S.C. 105)", + "attribution": "", + "fetched": "https://home.nps.gov/cany/planyourvisit/upload/IslandRoadsandTrailsUpdated24-508forweb.pdf", + "committed": false, + "bytes": 349001, + "sha256": "b29a639d9bc0d2e37ca41b68c21bcddba7637b1727dce86980c3373715610d55" + }, + { + "file": "slides-unige-open-access.pdf", + "group": "pdf", + "family": "pdf", + "title": "Open Access publishing at no cost thanks to UNIGE agreements (slides)", + "features": "ten slides with outline, links, tags and pictures", + "author": "Floriane Muller, Anouk Santos (University of Geneva)", + "source": "https://zenodo.org/records/23478694", + "evidence": "https://zenodo.org/records/23478694", + "evidence_quote": "Creative Commons Attribution 4.0 International", + "licence": "CC-BY-4.0", + "attribution": "Floriane Muller and Anouk Santos, Open Access publishing at no cost thanks to UNIGE agreements, in 15 minutes, Zenodo, https://doi.org/10.5281/zenodo.23478694, CC BY 4.0. Not modified.", + "fetched": "https://zenodo.org/api/records/23478694/files/2026-10-20_Read_and_publish_en15min_EN_zenodo.pdf/content", + "committed": false, + "bytes": 800339, + "sha256": "03356ed569a80f7d7dc1d96fcbfd75a2fbc663c63f6d74f4e89eb2390bb5ee64" + }, + { + "file": "paper-ja-labor-law.pdf", + "group": "pdf", + "family": "pdf", + "title": "A paper in Japanese on labour law and the constitution", + "features": "25 pages with embedded MS Mincho fonts", + "author": "Takashi Fujiki (藤木 è²´å�²)", + "source": "https://zenodo.org/records/23469422", + "evidence": "https://zenodo.org/records/23469422", + "evidence_quote": "Creative Commons Attribution 4.0 International", + "licence": "CC-BY-4.0", + "attribution": "藤木 è²´å�², アメリカ労åƒ�法ã�‹ã‚‰ã�¿ã�Ÿæ†²æ³•ã�®å½±éŸ¿, アメリカ憲法ã�®ç�†è«–ã�¨å®Ÿè·µ 創刊å�·, Zenodo, https://doi.org/10.5281/zenodo.23469422, CC BY 4.0. Not modified.", + "fetched": "https://zenodo.org/api/records/23469422/files/%E3%82%A2%E3%83%A1%E3%83%AA%E3%82%AB%E5%8A%B4%E5%83%8D%E6%B3%95%E3%81%8B%E3%82%89%E3%81%BF%E3%81%9F%E6%86%B2%E6%B3%95%E3%81%AE%E5%BD%B1%E9%9F%BF.pdf/content", + "committed": false, + "bytes": 881101, + "sha256": "08b2be3ebc781107f71003344ccf8b230229079e978687f1e0da2329bef1cbe9" + }, + { + "file": "monet-gardeners-house-antibes.jpg", + "group": "images", + "family": "jpeg", + "title": "Claude Monet, The Gardener's House at Antibes (1888)", + "features": "a painting, JPEG from the museum's web size", + "author": "Claude Monet, Cleveland Museum of Art (open access)", + "source": "https://clevelandart.org/art/1916.1044", + "evidence": "https://clevelandart.org/art/1916.1044", + "evidence_quote": "\"share_license_status\":\"CC0\"", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://openaccess-cdn.clevelandart.org/1916.1044/1916.1044_web.jpg", + "committed": false, + "bytes": 404254, + "sha256": "95142eba48d54f01352eb4ef6f04260cb3df3bcb1d9c86000c1284a7817674ca" + }, + { + "file": "queen-mab-cave.jpg", + "group": "images", + "family": "jpeg", + "title": "Queen Mab's Cave, in the manner of Turner", + "features": "a painting", + "author": "Imitator of J. M. W. Turner, Cleveland Museum of Art (open access)", + "source": "https://clevelandart.org/art/1916.1036", + "evidence": "https://clevelandart.org/art/1916.1036", + "evidence_quote": "\"share_license_status\":\"CC0\"", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://openaccess-cdn.clevelandart.org/1916.1036/1916.1036_web.jpg", + "committed": false, + "bytes": 218321, + "sha256": "b84e005332288229d808172a7610b501d9977c0b4668e333faea5ff780157223" + }, + { + "file": "rembrandt-st-francis.jpg", + "group": "images", + "family": "jpeg", + "title": "Rembrandt, Saint Francis Beneath a Tree Praying (etching)", + "features": "an etching, fine line work", + "author": "Rembrandt van Rijn, Cleveland Museum of Art (open access)", + "source": "https://clevelandart.org/art/2024.64", + "evidence": "https://clevelandart.org/art/2024.64", + "evidence_quote": "\"share_license_status\":\"CC0\"", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://openaccess-cdn.clevelandart.org/2024.64/2024.64_web.jpg", + "committed": false, + "bytes": 370411, + "sha256": "74b37aa3738914dd66c07533b3758f7694fefbaa918d2f23c263205cf987db7b" + }, + { + "file": "nolli-rome-plate.jpg", + "group": "images", + "family": "jpeg", + "title": "Nolli's map of Rome (1748), a plate", + "features": "an engraved city plan", + "author": "Giovanni Battista Nolli et al., Cleveland Museum of Art (open access)", + "source": "https://clevelandart.org/art/2020.276.3", + "evidence": "https://clevelandart.org/art/2020.276.3", + "evidence_quote": "\"share_license_status\":\"CC0\"", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://openaccess-cdn.clevelandart.org/2020.276.3/2020.276.3_web.jpg", + "committed": false, + "bytes": 322943, + "sha256": "7643c9e59f7706ebe62518a51daf7d72129acc8092dde7afc65516d3d11b6c77" + }, + { + "file": "pallid-swift.jpg", + "group": "images", + "family": "jpeg", + "title": "Pallid swift in flight (photograph)", + "features": "a camera JPEG with EXIF data (Canon EOS R6 Mark II)", + "author": "Hobbyfotowiki", + "source": "https://commons.wikimedia.org/wiki/File:Pallid_swift_(in_flight).jpg", + "evidence": "https://commons.wikimedia.org/wiki/File:Pallid_swift_(in_flight).jpg", + "evidence_quote": "This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Dedication.", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://upload.wikimedia.org/wikipedia/commons/d/df/Pallid_swift_%28in_flight%29.jpg", + "committed": false, + "bytes": 356572, + "sha256": "9d0f79f12dcc236f549cdefb66dc468f25335d444ebd26e98805efdd94afecbd" + }, + { + "file": "cyclotron-patent.png", + "group": "images", + "family": "png", + "title": "Drawing from Lawrence's cyclotron patent", + "features": "a black and white technical drawing", + "author": "Ernest O. Lawrence (US Patent Office)", + "source": "https://commons.wikimedia.org/wiki/File:Cyclotron_patent_p1.png", + "evidence": "https://commons.wikimedia.org/wiki/File:Cyclotron_patent_p1.png", + "evidence_quote": "The text and illustrations of US patents published before March 1, 1989 are in the public domain unl", + "licence": "public-domain (US patent text and drawings published before 1989)", + "attribution": "", + "fetched": "https://upload.wikimedia.org/wikipedia/commons/4/42/Cyclotron_patent_p1.png", + "committed": false, + "bytes": 207304, + "sha256": "0be9b59ae21bbadeb8a13fafde5e0bcfb6d470ba516244eab0ec1c74afd7394f" + }, + { + "file": "mature-flower-diagram.svg", + "group": "images", + "family": "svg", + "title": "Diagram of a mature flower", + "features": "85 texts, about 90 gradient references, many paths", + "author": "Mariana Ruiz Villarreal (LadyofHats)", + "source": "https://commons.wikimedia.org/wiki/File:Mature_flower_diagram.svg", + "evidence": "https://commons.wikimedia.org/wiki/File:Mature_flower_diagram.svg", + "evidence_quote": "This work has been released into the public domain by its author, LadyofHats.", + "licence": "public-domain (released by its author)", + "attribution": "", + "fetched": "https://upload.wikimedia.org/wikipedia/commons/7/7f/Mature_flower_diagram.svg", + "committed": false, + "bytes": 123527, + "sha256": "b40bd4e188c0a99e51e994b4f39f931d3fca28093ecb6454aa2bd93c575ea999" + }, + { + "file": "entamoeba-life-cycle.svg", + "group": "images", + "family": "svg", + "title": "Life cycle of Entamoeba histolytica", + "features": "547 paths, text and arrows", + "author": "Mariana Ruiz Villarreal (LadyofHats)", + "source": "https://commons.wikimedia.org/wiki/File:Entamoeba_histolytica_life_cycle-en.svg", + "evidence": "https://commons.wikimedia.org/wiki/File:Entamoeba_histolytica_life_cycle-en.svg", + "evidence_quote": "This work has been released into the public domain by its author, LadyofHats.", + "licence": "public-domain (released by its author)", + "attribution": "", + "fetched": "https://upload.wikimedia.org/wikipedia/commons/a/a1/Entamoeba_histolytica_life_cycle-en.svg", + "committed": false, + "bytes": 273234, + "sha256": "68a4a92289d81f0e7e9361abbba2da9a8c8b4e440e3ad9de5c420646eb133eaa" + }, + { + "file": "sieve-of-eratosthenes.svg", + "group": "images", + "family": "svg", + "title": "Sieve of Eratosthenes, animated", + "features": "SMIL animation with 179 animate elements", + "author": "Ricordisamoa, with later edits by Jc86035, HereToHelp and Glrx", + "source": "https://commons.wikimedia.org/wiki/File:Sieve_of_Eratosthenes_animation.svg", + "evidence": "https://commons.wikimedia.org/wiki/File:Sieve_of_Eratosthenes_animation.svg", + "evidence_quote": "This work is ineligible for copyright and therefore in the public domain because it consists entirel", + "licence": "public-domain (ineligible for copyright, Wikimedia Commons PD-ineligible)", + "attribution": "", + "fetched": "https://upload.wikimedia.org/wikipedia/commons/0/0b/Sieve_of_Eratosthenes_animation.svg", + "committed": false, + "bytes": 22054, + "sha256": "d8f1d6d0a4b5710ebe1e7766eab30b766b10dc9380c1058ccb39baccd7d51586" + }, + { + "file": "muybridge-horse.gif", + "group": "images", + "family": "gif", + "title": "Muybridge's horse in motion, animated GIF", + "features": "15 frames", + "author": "Eadweard Muybridge (photographs, 1887); animation by Waugsberg", + "source": "https://commons.wikimedia.org/wiki/File:Muybridge_race_horse_animated.gif", + "evidence": "https://commons.wikimedia.org/wiki/File:Muybridge_race_horse_animated.gif", + "evidence_quote": "The author died in 1904, so this work is in the public domain in its country of origin and other cou", + "licence": "public-domain (the author died in 1904)", + "attribution": "", + "fetched": "https://upload.wikimedia.org/wikipedia/commons/d/dd/Muybridge_race_horse_animated.gif", + "committed": false, + "bytes": 568203, + "sha256": "eb40bebc1f039e7c2a121673c3b55d4aa73582f858053dbbcca9ebce9e2b479d" + }, + { + "file": "geneva-mechanism.gif", + "group": "images", + "family": "gif", + "title": "Geneva mechanism with six spokes, animated GIF", + "features": "101 frames", + "author": "Mike1024", + "source": "https://commons.wikimedia.org/wiki/File:Geneva_mechanism_6spoke_animation.gif", + "evidence": "https://commons.wikimedia.org/wiki/File:Geneva_mechanism_6spoke_animation.gif", + "evidence_quote": "I, the copyright holder of this work, release this work into the public domain.", + "licence": "public-domain (released by its author)", + "attribution": "", + "fetched": "https://upload.wikimedia.org/wikipedia/commons/9/9b/Geneva_mechanism_6spoke_animation.gif", + "committed": false, + "bytes": 229346, + "sha256": "d7df5c9984109c2ca60f7aab1a51db1f0b578cddcdede5d43be9f67536e2a1ee" + }, + { + "file": "abundance-nemo-g4-6pages.tif", + "group": "images", + "family": "tiff-fax", + "title": "Les grans et merveilleux faictz du seigneur Nemo (scan, six pages, CCITT Group 4)", + "features": "a multi-page bilevel TIFF scanned from a 16th-century book", + "author": "Jean d'Abundance (16th century); scanned by the Bibliothèque nationale de France", + "source": "https://commons.wikimedia.org/wiki/File:Abundance_-_Les_grans_et_merveilleux_faictz_du_seigneur_Nemo%2C_avec_les_privil%C3%A8ges_qu%E2%80%99il_a.tif", + "evidence": "https://commons.wikimedia.org/wiki/File:Abundance_-_Les_grans_et_merveilleux_faictz_du_seigneur_Nemo%2C_avec_les_privil%C3%A8ges_qu%E2%80%99il_a.tif", + "evidence_quote": "This file is in the public domain because it is a mere mechanical scan or photocopy of a public doma", + "licence": "public-domain (a mechanical scan of a public domain book, Wikimedia Commons PD-scan)", + "attribution": "", + "fetched": "https://upload.wikimedia.org/wikipedia/commons/b/b5/Abundance_-_Les_grans_et_merveilleux_faictz_du_seigneur_Nemo%2C_avec_les_privil%C3%A8ges_qu%E2%80%99il_a.tif", + "committed": false, + "bytes": 330420, + "sha256": "38bab27c6d559e11468d6c7e4222f0bb1bee4ba0044540adcebfc012930e00d1" + }, + { + "file": "docx4j-getting-started.docx", + "group": "office", + "family": "docx", + "title": "docx4j Getting Started (Word)", + "features": "a manual with styles, tables, pictures and links", + "author": "Jason Harrop and the docx4j contributors", + "source": "https://github.com/plutext/docx4j/blob/c95b55be6832ff716131ffdbd7006755db92f696/docs/Docx4j_GettingStarted.docx", + "evidence": "https://raw.githubusercontent.com/plutext/docx4j/c95b55be6832ff716131ffdbd7006755db92f696/legals/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "docx4j, Jason Harrop / Plutext, https://github.com/plutext/docx4j, Apache-2.0. No changes.", + "fetched": "https://raw.githubusercontent.com/plutext/docx4j/c95b55be6832ff716131ffdbd7006755db92f696/docs/Docx4j_GettingStarted.docx", + "committed": false, + "bytes": 156287, + "sha256": "a518cffcbef0b60cf5c95930acd9af9a56484e47376c5f0c4d6e3a15a0799941" + }, + { + "file": "docx4j-two-charts.docx", + "group": "office", + "family": "docx", + "title": "docx4j chart test: two charts (Word)", + "features": "two native charts in a document", + "author": "Jason Harrop and the docx4j contributors", + "source": "https://github.com/plutext/docx4j/blob/c95b55be6832ff716131ffdbd7006755db92f696/docx4j-chart-render/src/test/resources/charts/render/office/p3-two-charts.docx", + "evidence": "https://raw.githubusercontent.com/plutext/docx4j/c95b55be6832ff716131ffdbd7006755db92f696/legals/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "docx4j, Jason Harrop / Plutext, https://github.com/plutext/docx4j, Apache-2.0. No changes.", + "fetched": "https://raw.githubusercontent.com/plutext/docx4j/c95b55be6832ff716131ffdbd7006755db92f696/docx4j-chart-render/src/test/resources/charts/render/office/p3-two-charts.docx", + "committed": false, + "bytes": 41590, + "sha256": "e0bc29916de415c53c03dcee14817bbd1e3eeea8f54a2b76629fe6754e6c641e" + }, + { + "file": "gsa-policy-review-template.xlsx", + "group": "office", + "family": "xlsx", + "title": "Section508.gov Policy Review Template (Excel)", + "features": "a government workbook with formatted tables", + "author": "U.S. General Services Administration and the agencies that wrote the documents (Section508.gov)", + "source": "https://github.com/GSA/Assets.Section508.gov/blob/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Policy%20Review%20Template.xlsx", + "evidence": "https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/LICENSE.md", + "evidence_quote": "this project is in the public domain within the United States of America. Additionally, we waive copyright and", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Policy%20Review%20Template.xlsx", + "committed": false, + "bytes": 222164, + "sha256": "840661eba4653879dca24f209bca1619f7b168ef1232b595df5713741b2465bd" + }, + { + "file": "closedxml-pivot-tables.xlsx", + "group": "office", + "family": "xlsx", + "title": "ClosedXML example: pivot tables (Excel)", + "features": "pivot tables over a data sheet", + "author": "ClosedXML contributors", + "source": "https://github.com/ClosedXML/ClosedXML/blob/09f2f21a60e821ce7fb18ca3576b272e5dd6d921/ClosedXML.Tests/Resource/Examples/PivotTables/PivotTables.xlsx", + "evidence": "https://raw.githubusercontent.com/ClosedXML/ClosedXML/09f2f21a60e821ce7fb18ca3576b272e5dd6d921/LICENSE", + "evidence_quote": "MIT License Copyright (c) 2016 ClosedXML", + "licence": "MIT", + "attribution": "Copyright (c) 2016 ClosedXML, MIT, https://github.com/ClosedXML/ClosedXML. No changes.", + "fetched": "https://raw.githubusercontent.com/ClosedXML/ClosedXML/09f2f21a60e821ce7fb18ca3576b272e5dd6d921/ClosedXML.Tests/Resource/Examples/PivotTables/PivotTables.xlsx", + "committed": false, + "bytes": 30912, + "sha256": "d13f149091c804cfe9b02c81301ea7ce13d20d1f3311cac799151541d0467d02" + }, + { + "file": "xlsxwriter-bar-chart.xlsx", + "group": "office", + "family": "xlsx", + "title": "XlsxWriter test file: a bar chart (Excel)", + "features": "a native bar chart saved in Excel", + "author": "John McNamara (XlsxWriter)", + "source": "https://github.com/jmcnamara/XlsxWriter/blob/5d4606d89a955226d2d0825a0f44309043ae7251/xlsxwriter/test/comparison/xlsx_files/chart_bar14.xlsx", + "evidence": "https://raw.githubusercontent.com/jmcnamara/XlsxWriter/5d4606d89a955226d2d0825a0f44309043ae7251/LICENSE.txt", + "evidence_quote": "BSD 2-Clause License Copyright (c) 2013-2025, John McNamara", + "licence": "BSD-2-Clause", + "attribution": "Copyright (c) 2013-2025, John McNamara, BSD-2-Clause, https://github.com/jmcnamara/XlsxWriter. No changes.", + "fetched": "https://raw.githubusercontent.com/jmcnamara/XlsxWriter/5d4606d89a955226d2d0825a0f44309043ae7251/xlsxwriter/test/comparison/xlsx_files/chart_bar14.xlsx", + "committed": false, + "bytes": 13879, + "sha256": "c4ed1e8117b4a0e014b95f42361c7e060728b398d4ea650395d902557429cdd2" + }, + { + "file": "python-pptx-chart-types.pptx", + "group": "office", + "family": "pptx", + "title": "python-pptx test file: one slide for each chart type (PowerPoint)", + "features": "many native chart types", + "author": "Steve Canny (python-pptx)", + "source": "https://github.com/scanny/python-pptx/blob/278b47b1dedd5b46ee84c286e77cdfb0bf4594be/features/steps/test_files/cht-chart-type.pptx", + "evidence": "https://raw.githubusercontent.com/scanny/python-pptx/278b47b1dedd5b46ee84c286e77cdfb0bf4594be/LICENSE", + "evidence_quote": "The MIT License (MIT) Copyright (c) 2013 Steve Canny", + "licence": "MIT", + "attribution": "Copyright (c) 2013 Steve Canny, MIT, https://github.com/scanny/python-pptx. No changes.", + "fetched": "https://raw.githubusercontent.com/scanny/python-pptx/278b47b1dedd5b46ee84c286e77cdfb0bf4594be/features/steps/test_files/cht-chart-type.pptx", + "committed": false, + "bytes": 1393564, + "sha256": "d0a7979d05970aa83fd8406f0829cd0019853a7bc4e16f8cda814586fc2eaccc" + }, + { + "file": "cdc-lifecycle-508.pptx", + "group": "office", + "family": "pptx", + "title": "Integrating Section 508 Requirements in the Development Lifecycle (PowerPoint)", + "features": "a government deck with pictures and diagrams", + "author": "Mark D. Urban, CDC Section 508 Coordinator (US federal government)", + "source": "https://github.com/GSA/Assets.Section508.gov/blob/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Integrating%20Section%20508%20Requirements%20in%20the%20Development%20Lifecycle.pptx", + "evidence": "https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/LICENSE.md", + "evidence_quote": "this project is in the public domain within the United States of America. Additionally, we waive copyright and", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Integrating%20Section%20508%20Requirements%20in%20the%20Development%20Lifecycle.pptx", + "committed": false, + "bytes": 611924, + "sha256": "51c7d6af2e6682e5ee66204b813a45488e62b0e6e13cecc9207a982fdeb1720a" + }, + { + "file": "poi-sample.doc", + "group": "converted", + "family": "doc", + "title": "Apache POI test document (Word 97)", + "features": "a binary .doc", + "author": "Apache POI committers", + "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/SampleDoc.doc", + "evidence": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/SampleDoc.doc", + "committed": false, + "bytes": 27136, + "sha256": "717585c0a88f20862c86220163dd03da87cd743970354c6b29add32725f2e833" + }, + { + "file": "poi-word95.doc", + "group": "converted", + "family": "doc", + "title": "Apache POI test document (Word 6 and 95 format)", + "features": "the pre-1997 Word format", + "author": "Nick Burch (Apache POI)", + "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/Word95.doc", + "evidence": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/Word95.doc", + "committed": false, + "bytes": 102400, + "sha256": "a7b9557e917daf29cfee6baaa90226fbfa7900ffa05cc35bdc03aafdefef5789" + }, + { + "file": "dhs-directive-139-02.doc", + "group": "converted", + "family": "doc", + "title": "DHS Directive 139-02 (Word 97)", + "features": "a government directive in the binary .doc format", + "author": "U.S. Department of Homeland Security", + "source": "https://github.com/GSA/Assets.Section508.gov/blob/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Directive_139.2_Final_10-28-2008.doc", + "evidence": "https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/LICENSE.md", + "evidence_quote": "this project is in the public domain within the United States of America. Additionally, we waive copyright and", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Directive_139.2_Final_10-28-2008.doc", + "committed": false, + "bytes": 82432, + "sha256": "48d1c85456d6b515ce8e3db6b43024f90bac69be86a3e78c1ae08406d4cad493" + }, + { + "file": "poi-formula-eval.xls", + "group": "converted", + "family": "xls", + "title": "Apache POI test workbook of formulas (Excel 97)", + "features": "hundreds of formula cases", + "author": "Apache POI committers", + "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/FormulaEvalTestData.xls", + "evidence": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/FormulaEvalTestData.xls", + "committed": false, + "bytes": 178176, + "sha256": "c2040c1fac1088f1e112abef197ae1f9bcb03547861783b89c1d4281a42049d1" + }, + { + "file": "poi-conditional-formats.xls", + "group": "converted", + "family": "xls", + "title": "Apache POI test workbook of conditional formats (Excel 97)", + "features": "colour scales, icon sets and data bars", + "author": "Nick Burch (Apache POI)", + "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/NewStyleConditionalFormattings.xls", + "evidence": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/NewStyleConditionalFormattings.xls", + "committed": false, + "bytes": 44544, + "sha256": "899a29aa6ce35fee0268847ff8b5d9459e6ce34d5e2ff462fd42ee9b80837b87" + }, + { + "file": "poi-excel5.xls", + "group": "converted", + "family": "xls", + "title": "Apache POI test workbook (Excel 5 and 95 format)", + "features": "the BIFF5 format of 1993 to 1995", + "author": "Apache POI committers", + "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/testEXCEL_5.xls", + "evidence": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/testEXCEL_5.xls", + "committed": false, + "bytes": 7680, + "sha256": "ac0ce3a2eff43e32e56d6b789df6aaa1645ae846d22fa3a2fe3057391d0f1cae" + }, + { + "file": "poi-sample-show.ppt", + "group": "converted", + "family": "ppt", + "title": "Apache POI test presentation (PowerPoint 97)", + "features": "a binary .ppt", + "author": "Apache POI committers", + "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/slideshow/SampleShow.ppt", + "evidence": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/slideshow/SampleShow.ppt", + "committed": false, + "bytes": 125440, + "sha256": "64275a6685b8f267827178037dcc59de927475e56385725916f4c6039c7ce7f6" + }, + { + "file": "tika-rtf-various.rtf", + "group": "converted", + "family": "rtf", + "title": "Apache Tika test document: various RTF features", + "features": "fonts, colours, tables and lists in RTF", + "author": "Michael McCandless (Apache Tika)", + "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/resources/test-documents/testRTFVarious.rtf", + "evidence": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/resources/test-documents/testRTFVarious.rtf", + "committed": false, + "bytes": 65517, + "sha256": "cf00c56fe7099d14b820a0d751324e415f2c09af580f2c96f08614a2aec42c1e" + }, + { + "file": "tdf-thesis-template.odt", + "group": "converted", + "family": "odt", + "title": "Thesis template in Spanish (OpenDocument text)", + "features": "styles, a table of contents, headers", + "author": "Phorious (Document Foundation wiki user)", + "source": "https://wiki.documentfoundation.org/File:Tesis-v1.0.4.odt", + "evidence": "https://wiki.documentfoundation.org/File:Tesis-v1.0.4.odt", + "evidence_quote": "This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Ded", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://wiki.documentfoundation.org/images/5/54/Tesis-v1.0.4.odt", + "committed": false, + "bytes": 67249, + "sha256": "ec323e9fde67103a7f0039d8a59625bd7e2c5afa9e057563f5064c6b68d442a1" + }, + { + "file": "tika-odt-ooo3.odt", + "group": "converted", + "family": "odt", + "title": "Apache Tika test document written with OpenOffice 3 (OpenDocument text)", + "features": "an .odt of 2009", + "author": "Apache Tika committers", + "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/test/resources/test-documents/testODFwithOOo3.odt", + "evidence": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/test/resources/test-documents/testODFwithOOo3.odt", + "committed": false, + "bytes": 24286, + "sha256": "b6cd74b570a98fcb6d838dd85ab869604e0711812d9533d5ecde0000b24ba7ef" + }, + { + "file": "tdf-household-budget.ods", + "group": "converted", + "family": "ods", + "title": "Household budget book (OpenDocument spreadsheet)", + "features": "formulas, charts and several sheets", + "author": "Hrbrgr (Document Foundation wiki user)", + "source": "https://wiki.documentfoundation.org/File:Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods", + "evidence": "https://wiki.documentfoundation.org/File:Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods", + "evidence_quote": "This work is licensed under the Attribution 3.0 Unported License", + "licence": "CC-BY-3.0", + "attribution": "Hrbrgr (Document Foundation wiki user), Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods, https://wiki.documentfoundation.org/File:Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods, CC BY 3.0. No changes.", + "fetched": "https://wiki.documentfoundation.org/images/b/bc/Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods", + "committed": false, + "bytes": 21595, + "sha256": "aacd76666860f7bf879e1518a07b90d535815ce92d076ea26c835061b8aff854" + }, + { + "file": "odfdo-flat.fods", + "group": "converted", + "family": "fods", + "title": "odfdo test sample (flat OpenDocument spreadsheet)", + "features": "one XML file", + "author": "Jérôme Dumonteil (odfdo)", + "source": "https://github.com/jdum/odfdo/blob/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/test_flat_lo.fods", + "evidence": "https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Copyright Jérôme Dumonteil, odfdo, Apache-2.0, https://github.com/jdum/odfdo. No changes.", + "fetched": "https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/test_flat_lo.fods", + "committed": false, + "bytes": 33177, + "sha256": "4966023bf427dbc9c975dc9b11816b4a90158f7dab452c59104b8800fb27ec36" + }, + { + "file": "tdf-presentation-template.odp", + "group": "converted", + "family": "odp", + "title": "Presentation template (OpenDocument presentation)", + "features": "master slides, pictures and layouts", + "author": "Phorious (Document Foundation wiki user)", + "source": "https://wiki.documentfoundation.org/File:Presenta.odp", + "evidence": "https://wiki.documentfoundation.org/File:Presenta.odp", + "evidence_quote": "This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Ded", + "licence": "CC0-1.0", + "attribution": "", + "fetched": "https://wiki.documentfoundation.org/images/5/51/Presenta.odp", + "committed": false, + "bytes": 412768, + "sha256": "147ca9c6dbcdd45470627b84c04824c7f3e07de57485a8190018eea5f23c64b3" + }, + { + "file": "odfdo-example.odp", + "group": "converted", + "family": "odp", + "title": "odfdo test sample (OpenDocument presentation)", + "features": "slides with text and shapes", + "author": "Jérôme Dumonteil (odfdo)", + "source": "https://github.com/jdum/odfdo/blob/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/example.odp", + "evidence": "https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Copyright Jérôme Dumonteil, odfdo, Apache-2.0, https://github.com/jdum/odfdo. No changes.", + "fetched": "https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/example.odp", + "committed": false, + "bytes": 55687, + "sha256": "9075b87e36bb4618bdc9a8a6138bcaaf31b2b81e089e9006ac906e66a94f912b" + }, + { + "file": "tdf-diagram-gallery.odg", + "group": "converted", + "family": "odg", + "title": "A gallery of diagrams (OpenDocument drawing)", + "features": "several diagram types", + "author": "Hrbrgr (Document Foundation wiki user)", + "source": "https://wiki.documentfoundation.org/File:Diagramme.odg", + "evidence": "https://wiki.documentfoundation.org/File:Diagramme.odg", + "evidence_quote": "This work is licensed under the Attribution 3.0 Unported License", + "licence": "CC-BY-3.0", + "attribution": "Hrbrgr (Document Foundation wiki user), Diagramme.odg, https://wiki.documentfoundation.org/File:Diagramme.odg, CC BY 3.0. No changes.", + "fetched": "https://wiki.documentfoundation.org/images/0/07/Diagramme.odg", + "committed": false, + "bytes": 91383, + "sha256": "2e5f43734db7c600256e0670f6ec9da9428eb6b7a074c4742fd506e32c833a5a" + }, + { + "file": "odfdo-shapes.odg", + "group": "converted", + "family": "odg", + "title": "odfdo test sample: basic shapes (OpenDocument drawing)", + "features": "rectangles, ellipses, lines and polygons", + "author": "Jérôme Dumonteil (odfdo)", + "source": "https://github.com/jdum/odfdo/blob/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/base_shapes.odg", + "evidence": "https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Copyright Jérôme Dumonteil, odfdo, Apache-2.0, https://github.com/jdum/odfdo. No changes.", + "fetched": "https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/base_shapes.odg", + "committed": false, + "bytes": 10351, + "sha256": "dfe6a6c83ba5caec340889d6c77a899e420060d55f4b08fd9a1fb7b36e0b799f" + }, + { + "file": "tika-keynote09.key", + "group": "converted", + "family": "keynote", + "title": "Apache Tika test presentation (Keynote '09)", + "features": "an XML Keynote document (index.apxl)", + "author": "Jukka Zitting (Apache Tika)", + "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote.key", + "evidence": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote.key", + "committed": false, + "bytes": 221745, + "sha256": "4a270c2427f11d77f82fae696e3fd6eda945bae0422ae87c5fac6cf2bd06015c" + }, + { + "file": "tika-keynote2013.key", + "group": "converted", + "family": "keynote", + "title": "Apache Tika test presentation (Keynote 2013, IWA format)", + "features": "a Keynote document in the iWork archive format", + "author": "Tim Allison (Apache Tika)", + "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote2013.key", + "evidence": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote2013.key", + "committed": false, + "bytes": 274397, + "sha256": "8da93f6b566bc9eb22f4791bbfd5f2179162f39bf80968187b164c33d31824db" + }, + { + "file": "tika-numbers09-charts.numbers", + "group": "converted", + "family": "numbers", + "title": "Apache Tika test spreadsheet with charts (Numbers '09)", + "features": "an XML Numbers document with charts", + "author": "Michael McCandless (Apache Tika)", + "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testNumbersCharts.numbers", + "evidence": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testNumbersCharts.numbers", + "committed": false, + "bytes": 104547, + "sha256": "f4430f2aa0ddab186e7e32f15552b58b7b03abada7a978dfbcd51e5548757789" + }, + { + "file": "numbers-formulas.numbers", + "group": "converted", + "family": "numbers", + "title": "numbers-parser test spreadsheet of formulas (Numbers)", + "features": "formulas across tables", + "author": "Jon Connell (numbers-parser)", + "source": "https://github.com/masaccio/numbers-parser/blob/a6affe5599c8373f575192ac5777d0c6426da696/tests/data/create-formulas.numbers", + "evidence": "https://raw.githubusercontent.com/masaccio/numbers-parser/a6affe5599c8373f575192ac5777d0c6426da696/LICENSE.rst", + "evidence_quote": "Permission is hereby granted, free of charge, to any person obtaining a copy of this softw", + "licence": "MIT", + "attribution": "Copyright 2021 Jon Connell, numbers-parser, MIT, https://github.com/masaccio/numbers-parser. No changes.", + "fetched": "https://raw.githubusercontent.com/masaccio/numbers-parser/a6affe5599c8373f575192ac5777d0c6426da696/tests/data/create-formulas.numbers", + "committed": false, + "bytes": 330282, + "sha256": "9371c5b1d6ee4dfa17569097f064eba9c67f804d88b48638efbbeeb459d07dd4" + }, + { + "file": "poi-network.vsdx", + "group": "converted", + "family": "visio", + "title": "Apache POI test diagram (Visio): a network", + "features": "a use-case diagram: actors, ovals and connecting lines", + "author": "A reporter of Apache POI bug 60489 (committed by Tim Allison)", + "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/diagram/60489.vsdx", + "evidence": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/diagram/60489.vsdx", + "committed": false, + "bytes": 44426, + "sha256": "15494702ecb5554c1dfaee2c09ac35e2ea656e2eed7ba4ba0cf1039e6125fbe1" + }, + { + "file": "vsdx-house.vsdx", + "group": "converted", + "family": "visio", + "title": "vsdx library test drawing (Visio): a house", + "features": "boxes and house shapes with text", + "author": "Dave Howard (vsdx library)", + "source": "https://github.com/dave-howard/vsdx/blob/6703e6c2c906bea4051f43525ec9af9dcf735c13/tests/test3_house.vsdx", + "evidence": "https://raw.githubusercontent.com/dave-howard/vsdx/6703e6c2c906bea4051f43525ec9af9dcf735c13/LICENSE", + "evidence_quote": "BSD 3-Clause License Copyright (c) 2020, Dave Howard", + "licence": "BSD-3-Clause", + "attribution": "Copyright (c) 2020, Dave Howard, BSD-3-Clause, https://github.com/dave-howard/vsdx. No changes.", + "fetched": "https://raw.githubusercontent.com/dave-howard/vsdx/6703e6c2c906bea4051f43525ec9af9dcf735c13/tests/test3_house.vsdx", + "committed": false, + "bytes": 20914, + "sha256": "e454217e49d1ec2aaa7c9b8f38b148ffc0d028ce44ba096fe3386e9894b1775f" + }, + { + "file": "tika-pages09-layout.pages", + "group": "unsupported", + "family": "pages", + "title": "Apache Tika test document (Pages '09)", + "features": "kept to show what the viewer says about Pages files, which it does not list yet", + "author": "Michael McCandless (Apache Tika)", + "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testPagesLayout.pages", + "evidence": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt", + "evidence_quote": "Version 2.0, January 2004", + "licence": "Apache-2.0", + "attribution": "Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes.", + "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testPagesLayout.pages", + "committed": false, + "bytes": 66480, + "sha256": "6157fe7a95f7bc7d42251872f990d2f2d589f7f5e25a52b58e25c14cc447a4b2" + } + ] +} diff --git a/crates/exav-viewer/demo/examples/files/archives/encrypted-aes.zip b/crates/exav-viewer/demo/examples/files/archives/encrypted-aes.zip new file mode 100644 index 0000000..adc147a Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/encrypted-aes.zip differ diff --git a/crates/exav-viewer/demo/examples/files/archives/encrypted-zipcrypto.zip b/crates/exav-viewer/demo/examples/files/archives/encrypted-zipcrypto.zip new file mode 100644 index 0000000..cdb7fa4 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/encrypted-zipcrypto.zip differ diff --git a/crates/exav-viewer/demo/examples/files/archives/encrypted.7z b/crates/exav-viewer/demo/examples/files/archives/encrypted.7z new file mode 100644 index 0000000..e1cc2da Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/encrypted.7z differ diff --git a/crates/exav-viewer/demo/examples/files/archives/example.jar b/crates/exav-viewer/demo/examples/files/archives/example.jar new file mode 100644 index 0000000..6f07e39 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/example.jar differ diff --git a/crates/exav-viewer/demo/examples/files/archives/exav-example.deb b/crates/exav-viewer/demo/examples/files/archives/exav-example.deb new file mode 100644 index 0000000..7bfac73 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/exav-example.deb differ diff --git a/crates/exav-viewer/demo/examples/files/archives/libexample.a b/crates/exav-viewer/demo/examples/files/archives/libexample.a new file mode 100644 index 0000000..075883e --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/archives/libexample.a @@ -0,0 +1,40 @@ +! +README.txt/ 0 0 0 644 227 ` +Example archive +=============== + +This archive holds a few files of the exav demo. It is in the public domain +(CC0-1.0). Look at the folders: docs, data, images, src, an empty one, and a +folder with accented and Japanese names. + +field-notes.txt/0 0 0 644 1632 ` +Field notes +=========== + +Plain text is shown as it is written: line breaks, indentation, tabs and +long lines are kept. + + A line that starts with a tab. + A line that starts with eight spaces. + +A very long line, to see how the viewer wraps or scrolls it: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + +Pangrams, one for each script: + + English The quick brown fox jumps over the lazy dog. + Français Portez ce vieux whisky au juge blond qui fume. + Deutsch Zwölf Boxkämpfer jagen Viktor quer über den großen Sylter Deich. + Español El pingüino Wenceslao hizo kilómetros bajo exhaustiva lluvia y frío. + Ελληνικά Ξεσκεπάζω την ψυχοφθόÏ�α βδελυγμία. + РуÑ�Ñ�кий Съешь же ещё Ñ�тих мÑ�гких французÑ�ких булок да выпей чаю. + 日本語 ã�„ã‚�ã�¯ã�«ã�»ã�¸ã�¨ ã�¡ã‚Šã�¬ã‚‹ã‚’ ã‚�ã�‹ã‚ˆã�Ÿã‚Œã�� ã�¤ã�­ã�ªã‚‰ã‚€ + العربية نص حكيم له سر قاطع وذو شأن عظيم مكتوب على ثوب أخضر ومزخرÙ� + עברית דג סקרן שט בי×� מ×�וכזב ולפתע מצ×� לו חברה ×�יך הקליטה + +Symbols and box drawing: + + ┌──────┬──────â”� â†� ↑ → ↓ ✓ ✗ ½ â…“ ¾ ± × ÷ ≠ ≤ ≥ ∞ + │ a │ b │ € £ Â¥ â‚¿ © ® â„¢ ☀ â˜� ☂ ☃ + └──────┴──────┘ + +The last line has no newline at the end. \ No newline at end of file diff --git a/crates/exav-viewer/demo/examples/files/archives/matryoshka.zip b/crates/exav-viewer/demo/examples/files/archives/matryoshka.zip new file mode 100644 index 0000000..cb36454 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/matryoshka.zip differ diff --git a/crates/exav-viewer/demo/examples/files/archives/pages.cbz b/crates/exav-viewer/demo/examples/files/archives/pages.cbz new file mode 100644 index 0000000..04c5fd2 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/pages.cbz differ diff --git a/crates/exav-viewer/demo/examples/files/archives/sample.7z b/crates/exav-viewer/demo/examples/files/archives/sample.7z new file mode 100644 index 0000000..11e20bf Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/sample.7z differ diff --git a/crates/exav-viewer/demo/examples/files/archives/sample.cab b/crates/exav-viewer/demo/examples/files/archives/sample.cab new file mode 100644 index 0000000..8a7e54c Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/sample.cab differ diff --git a/crates/exav-viewer/demo/examples/files/archives/sample.cpio b/crates/exav-viewer/demo/examples/files/archives/sample.cpio new file mode 100644 index 0000000..53c7d50 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/sample.cpio differ diff --git a/crates/exav-viewer/demo/examples/files/archives/sample.iso b/crates/exav-viewer/demo/examples/files/archives/sample.iso new file mode 100644 index 0000000..17b5c7c Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/sample.iso differ diff --git a/crates/exav-viewer/demo/examples/files/archives/sample.rar b/crates/exav-viewer/demo/examples/files/archives/sample.rar new file mode 100644 index 0000000..b1b3f91 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/sample.rar differ diff --git a/crates/exav-viewer/demo/examples/files/archives/sample.tar b/crates/exav-viewer/demo/examples/files/archives/sample.tar new file mode 100644 index 0000000..af4121b Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/sample.tar differ diff --git a/crates/exav-viewer/demo/examples/files/archives/sample.tar.bz2 b/crates/exav-viewer/demo/examples/files/archives/sample.tar.bz2 new file mode 100644 index 0000000..e324763 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/sample.tar.bz2 differ diff --git a/crates/exav-viewer/demo/examples/files/archives/sample.tar.gz b/crates/exav-viewer/demo/examples/files/archives/sample.tar.gz new file mode 100644 index 0000000..e2226a9 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/sample.tar.gz differ diff --git a/crates/exav-viewer/demo/examples/files/archives/sample.tar.xz b/crates/exav-viewer/demo/examples/files/archives/sample.tar.xz new file mode 100644 index 0000000..67a330d Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/sample.tar.xz differ diff --git a/crates/exav-viewer/demo/examples/files/archives/sample.tar.zst b/crates/exav-viewer/demo/examples/files/archives/sample.tar.zst new file mode 100644 index 0000000..be2a171 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/sample.tar.zst differ diff --git a/crates/exav-viewer/demo/examples/files/archives/sample.zip b/crates/exav-viewer/demo/examples/files/archives/sample.zip new file mode 100644 index 0000000..8dfb9b3 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/sample.zip differ diff --git a/crates/exav-viewer/demo/examples/files/archives/server.log.bz2 b/crates/exav-viewer/demo/examples/files/archives/server.log.bz2 new file mode 100644 index 0000000..0ee7140 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/server.log.bz2 differ diff --git a/crates/exav-viewer/demo/examples/files/archives/server.log.gz b/crates/exav-viewer/demo/examples/files/archives/server.log.gz new file mode 100644 index 0000000..c466381 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/server.log.gz differ diff --git a/crates/exav-viewer/demo/examples/files/archives/server.log.xz b/crates/exav-viewer/demo/examples/files/archives/server.log.xz new file mode 100644 index 0000000..d6fbea0 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/archives/server.log.xz differ diff --git a/crates/exav-viewer/demo/examples/files/cad/blocks.dxf b/crates/exav-viewer/demo/examples/files/cad/blocks.dxf new file mode 100644 index 0000000..e7273b7 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/cad/blocks.dxf @@ -0,0 +1,6052 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1032 + 9 +$ACADMAINTVER + 90 +4 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$LASTSAVEDBY + 1 +ezdxf + 9 +$REQUIREDVERSIONS +160 +0 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$EXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 +0 + 9 +$REGENMODE + 70 +1 + 9 +$FILLMODE + 70 +1 + 9 +$QTEXTMODE + 70 +0 + 9 +$MIRRTEXT + 70 +1 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 +1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 +256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 +0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 +0 + 9 +$DIMLIM + 70 +0 + 9 +$DIMTIH + 70 +0 + 9 +$DIMTOH + 70 +0 + 9 +$DIMSE1 + 70 +0 + 9 +$DIMSE2 + 70 +0 + 9 +$DIMTAD + 70 +1 + 9 +$DIMZIN + 70 +8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 +1 + 9 +$DIMSHO + 70 +1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 +0 + 9 +$DIMALTD + 70 +3 + 9 +$DIMALTF + 40 +0.03937007874 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 +1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 +0 + 9 +$DIMSOXD + 70 +0 + 9 +$DIMSAH + 70 +0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 +0 + 9 +$DIMCLRE + 70 +0 + 9 +$DIMCLRT + 70 +0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 +0 + 9 +$DIMSD1 + 70 +0 + 9 +$DIMSD2 + 70 +0 + 9 +$DIMTOLJ + 70 +0 + 9 +$DIMTZIN + 70 +8 + 9 +$DIMALTZ + 70 +0 + 9 +$DIMALTTZ + 70 +0 + 9 +$DIMUPT + 70 +0 + 9 +$DIMDEC + 70 +2 + 9 +$DIMTDEC + 70 +2 + 9 +$DIMALTU + 70 +2 + 9 +$DIMALTTD + 70 +3 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 +0 + 9 +$DIMADEC + 70 +0 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 +0 + 9 +$DIMDSEP + 70 +44 + 9 +$DIMATFIT + 70 +3 + 9 +$DIMFRAC + 70 +0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 +2 + 9 +$DIMLWD + 70 +-2 + 9 +$DIMLWE + 70 +-2 + 9 +$DIMTMOVE + 70 +0 + 9 +$DIMFXL + 40 +1.0 + 9 +$DIMFXLON + 70 +0 + 9 +$DIMJOGANG + 40 +0.785398163397 + 9 +$DIMTFILL + 70 +0 + 9 +$DIMTFILLCLR + 70 +0 + 9 +$DIMARCSYM + 70 +0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$DIMTXTDIRECTION + 70 +0 + 9 +$LUNITS + 70 +2 + 9 +$LUPREC + 70 +4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 +0 + 9 +$AUPREC + 70 +2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 +0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 +0 + 9 +$TDCREATE + 40 +2451545.0 + 9 +$TDUCREATE + 40 +2451545.0 + 9 +$TDUPDATE + 40 +2451545.0 + 9 +$TDUUPDATE + 40 +2451545.0 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 +1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 +0 + 9 +$PDMODE + 70 +0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 +0 + 9 +$SPLINETYPE + 70 +6 + 9 +$SPLINESEGS + 70 +8 + 9 +$HANDSEED + 5 +A2 + 9 +$SURFTAB1 + 70 +6 + 9 +$SURFTAB2 + 70 +6 + 9 +$SURFTYPE + 70 +6 + 9 +$SURFU + 70 +6 + 9 +$SURFV + 70 +6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 +0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 +0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 +0 + 9 +$USERI2 + 70 +0 + 9 +$USERI3 + 70 +0 + 9 +$USERI4 + 70 +0 + 9 +$USERI5 + 70 +0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 +1 + 9 +$SHADEDGE + 70 +3 + 9 +$SHADEDIF + 70 +70 + 9 +$TILEMODE + 70 +1 + 9 +$MAXACTVP + 70 +64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 +0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 +0 + 9 +$VISRETAIN + 70 +1 + 9 +$PLINEGEN + 70 +0 + 9 +$PSLTSCALE + 70 +1 + 9 +$TREEDEPTH + 70 +3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 +0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 +1 + 9 +$MEASUREMENT + 70 +1 + 9 +$CELWEIGHT +370 +-1 + 9 +$ENDCAPS +280 +0 + 9 +$JOINSTYLE +280 +0 + 9 +$LWDISPLAY +290 +0 + 9 +$INSUNITS + 70 +4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 +1 + 9 +$CEPSNTYPE +380 +0 + 9 +$PSTYLEMODE +290 +1 + 9 +$FINGERPRINTGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$VERSIONGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$EXTNAMES +290 +1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 +0 + 9 +$SORTENTS +280 +127 + 9 +$INDEXCTL +280 +0 + 9 +$HIDETEXT +280 +1 + 9 +$XCLIPFRAME +280 +1 + 9 +$HALOGAP +280 +0 + 9 +$OBSCOLOR + 70 +257 + 9 +$OBSLTYPE +280 +0 + 9 +$INTERSECTIONDISPLAY +280 +0 + 9 +$INTERSECTIONCOLOR + 70 +257 + 9 +$DIMASSOC +280 +2 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 +0 + 9 +$LENSLENGTH + 40 +50.0 + 9 +$CAMERAHEIGHT + 40 +0.0 + 9 +$STEPSPERSEC + 40 +24.0 + 9 +$STEPSIZE + 40 +100.0 + 9 +$3DDWFPREC + 40 +2.0 + 9 +$PSOLWIDTH + 40 +0.005 + 9 +$PSOLHEIGHT + 40 +0.08 + 9 +$LOFTANG1 + 40 +1.570796326795 + 9 +$LOFTANG2 + 40 +1.570796326795 + 9 +$LOFTMAG1 + 40 +0.0 + 9 +$LOFTMAG2 + 40 +0.0 + 9 +$LOFTPARAM + 70 +7 + 9 +$LOFTNORMALS +280 +1 + 9 +$LATITUDE + 40 +37.795 + 9 +$LONGITUDE + 40 +-122.394 + 9 +$NORTHDIRECTION + 40 +0.0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 +1 + 9 +$TILEMODELIGHTSYNCH +280 +1 + 9 +$CMATERIAL +347 +20 + 9 +$SOLIDHIST +280 +0 + 9 +$SHOWHIST +280 +1 + 9 +$DWFFRAME +280 +2 + 9 +$DGNFRAME +280 +2 + 9 +$REALWORLDSCALE +290 +1 + 9 +$INTERFERECOLOR + 62 +256 + 9 +$CSHADOW +280 +0 + 9 +$SHADOWPLANELOCATION + 40 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +CELLSTYLEMAP + 2 +AcDbCellStyleMap + 3 +ObjectDBX Classes + 90 +1152 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MENTALRAYRENDERSETTINGS + 2 +AcDbMentalRayRenderSettings + 3 +SCENEOE + 90 +1024 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBDETAILVIEWSTYLE + 2 +AcDbDetailViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBSECTIONVIEWSTYLE + 2 +AcDbSectionViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +RASTERVARIABLES + 2 +AcDbRasterVariables + 3 +ISM + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 +1 + 0 +VPORT + 5 +9E +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +298.30127018922195 + 22 +-110.57066309444073 + 13 +0.0 + 23 +0.0 + 14 +0.5 + 24 +0.5 + 15 +0.5 + 25 +0.5 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +421.1983924983256 + 41 +1.34 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +1000 + 73 +1 + 74 +3 + 75 +0 + 76 +0 + 77 +0 + 78 +0 +281 +0 + 65 +1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 +21 + 0 +LTYPE + 5 +24 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +25 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +26 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +2F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 +0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +5.08 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +30 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 +0 + 3 +Center (2x) ________ __ ________ __ ________ + 72 +65 + 73 +4 + 40 +8.89 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 +0 + 3 +Center (.5x) ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +2.54 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +32 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 +0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 +65 + 73 +2 + 40 +1.524 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +33 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 +0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ____ + 72 +65 + 73 +2 + 40 +3.048 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +34 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 +0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 +65 + 73 +2 + 40 +0.762 + 49 +0.635 + 74 +0 + 49 +-0.127 + 74 +0 + 0 +LTYPE + 5 +35 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM + 70 +0 + 3 +Phantom ______ __ __ ______ __ __ ______ + 72 +65 + 73 +6 + 40 +6.35 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOMX2 + 70 +0 + 3 +Phantom (2x)____________ ____ ____ ____________ + 72 +65 + 73 +6 + 40 +10.795 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +37 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 +0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___ + 72 +65 + 73 +6 + 40 +3.175 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +38 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 +0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 +65 + 73 +4 + 40 +3.556 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +39 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 +0 + 3 +Dash dot (2x) ____ . ____ . ____ . ____ + 72 +65 + 73 +4 + 40 +6.096 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 +0 + 3 +Dash dot (.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +4 + 40 +1.778 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 +0 + 3 +Dot . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.508 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 +0 + 3 +Dot (2x) . . . . . . . . + 72 +65 + 73 +2 + 40 +1.016 + 49 +0.0 + 74 +0 + 49 +-1.016 + 74 +0 + 0 +LTYPE + 5 +3D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 +0 + 3 +Dot (.5) . . . . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.254 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 +0 + 3 +Divide __ . . __ . . __ . . __ . . __ . . __ + 72 +65 + 73 +6 + 40 +4.064 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 +0 + 3 +Divide (2x) ____ . . ____ . . ____ . . ____ + 72 +65 + 73 +6 + 40 +6.604 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +40 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 +0 + 3 +Divide(.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +6 + 40 +2.032 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 +5 + 0 +LAYER + 5 +27 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 62 +7 + 6 +Continuous +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +28 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Defpoints + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +41 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +PARTS + 70 +0 + 62 +7 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +42 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +NOTE + 70 +0 + 62 +8 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +43 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +RED + 70 +0 + 62 +1 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 +2 + 0 +STYLE + 5 +29 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +44 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +BL-TEXT + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 +3 + 0 +APPID + 5 +2A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 +0 + 0 +APPID + 5 +9F +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +HATCHBACKGROUNDCOLOR + 70 +0 + 0 +APPID + 5 +A0 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +EZDXF + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +4 +330 +0 +100 +AcDbSymbolTable + 70 +1 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +2B +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 +0 + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +0 +177 +0 +178 +0 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +371 +-2 +372 +-2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 +6 + 0 +BLOCK_RECORD + 5 +17 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +1A + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +45 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +BOLT +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +52 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +PLATE +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +67 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +FRAME +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +8F +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +SYMBOL +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +18 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +19 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +46 +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +BOLT + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +BOLT + 1 + + 0 +LWPOLYLINE + 5 +48 +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +-6.0 + 20 +0.0 + 10 +6.0 + 20 +0.0 + 10 +6.0 + 20 +4.0 + 10 +-6.0 + 20 +4.0 + 0 +LWPOLYLINE + 5 +49 +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +-3.0 + 20 +0.0 + 10 +3.0 + 20 +0.0 + 10 +3.0 + 20 +-22.0 + 10 +-3.0 + 20 +-22.0 + 0 +LINE + 5 +4A +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +-3.0 + 20 +-4.0 + 30 +0.0 + 11 +3.0 + 21 +-6.5 + 31 +0.0 + 0 +LINE + 5 +4B +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +-3.0 + 20 +-6.5 + 30 +0.0 + 11 +3.0 + 21 +-9.0 + 31 +0.0 + 0 +LINE + 5 +4C +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +-3.0 + 20 +-9.0 + 30 +0.0 + 11 +3.0 + 21 +-11.5 + 31 +0.0 + 0 +LINE + 5 +4D +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +-3.0 + 20 +-11.5 + 30 +0.0 + 11 +3.0 + 21 +-14.0 + 31 +0.0 + 0 +LINE + 5 +4E +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +-3.0 + 20 +-14.0 + 30 +0.0 + 11 +3.0 + 21 +-16.5 + 31 +0.0 + 0 +LINE + 5 +4F +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +-3.0 + 20 +-16.5 + 30 +0.0 + 11 +3.0 + 21 +-19.0 + 31 +0.0 + 0 +LINE + 5 +50 +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +-3.0 + 20 +-19.0 + 30 +0.0 + 11 +3.0 + 21 +-21.5 + 31 +0.0 + 0 +ATTDEF + 5 +51 +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +8.0 + 20 +1.0 + 30 +0.0 + 40 +2.5 + 1 +M6 +100 +AcDbAttributeDefinition + 3 + + 2 +SIZE + 70 +0 + 71 +1 + 72 +0 + 0 +ENDBLK + 5 +47 +330 +45 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +53 +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +PLATE + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +PLATE + 1 + + 0 +LWPOLYLINE + 5 +55 +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +100.0 + 20 +0.0 + 10 +100.0 + 20 +60.0 + 10 +0.0 + 20 +60.0 + 0 +CIRCLE + 5 +56 +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbCircle + 10 +15.0 + 20 +15.0 + 30 +0.0 + 40 +4.0 + 0 +INSERT + 5 +57 +330 +52 +100 +AcDbEntity + 8 +RED +100 +AcDbBlockReference + 66 +1 + 2 +BOLT + 10 +15.0 + 20 +15.0 + 30 +0.0 + 0 +ATTRIB + 5 +59 +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +23.0 + 20 +16.0 + 30 +0.0 + 40 +2.5 + 1 +M6 + 11 +23.0 + 21 +16.0 + 31 +0.0 +100 +AcDbAttribute + 2 +SIZE + 70 +0 + 71 +1 + 72 +0 + 11 +23.0 + 21 +16.0 + 31 +0.0 + 0 +SEQEND + 5 +58 +330 +57 +100 +AcDbEntity + 8 +RED + 0 +CIRCLE + 5 +5A +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbCircle + 10 +85.0 + 20 +15.0 + 30 +0.0 + 40 +4.0 + 0 +INSERT + 5 +5B +330 +52 +100 +AcDbEntity + 8 +RED +100 +AcDbBlockReference + 66 +1 + 2 +BOLT + 10 +85.0 + 20 +15.0 + 30 +0.0 + 0 +ATTRIB + 5 +5D +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +93.0 + 20 +16.0 + 30 +0.0 + 40 +2.5 + 1 +M6 + 11 +93.0 + 21 +16.0 + 31 +0.0 +100 +AcDbAttribute + 2 +SIZE + 70 +0 + 71 +1 + 72 +0 + 11 +93.0 + 21 +16.0 + 31 +0.0 + 0 +SEQEND + 5 +5C +330 +5B +100 +AcDbEntity + 8 +RED + 0 +CIRCLE + 5 +5E +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbCircle + 10 +15.0 + 20 +45.0 + 30 +0.0 + 40 +4.0 + 0 +INSERT + 5 +5F +330 +52 +100 +AcDbEntity + 8 +RED +100 +AcDbBlockReference + 66 +1 + 2 +BOLT + 10 +15.0 + 20 +45.0 + 30 +0.0 + 0 +ATTRIB + 5 +61 +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +23.0 + 20 +46.0 + 30 +0.0 + 40 +2.5 + 1 +M6 + 11 +23.0 + 21 +46.0 + 31 +0.0 +100 +AcDbAttribute + 2 +SIZE + 70 +0 + 71 +1 + 72 +0 + 11 +23.0 + 21 +46.0 + 31 +0.0 + 0 +SEQEND + 5 +60 +330 +5F +100 +AcDbEntity + 8 +RED + 0 +CIRCLE + 5 +62 +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbCircle + 10 +85.0 + 20 +45.0 + 30 +0.0 + 40 +4.0 + 0 +INSERT + 5 +63 +330 +52 +100 +AcDbEntity + 8 +RED +100 +AcDbBlockReference + 66 +1 + 2 +BOLT + 10 +85.0 + 20 +45.0 + 30 +0.0 + 0 +ATTRIB + 5 +65 +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +93.0 + 20 +46.0 + 30 +0.0 + 40 +2.5 + 1 +M6 + 11 +93.0 + 21 +46.0 + 31 +0.0 +100 +AcDbAttribute + 2 +SIZE + 70 +0 + 71 +1 + 72 +0 + 11 +93.0 + 21 +46.0 + 31 +0.0 + 0 +SEQEND + 5 +64 +330 +63 +100 +AcDbEntity + 8 +RED + 0 +ATTDEF + 5 +66 +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +50.0 + 20 +30.0 + 30 +0.0 + 40 +6.0 + 1 +P-1 + 72 +4 + 11 +50.0 + 21 +30.0 + 31 +0.0 +100 +AcDbAttributeDefinition + 3 + + 2 +MARK + 70 +0 + 71 +1 + 72 +0 + 11 +50.0 + 21 +30.0 + 31 +0.0 + 0 +ENDBLK + 5 +54 +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +68 +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +FRAME + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +FRAME + 1 + + 0 +LWPOLYLINE + 5 +6A +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +-10.0 + 20 +-10.0 + 10 +330.0 + 20 +-10.0 + 10 +330.0 + 20 +90.0 + 10 +-10.0 + 20 +90.0 + 0 +INSERT + 5 +6B +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 66 +1 + 2 +PLATE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +ATTRIB + 5 +6D +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +50.0 + 20 +30.0 + 30 +0.0 + 40 +6.0 + 1 +A + 72 +4 + 11 +50.0 + 21 +30.0 + 31 +0.0 +100 +AcDbAttribute + 2 +MARK + 70 +0 + 71 +1 + 72 +0 + 11 +50.0 + 21 +30.0 + 31 +0.0 + 0 +SEQEND + 5 +6C +330 +6B +100 +AcDbEntity + 8 +0 + 0 +INSERT + 5 +6E +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 66 +1 + 2 +PLATE + 10 +120.0 + 20 +0.0 + 30 +0.0 + 41 +0.7 + 42 +0.7 + 0 +ATTRIB + 5 +70 +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +155.0 + 20 +21.0 + 30 +0.0 + 40 +4.199999999999999 + 1 +B + 72 +4 + 11 +155.0 + 21 +21.0 + 31 +0.0 +100 +AcDbAttribute + 2 +MARK + 70 +0 + 71 +1 + 72 +0 + 11 +155.0 + 21 +21.0 + 31 +0.0 + 0 +SEQEND + 5 +6F +330 +6E +100 +AcDbEntity + 8 +0 + 0 +INSERT + 5 +71 +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 66 +1 + 2 +PLATE + 10 +230.0 + 20 +70.0 + 30 +0.0 + 41 +0.6 + 42 +0.6 + 50 +-90.0 + 0 +ATTRIB + 5 +73 +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +248.0 + 20 +40.0 + 30 +0.0 + 40 +3.5999999999999996 + 1 +C + 50 +-90.0 + 72 +4 + 11 +248.0 + 21 +40.0 + 31 +0.0 +100 +AcDbAttribute + 2 +MARK + 70 +0 + 71 +1 + 72 +0 + 11 +248.0 + 21 +40.0 + 31 +0.0 + 0 +SEQEND + 5 +72 +330 +71 +100 +AcDbEntity + 8 +0 + 0 +ENDBLK + 5 +69 +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +90 +330 +8F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +SYMBOL + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +SYMBOL + 1 + + 0 +CIRCLE + 5 +92 +330 +8F +100 +AcDbEntity + 8 +0 + 62 +0 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +10.0 + 0 +LINE + 5 +93 +330 +8F +100 +AcDbEntity + 8 +0 + 62 +0 +100 +AcDbLine + 10 +-10.0 + 20 +0.0 + 30 +0.0 + 11 +10.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +94 +330 +8F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +0.0 + 20 +-10.0 + 30 +0.0 + 11 +0.0 + 21 +10.0 + 31 +0.0 + 0 +ENDBLK + 5 +91 +330 +8F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +INSERT + 5 +74 +330 +17 +100 +AcDbEntity + 8 +PARTS +100 +AcDbBlockReference + 2 +FRAME + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +TEXT + 5 +76 +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbText + 10 +0.0 + 20 +-20.0 + 30 +0.0 + 40 +4.0 + 1 +FRAME: nested PLATE, BOLT blocks, attributes + 7 +BL-TEXT + 11 +0.0 + 21 +-20.0 + 31 +0.0 +100 +AcDbText + 0 +INSERT + 5 +77 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 66 +1 + 2 +PLATE + 10 +0.0 + 20 +-80.0 + 30 +0.0 + 0 +ATTRIB + 5 +79 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +50.0 + 20 +-50.0 + 30 +0.0 + 40 +6.0 + 1 +scale 1 + 72 +4 + 11 +50.0 + 21 +-50.0 + 31 +0.0 +100 +AcDbAttribute + 2 +MARK + 70 +0 + 71 +1 + 72 +0 + 11 +50.0 + 21 +-50.0 + 31 +0.0 + 0 +SEQEND + 5 +78 +330 +77 +100 +AcDbEntity + 8 +0 + 0 +TEXT + 5 +7A +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbText + 10 +0.0 + 20 +-100.0 + 30 +0.0 + 40 +4.0 + 1 +scale 1 + 7 +BL-TEXT + 11 +0.0 + 21 +-100.0 + 31 +0.0 +100 +AcDbText + 0 +INSERT + 5 +7B +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 66 +1 + 2 +PLATE + 10 +230.0 + 20 +-80.0 + 30 +0.0 + 41 +-1.0 + 0 +ATTRIB + 5 +7D +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +-180.0 + 20 +-50.0 + 30 +0.0 + 40 +6.0 + 1 +xscale -1 + 72 +4 + 11 +-180.0 + 21 +-50.0 + 31 +0.0 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbAttribute + 2 +MARK + 70 +0 + 71 +1 + 72 +0 + 11 +-180.0 + 21 +-50.0 + 31 +0.0 + 0 +SEQEND + 5 +7C +330 +7B +100 +AcDbEntity + 8 +0 + 0 +TEXT + 5 +7E +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbText + 10 +130.0 + 20 +-100.0 + 30 +0.0 + 40 +4.0 + 1 +xscale -1 + 7 +BL-TEXT + 11 +130.0 + 21 +-100.0 + 31 +0.0 +100 +AcDbText + 0 +INSERT + 5 +7F +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 66 +1 + 2 +PLATE + 10 +260.0 + 20 +-20.0 + 30 +0.0 + 42 +-1.0 + 0 +ATTRIB + 5 +81 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +-310.0 + 20 +-50.0 + 30 +0.0 + 40 +6.0 + 1 +yscale -1 + 50 +180.0 + 72 +4 + 11 +-310.0 + 21 +-50.0 + 31 +0.0 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbAttribute + 2 +MARK + 70 +0 + 71 +1 + 72 +0 + 11 +-310.0 + 21 +-50.0 + 31 +0.0 + 0 +SEQEND + 5 +80 +330 +7F +100 +AcDbEntity + 8 +0 + 0 +TEXT + 5 +82 +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbText + 10 +260.0 + 20 +-100.0 + 30 +0.0 + 40 +4.0 + 1 +yscale -1 + 7 +BL-TEXT + 11 +260.0 + 21 +-100.0 + 31 +0.0 +100 +AcDbText + 0 +INSERT + 5 +83 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 66 +1 + 2 +PLATE + 10 +390.0 + 20 +-80.0 + 30 +0.0 + 41 +1.5 + 42 +0.6 + 0 +ATTRIB + 5 +85 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +465.0 + 20 +-62.0 + 30 +0.0 + 40 +3.5999999999999996 + 1 +1.5 by 0.6 + 41 +2.5 + 72 +4 + 11 +465.0 + 21 +-62.0 + 31 +0.0 +100 +AcDbAttribute + 2 +MARK + 70 +0 + 71 +1 + 72 +0 + 11 +465.0 + 21 +-62.0 + 31 +0.0 + 0 +SEQEND + 5 +84 +330 +83 +100 +AcDbEntity + 8 +0 + 0 +TEXT + 5 +86 +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbText + 10 +390.0 + 20 +-100.0 + 30 +0.0 + 40 +4.0 + 1 +1.5 by 0.6 + 7 +BL-TEXT + 11 +390.0 + 21 +-100.0 + 31 +0.0 +100 +AcDbText + 0 +INSERT + 5 +87 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 66 +1 + 2 +PLATE + 10 +520.0 + 20 +-80.0 + 30 +0.0 + 50 +30.0 + 0 +ATTRIB + 5 +89 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +548.3012701892219 + 20 +-29.01923788646684 + 30 +0.0 + 40 +6.0 + 1 +rotated 30 + 50 +29.999999999999996 + 72 +4 + 11 +548.3012701892219 + 21 +-29.01923788646684 + 31 +0.0 +100 +AcDbAttribute + 2 +MARK + 70 +0 + 71 +1 + 72 +0 + 11 +548.3012701892219 + 21 +-29.01923788646684 + 31 +0.0 + 0 +SEQEND + 5 +88 +330 +87 +100 +AcDbEntity + 8 +0 + 0 +TEXT + 5 +8A +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbText + 10 +520.0 + 20 +-100.0 + 30 +0.0 + 40 +4.0 + 1 +rotated 30 + 7 +BL-TEXT + 11 +520.0 + 21 +-100.0 + 31 +0.0 +100 +AcDbText + 0 +INSERT + 5 +8B +330 +17 +100 +AcDbEntity + 8 +PARTS +100 +AcDbMInsertBlock + 66 +1 + 2 +BOLT + 10 +0.0 + 20 +-200.0 + 30 +0.0 + 70 +8 + 71 +3 + 44 +20.0 + 45 +35.0 + 0 +ATTRIB + 5 +8D +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +8.0 + 20 +-199.0 + 30 +0.0 + 40 +2.5 + 1 +M6 + 11 +8.0 + 21 +-199.0 + 31 +0.0 +100 +AcDbAttribute + 2 +SIZE + 70 +0 + 71 +1 + 72 +0 + 11 +8.0 + 21 +-199.0 + 31 +0.0 + 0 +SEQEND + 5 +8C +330 +8B +100 +AcDbEntity + 8 +PARTS + 0 +TEXT + 5 +8E +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbText + 10 +0.0 + 20 +-310.0 + 30 +0.0 + 40 +4.0 + 1 +MINSERT: 3 rows by 8 columns of BOLT + 7 +BL-TEXT + 11 +0.0 + 21 +-310.0 + 31 +0.0 +100 +AcDbText + 0 +INSERT + 5 +95 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbBlockReference + 2 +SYMBOL + 10 +200.0 + 20 +-220.0 + 30 +0.0 + 0 +INSERT + 5 +97 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbBlockReference + 2 +SYMBOL + 10 +230.0 + 20 +-220.0 + 30 +0.0 + 0 +INSERT + 5 +99 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +5 +100 +AcDbBlockReference + 2 +SYMBOL + 10 +260.0 + 20 +-220.0 + 30 +0.0 + 0 +INSERT + 5 +9B +330 +17 +100 +AcDbEntity + 8 +0 + 62 +6 +100 +AcDbBlockReference + 2 +SYMBOL + 10 +290.0 + 20 +-220.0 + 30 +0.0 + 0 +TEXT + 5 +9D +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbText + 10 +200.0 + 20 +-240.0 + 30 +0.0 + 40 +3.0 + 1 +BYBLOCK circle and cross, BYLAYER vertical line: insert colour 1, 3, 5, 6 + 7 +BL-TEXT + 11 +200.0 + 21 +-240.0 + 31 +0.0 +100 +AcDbText + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +A +330 +0 +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ACAD_COLOR +350 +B + 3 +ACAD_GROUP +350 +C + 3 +ACAD_LAYOUT +350 +D + 3 +ACAD_MATERIAL +350 +E + 3 +ACAD_MLEADERSTYLE +350 +F + 3 +ACAD_MLINESTYLE +350 +10 + 3 +ACAD_PLOTSETTINGS +350 +11 + 3 +ACAD_PLOTSTYLENAME +350 +12 + 3 +ACAD_SCALELIST +350 +14 + 3 +ACAD_TABLESTYLE +350 +15 + 3 +ACAD_VISUALSTYLE +350 +16 + 3 +EZDXF_META +350 +2D + 0 +DICTIONARY + 5 +B +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +C +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +D +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Model +350 +1A + 3 +Layout1 +350 +1E + 0 +DICTIONARY + 5 +E +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ByBlock +350 +1F + 3 +ByLayer +350 +20 + 3 +Global +350 +21 + 0 +DICTIONARY + 5 +F +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +2C + 0 +DICTIONARY + 5 +10 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +22 + 0 +DICTIONARY + 5 +11 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +ACDBDICTIONARYWDFLT + 5 +12 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Normal +350 +13 +100 +AcDbDictionaryWithDefault +340 +13 + 0 +ACDBPLACEHOLDER + 5 +13 +330 +12 + 0 +DICTIONARY + 5 +14 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +15 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +16 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +LAYOUT + 5 +1A +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +1024 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 +1 + 71 +0 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +17 + 0 +LAYOUT + 5 +1E +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +0 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 +1 + 71 +1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +1B + 0 +MATERIAL + 5 +1F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByBlock + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +20 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByLayer + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +21 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +Global + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MLINESTYLE + 5 +22 +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMlineStyle + 2 +Standard + 70 +0 + 3 + + 62 +256 + 51 +90.0 + 52 +90.0 + 71 +2 + 49 +0.5 + 62 +256 + 6 +BYLAYER + 49 +-0.5 + 62 +256 + 6 +BYLAYER + 0 +MLEADERSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +F +102 +} +330 +F +100 +AcDbMLeaderStyle +179 +2 +170 +2 +171 +1 +172 +0 + 90 +2 + 40 +0.0 + 41 +0.0 +173 +1 + 91 +-1056964608 + 92 +-2 +290 +1 + 42 +2.0 +291 +1 + 43 +8.0 + 3 +Standard + 44 +4.0 +300 + +342 +29 +174 +1 +175 +1 +176 +0 +178 +1 + 93 +-1056964608 + 45 +4.0 +292 +0 +297 +0 + 46 +4.0 + 94 +-1056964608 + 47 +1.0 + 49 +1.0 +140 +1.0 +294 +1 +141 +0.0 +177 +0 +142 +1.0 +295 +0 +296 +0 +143 +3.75 +271 +0 +272 +9 +273 +9 + 0 +DICTIONARY + 5 +2D +330 +A +100 +AcDbDictionary +281 +1 + 3 +CREATED_BY_EZDXF +350 +2E + 3 +WRITTEN_BY_EZDXF +350 +A1 + 0 +DICTIONARYVAR + 5 +2E +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +DICTIONARYVAR + 5 +A1 +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +ENDSEC + 0 +EOF diff --git a/crates/exav-viewer/demo/examples/files/cad/bracket.dxf b/crates/exav-viewer/demo/examples/files/cad/bracket.dxf new file mode 100644 index 0000000..b099700 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/cad/bracket.dxf @@ -0,0 +1,8288 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1032 + 9 +$ACADMAINTVER + 90 +4 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$LASTSAVEDBY + 1 +ezdxf + 9 +$REQUIREDVERSIONS +160 +0 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$EXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 +0 + 9 +$REGENMODE + 70 +1 + 9 +$FILLMODE + 70 +1 + 9 +$QTEXTMODE + 70 +0 + 9 +$MIRRTEXT + 70 +1 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 +1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 +256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 +0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 +0 + 9 +$DIMLIM + 70 +0 + 9 +$DIMTIH + 70 +0 + 9 +$DIMTOH + 70 +0 + 9 +$DIMSE1 + 70 +0 + 9 +$DIMSE2 + 70 +0 + 9 +$DIMTAD + 70 +1 + 9 +$DIMZIN + 70 +8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 +1 + 9 +$DIMSHO + 70 +1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 +0 + 9 +$DIMALTD + 70 +3 + 9 +$DIMALTF + 40 +0.03937007874 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 +1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 +0 + 9 +$DIMSOXD + 70 +0 + 9 +$DIMSAH + 70 +0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 +0 + 9 +$DIMCLRE + 70 +0 + 9 +$DIMCLRT + 70 +0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 +0 + 9 +$DIMSD1 + 70 +0 + 9 +$DIMSD2 + 70 +0 + 9 +$DIMTOLJ + 70 +0 + 9 +$DIMTZIN + 70 +8 + 9 +$DIMALTZ + 70 +0 + 9 +$DIMALTTZ + 70 +0 + 9 +$DIMUPT + 70 +0 + 9 +$DIMDEC + 70 +2 + 9 +$DIMTDEC + 70 +2 + 9 +$DIMALTU + 70 +2 + 9 +$DIMALTTD + 70 +3 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 +0 + 9 +$DIMADEC + 70 +0 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 +0 + 9 +$DIMDSEP + 70 +44 + 9 +$DIMATFIT + 70 +3 + 9 +$DIMFRAC + 70 +0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 +2 + 9 +$DIMLWD + 70 +-2 + 9 +$DIMLWE + 70 +-2 + 9 +$DIMTMOVE + 70 +0 + 9 +$DIMFXL + 40 +1.0 + 9 +$DIMFXLON + 70 +0 + 9 +$DIMJOGANG + 40 +0.785398163397 + 9 +$DIMTFILL + 70 +0 + 9 +$DIMTFILLCLR + 70 +0 + 9 +$DIMARCSYM + 70 +0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$DIMTXTDIRECTION + 70 +0 + 9 +$LUNITS + 70 +2 + 9 +$LUPREC + 70 +4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 +0 + 9 +$AUPREC + 70 +2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 +0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 +0 + 9 +$TDCREATE + 40 +2451545.0 + 9 +$TDUCREATE + 40 +2451545.0 + 9 +$TDUPDATE + 40 +2451545.0 + 9 +$TDUUPDATE + 40 +2451545.0 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 +1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 +0 + 9 +$PDMODE + 70 +0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 +0 + 9 +$SPLINETYPE + 70 +6 + 9 +$SPLINESEGS + 70 +8 + 9 +$HANDSEED + 5 +E9 + 9 +$SURFTAB1 + 70 +6 + 9 +$SURFTAB2 + 70 +6 + 9 +$SURFTYPE + 70 +6 + 9 +$SURFU + 70 +6 + 9 +$SURFV + 70 +6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 +0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 +0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 +0 + 9 +$USERI2 + 70 +0 + 9 +$USERI3 + 70 +0 + 9 +$USERI4 + 70 +0 + 9 +$USERI5 + 70 +0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 +1 + 9 +$SHADEDGE + 70 +3 + 9 +$SHADEDIF + 70 +70 + 9 +$TILEMODE + 70 +1 + 9 +$MAXACTVP + 70 +64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 +0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 +0 + 9 +$VISRETAIN + 70 +1 + 9 +$PLINEGEN + 70 +0 + 9 +$PSLTSCALE + 70 +1 + 9 +$TREEDEPTH + 70 +3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 +0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 +1 + 9 +$MEASUREMENT + 70 +1 + 9 +$CELWEIGHT +370 +-1 + 9 +$ENDCAPS +280 +0 + 9 +$JOINSTYLE +280 +0 + 9 +$LWDISPLAY +290 +0 + 9 +$INSUNITS + 70 +4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 +1 + 9 +$CEPSNTYPE +380 +0 + 9 +$PSTYLEMODE +290 +1 + 9 +$FINGERPRINTGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$VERSIONGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$EXTNAMES +290 +1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 +0 + 9 +$SORTENTS +280 +127 + 9 +$INDEXCTL +280 +0 + 9 +$HIDETEXT +280 +1 + 9 +$XCLIPFRAME +280 +1 + 9 +$HALOGAP +280 +0 + 9 +$OBSCOLOR + 70 +257 + 9 +$OBSLTYPE +280 +0 + 9 +$INTERSECTIONDISPLAY +280 +0 + 9 +$INTERSECTIONCOLOR + 70 +257 + 9 +$DIMASSOC +280 +2 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 +0 + 9 +$LENSLENGTH + 40 +50.0 + 9 +$CAMERAHEIGHT + 40 +0.0 + 9 +$STEPSPERSEC + 40 +24.0 + 9 +$STEPSIZE + 40 +100.0 + 9 +$3DDWFPREC + 40 +2.0 + 9 +$PSOLWIDTH + 40 +0.005 + 9 +$PSOLHEIGHT + 40 +0.08 + 9 +$LOFTANG1 + 40 +1.570796326795 + 9 +$LOFTANG2 + 40 +1.570796326795 + 9 +$LOFTMAG1 + 40 +0.0 + 9 +$LOFTMAG2 + 40 +0.0 + 9 +$LOFTPARAM + 70 +7 + 9 +$LOFTNORMALS +280 +1 + 9 +$LATITUDE + 40 +37.795 + 9 +$LONGITUDE + 40 +-122.394 + 9 +$NORTHDIRECTION + 40 +0.0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 +1 + 9 +$TILEMODELIGHTSYNCH +280 +1 + 9 +$CMATERIAL +347 +20 + 9 +$SOLIDHIST +280 +0 + 9 +$SHOWHIST +280 +1 + 9 +$DWFFRAME +280 +2 + 9 +$DGNFRAME +280 +2 + 9 +$REALWORLDSCALE +290 +1 + 9 +$INTERFERECOLOR + 62 +256 + 9 +$CSHADOW +280 +0 + 9 +$SHADOWPLANELOCATION + 40 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +CELLSTYLEMAP + 2 +AcDbCellStyleMap + 3 +ObjectDBX Classes + 90 +1152 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MENTALRAYRENDERSETTINGS + 2 +AcDbMentalRayRenderSettings + 3 +SCENEOE + 90 +1024 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBDETAILVIEWSTYLE + 2 +AcDbDetailViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBSECTIONVIEWSTYLE + 2 +AcDbSectionViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +RASTERVARIABLES + 2 +AcDbRasterVariables + 3 +ISM + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 +1 + 0 +VPORT + 5 +E5 +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +101.06408489618218 + 22 +-32.25 + 13 +0.0 + 23 +0.0 + 14 +0.5 + 24 +0.5 + 15 +0.5 + 25 +0.5 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +247.275 + 41 +1.34 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +1000 + 73 +1 + 74 +3 + 75 +0 + 76 +0 + 77 +0 + 78 +0 +281 +0 + 65 +1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 +21 + 0 +LTYPE + 5 +24 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +25 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +26 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +2F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 +0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +5.08 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +30 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 +0 + 3 +Center (2x) ________ __ ________ __ ________ + 72 +65 + 73 +4 + 40 +8.89 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 +0 + 3 +Center (.5x) ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +2.54 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +32 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 +0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 +65 + 73 +2 + 40 +1.524 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +33 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 +0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ____ + 72 +65 + 73 +2 + 40 +3.048 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +34 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 +0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 +65 + 73 +2 + 40 +0.762 + 49 +0.635 + 74 +0 + 49 +-0.127 + 74 +0 + 0 +LTYPE + 5 +35 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM + 70 +0 + 3 +Phantom ______ __ __ ______ __ __ ______ + 72 +65 + 73 +6 + 40 +6.35 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOMX2 + 70 +0 + 3 +Phantom (2x)____________ ____ ____ ____________ + 72 +65 + 73 +6 + 40 +10.795 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +37 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 +0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___ + 72 +65 + 73 +6 + 40 +3.175 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +38 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 +0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 +65 + 73 +4 + 40 +3.556 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +39 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 +0 + 3 +Dash dot (2x) ____ . ____ . ____ . ____ + 72 +65 + 73 +4 + 40 +6.096 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 +0 + 3 +Dash dot (.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +4 + 40 +1.778 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 +0 + 3 +Dot . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.508 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 +0 + 3 +Dot (2x) . . . . . . . . + 72 +65 + 73 +2 + 40 +1.016 + 49 +0.0 + 74 +0 + 49 +-1.016 + 74 +0 + 0 +LTYPE + 5 +3D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 +0 + 3 +Dot (.5) . . . . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.254 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 +0 + 3 +Divide __ . . __ . . __ . . __ . . __ . . __ + 72 +65 + 73 +6 + 40 +4.064 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 +0 + 3 +Divide (2x) ____ . . ____ . . ____ . . ____ + 72 +65 + 73 +6 + 40 +6.604 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +40 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 +0 + 3 +Divide(.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +6 + 40 +2.032 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 +9 + 0 +LAYER + 5 +27 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 62 +7 + 6 +Continuous +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +28 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Defpoints + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +41 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +OUTLINE + 70 +0 + 62 +7 + 6 +Continuous +370 +50 +390 +13 +347 +21 + 0 +LAYER + 5 +42 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +HIDDEN + 70 +0 + 62 +4 + 6 +DASHED +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +43 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +CENTER + 70 +0 + 62 +1 + 6 +CENTER +370 +18 +390 +13 +347 +21 + 0 +LAYER + 5 +44 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +SECTION + 70 +0 + 62 +8 + 6 +Continuous +370 +9 +390 +13 +347 +21 + 0 +LAYER + 5 +45 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +DIMS + 70 +0 + 62 +3 + 6 +Continuous +370 +18 +390 +13 +347 +21 + 0 +LAYER + 5 +46 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +SHEET + 70 +0 + 62 +7 + 6 +Continuous +370 +35 +390 +13 +347 +21 + 0 +LAYER + 5 +47 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +TEXT + 70 +0 + 62 +2 + 6 +Continuous +370 +18 +390 +13 +347 +21 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 +2 + 0 +STYLE + 5 +29 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +48 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +MECH + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 +3 + 0 +APPID + 5 +2A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 +0 + 0 +APPID + 5 +E6 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +HATCHBACKGROUNDCOLOR + 70 +0 + 0 +APPID + 5 +E7 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +EZDXF + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +4 +330 +0 +100 +AcDbSymbolTable + 70 +3 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +2B +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 +0 + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +0 +177 +0 +178 +0 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +371 +-2 +372 +-2 + 0 +DIMSTYLE +105 +49 +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +MECH + 70 +0 + 40 +1.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 43 +3.75 + 44 +2.1 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +3.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +1.05 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +3 +177 +3 +178 +2 +179 +2 +271 +1 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +340 +48 +371 +-2 +372 +-2 + 0 +DIMSTYLE +105 +4A +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +MECHTOL + 70 +0 + 40 +1.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 43 +3.75 + 44 +2.1 + 45 +0.0 + 46 +0.0 + 47 +0.1 + 48 +0.0 + 49 +2.5 +140 +3.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +0.7 +147 +1.05 +148 +0.0 + 69 +0 + 70 +0 + 71 +1 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +3 +177 +3 +178 +2 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +1 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +340 +48 +371 +-2 +372 +-2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 +11 + 0 +BLOCK_RECORD + 5 +17 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +1A + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +6D +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D1 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +72 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_CLOSEDFILLED +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +80 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D2 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +8F +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D3 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +9E +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D4 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +A9 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D5 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +B8 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D6 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +C5 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D7 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +D5 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space0 +340 +D8 + 70 +0 +280 +1 +281 +0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +18 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +19 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +6E +330 +6D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D1 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D1 + 1 + + 0 +LINE + 5 +70 +330 +6D +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +-2.8000000000000003 + 30 +0.0 + 11 +0.0 + 21 +-14.1 + 31 +0.0 + 0 +LINE + 5 +71 +330 +6D +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +100.0 + 20 +-2.8000000000000003 + 30 +0.0 + 11 +100.0 + 21 +-14.1 + 31 +0.0 + 0 +INSERT + 5 +76 +330 +6D +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +-12.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +180.0 + 0 +INSERT + 5 +78 +330 +6D +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +100.0 + 20 +-12.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 0 +LINE + 5 +7A +330 +6D +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +2.8000000000000003 + 20 +-12.0 + 30 +0.0 + 11 +97.2 + 21 +-12.0 + 31 +0.0 + 0 +MTEXT + 5 +7B +330 +6D +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +50.0 + 20 +-9.2 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +100 + 7 +MECH + 0 +POINT + 5 +7C +330 +6D +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-12.0 + 30 +0.0 + 0 +POINT + 5 +7D +330 +6D +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +7E +330 +6D +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +100.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +6F +330 +6D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +73 +330 +72 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_CLOSEDFILLED + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_CLOSEDFILLED + 1 + + 0 +SOLID + 5 +75 +330 +72 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 +0 +100 +AcDbTrace + 10 +-1.0 + 20 +0.16439898372402537 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 12 +-1.0 + 22 +-0.16439898372402537 + 32 +0.0 + 13 +-1.0 + 23 +-0.16439898372402537 + 33 +0.0 + 0 +ENDBLK + 5 +74 +330 +72 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +81 +330 +80 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D2 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D2 + 1 + + 0 +LINE + 5 +83 +330 +80 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-2.8000000000000003 + 20 +0.0 + 30 +0.0 + 11 +-14.1 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +84 +330 +80 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-2.8000000000000003 + 20 +72.0 + 30 +0.0 + 11 +-14.1 + 21 +72.0 + 31 +0.0 + 0 +INSERT + 5 +85 +330 +80 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-12.0 + 20 +0.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +270.0 + 0 +INSERT + 5 +87 +330 +80 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-12.0 + 20 +72.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +90.0 + 0 +LINE + 5 +89 +330 +80 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-12.0 + 20 +2.8000000000000003 + 30 +0.0 + 11 +-12.0 + 21 +69.2 + 31 +0.0 + 0 +MTEXT + 5 +8A +330 +80 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +-14.8 + 20 +36.0 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +\A1;72{\H0.70x;\S+0,10^ 0,00;} + 7 +MECH + 50 +90.0 + 0 +POINT + 5 +8B +330 +80 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-12.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +8C +330 +80 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +8D +330 +80 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +72.0 + 30 +0.0 + 0 +ENDBLK + 5 +82 +330 +80 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +90 +330 +8F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D3 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D3 + 1 + + 0 +LINE + 5 +92 +330 +8F +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +35.0 + 20 +-2.8000000000000003 + 30 +0.0 + 11 +35.0 + 21 +-26.1 + 31 +0.0 + 0 +LINE + 5 +93 +330 +8F +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +80.0 + 20 +-2.8000000000000003 + 30 +0.0 + 11 +80.0 + 21 +-26.1 + 31 +0.0 + 0 +INSERT + 5 +94 +330 +8F +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +35.0 + 20 +-24.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +180.0 + 0 +INSERT + 5 +96 +330 +8F +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +80.0 + 20 +-24.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 0 +LINE + 5 +98 +330 +8F +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +37.8 + 20 +-24.0 + 30 +0.0 + 11 +77.2 + 21 +-24.0 + 31 +0.0 + 0 +MTEXT + 5 +99 +330 +8F +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +57.5 + 20 +-21.2 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +\A1;45{\H0.70x;\S+0,10^ 0,00;} + 7 +MECH + 0 +POINT + 5 +9A +330 +8F +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +35.0 + 20 +-24.0 + 30 +0.0 + 0 +POINT + 5 +9B +330 +8F +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +35.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +9C +330 +8F +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +80.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +91 +330 +8F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +9F +330 +9E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D4 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D4 + 1 + + 0 +INSERT + 5 +A1 +330 +9E +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +14.343145750507619 + 20 +14.34314575050762 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +44.99999999999997 + 0 +LINE + 5 +A3 +330 +9E +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +20.0 + 20 +20.0 + 30 +0.0 + 11 +14.343145750507619 + 21 +14.34314575050762 + 31 +0.0 + 0 +LINE + 5 +A4 +330 +9E +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +12.363246763185284 + 20 +12.363246763185288 + 30 +0.0 + 11 +6.671037174633574 + 21 +6.67103717463358 + 31 +0.0 + 0 +MTEXT + 5 +A5 +330 +9E +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +7.166011921464162 + 20 +11.125809896108832 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +R8 + 7 +MECH + 50 +44.99999999999997 + 0 +POINT + 5 +A6 +330 +9E +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +20.0 + 20 +20.0 + 30 +0.0 + 0 +POINT + 5 +A7 +330 +9E +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +14.343145750507619 + 20 +14.34314575050762 + 30 +0.0 + 0 +ENDBLK + 5 +A0 +330 +9E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +AA +330 +A9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D5 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D5 + 1 + + 0 +LINE + 5 +AC +330 +A9 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +-87.2 + 30 +0.0 + 11 +0.0 + 21 +-75.9 + 31 +0.0 + 0 +LINE + 5 +AD +330 +A9 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +100.0 + 20 +-87.2 + 30 +0.0 + 11 +100.0 + 21 +-75.9 + 31 +0.0 + 0 +INSERT + 5 +AE +330 +A9 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +-78.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +180.0 + 0 +INSERT + 5 +B0 +330 +A9 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +100.0 + 20 +-78.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 0 +LINE + 5 +B2 +330 +A9 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +2.8000000000000003 + 20 +-78.0 + 30 +0.0 + 11 +97.2 + 21 +-78.0 + 31 +0.0 + 0 +MTEXT + 5 +B3 +330 +A9 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +50.0 + 20 +-75.2 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +100 + 7 +MECH + 0 +POINT + 5 +B4 +330 +A9 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-78.0 + 30 +0.0 + 0 +POINT + 5 +B5 +330 +A9 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-90.0 + 30 +0.0 + 0 +POINT + 5 +B6 +330 +A9 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +100.0 + 20 +-90.0 + 30 +0.0 + 0 +ENDBLK + 5 +AB +330 +A9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B9 +330 +B8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D6 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D6 + 1 + + 0 +INSERT + 5 +BB +330 +B8 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +76.72339182284404 + 20 +-122.29430574540419 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +35.00000000000006 + 0 +INSERT + 5 +BD +330 +B8 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +83.27660817715596 + 20 +-117.70569425459581 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +35.00000000000006 + 0 +LINE + 5 +BF +330 +B8 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +74.42976609883486 + 20 +-123.90031976718711 + 30 +0.0 + 11 +80.98298245314679 + 21 +-119.31170827637874 + 31 +0.0 + 0 +LINE + 5 +C0 +330 +B8 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +74.42976609883486 + 20 +-123.90031976718711 + 30 +0.0 + 11 +56.367463522262604 + 21 +-136.5476801887277 + 31 +0.0 + 0 +MTEXT + 5 +C1 +330 +B8 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +63.36254596551408 + 20 +-128.23150188303254 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +2x ⌀%%c8 + 7 +MECH + 50 +35.00000000000006 + 0 +POINT + 5 +C2 +330 +B8 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +80.0 + 20 +-120.0 + 30 +0.0 + 0 +POINT + 5 +C3 +330 +B8 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +76.72339182284404 + 20 +-122.29430574540419 + 30 +0.0 + 0 +ENDBLK + 5 +BA +330 +B8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +C6 +330 +C5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D7 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D7 + 1 + + 0 +LINE + 5 +C8 +330 +C5 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +212.8 + 20 +0.0 + 30 +0.0 + 11 +222.1 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +C9 +330 +C5 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +212.8 + 20 +12.0 + 30 +0.0 + 11 +222.1 + 21 +12.0 + 31 +0.0 + 0 +INSERT + 5 +CA +330 +C5 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +220.0 + 20 +0.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +270.0 + 0 +INSERT + 5 +CC +330 +C5 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +220.0 + 20 +12.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +90.0 + 0 +LINE + 5 +CE +330 +C5 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +220.0 + 20 +2.8000000000000003 + 30 +0.0 + 11 +220.0 + 21 +9.2 + 31 +0.0 + 0 +MTEXT + 5 +CF +330 +C5 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +217.2 + 20 +6.0 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +12 + 7 +MECH + 50 +90.0 + 0 +POINT + 5 +D0 +330 +C5 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +220.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +D1 +330 +C5 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +210.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +D2 +330 +C5 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +210.0 + 20 +12.0 + 30 +0.0 + 0 +ENDBLK + 5 +C7 +330 +C5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +D6 +330 +D5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space0 + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space0 + 1 + + 0 +VIEWPORT + 5 +D9 +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +VIEWPORTS +100 +AcDbViewport + 10 +143.5 + 20 +100.0 + 30 +0.0 + 40 +326.70000000000005 + 41 +231.00000000000003 + 68 +1 + 69 +1 + 12 +143.5 + 22 +100.0 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 45 +231.00000000000003 + 50 +0.0 + 51 +0.0 + 72 +100 + 90 +557088 + 1 + +281 +0 + 71 +0 + 74 +0 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 +282 +0 + 0 +LWPOLYLINE + 5 +DA +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +SHEET +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +5.0 + 20 +5.0 + 10 +292.0 + 20 +5.0 + 10 +292.0 + 20 +205.0 + 10 +5.0 + 20 +205.0 + 0 +LWPOLYLINE + 5 +DB +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +SHEET +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +137.0 + 20 +5.0 + 10 +292.0 + 20 +5.0 + 10 +292.0 + 20 +45.0 + 10 +137.0 + 20 +45.0 + 0 +LINE + 5 +DC +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +SHEET +100 +AcDbLine + 10 +137.0 + 20 +25.0 + 30 +0.0 + 11 +292.0 + 21 +25.0 + 31 +0.0 + 0 +LINE + 5 +DD +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +SHEET +100 +AcDbLine + 10 +200.0 + 20 +5.0 + 30 +0.0 + 11 +200.0 + 21 +25.0 + 31 +0.0 + 0 +LINE + 5 +DE +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +SHEET +100 +AcDbLine + 10 +250.0 + 20 +5.0 + 30 +0.0 + 11 +250.0 + 21 +25.0 + 31 +0.0 + 0 +TEXT + 5 +DF +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +SHEET +100 +AcDbText + 10 +142.0 + 20 +33.0 + 30 +0.0 + 40 +6.0 + 1 +L-BRACKET 100 x 72 x 60 + 7 +MECH + 11 +142.0 + 21 +33.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +E0 +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +SHEET +100 +AcDbText + 10 +142.0 + 20 +15.0 + 30 +0.0 + 40 +3.5 + 1 +Material: steel S235 + 7 +MECH + 11 +142.0 + 21 +15.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +E1 +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +SHEET +100 +AcDbText + 10 +205.0 + 20 +15.0 + 30 +0.0 + 40 +3.5 + 1 +Scale 1:1 + 7 +MECH + 11 +205.0 + 21 +15.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +E2 +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +SHEET +100 +AcDbText + 10 +255.0 + 20 +15.0 + 30 +0.0 + 40 +3.5 + 1 +Sheet 1/1 + 7 +MECH + 11 +255.0 + 21 +15.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +E3 +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +SHEET +100 +AcDbText + 10 +142.0 + 20 +8.0 + 30 +0.0 + 40 +3.0 + 1 +Drawn: exav demo + 7 +MECH + 11 +142.0 + 21 +8.0 + 31 +0.0 +100 +AcDbText + 0 +VIEWPORT + 5 +E4 +330 +D5 +100 +AcDbEntity + 67 +1 + 8 +VIEWPORTS +100 +AcDbViewport + 10 +130.0 + 20 +120.0 + 30 +0.0 + 40 +250.0 + 41 +140.0 + 68 +1 + 69 +3 + 12 +90.0 + 22 +-30.0 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 45 +140.0 + 50 +0.0 + 51 +0.0 + 72 +100 + 90 +0 + 1 + +281 +0 + 71 +0 + 74 +0 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 +282 +0 + 0 +ENDBLK + 5 +D7 +330 +D5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LWPOLYLINE + 5 +4B +330 +17 +100 +AcDbEntity + 8 +OUTLINE +100 +AcDbPolyline + 90 +7 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +100.0 + 20 +0.0 + 10 +100.0 + 20 +12.0 + 10 +20.0 + 20 +12.0 + 10 +12.0 + 20 +12.0 + 10 +12.0 + 20 +72.0 + 10 +0.0 + 20 +72.0 + 0 +ARC + 5 +4C +330 +17 +100 +AcDbEntity + 8 +OUTLINE +100 +AcDbCircle + 10 +20.0 + 20 +20.0 + 30 +0.0 + 40 +8.0 +100 +AcDbArc + 50 +180.0 + 51 +270.0 + 0 +LINE + 5 +4D +330 +17 +100 +AcDbEntity + 8 +OUTLINE + 62 +8 +100 +AcDbLine + 10 +12.0 + 20 +12.0 + 30 +0.0 + 11 +12.0 + 21 +20.0 + 31 +0.0 + 0 +LINE + 5 +4E +330 +17 +100 +AcDbEntity + 8 +OUTLINE +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +100.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +4F +330 +17 +100 +AcDbEntity + 8 +HIDDEN +100 +AcDbLine + 10 +31.0 + 20 +0.0 + 30 +0.0 + 11 +31.0 + 21 +12.0 + 31 +0.0 + 0 +LINE + 5 +50 +330 +17 +100 +AcDbEntity + 8 +HIDDEN +100 +AcDbLine + 10 +39.0 + 20 +0.0 + 30 +0.0 + 11 +39.0 + 21 +12.0 + 31 +0.0 + 0 +LINE + 5 +51 +330 +17 +100 +AcDbEntity + 8 +CENTER +100 +AcDbLine + 10 +35.0 + 20 +-6.0 + 30 +0.0 + 11 +35.0 + 21 +18.0 + 31 +0.0 + 0 +LINE + 5 +52 +330 +17 +100 +AcDbEntity + 8 +HIDDEN +100 +AcDbLine + 10 +76.0 + 20 +0.0 + 30 +0.0 + 11 +76.0 + 21 +12.0 + 31 +0.0 + 0 +LINE + 5 +53 +330 +17 +100 +AcDbEntity + 8 +HIDDEN +100 +AcDbLine + 10 +84.0 + 20 +0.0 + 30 +0.0 + 11 +84.0 + 21 +12.0 + 31 +0.0 + 0 +LINE + 5 +54 +330 +17 +100 +AcDbEntity + 8 +CENTER +100 +AcDbLine + 10 +80.0 + 20 +-6.0 + 30 +0.0 + 11 +80.0 + 21 +18.0 + 31 +0.0 + 0 +LINE + 5 +55 +330 +17 +100 +AcDbEntity + 8 +CENTER +100 +AcDbLine + 10 +-6.0 + 20 +52.0 + 30 +0.0 + 11 +18.0 + 21 +52.0 + 31 +0.0 + 0 +LINE + 5 +56 +330 +17 +100 +AcDbEntity + 8 +HIDDEN +100 +AcDbLine + 10 +0.0 + 20 +45.0 + 30 +0.0 + 11 +12.0 + 21 +45.0 + 31 +0.0 + 0 +LINE + 5 +57 +330 +17 +100 +AcDbEntity + 8 +HIDDEN +100 +AcDbLine + 10 +0.0 + 20 +59.0 + 30 +0.0 + 11 +12.0 + 21 +59.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +58 +330 +17 +100 +AcDbEntity + 8 +OUTLINE +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-90.0 + 10 +100.0 + 20 +-90.0 + 10 +100.0 + 20 +-150.0 + 10 +0.0 + 20 +-150.0 + 0 +LINE + 5 +59 +330 +17 +100 +AcDbEntity + 8 +OUTLINE +100 +AcDbLine + 10 +12.0 + 20 +-90.0 + 30 +0.0 + 11 +12.0 + 21 +-150.0 + 31 +0.0 + 0 +CIRCLE + 5 +5A +330 +17 +100 +AcDbEntity + 8 +OUTLINE +100 +AcDbCircle + 10 +35.0 + 20 +-120.0 + 30 +0.0 + 40 +4.0 + 0 +LINE + 5 +5B +330 +17 +100 +AcDbEntity + 8 +CENTER +100 +AcDbLine + 10 +27.0 + 20 +-120.0 + 30 +0.0 + 11 +43.0 + 21 +-120.0 + 31 +0.0 + 0 +LINE + 5 +5C +330 +17 +100 +AcDbEntity + 8 +CENTER +100 +AcDbLine + 10 +35.0 + 20 +-112.0 + 30 +0.0 + 11 +35.0 + 21 +-128.0 + 31 +0.0 + 0 +CIRCLE + 5 +5D +330 +17 +100 +AcDbEntity + 8 +OUTLINE +100 +AcDbCircle + 10 +80.0 + 20 +-120.0 + 30 +0.0 + 40 +4.0 + 0 +LINE + 5 +5E +330 +17 +100 +AcDbEntity + 8 +CENTER +100 +AcDbLine + 10 +72.0 + 20 +-120.0 + 30 +0.0 + 11 +88.0 + 21 +-120.0 + 31 +0.0 + 0 +LINE + 5 +5F +330 +17 +100 +AcDbEntity + 8 +CENTER +100 +AcDbLine + 10 +80.0 + 20 +-112.0 + 30 +0.0 + 11 +80.0 + 21 +-128.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +60 +330 +17 +100 +AcDbEntity + 8 +HIDDEN +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +0.0 + 20 +-110.0 + 10 +12.0 + 20 +-110.0 + 0 +LWPOLYLINE + 5 +61 +330 +17 +100 +AcDbEntity + 8 +HIDDEN +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +0.0 + 20 +-130.0 + 10 +12.0 + 20 +-130.0 + 0 +LWPOLYLINE + 5 +62 +330 +17 +100 +AcDbEntity + 8 +OUTLINE + 62 +8 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +0.0 + 20 +-110.0 + 10 +0.0 + 20 +-130.0 + 0 +LWPOLYLINE + 5 +63 +330 +17 +100 +AcDbEntity + 8 +OUTLINE +100 +AcDbPolyline + 90 +6 + 70 +1 + 10 +150.0 + 20 +0.0 + 10 +181.0 + 20 +0.0 + 10 +181.0 + 20 +12.0 + 10 +162.0 + 20 +12.0 + 10 +162.0 + 20 +72.0 + 10 +150.0 + 20 +72.0 + 0 +LWPOLYLINE + 5 +64 +330 +17 +100 +AcDbEntity + 8 +OUTLINE +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +189.0 + 20 +0.0 + 10 +210.0 + 20 +0.0 + 10 +210.0 + 20 +12.0 + 10 +189.0 + 20 +12.0 + 0 +HATCH + 5 +65 +330 +17 +100 +AcDbEntity + 8 +SECTION + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +6 + 10 +150.0 + 20 +0.0 + 10 +181.0 + 20 +0.0 + 10 +181.0 + 20 +12.0 + 10 +162.0 + 20 +12.0 + 10 +162.0 + 20 +72.0 + 10 +150.0 + 20 +72.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +2.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-4.4901280606 + 46 +4.4901280606 + 79 +0 + 98 +0 + 0 +HATCH + 5 +66 +330 +17 +100 +AcDbEntity + 8 +SECTION + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +189.0 + 20 +0.0 + 10 +210.0 + 20 +0.0 + 10 +210.0 + 20 +12.0 + 10 +189.0 + 20 +12.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +2.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-4.4901280606 + 46 +4.4901280606 + 79 +0 + 98 +0 + 0 +LINE + 5 +67 +330 +17 +100 +AcDbEntity + 8 +CENTER +100 +AcDbLine + 10 +185.0 + 20 +-6.0 + 30 +0.0 + 11 +185.0 + 21 +18.0 + 31 +0.0 + 0 +TEXT + 5 +68 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +150.0 + 20 +-14.0 + 30 +0.0 + 40 +5.0 + 1 +SECTION A-A + 7 +MECH + 11 +150.0 + 21 +-14.0 + 31 +0.0 +100 +AcDbText + 0 +LWPOLYLINE + 5 +69 +330 +17 +100 +AcDbEntity + 8 +CENTER +370 +50 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +-8.0 + 20 +-120.0 + 10 +108.0 + 20 +-120.0 + 0 +TEXT + 5 +6A +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +-14.0 + 20 +-123.0 + 30 +0.0 + 40 +6.0 + 1 +A + 7 +MECH + 11 +-14.0 + 21 +-123.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +6B +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +112.0 + 20 +-123.0 + 30 +0.0 + 40 +6.0 + 1 +A + 7 +MECH + 11 +112.0 + 21 +-123.0 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +6C +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D1 + 3 +MECH + 10 +0.0 + 20 +-12.0 + 30 +0.0 + 11 +50.0 + 21 +-9.2 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +100.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +7F +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D2 + 3 +MECHTOL + 10 +-12.0 + 20 +0.0 + 30 +0.0 + 11 +-14.8 + 21 +36.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +0.0 + 24 +72.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +8E +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D3 + 3 +MECHTOL + 10 +35.0 + 20 +-24.0 + 30 +0.0 + 11 +57.5 + 21 +-21.2 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +35.0 + 23 +0.0 + 33 +0.0 + 14 +80.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +9D +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D4 + 3 +MECH + 10 +20.0 + 20 +20.0 + 30 +0.0 + 11 +7.166011921464162 + 21 +11.125809896108832 + 31 +0.0 + 70 +36 + 71 +5 + 1 +<> +100 +AcDbRadialDimension + 15 +14.343145750507619 + 25 +14.34314575050762 + 35 +0.0 + 0 +DIMENSION + 5 +A8 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D5 + 3 +MECH + 10 +0.0 + 20 +-78.0 + 30 +0.0 + 11 +50.0 + 21 +-75.2 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +-90.0 + 33 +0.0 + 14 +100.0 + 24 +-90.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +B7 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D6 + 3 +MECH + 10 +83.27660817715596 + 20 +-117.70569425459581 + 30 +0.0 + 11 +63.36254596551408 + 21 +-128.23150188303254 + 31 +0.0 + 70 +35 + 71 +5 + 1 +2x ⌀<> +100 +AcDbDiametricDimension + 15 +76.72339182284404 + 25 +-122.29430574540419 + 35 +0.0 + 0 +DIMENSION + 5 +C4 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D7 + 3 +MECH + 10 +220.0 + 20 +0.0 + 30 +0.0 + 11 +217.2 + 21 +6.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +210.0 + 23 +0.0 + 33 +0.0 + 14 +210.0 + 24 +12.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +LEADER + 5 +D3 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbLeader + 3 +Standard + 73 +3 + 76 +3 + 10 +155.0 + 20 +60.0 + 30 +0.0 + 10 +138.0 + 20 +80.0 + 30 +0.0 + 10 +110.0 + 20 +80.0 + 30 +0.0 + 0 +TEXT + 5 +D4 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +110.0 + 20 +82.0 + 30 +0.0 + 40 +3.5 + 1 +slot 14 x 12 + 7 +MECH + 11 +110.0 + 21 +82.0 + 31 +0.0 +100 +AcDbText + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +A +330 +0 +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ACAD_COLOR +350 +B + 3 +ACAD_GROUP +350 +C + 3 +ACAD_LAYOUT +350 +D + 3 +ACAD_MATERIAL +350 +E + 3 +ACAD_MLEADERSTYLE +350 +F + 3 +ACAD_MLINESTYLE +350 +10 + 3 +ACAD_PLOTSETTINGS +350 +11 + 3 +ACAD_PLOTSTYLENAME +350 +12 + 3 +ACAD_SCALELIST +350 +14 + 3 +ACAD_TABLESTYLE +350 +15 + 3 +ACAD_VISUALSTYLE +350 +16 + 3 +EZDXF_META +350 +2D + 0 +DICTIONARY + 5 +B +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +C +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +D +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Model +350 +1A + 3 +Layout1 +350 +1E + 3 +A4 Sheet +350 +D8 + 0 +DICTIONARY + 5 +E +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ByBlock +350 +1F + 3 +ByLayer +350 +20 + 3 +Global +350 +21 + 0 +DICTIONARY + 5 +F +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +2C + 0 +DICTIONARY + 5 +10 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +22 + 0 +DICTIONARY + 5 +11 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +ACDBDICTIONARYWDFLT + 5 +12 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Normal +350 +13 +100 +AcDbDictionaryWithDefault +340 +13 + 0 +ACDBPLACEHOLDER + 5 +13 +330 +12 + 0 +DICTIONARY + 5 +14 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +15 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +16 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +LAYOUT + 5 +1A +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +1024 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 +1 + 71 +0 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +17 + 0 +LAYOUT + 5 +1E +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +0 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 +1 + 71 +1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +1B + 0 +MATERIAL + 5 +1F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByBlock + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +20 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByLayer + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +21 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +Global + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MLINESTYLE + 5 +22 +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMlineStyle + 2 +Standard + 70 +0 + 3 + + 62 +256 + 51 +90.0 + 52 +90.0 + 71 +2 + 49 +0.5 + 62 +256 + 6 +BYLAYER + 49 +-0.5 + 62 +256 + 6 +BYLAYER + 0 +MLEADERSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +F +102 +} +330 +F +100 +AcDbMLeaderStyle +179 +2 +170 +2 +171 +1 +172 +0 + 90 +2 + 40 +0.0 + 41 +0.0 +173 +1 + 91 +-1056964608 + 92 +-2 +290 +1 + 42 +2.0 +291 +1 + 43 +8.0 + 3 +Standard + 44 +4.0 +300 + +342 +29 +174 +1 +175 +1 +176 +0 +178 +1 + 93 +-1056964608 + 45 +4.0 +292 +0 +297 +0 + 46 +4.0 + 94 +-1056964608 + 47 +1.0 + 49 +1.0 +140 +1.0 +294 +1 +141 +0.0 +177 +0 +142 +1.0 +295 +0 +296 +0 +143 +3.75 +271 +0 +272 +9 +273 +9 + 0 +DICTIONARY + 5 +2D +330 +A +100 +AcDbDictionary +281 +1 + 3 +CREATED_BY_EZDXF +350 +2E + 3 +WRITTEN_BY_EZDXF +350 +E8 + 0 +DICTIONARYVAR + 5 +2E +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +LAYOUT + 5 +D8 +330 +D +100 +AcDbPlotSettings + 1 + + 2 +DWG to PDF.pc3 + 4 +ezdxf_(297.00_x_210.00_MM) + 6 + + 40 +5.0 + 41 +5.0 + 42 +5.0 + 43 +5.0 + 44 +297.0 + 45 +210.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +672 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +A4 Sheet + 70 +1 + 71 +3 + 10 +-5.0 + 20 +-5.0 + 11 +292.0 + 21 +205.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +D5 +331 +D9 + 0 +DICTIONARYVAR + 5 +E8 +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +ENDSEC + 0 +EOF diff --git a/crates/exav-viewer/demo/examples/files/cad/dimensions.dxf b/crates/exav-viewer/demo/examples/files/cad/dimensions.dxf new file mode 100644 index 0000000..87ae230 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/cad/dimensions.dxf @@ -0,0 +1,10562 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1032 + 9 +$ACADMAINTVER + 90 +4 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$LASTSAVEDBY + 1 +ezdxf + 9 +$REQUIREDVERSIONS +160 +0 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$EXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 +0 + 9 +$REGENMODE + 70 +1 + 9 +$FILLMODE + 70 +1 + 9 +$QTEXTMODE + 70 +0 + 9 +$MIRRTEXT + 70 +1 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 +1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 +256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 +0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 +0 + 9 +$DIMLIM + 70 +0 + 9 +$DIMTIH + 70 +0 + 9 +$DIMTOH + 70 +0 + 9 +$DIMSE1 + 70 +0 + 9 +$DIMSE2 + 70 +0 + 9 +$DIMTAD + 70 +1 + 9 +$DIMZIN + 70 +8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 +1 + 9 +$DIMSHO + 70 +1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 +0 + 9 +$DIMALTD + 70 +3 + 9 +$DIMALTF + 40 +0.03937007874 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 +1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 +0 + 9 +$DIMSOXD + 70 +0 + 9 +$DIMSAH + 70 +0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 +0 + 9 +$DIMCLRE + 70 +0 + 9 +$DIMCLRT + 70 +0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 +0 + 9 +$DIMSD1 + 70 +0 + 9 +$DIMSD2 + 70 +0 + 9 +$DIMTOLJ + 70 +0 + 9 +$DIMTZIN + 70 +8 + 9 +$DIMALTZ + 70 +0 + 9 +$DIMALTTZ + 70 +0 + 9 +$DIMUPT + 70 +0 + 9 +$DIMDEC + 70 +2 + 9 +$DIMTDEC + 70 +2 + 9 +$DIMALTU + 70 +2 + 9 +$DIMALTTD + 70 +3 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 +0 + 9 +$DIMADEC + 70 +0 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 +0 + 9 +$DIMDSEP + 70 +44 + 9 +$DIMATFIT + 70 +3 + 9 +$DIMFRAC + 70 +0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 +2 + 9 +$DIMLWD + 70 +-2 + 9 +$DIMLWE + 70 +-2 + 9 +$DIMTMOVE + 70 +0 + 9 +$DIMFXL + 40 +1.0 + 9 +$DIMFXLON + 70 +0 + 9 +$DIMJOGANG + 40 +0.785398163397 + 9 +$DIMTFILL + 70 +0 + 9 +$DIMTFILLCLR + 70 +0 + 9 +$DIMARCSYM + 70 +0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$DIMTXTDIRECTION + 70 +0 + 9 +$LUNITS + 70 +2 + 9 +$LUPREC + 70 +4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 +0 + 9 +$AUPREC + 70 +2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 +0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 +0 + 9 +$TDCREATE + 40 +2451545.0 + 9 +$TDUCREATE + 40 +2451545.0 + 9 +$TDUPDATE + 40 +2451545.0 + 9 +$TDUUPDATE + 40 +2451545.0 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 +1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 +0 + 9 +$PDMODE + 70 +0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 +0 + 9 +$SPLINETYPE + 70 +6 + 9 +$SPLINESEGS + 70 +8 + 9 +$HANDSEED + 5 +153 + 9 +$SURFTAB1 + 70 +6 + 9 +$SURFTAB2 + 70 +6 + 9 +$SURFTYPE + 70 +6 + 9 +$SURFU + 70 +6 + 9 +$SURFV + 70 +6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 +0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 +0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 +0 + 9 +$USERI2 + 70 +0 + 9 +$USERI3 + 70 +0 + 9 +$USERI4 + 70 +0 + 9 +$USERI5 + 70 +0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 +1 + 9 +$SHADEDGE + 70 +3 + 9 +$SHADEDIF + 70 +70 + 9 +$TILEMODE + 70 +1 + 9 +$MAXACTVP + 70 +64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 +0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 +0 + 9 +$VISRETAIN + 70 +1 + 9 +$PLINEGEN + 70 +0 + 9 +$PSLTSCALE + 70 +1 + 9 +$TREEDEPTH + 70 +3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 +0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 +1 + 9 +$MEASUREMENT + 70 +1 + 9 +$CELWEIGHT +370 +-1 + 9 +$ENDCAPS +280 +0 + 9 +$JOINSTYLE +280 +0 + 9 +$LWDISPLAY +290 +0 + 9 +$INSUNITS + 70 +4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 +1 + 9 +$CEPSNTYPE +380 +0 + 9 +$PSTYLEMODE +290 +1 + 9 +$FINGERPRINTGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$VERSIONGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$EXTNAMES +290 +1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 +0 + 9 +$SORTENTS +280 +127 + 9 +$INDEXCTL +280 +0 + 9 +$HIDETEXT +280 +1 + 9 +$XCLIPFRAME +280 +1 + 9 +$HALOGAP +280 +0 + 9 +$OBSCOLOR + 70 +257 + 9 +$OBSLTYPE +280 +0 + 9 +$INTERSECTIONDISPLAY +280 +0 + 9 +$INTERSECTIONCOLOR + 70 +257 + 9 +$DIMASSOC +280 +2 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 +0 + 9 +$LENSLENGTH + 40 +50.0 + 9 +$CAMERAHEIGHT + 40 +0.0 + 9 +$STEPSPERSEC + 40 +24.0 + 9 +$STEPSIZE + 40 +100.0 + 9 +$3DDWFPREC + 40 +2.0 + 9 +$PSOLWIDTH + 40 +0.005 + 9 +$PSOLHEIGHT + 40 +0.08 + 9 +$LOFTANG1 + 40 +1.570796326795 + 9 +$LOFTANG2 + 40 +1.570796326795 + 9 +$LOFTMAG1 + 40 +0.0 + 9 +$LOFTMAG2 + 40 +0.0 + 9 +$LOFTPARAM + 70 +7 + 9 +$LOFTNORMALS +280 +1 + 9 +$LATITUDE + 40 +37.795 + 9 +$LONGITUDE + 40 +-122.394 + 9 +$NORTHDIRECTION + 40 +0.0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 +1 + 9 +$TILEMODELIGHTSYNCH +280 +1 + 9 +$CMATERIAL +347 +20 + 9 +$SOLIDHIST +280 +0 + 9 +$SHOWHIST +280 +1 + 9 +$DWFFRAME +280 +2 + 9 +$DGNFRAME +280 +2 + 9 +$REALWORLDSCALE +290 +1 + 9 +$INTERFERECOLOR + 62 +256 + 9 +$CSHADOW +280 +0 + 9 +$SHADOWPLANELOCATION + 40 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +CELLSTYLEMAP + 2 +AcDbCellStyleMap + 3 +ObjectDBX Classes + 90 +1152 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MENTALRAYRENDERSETTINGS + 2 +AcDbMentalRayRenderSettings + 3 +SCENEOE + 90 +1024 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBDETAILVIEWSTYLE + 2 +AcDbDetailViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBSECTIONVIEWSTYLE + 2 +AcDbSectionViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +RASTERVARIABLES + 2 +AcDbRasterVariables + 3 +ISM + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ARC_DIMENSION + 2 +AcDbArcDimension + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +1 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 +1 + 0 +VPORT + 5 +14F +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +152.28944372309257 + 22 +-33.04999999999998 + 13 +0.0 + 23 +0.0 + 14 +0.5 + 24 +0.5 + 15 +0.5 + 25 +0.5 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +308.80500000000006 + 41 +1.34 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +1000 + 73 +1 + 74 +3 + 75 +0 + 76 +0 + 77 +0 + 78 +0 +281 +0 + 65 +1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 +21 + 0 +LTYPE + 5 +24 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +25 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +26 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +2F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 +0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +5.08 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +30 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 +0 + 3 +Center (2x) ________ __ ________ __ ________ + 72 +65 + 73 +4 + 40 +8.89 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 +0 + 3 +Center (.5x) ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +2.54 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +32 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 +0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 +65 + 73 +2 + 40 +1.524 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +33 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 +0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ____ + 72 +65 + 73 +2 + 40 +3.048 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +34 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 +0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 +65 + 73 +2 + 40 +0.762 + 49 +0.635 + 74 +0 + 49 +-0.127 + 74 +0 + 0 +LTYPE + 5 +35 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM + 70 +0 + 3 +Phantom ______ __ __ ______ __ __ ______ + 72 +65 + 73 +6 + 40 +6.35 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOMX2 + 70 +0 + 3 +Phantom (2x)____________ ____ ____ ____________ + 72 +65 + 73 +6 + 40 +10.795 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +37 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 +0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___ + 72 +65 + 73 +6 + 40 +3.175 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +38 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 +0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 +65 + 73 +4 + 40 +3.556 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +39 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 +0 + 3 +Dash dot (2x) ____ . ____ . ____ . ____ + 72 +65 + 73 +4 + 40 +6.096 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 +0 + 3 +Dash dot (.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +4 + 40 +1.778 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 +0 + 3 +Dot . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.508 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 +0 + 3 +Dot (2x) . . . . . . . . + 72 +65 + 73 +2 + 40 +1.016 + 49 +0.0 + 74 +0 + 49 +-1.016 + 74 +0 + 0 +LTYPE + 5 +3D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 +0 + 3 +Dot (.5) . . . . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.254 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 +0 + 3 +Divide __ . . __ . . __ . . __ . . __ . . __ + 72 +65 + 73 +6 + 40 +4.064 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 +0 + 3 +Divide (2x) ____ . . ____ . . ____ . . ____ + 72 +65 + 73 +6 + 40 +6.604 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +40 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 +0 + 3 +Divide(.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +6 + 40 +2.032 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 +5 + 0 +LAYER + 5 +27 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 62 +7 + 6 +Continuous +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +28 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Defpoints + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +41 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +OBJECT + 70 +0 + 62 +7 + 6 +Continuous +370 +35 +390 +13 +347 +21 + 0 +LAYER + 5 +42 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +DIMS + 70 +0 + 62 +3 + 6 +Continuous +370 +13 +390 +13 +347 +21 + 0 +LAYER + 5 +43 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +NOTE + 70 +0 + 62 +2 + 6 +Continuous +370 +13 +390 +13 +347 +21 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 +2 + 0 +STYLE + 5 +29 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +44 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +DIM-TEXT + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 +3 + 0 +APPID + 5 +2A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 +0 + 0 +APPID + 5 +150 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +HATCHBACKGROUNDCOLOR + 70 +0 + 0 +APPID + 5 +151 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +EZDXF + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +4 +330 +0 +100 +AcDbSymbolTable + 70 +4 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +2B +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 +0 + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +0 +177 +0 +178 +0 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +371 +-2 +372 +-2 + 0 +DIMSTYLE +105 +45 +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +METRIC + 70 +0 + 40 +1.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 43 +3.75 + 44 +2.1 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +3.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +1.05 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +3 +177 +3 +178 +2 +179 +2 +271 +1 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +340 +44 +371 +-2 +372 +-2 + 0 +DIMSTYLE +105 +46 +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +TOL + 70 +0 + 40 +1.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 43 +3.75 + 44 +2.1 + 45 +0.0 + 46 +0.0 + 47 +0.05 + 48 +0.02 + 49 +2.5 +140 +3.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +0.7 +147 +1.05 +148 +0.0 + 69 +0 + 70 +0 + 71 +1 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +3 +177 +3 +178 +2 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +1 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +340 +44 +371 +-2 +372 +-2 + 0 +DIMSTYLE +105 +47 +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ARCH + 70 +0 + 40 +1.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 43 +3.75 + 44 +2.1 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +3.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +1.05 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +1 + 74 +0 + 75 +0 + 76 +0 + 77 +0 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +3 +177 +3 +178 +2 +179 +2 +271 +0 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +340 +44 +371 +-2 +372 +-2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 +21 + 0 +BLOCK_RECORD + 5 +17 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +1A + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +4A +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D1 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +4F +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_CLOSEDFILLED +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +5D +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D2 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +6C +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D3 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +7B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D4 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +8A +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D5 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +9A +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D6 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +A8 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D7 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +B4 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D8 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +C6 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D9 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +D7 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D10 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +EA +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D11 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +F5 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D12 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +100 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D13 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +10B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D14 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +116 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D15 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +121 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D16 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +131 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D17 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +141 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D18 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +18 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +19 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +4B +330 +4A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D1 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D1 + 1 + + 0 +LINE + 5 +4D +330 +4A +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +-2.8000000000000003 + 30 +0.0 + 11 +0.0 + 21 +-14.1 + 31 +0.0 + 0 +LINE + 5 +4E +330 +4A +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +80.0 + 20 +-2.8000000000000003 + 30 +0.0 + 11 +80.0 + 21 +-14.1 + 31 +0.0 + 0 +INSERT + 5 +53 +330 +4A +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +-12.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +180.0 + 0 +INSERT + 5 +55 +330 +4A +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +80.0 + 20 +-12.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 0 +LINE + 5 +57 +330 +4A +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +2.8000000000000003 + 20 +-12.0 + 30 +0.0 + 11 +77.2 + 21 +-12.0 + 31 +0.0 + 0 +MTEXT + 5 +58 +330 +4A +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +40.0 + 20 +-9.2 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +80 + 7 +DIM-TEXT + 0 +POINT + 5 +59 +330 +4A +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-12.0 + 30 +0.0 + 0 +POINT + 5 +5A +330 +4A +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +5B +330 +4A +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +80.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +4C +330 +4A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +50 +330 +4F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_CLOSEDFILLED + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_CLOSEDFILLED + 1 + + 0 +SOLID + 5 +52 +330 +4F +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 +0 +100 +AcDbTrace + 10 +-1.0 + 20 +0.16439898372402537 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 12 +-1.0 + 22 +-0.16439898372402537 + 32 +0.0 + 13 +-1.0 + 23 +-0.16439898372402537 + 33 +0.0 + 0 +ENDBLK + 5 +51 +330 +4F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +5E +330 +5D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D2 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D2 + 1 + + 0 +LINE + 5 +60 +330 +5D +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-2.8000000000000003 + 20 +0.0 + 30 +0.0 + 11 +-16.1 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +61 +330 +5D +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-2.8000000000000003 + 20 +50.0 + 30 +0.0 + 11 +-16.1 + 21 +50.0 + 31 +0.0 + 0 +INSERT + 5 +62 +330 +5D +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-14.0 + 20 +0.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +270.0 + 0 +INSERT + 5 +64 +330 +5D +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-14.0 + 20 +50.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +90.0 + 0 +LINE + 5 +66 +330 +5D +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-14.0 + 20 +2.8000000000000003 + 30 +0.0 + 11 +-14.0 + 21 +47.2 + 31 +0.0 + 0 +MTEXT + 5 +67 +330 +5D +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +-16.8 + 20 +25.0 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +50 + 7 +DIM-TEXT + 50 +90.0 + 0 +POINT + 5 +68 +330 +5D +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-14.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +69 +330 +5D +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +6A +330 +5D +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +50.0 + 30 +0.0 + 0 +ENDBLK + 5 +5F +330 +5D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +6D +330 +6C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D3 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D3 + 1 + + 0 +LINE + 5 +6F +330 +6C +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +52.8 + 30 +0.0 + 11 +0.0 + 21 +64.1 + 31 +0.0 + 0 +LINE + 5 +70 +330 +6C +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +80.0 + 20 +52.8 + 30 +0.0 + 11 +80.0 + 21 +64.1 + 31 +0.0 + 0 +INSERT + 5 +71 +330 +6C +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +62.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +180.0 + 0 +INSERT + 5 +73 +330 +6C +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +80.0 + 20 +62.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 0 +LINE + 5 +75 +330 +6C +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +2.8000000000000003 + 20 +62.0 + 30 +0.0 + 11 +77.2 + 21 +62.0 + 31 +0.0 + 0 +MTEXT + 5 +76 +330 +6C +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +40.0 + 20 +64.8 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +\A1;80{\H0.70x;\S+0,05^ -0,02;} + 7 +DIM-TEXT + 0 +POINT + 5 +77 +330 +6C +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +62.0 + 30 +0.0 + 0 +POINT + 5 +78 +330 +6C +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +50.0 + 30 +0.0 + 0 +POINT + 5 +79 +330 +6C +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +80.0 + 20 +50.0 + 30 +0.0 + 0 +ENDBLK + 5 +6E +330 +6C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +7C +330 +7B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D4 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D4 + 1 + + 0 +LINE + 5 +7E +330 +7B +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +52.8 + 30 +0.0 + 11 +0.0 + 21 +72.1 + 31 +0.0 + 0 +LINE + 5 +7F +330 +7B +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +80.0 + 20 +52.8 + 30 +0.0 + 11 +80.0 + 21 +72.1 + 31 +0.0 + 0 +INSERT + 5 +80 +330 +7B +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +70.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +180.0 + 0 +INSERT + 5 +82 +330 +7B +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +80.0 + 20 +70.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 0 +LINE + 5 +84 +330 +7B +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +2.8000000000000003 + 20 +70.0 + 30 +0.0 + 11 +77.2 + 21 +70.0 + 31 +0.0 + 0 +MTEXT + 5 +85 +330 +7B +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +40.0 + 20 +74.9 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +80 overall (text override) + 7 +DIM-TEXT + 0 +POINT + 5 +86 +330 +7B +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +70.0 + 30 +0.0 + 0 +POINT + 5 +87 +330 +7B +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +50.0 + 30 +0.0 + 0 +POINT + 5 +88 +330 +7B +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +80.0 + 20 +50.0 + 30 +0.0 + 0 +ENDBLK + 5 +7D +330 +7B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8B +330 +8A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D5 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D5 + 1 + + 0 +LINE + 5 +8D +330 +8A +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +77.59901980800488 + 20 +1.4405881151970736 + 30 +0.0 + 11 +67.90934974745312 + 21 +7.254390151528121 + 31 +0.0 + 0 +LINE + 5 +8E +330 +8A +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +107.59901980800488 + 20 +51.44058811519707 + 30 +0.0 + 11 +97.90934974745312 + 21 +57.254390151528135 + 31 +0.0 + 0 +INSERT + 5 +8F +330 +8A +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +69.71008489144947 + 20 +6.173949065130316 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +239.03624346792648 + 0 +INSERT + 5 +91 +330 +8A +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +99.71008489144947 + 20 +56.17394906513033 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +59.03624346792648 + 0 +LINE + 5 +93 +330 +8A +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +71.15067300664654 + 20 +8.57492925712544 + 30 +0.0 + 11 +98.2694967762524 + 21 +53.772968873135206 + 31 +0.0 + 0 +MTEXT + 5 +94 +330 +8A +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +82.30910469945435 + 20 +32.614537180327396 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +58,3 + 7 +DIM-TEXT + 50 +59.03624346792648 + 0 +POINT + 5 +95 +330 +8A +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +69.71008489144947 + 20 +6.173949065130316 + 30 +0.0 + 0 +POINT + 5 +96 +330 +8A +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +80.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +97 +330 +8A +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +110.0 + 20 +50.0 + 30 +0.0 + 0 +ENDBLK + 5 +8C +330 +8A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +9B +330 +9A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D6 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D6 + 1 + + 0 +INSERT + 5 +9D +330 +9A +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +130.84888892202554 + 20 +8.930309757836518 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +39.99999999999997 + 0 +INSERT + 5 +9F +330 +9A +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +169.15111107797446 + 20 +41.06969024216348 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +39.99999999999997 + 0 +LINE + 5 +A1 +330 +9A +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +128.7039644812924 + 20 +7.130504450714209 + 30 +0.0 + 11 +167.0061866372413 + 21 +39.26988493504117 + 31 +0.0 + 0 +LINE + 5 +A2 +330 +9A +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +128.7039644812924 + 20 +7.130504450714209 + 30 +0.0 + 11 +119.8561511632682 + 21 +-0.2936924411653168 + 31 +0.0 + 0 +MTEXT + 5 +A3 +330 +9A +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +122.07807918252053 + 20 +5.2258669504221515 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +%%c50 + 7 +DIM-TEXT + 50 +39.99999999999997 + 0 +POINT + 5 +A4 +330 +9A +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +150.0 + 20 +25.0 + 30 +0.0 + 0 +POINT + 5 +A5 +330 +9A +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +130.84888892202554 + 20 +8.930309757836518 + 30 +0.0 + 0 +ENDBLK + 5 +9C +330 +9A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +A9 +330 +A8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D7 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D7 + 1 + + 0 +INSERT + 5 +AB +330 +A8 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +229.0 + 20 +9.411542731880106 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +120.0 + 0 +LINE + 5 +AD +330 +A8 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +220.0 + 20 +25.0 + 30 +0.0 + 11 +229.0 + 21 +9.411542731880106 + 31 +0.0 + 0 +LINE + 5 +AE +330 +A8 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +230.4 + 20 +6.9866716012836765 + 30 +0.0 + 11 +236.175 + 21 +-3.0159218124265887 + 31 +0.0 + 0 +MTEXT + 5 +AF +330 +A8 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +235.97487113059643 + 20 +2.9307115574417146 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +R18 + 7 +DIM-TEXT + 50 +300.0 + 0 +POINT + 5 +B0 +330 +A8 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +220.0 + 20 +25.0 + 30 +0.0 + 0 +POINT + 5 +B1 +330 +A8 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +229.0 + 20 +9.411542731880106 + 30 +0.0 + 0 +ENDBLK + 5 +AA +330 +A8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B5 +330 +B4 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D8 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D8 + 1 + + 0 +LINE + 5 +B7 +330 +B4 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +330.2188441696369 + 20 +14.63846213433862 + 30 +0.0 + 11 +337.078600301374 + 21 +17.135209180616002 + 31 +0.0 + 0 +LINE + 5 +B8 +330 +B4 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +257.2132978345078 + 20 +27.511309694583893 + 30 +0.0 + 11 +251.62117339973923 + 21 +32.20365924529563 + 31 +0.0 + 0 +INSERT + 5 +B9 +330 +B4 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +335.10524579772357 + 20 +16.4169668796321 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +291.6711269024649 + 0 +INSERT + 5 +BB +330 +B4 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +253.22986673028907 + 20 +30.853805264953902 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +-131.67112690246492 + 0 +MTEXT + 5 +BD +330 +B4 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +298.8213274254801 + 20 +50.028233853020154 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +83,8 + 7 +DIM-TEXT + 50 +-10.000000000000018 + 0 +ARC + 5 +BE +330 +B4 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbCircle + 10 +290.0 + 20 +0.0 + 30 +0.0 + 40 +47.99999999999999 +100 +AcDbArc + 50 +23.342253804929804 + 51 +136.6577461950702 + 0 +POINT + 5 +BF +330 +B4 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +298.33511252801264 + 20 +47.27077214458598 + 30 +0.0 + 0 +POINT + 5 +C0 +330 +B4 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +327.5877048314363 + 20 +13.680805733026748 + 30 +0.0 + 0 +POINT + 5 +C1 +330 +B4 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +259.3582222752409 + 20 +25.71150438746158 + 30 +0.0 + 0 +POINT + 5 +C2 +330 +B4 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +290.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +B6 +330 +B4 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +C7 +330 +C6 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D9 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D9 + 1 + + 0 +LINE + 5 +C9 +330 +C6 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +2.0927460923142474 + 20 +-58.139781251276226 + 30 +0.0 + 11 +24.190270250470654 + 21 +-38.49753755513719 + 31 +0.0 + 0 +LINE + 5 +CA +330 +C6 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +57.2 + 20 +-60.0 + 30 +0.0 + 11 +28.16549190084311 + 21 +-60.0 + 31 +0.0 + 0 +INSERT + 5 +CB +330 +C6 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +22.62071068123497 + 20 +-39.89270161668003 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +314.2838875146575 + 0 +INSERT + 5 +CD +330 +C6 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +30.265491900843113 + 20 +-60.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +87.3496518219127 + 0 +MTEXT + 5 +CF +330 +C6 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +-30.907032852025363 + 20 +-71.75083294615946 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +318,37° + 7 +DIM-TEXT + 50 +290.8167696682851 + 0 +ARC + 5 +D0 +330 +C6 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbCircle + 10 +0.0 + 20 +-60.0 + 30 +0.0 + 40 +30.265491900843113 +100 +AcDbArc + 50 +46.934235692744785 + 51 +-5.300696356174586 + 0 +POINT + 5 +D1 +330 +C6 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +45.0 + 20 +-20.0 + 30 +0.0 + 0 +POINT + 5 +D2 +330 +C6 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-60.0 + 30 +0.0 + 0 +POINT + 5 +D3 +330 +C6 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +60.0 + 20 +-60.0 + 30 +0.0 + 0 +POINT + 5 +D4 +330 +C6 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-60.0 + 30 +0.0 + 0 +POINT + 5 +D5 +330 +C6 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +30.0 + 20 +-56.0 + 30 +0.0 + 0 +ENDBLK + 5 +C8 +330 +C6 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +D8 +330 +D7 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D10 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D10 + 1 + + 0 +LINE + 5 +DA +330 +D7 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +148.61081097260086 + 20 +-47.43108079794849 + 30 +0.0 + 11 +140.05211215395522 + 21 +-62.40880373057834 + 31 +0.0 + 0 +LINE + 5 +DB +330 +D7 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +167.2 + 20 +-80.0 + 30 +0.0 + 11 +150.2606797749979 + 21 +-80.0 + 31 +0.0 + 0 +INSERT + 5 +DC +330 +D7 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +141.0940039245046 + 20 +-60.58549313211698 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +333.8424019218803 + 0 +INSERT + 5 +DE +330 +D7 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +152.3606797749979 + 20 +-80.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +86.41271678117742 + 0 +MTEXT + 5 +E0 +330 +D7 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +108.23827411287941 + 20 +-92.62881994304354 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +299,74° + 7 +DIM-TEXT + 50 +300.12755935152893 + 0 +ARC + 5 +E1 +330 +D7 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbCircle + 10 +130.0 + 20 +-80.0 + 30 +0.0 + 40 +22.360679774997898 +100 +AcDbArc + 50 +67.42968514070293 + 51 +-7.1745664376451455 + 0 +POINT + 5 +E2 +330 +D7 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +140.0 + 20 +-60.0 + 30 +0.0 + 0 +POINT + 5 +E3 +330 +D7 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +150.0 + 20 +-45.0 + 30 +0.0 + 0 +POINT + 5 +E4 +330 +D7 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +170.0 + 20 +-80.0 + 30 +0.0 + 0 +POINT + 5 +E5 +330 +D7 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +130.0 + 20 +-80.0 + 30 +0.0 + 0 +ENDBLK + 5 +D9 +330 +D7 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +EB +330 +EA +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D11 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D11 + 1 + + 0 +LINE + 5 +ED +330 +EA +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +220.0 + 20 +-92.8 + 30 +0.0 + 11 +220.0 + 21 +-95.6 + 31 +0.0 + 0 +LINE + 5 +EE +330 +EA +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +220.0 + 20 +-95.6 + 30 +0.0 + 11 +220.0 + 21 +-96.39999999999999 + 31 +0.0 + 0 +LINE + 5 +EF +330 +EA +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +220.0 + 20 +-96.39999999999999 + 30 +0.0 + 11 +220.0 + 21 +-105.49999999999999 + 31 +0.0 + 0 +MTEXT + 5 +F0 +330 +EA +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +217.2 + 20 +-103.74999999999999 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +0 + 7 +DIM-TEXT + 50 +90.0 + 0 +POINT + 5 +F1 +330 +EA +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 0 +POINT + 5 +F2 +330 +EA +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 0 +POINT + 5 +F3 +330 +EA +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +220.0 + 20 +-101.99999999999999 + 30 +0.0 + 0 +ENDBLK + 5 +EC +330 +EA +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +F6 +330 +F5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D12 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D12 + 1 + + 0 +LINE + 5 +F8 +330 +F5 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +260.0 + 20 +-92.8 + 30 +0.0 + 11 +260.0 + 21 +-95.6 + 31 +0.0 + 0 +LINE + 5 +F9 +330 +F5 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +260.0 + 20 +-95.6 + 30 +0.0 + 11 +259.99999999999994 + 21 +-96.39999999999999 + 31 +0.0 + 0 +LINE + 5 +FA +330 +F5 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +259.99999999999994 + 20 +-96.39999999999999 + 30 +0.0 + 11 +259.99999999999994 + 21 +-108.99999999999999 + 31 +0.0 + 0 +MTEXT + 5 +FB +330 +F5 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +257.19999999999993 + 20 +-105.49999999999999 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +40 + 7 +DIM-TEXT + 50 +90.0 + 0 +POINT + 5 +FC +330 +F5 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 0 +POINT + 5 +FD +330 +F5 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +260.0 + 20 +-90.0 + 30 +0.0 + 0 +POINT + 5 +FE +330 +F5 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +259.99999999999994 + 20 +-101.99999999999999 + 30 +0.0 + 0 +ENDBLK + 5 +F7 +330 +F5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +101 +330 +100 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D13 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D13 + 1 + + 0 +LINE + 5 +103 +330 +100 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +320.0 + 20 +-92.8 + 30 +0.0 + 11 +320.0 + 21 +-95.6 + 31 +0.0 + 0 +LINE + 5 +104 +330 +100 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +320.0 + 20 +-95.6 + 30 +0.0 + 11 +320.0 + 21 +-96.4 + 31 +0.0 + 0 +LINE + 5 +105 +330 +100 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +320.0 + 20 +-96.4 + 30 +0.0 + 11 +320.0 + 21 +-112.5 + 31 +0.0 + 0 +MTEXT + 5 +106 +330 +100 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +317.2 + 20 +-107.25 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +100 + 7 +DIM-TEXT + 50 +90.0 + 0 +POINT + 5 +107 +330 +100 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 0 +POINT + 5 +108 +330 +100 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +320.0 + 20 +-90.0 + 30 +0.0 + 0 +POINT + 5 +109 +330 +100 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +320.0 + 20 +-102.0 + 30 +0.0 + 0 +ENDBLK + 5 +102 +330 +100 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +10C +330 +10B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D14 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D14 + 1 + + 0 +LINE + 5 +10E +330 +10B +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +322.8 + 20 +-90.0 + 30 +0.0 + 11 +325.6 + 21 +-90.0 + 31 +0.0 + 0 +LINE + 5 +10F +330 +10B +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +325.6 + 20 +-90.0 + 30 +0.0 + 11 +328.4 + 21 +-90.0 + 31 +0.0 + 0 +LINE + 5 +110 +330 +10B +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +328.4 + 20 +-90.0 + 30 +0.0 + 11 +337.5 + 21 +-90.0 + 31 +0.0 + 0 +MTEXT + 5 +111 +330 +10B +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +335.75 + 20 +-87.2 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +0 + 7 +DIM-TEXT + 0 +POINT + 5 +112 +330 +10B +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 0 +POINT + 5 +113 +330 +10B +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +320.0 + 20 +-90.0 + 30 +0.0 + 0 +POINT + 5 +114 +330 +10B +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +334.0 + 20 +-90.0 + 30 +0.0 + 0 +ENDBLK + 5 +10D +330 +10B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +117 +330 +116 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D15 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D15 + 1 + + 0 +LINE + 5 +119 +330 +116 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +322.8 + 20 +-60.0 + 30 +0.0 + 11 +325.6 + 21 +-60.0 + 31 +0.0 + 0 +LINE + 5 +11A +330 +116 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +325.6 + 20 +-60.0 + 30 +0.0 + 11 +328.4 + 21 +-59.999999999999986 + 31 +0.0 + 0 +LINE + 5 +11B +330 +116 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +328.4 + 20 +-59.999999999999986 + 30 +0.0 + 11 +341.0 + 21 +-59.999999999999986 + 31 +0.0 + 0 +MTEXT + 5 +11C +330 +116 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +337.5 + 20 +-57.19999999999999 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +30 + 7 +DIM-TEXT + 0 +POINT + 5 +11D +330 +116 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 0 +POINT + 5 +11E +330 +116 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +320.0 + 20 +-60.0 + 30 +0.0 + 0 +POINT + 5 +11F +330 +116 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +334.0 + 20 +-59.999999999999986 + 30 +0.0 + 0 +ENDBLK + 5 +118 +330 +116 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +122 +330 +121 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D16 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D16 + 1 + + 0 +LINE + 5 +124 +330 +121 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +322.8 + 20 +-40.0 + 30 +0.0 + 11 +325.6 + 21 +-40.0 + 31 +0.0 + 0 +LINE + 5 +125 +330 +121 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +325.6 + 20 +-40.0 + 30 +0.0 + 11 +328.4 + 21 +-40.00000000000001 + 31 +0.0 + 0 +LINE + 5 +126 +330 +121 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +328.4 + 20 +-40.00000000000001 + 30 +0.0 + 11 +341.0 + 21 +-40.00000000000001 + 31 +0.0 + 0 +MTEXT + 5 +127 +330 +121 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +337.5 + 20 +-37.20000000000001 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +50 + 7 +DIM-TEXT + 0 +POINT + 5 +128 +330 +121 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 0 +POINT + 5 +129 +330 +121 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +320.0 + 20 +-40.0 + 30 +0.0 + 0 +POINT + 5 +12A +330 +121 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +334.0 + 20 +-40.00000000000001 + 30 +0.0 + 0 +ENDBLK + 5 +123 +330 +121 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +132 +330 +131 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D17 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D17 + 1 + + 0 +LINE + 5 +134 +330 +131 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +-162.8 + 30 +0.0 + 11 +0.0 + 21 +-170.1 + 31 +0.0 + 0 +LINE + 5 +135 +330 +131 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +60.0 + 20 +-162.8 + 30 +0.0 + 11 +60.0 + 21 +-170.1 + 31 +0.0 + 0 +INSERT + 5 +136 +330 +131 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +-168.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +180.0 + 0 +INSERT + 5 +138 +330 +131 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +60.0 + 20 +-168.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 0 +LINE + 5 +13A +330 +131 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +2.8000000000000003 + 20 +-168.0 + 30 +0.0 + 11 +26.5 + 21 +-168.0 + 31 +0.0 + 0 +LINE + 5 +13B +330 +131 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +33.49999999999999 + 20 +-168.0 + 30 +0.0 + 11 +57.2 + 21 +-168.0 + 31 +0.0 + 0 +MTEXT + 5 +13C +330 +131 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +30.0 + 20 +-168.0 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +60 + 7 +DIM-TEXT + 0 +POINT + 5 +13D +330 +131 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-168.0 + 30 +0.0 + 0 +POINT + 5 +13E +330 +131 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-160.0 + 30 +0.0 + 0 +POINT + 5 +13F +330 +131 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +60.0 + 20 +-160.0 + 30 +0.0 + 0 +ENDBLK + 5 +133 +330 +131 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +142 +330 +141 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D18 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D18 + 1 + + 0 +LINE + 5 +144 +330 +141 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +-162.8 + 30 +0.0 + 11 +0.0 + 21 +-180.1 + 31 +0.0 + 0 +LINE + 5 +145 +330 +141 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +60.0 + 20 +-162.8 + 30 +0.0 + 11 +60.0 + 21 +-180.1 + 31 +0.0 + 0 +INSERT + 5 +146 +330 +141 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +-178.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 50 +180.0 + 0 +INSERT + 5 +148 +330 +141 +100 +AcDbEntity + 8 +DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +60.0 + 20 +-178.0 + 30 +0.0 + 41 +2.8000000000000003 + 42 +2.8000000000000003 + 0 +LINE + 5 +14A +330 +141 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +2.8000000000000003 + 20 +-178.0 + 30 +0.0 + 11 +57.2 + 21 +-178.0 + 31 +0.0 + 0 +MTEXT + 5 +14B +330 +141 +100 +AcDbEntity + 8 +DIMS + 62 +2 +100 +AcDbMText + 10 +30.0 + 20 +-175.2 + 30 +0.0 + 40 +3.5 + 71 +5 + 1 +\A1;60{\H0.70x;\S+0,05^ -0,02;} + 7 +DIM-TEXT + 0 +POINT + 5 +14C +330 +141 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-178.0 + 30 +0.0 + 0 +POINT + 5 +14D +330 +141 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-160.0 + 30 +0.0 + 0 +POINT + 5 +14E +330 +141 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +60.0 + 20 +-160.0 + 30 +0.0 + 0 +ENDBLK + 5 +143 +330 +141 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LWPOLYLINE + 5 +48 +330 +17 +100 +AcDbEntity + 8 +OBJECT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +80.0 + 20 +0.0 + 10 +80.0 + 20 +50.0 + 10 +0.0 + 20 +50.0 + 0 +DIMENSION + 5 +49 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D1 + 3 +METRIC + 10 +0.0 + 20 +-12.0 + 30 +0.0 + 11 +40.0 + 21 +-9.2 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +80.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +5C +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D2 + 3 +METRIC + 10 +-14.0 + 20 +0.0 + 30 +0.0 + 11 +-16.8 + 21 +25.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +0.0 + 24 +50.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +6B +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D3 + 3 +TOL + 10 +0.0 + 20 +62.0 + 30 +0.0 + 11 +40.0 + 21 +64.8 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +50.0 + 33 +0.0 + 14 +80.0 + 24 +50.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +7A +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D4 + 3 +METRIC + 10 +0.0 + 20 +70.0 + 30 +0.0 + 11 +40.0 + 21 +74.9 + 31 +0.0 + 70 +32 + 71 +5 + 1 +80 overall (text override) +100 +AcDbAlignedDimension + 13 +0.0 + 23 +50.0 + 33 +0.0 + 14 +80.0 + 24 +50.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +89 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D5 + 3 +METRIC + 10 +69.71008489144947 + 20 +6.173949065130316 + 30 +0.0 + 11 +82.30910469945435 + 21 +32.614537180327396 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +80.0 + 23 +0.0 + 33 +0.0 + 14 +110.0 + 24 +50.0 + 34 +0.0 + 50 +59.03624346792648 +100 +AcDbRotatedDimension + 0 +CIRCLE + 5 +98 +330 +17 +100 +AcDbEntity + 8 +OBJECT +100 +AcDbCircle + 10 +150.0 + 20 +25.0 + 30 +0.0 + 40 +25.0 + 0 +DIMENSION + 5 +99 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D6 + 3 +METRIC + 10 +169.15111107797446 + 20 +41.06969024216348 + 30 +0.0 + 11 +122.07807918252053 + 21 +5.2258669504221515 + 31 +0.0 + 70 +35 + 71 +5 + 1 +<> +100 +AcDbDiametricDimension + 15 +130.84888892202554 + 25 +8.930309757836518 + 35 +0.0 + 0 +CIRCLE + 5 +A6 +330 +17 +100 +AcDbEntity + 8 +OBJECT +100 +AcDbCircle + 10 +220.0 + 20 +25.0 + 30 +0.0 + 40 +18.0 + 0 +DIMENSION + 5 +A7 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D7 + 3 +METRIC + 10 +220.0 + 20 +25.0 + 30 +0.0 + 11 +235.97487113059643 + 21 +2.9307115574417146 + 31 +0.0 + 70 +36 + 71 +5 + 1 +<> +100 +AcDbRadialDimension + 15 +229.0 + 25 +9.411542731880106 + 35 +0.0 + 0 +ARC + 5 +B2 +330 +17 +100 +AcDbEntity + 8 +OBJECT +100 +AcDbCircle + 10 +290.0 + 20 +0.0 + 30 +0.0 + 40 +40.0 +100 +AcDbArc + 50 +20.0 + 51 +140.0 + 0 +ARC_DIMENSION + 5 +B3 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D8 + 3 +METRIC + 10 +298.33511252801264 + 20 +47.27077214458598 + 30 +0.0 + 11 +298.8213274254801 + 21 +50.028233853020154 + 31 +0.0 + 70 +40 + 71 +5 + 1 +<> +100 +AcDbArcDimension + 13 +327.5877048314363 + 23 +13.680805733026748 + 33 +0.0 + 14 +259.3582222752409 + 24 +25.71150438746158 + 34 +0.0 + 15 +290.0 + 25 +0.0 + 35 +0.0 + 40 +0.0 + 41 +0.0 + 70 +0 + 71 +0 + 16 +0.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 0 +LINE + 5 +C3 +330 +17 +100 +AcDbEntity + 8 +OBJECT +100 +AcDbLine + 10 +0.0 + 20 +-60.0 + 30 +0.0 + 11 +60.0 + 21 +-60.0 + 31 +0.0 + 0 +LINE + 5 +C4 +330 +17 +100 +AcDbEntity + 8 +OBJECT +100 +AcDbLine + 10 +0.0 + 20 +-60.0 + 30 +0.0 + 11 +45.0 + 21 +-20.0 + 31 +0.0 + 0 +DIMENSION + 5 +C5 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D9 + 3 +METRIC + 10 +45.0 + 20 +-20.0 + 30 +0.0 + 11 +-30.907032852025363 + 21 +-71.75083294615946 + 31 +0.0 + 70 +34 + 71 +5 + 1 +<> +100 +AcDb2LineAngularDimension + 13 +0.0 + 23 +-60.0 + 33 +0.0 + 14 +60.0 + 24 +-60.0 + 34 +0.0 + 15 +0.0 + 25 +-60.0 + 35 +0.0 + 16 +30.0 + 26 +-56.0 + 36 +0.0 + 0 +DIMENSION + 5 +D6 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D10 + 3 +METRIC + 10 +140.0 + 20 +-60.0 + 30 +0.0 + 11 +108.23827411287941 + 21 +-92.62881994304354 + 31 +0.0 + 70 +37 + 71 +5 + 1 +<> +100 +AcDb3PointAngularDimension + 13 +150.0 + 23 +-45.0 + 33 +0.0 + 14 +170.0 + 24 +-80.0 + 34 +0.0 + 15 +130.0 + 25 +-80.0 + 35 +0.0 + 16 +0.0 + 26 +0.0 + 36 +0.0 + 0 +LINE + 5 +E6 +330 +17 +100 +AcDbEntity + 8 +OBJECT +100 +AcDbLine + 10 +130.0 + 20 +-80.0 + 30 +0.0 + 11 +170.0 + 21 +-80.0 + 31 +0.0 + 0 +LINE + 5 +E7 +330 +17 +100 +AcDbEntity + 8 +OBJECT +100 +AcDbLine + 10 +130.0 + 20 +-80.0 + 30 +0.0 + 11 +150.0 + 21 +-45.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +E8 +330 +17 +100 +AcDbEntity + 8 +OBJECT +100 +AcDbPolyline + 90 +6 + 70 +1 + 10 +220.0 + 20 +-90.0 + 10 +320.0 + 20 +-90.0 + 10 +320.0 + 20 +-40.0 + 10 +260.0 + 20 +-40.0 + 10 +260.0 + 20 +-60.0 + 10 +220.0 + 20 +-60.0 + 0 +DIMENSION + 5 +E9 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D11 + 3 +METRIC + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 11 +217.2 + 21 +-103.74999999999999 + 31 +0.0 + 70 +102 + 71 +5 + 1 +<> +100 +AcDbOrdinateDimension + 13 +220.0 + 23 +-90.0 + 33 +0.0 + 14 +220.0 + 24 +-101.99999999999999 + 34 +0.0 + 0 +DIMENSION + 5 +F4 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D12 + 3 +METRIC + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 11 +257.19999999999993 + 21 +-105.49999999999999 + 31 +0.0 + 70 +102 + 71 +5 + 1 +<> +100 +AcDbOrdinateDimension + 13 +260.0 + 23 +-90.0 + 33 +0.0 + 14 +259.99999999999994 + 24 +-101.99999999999999 + 34 +0.0 + 0 +DIMENSION + 5 +FF +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D13 + 3 +METRIC + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 11 +317.2 + 21 +-107.25 + 31 +0.0 + 70 +102 + 71 +5 + 1 +<> +100 +AcDbOrdinateDimension + 13 +320.0 + 23 +-90.0 + 33 +0.0 + 14 +320.0 + 24 +-102.0 + 34 +0.0 + 0 +DIMENSION + 5 +10A +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D14 + 3 +METRIC + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 11 +335.75 + 21 +-87.2 + 31 +0.0 + 70 +38 + 71 +5 + 1 +<> +100 +AcDbOrdinateDimension + 13 +320.0 + 23 +-90.0 + 33 +0.0 + 14 +334.0 + 24 +-90.0 + 34 +0.0 + 0 +DIMENSION + 5 +115 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D15 + 3 +METRIC + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 11 +337.5 + 21 +-57.19999999999999 + 31 +0.0 + 70 +38 + 71 +5 + 1 +<> +100 +AcDbOrdinateDimension + 13 +320.0 + 23 +-60.0 + 33 +0.0 + 14 +334.0 + 24 +-59.999999999999986 + 34 +0.0 + 0 +DIMENSION + 5 +120 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D16 + 3 +METRIC + 10 +220.0 + 20 +-90.0 + 30 +0.0 + 11 +337.5 + 21 +-37.20000000000001 + 31 +0.0 + 70 +38 + 71 +5 + 1 +<> +100 +AcDbOrdinateDimension + 13 +320.0 + 23 +-40.0 + 33 +0.0 + 14 +334.0 + 24 +-40.00000000000001 + 34 +0.0 + 0 +MULTILEADER + 5 +12B +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbMLeader +270 +2 +300 +CONTEXT_DATA{ + 40 +1.0 + 10 +98.0 + 20 +83.25 + 30 +0.0 + 41 +3.5 +140 +4.0 +145 +2.0 +174 +1 +175 +1 +176 +0 +177 +0 +290 +1 +304 +Chamfer 2 x 45° + 11 +0.0 + 21 +0.0 + 31 +1.0 +340 +29 + 12 +100.0 + 22 +85.0 + 32 +0.0 + 13 +1.0 + 23 +0.0 + 33 +0.0 + 42 +0.0 + 43 +0.0 + 44 +0.0 + 45 +1.0 +170 +1 + 90 +-1056964608 +171 +1 +172 +1 + 91 +-939524096 +141 +1.5 + 92 +0 +291 +0 +292 +0 +173 +0 +293 +0 +142 +0.0 +143 +0.0 +294 +0 +295 +1 +296 +0 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 +297 +0 +302 +LEADER{ +290 +1 +291 +1 + 10 +90.0 + 20 +83.25 + 30 +0.0 + 11 +1.0 + 21 +0.0 + 31 +0.0 + 90 +0 + 40 +8.0 +304 +LEADER_LINE{ + 10 +75.0 + 20 +45.0 + 30 +0.0 + 91 +0 + 92 +-1056964608 +305 +} +271 +0 +303 +} +272 +9 +273 +9 +301 +} +340 +2C + 90 +2147483647 +170 +1 + 91 +-1056964608 +341 +25 +171 +-2 +290 +1 +291 +1 + 41 +8.0 + 42 +4.0 +172 +2 +343 +29 +173 +1 + 95 +1 +174 +1 +175 +0 + 92 +-1056964608 +292 +0 + 93 +-1056964608 + 10 +1.0 + 20 +1.0 + 30 +1.0 + 43 +0.0 +176 +0 +293 +0 +294 +0 +178 +0 +179 +1 + 45 +1.0 +271 +0 +272 +9 +273 +9 +295 +0 + 0 +LEADER + 5 +12C +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbLeader + 3 +METRIC + 73 +3 + 76 +3 + 10 +15.0 + 20 +15.0 + 30 +0.0 + 10 +30.0 + 20 +30.0 + 30 +0.0 + 10 +40.0 + 20 +30.0 + 30 +0.0 + 0 +TEXT + 5 +12D +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbText + 10 +41.0 + 20 +29.0 + 30 +0.0 + 40 +3.5 + 1 +hole 5 + 7 +DIM-TEXT + 11 +41.0 + 21 +29.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +12E +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbText + 10 +0.0 + 20 +110.0 + 30 +0.0 + 40 +4.0 + 1 +METRIC style (left), TOL style with tolerances, ARCH (text horizontal) + 7 +DIM-TEXT + 11 +0.0 + 21 +110.0 + 31 +0.0 +100 +AcDbText + 0 +LWPOLYLINE + 5 +12F +330 +17 +100 +AcDbEntity + 8 +OBJECT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-160.0 + 10 +60.0 + 20 +-160.0 + 10 +60.0 + 20 +-130.0 + 10 +0.0 + 20 +-130.0 + 0 +DIMENSION + 5 +130 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D17 + 3 +ARCH + 10 +0.0 + 20 +-168.0 + 30 +0.0 + 11 +30.0 + 21 +-168.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +-160.0 + 33 +0.0 + 14 +60.0 + 24 +-160.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +140 +330 +17 +100 +AcDbEntity + 8 +DIMS +100 +AcDbDimension +280 +0 + 2 +*D18 + 3 +TOL + 10 +0.0 + 20 +-178.0 + 30 +0.0 + 11 +30.0 + 21 +-175.2 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +-160.0 + 33 +0.0 + 14 +60.0 + 24 +-160.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +A +330 +0 +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ACAD_COLOR +350 +B + 3 +ACAD_GROUP +350 +C + 3 +ACAD_LAYOUT +350 +D + 3 +ACAD_MATERIAL +350 +E + 3 +ACAD_MLEADERSTYLE +350 +F + 3 +ACAD_MLINESTYLE +350 +10 + 3 +ACAD_PLOTSETTINGS +350 +11 + 3 +ACAD_PLOTSTYLENAME +350 +12 + 3 +ACAD_SCALELIST +350 +14 + 3 +ACAD_TABLESTYLE +350 +15 + 3 +ACAD_VISUALSTYLE +350 +16 + 3 +EZDXF_META +350 +2D + 0 +DICTIONARY + 5 +B +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +C +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +D +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Model +350 +1A + 3 +Layout1 +350 +1E + 0 +DICTIONARY + 5 +E +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ByBlock +350 +1F + 3 +ByLayer +350 +20 + 3 +Global +350 +21 + 0 +DICTIONARY + 5 +F +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +2C + 0 +DICTIONARY + 5 +10 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +22 + 0 +DICTIONARY + 5 +11 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +ACDBDICTIONARYWDFLT + 5 +12 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Normal +350 +13 +100 +AcDbDictionaryWithDefault +340 +13 + 0 +ACDBPLACEHOLDER + 5 +13 +330 +12 + 0 +DICTIONARY + 5 +14 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +15 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +16 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +LAYOUT + 5 +1A +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +1024 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 +1 + 71 +0 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +17 + 0 +LAYOUT + 5 +1E +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +0 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 +1 + 71 +1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +1B + 0 +MATERIAL + 5 +1F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByBlock + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +20 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByLayer + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +21 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +Global + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MLINESTYLE + 5 +22 +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMlineStyle + 2 +Standard + 70 +0 + 3 + + 62 +256 + 51 +90.0 + 52 +90.0 + 71 +2 + 49 +0.5 + 62 +256 + 6 +BYLAYER + 49 +-0.5 + 62 +256 + 6 +BYLAYER + 0 +MLEADERSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +F +102 +} +330 +F +100 +AcDbMLeaderStyle +179 +2 +170 +2 +171 +1 +172 +0 + 90 +2 + 40 +0.0 + 41 +0.0 +173 +1 + 91 +-1056964608 + 92 +-2 +290 +1 + 42 +2.0 +291 +1 + 43 +8.0 + 3 +Standard + 44 +4.0 +300 + +342 +29 +174 +1 +175 +1 +176 +0 +178 +1 + 93 +-1056964608 + 45 +4.0 +292 +0 +297 +0 + 46 +4.0 + 94 +-1056964608 + 47 +1.0 + 49 +1.0 +140 +1.0 +294 +1 +141 +0.0 +177 +0 +142 +1.0 +295 +0 +296 +0 +143 +3.75 +271 +0 +272 +9 +273 +9 + 0 +DICTIONARY + 5 +2D +330 +A +100 +AcDbDictionary +281 +1 + 3 +CREATED_BY_EZDXF +350 +2E + 3 +WRITTEN_BY_EZDXF +350 +152 + 0 +DICTIONARYVAR + 5 +2E +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +DICTIONARYVAR + 5 +152 +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +ENDSEC + 0 +EOF diff --git a/crates/exav-viewer/demo/examples/files/cad/hatch-gallery.dxf b/crates/exav-viewer/demo/examples/files/cad/hatch-gallery.dxf new file mode 100644 index 0000000..bb8bfeb --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/cad/hatch-gallery.dxf @@ -0,0 +1,26910 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1032 + 9 +$ACADMAINTVER + 90 +4 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$LASTSAVEDBY + 1 +ezdxf + 9 +$REQUIREDVERSIONS +160 +0 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$EXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 +0 + 9 +$REGENMODE + 70 +1 + 9 +$FILLMODE + 70 +1 + 9 +$QTEXTMODE + 70 +0 + 9 +$MIRRTEXT + 70 +1 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 +1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 +256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 +0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 +0 + 9 +$DIMLIM + 70 +0 + 9 +$DIMTIH + 70 +0 + 9 +$DIMTOH + 70 +0 + 9 +$DIMSE1 + 70 +0 + 9 +$DIMSE2 + 70 +0 + 9 +$DIMTAD + 70 +1 + 9 +$DIMZIN + 70 +8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 +1 + 9 +$DIMSHO + 70 +1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 +0 + 9 +$DIMALTD + 70 +3 + 9 +$DIMALTF + 40 +0.03937007874 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 +1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 +0 + 9 +$DIMSOXD + 70 +0 + 9 +$DIMSAH + 70 +0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 +0 + 9 +$DIMCLRE + 70 +0 + 9 +$DIMCLRT + 70 +0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 +0 + 9 +$DIMSD1 + 70 +0 + 9 +$DIMSD2 + 70 +0 + 9 +$DIMTOLJ + 70 +0 + 9 +$DIMTZIN + 70 +8 + 9 +$DIMALTZ + 70 +0 + 9 +$DIMALTTZ + 70 +0 + 9 +$DIMUPT + 70 +0 + 9 +$DIMDEC + 70 +2 + 9 +$DIMTDEC + 70 +2 + 9 +$DIMALTU + 70 +2 + 9 +$DIMALTTD + 70 +3 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 +0 + 9 +$DIMADEC + 70 +0 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 +0 + 9 +$DIMDSEP + 70 +44 + 9 +$DIMATFIT + 70 +3 + 9 +$DIMFRAC + 70 +0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 +2 + 9 +$DIMLWD + 70 +-2 + 9 +$DIMLWE + 70 +-2 + 9 +$DIMTMOVE + 70 +0 + 9 +$DIMFXL + 40 +1.0 + 9 +$DIMFXLON + 70 +0 + 9 +$DIMJOGANG + 40 +0.785398163397 + 9 +$DIMTFILL + 70 +0 + 9 +$DIMTFILLCLR + 70 +0 + 9 +$DIMARCSYM + 70 +0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$DIMTXTDIRECTION + 70 +0 + 9 +$LUNITS + 70 +2 + 9 +$LUPREC + 70 +4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 +0 + 9 +$AUPREC + 70 +2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 +0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 +0 + 9 +$TDCREATE + 40 +2451545.0 + 9 +$TDUCREATE + 40 +2451545.0 + 9 +$TDUPDATE + 40 +2451545.0 + 9 +$TDUUPDATE + 40 +2451545.0 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 +1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 +0 + 9 +$PDMODE + 70 +0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 +0 + 9 +$SPLINETYPE + 70 +6 + 9 +$SPLINESEGS + 70 +8 + 9 +$HANDSEED + 5 +13E + 9 +$SURFTAB1 + 70 +6 + 9 +$SURFTAB2 + 70 +6 + 9 +$SURFTYPE + 70 +6 + 9 +$SURFU + 70 +6 + 9 +$SURFV + 70 +6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 +0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 +0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 +0 + 9 +$USERI2 + 70 +0 + 9 +$USERI3 + 70 +0 + 9 +$USERI4 + 70 +0 + 9 +$USERI5 + 70 +0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 +1 + 9 +$SHADEDGE + 70 +3 + 9 +$SHADEDIF + 70 +70 + 9 +$TILEMODE + 70 +1 + 9 +$MAXACTVP + 70 +64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 +0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 +0 + 9 +$VISRETAIN + 70 +1 + 9 +$PLINEGEN + 70 +0 + 9 +$PSLTSCALE + 70 +1 + 9 +$TREEDEPTH + 70 +3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 +0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 +1 + 9 +$MEASUREMENT + 70 +1 + 9 +$CELWEIGHT +370 +-1 + 9 +$ENDCAPS +280 +0 + 9 +$JOINSTYLE +280 +0 + 9 +$LWDISPLAY +290 +0 + 9 +$INSUNITS + 70 +4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 +1 + 9 +$CEPSNTYPE +380 +0 + 9 +$PSTYLEMODE +290 +1 + 9 +$FINGERPRINTGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$VERSIONGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$EXTNAMES +290 +1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 +0 + 9 +$SORTENTS +280 +127 + 9 +$INDEXCTL +280 +0 + 9 +$HIDETEXT +280 +1 + 9 +$XCLIPFRAME +280 +1 + 9 +$HALOGAP +280 +0 + 9 +$OBSCOLOR + 70 +257 + 9 +$OBSLTYPE +280 +0 + 9 +$INTERSECTIONDISPLAY +280 +0 + 9 +$INTERSECTIONCOLOR + 70 +257 + 9 +$DIMASSOC +280 +2 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 +0 + 9 +$LENSLENGTH + 40 +50.0 + 9 +$CAMERAHEIGHT + 40 +0.0 + 9 +$STEPSPERSEC + 40 +24.0 + 9 +$STEPSIZE + 40 +100.0 + 9 +$3DDWFPREC + 40 +2.0 + 9 +$PSOLWIDTH + 40 +0.005 + 9 +$PSOLHEIGHT + 40 +0.08 + 9 +$LOFTANG1 + 40 +1.570796326795 + 9 +$LOFTANG2 + 40 +1.570796326795 + 9 +$LOFTMAG1 + 40 +0.0 + 9 +$LOFTMAG2 + 40 +0.0 + 9 +$LOFTPARAM + 70 +7 + 9 +$LOFTNORMALS +280 +1 + 9 +$LATITUDE + 40 +37.795 + 9 +$LONGITUDE + 40 +-122.394 + 9 +$NORTHDIRECTION + 40 +0.0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 +1 + 9 +$TILEMODELIGHTSYNCH +280 +1 + 9 +$CMATERIAL +347 +20 + 9 +$SOLIDHIST +280 +0 + 9 +$SHOWHIST +280 +1 + 9 +$DWFFRAME +280 +2 + 9 +$DGNFRAME +280 +2 + 9 +$REALWORLDSCALE +290 +1 + 9 +$INTERFERECOLOR + 62 +256 + 9 +$CSHADOW +280 +0 + 9 +$SHADOWPLANELOCATION + 40 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +CELLSTYLEMAP + 2 +AcDbCellStyleMap + 3 +ObjectDBX Classes + 90 +1152 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MENTALRAYRENDERSETTINGS + 2 +AcDbMentalRayRenderSettings + 3 +SCENEOE + 90 +1024 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBDETAILVIEWSTYLE + 2 +AcDbDetailViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBSECTIONVIEWSTYLE + 2 +AcDbSectionViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +RASTERVARIABLES + 2 +AcDbRasterVariables + 3 +ISM + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 +1 + 0 +VPORT + 5 +13A +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +630.0 + 22 +-965.7839919624917 + 13 +0.0 + 23 +0.0 + 14 +0.5 + 24 +0.5 + 15 +0.5 + 25 +0.5 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +2238.1463831212327 + 41 +1.34 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +1000 + 73 +1 + 74 +3 + 75 +0 + 76 +0 + 77 +0 + 78 +0 +281 +0 + 65 +1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 +21 + 0 +LTYPE + 5 +24 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +25 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +26 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +2F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 +0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +5.08 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +30 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 +0 + 3 +Center (2x) ________ __ ________ __ ________ + 72 +65 + 73 +4 + 40 +8.89 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 +0 + 3 +Center (.5x) ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +2.54 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +32 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 +0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 +65 + 73 +2 + 40 +1.524 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +33 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 +0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ____ + 72 +65 + 73 +2 + 40 +3.048 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +34 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 +0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 +65 + 73 +2 + 40 +0.762 + 49 +0.635 + 74 +0 + 49 +-0.127 + 74 +0 + 0 +LTYPE + 5 +35 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM + 70 +0 + 3 +Phantom ______ __ __ ______ __ __ ______ + 72 +65 + 73 +6 + 40 +6.35 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOMX2 + 70 +0 + 3 +Phantom (2x)____________ ____ ____ ____________ + 72 +65 + 73 +6 + 40 +10.795 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +37 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 +0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___ + 72 +65 + 73 +6 + 40 +3.175 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +38 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 +0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 +65 + 73 +4 + 40 +3.556 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +39 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 +0 + 3 +Dash dot (2x) ____ . ____ . ____ . ____ + 72 +65 + 73 +4 + 40 +6.096 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 +0 + 3 +Dash dot (.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +4 + 40 +1.778 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 +0 + 3 +Dot . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.508 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 +0 + 3 +Dot (2x) . . . . . . . . + 72 +65 + 73 +2 + 40 +1.016 + 49 +0.0 + 74 +0 + 49 +-1.016 + 74 +0 + 0 +LTYPE + 5 +3D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 +0 + 3 +Dot (.5) . . . . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.254 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 +0 + 3 +Divide __ . . __ . . __ . . __ . . __ . . __ + 72 +65 + 73 +6 + 40 +4.064 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 +0 + 3 +Divide (2x) ____ . . ____ . . ____ . . ____ + 72 +65 + 73 +6 + 40 +6.604 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +40 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 +0 + 3 +Divide(.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +6 + 40 +2.032 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 +7 + 0 +LAYER + 5 +27 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 62 +7 + 6 +Continuous +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +28 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Defpoints + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +41 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +PATTERNS + 70 +0 + 62 +7 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +42 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +GRADIENTS + 70 +0 + 62 +5 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +43 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +ISLANDS + 70 +0 + 62 +1 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +44 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +EDGES + 70 +0 + 62 +3 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +45 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LABELS + 70 +0 + 62 +2 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 +2 + 0 +STYLE + 5 +29 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +46 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +LABEL + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 +3 + 0 +APPID + 5 +2A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 +0 + 0 +APPID + 5 +13B +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +HATCHBACKGROUNDCOLOR + 70 +0 + 0 +APPID + 5 +13C +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +EZDXF + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +4 +330 +0 +100 +AcDbSymbolTable + 70 +1 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +2B +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 +0 + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +0 +177 +0 +178 +0 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +371 +-2 +372 +-2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 +2 + 0 +BLOCK_RECORD + 5 +17 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +1A + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 70 +0 +280 +1 +281 +0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +18 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +19 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +HATCH + 5 +47 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +0.0 + 10 +100.0 + 20 +0.0 + 10 +100.0 + 20 +100.0 + 10 +0.0 + 20 +100.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-2.2450640303 + 46 +2.2450640303 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +48 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +100.0 + 20 +0.0 + 10 +100.0 + 20 +100.0 + 10 +0.0 + 20 +100.0 + 0 +TEXT + 5 +49 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-14.0 + 30 +0.0 + 40 +9.0 + 1 +ANSI31 + 7 +LABEL + 11 +0.0 + 21 +-14.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +4A +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI32 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +140.0 + 20 +0.0 + 10 +240.0 + 20 +0.0 + 10 +240.0 + 20 +100.0 + 10 +140.0 + 20 +100.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-6.7351920908 + 46 +6.7351920908 + 79 +0 + 53 +45.0 + 43 +4.490128053 + 44 +0.0 + 45 +-6.7351920908 + 46 +6.7351920908 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +4B +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +140.0 + 20 +0.0 + 10 +240.0 + 20 +0.0 + 10 +240.0 + 20 +100.0 + 10 +140.0 + 20 +100.0 + 0 +TEXT + 5 +4C +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +140.0 + 20 +-14.0 + 30 +0.0 + 40 +9.0 + 1 +ANSI32 + 7 +LABEL + 11 +140.0 + 21 +-14.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +4D +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI33 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +280.0 + 20 +0.0 + 10 +380.0 + 20 +0.0 + 10 +380.0 + 20 +100.0 + 10 +280.0 + 20 +100.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-4.4901280605 + 46 +4.4901280605 + 79 +0 + 53 +45.0 + 43 +4.490128053 + 44 +0.0 + 45 +-4.4901280605 + 46 +4.4901280605 + 79 +2 + 49 +3.175 + 49 +-1.5875 + 98 +0 + 0 +LWPOLYLINE + 5 +4E +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +280.0 + 20 +0.0 + 10 +380.0 + 20 +0.0 + 10 +380.0 + 20 +100.0 + 10 +280.0 + 20 +100.0 + 0 +TEXT + 5 +4F +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +280.0 + 20 +-14.0 + 30 +0.0 + 40 +9.0 + 1 +ANSI33 + 7 +LABEL + 11 +280.0 + 21 +-14.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +50 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI34 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +420.0 + 20 +0.0 + 10 +520.0 + 20 +0.0 + 10 +520.0 + 20 +100.0 + 10 +420.0 + 20 +100.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +4 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-13.4703841816 + 46 +13.4703841816 + 79 +0 + 53 +45.0 + 43 +4.490128053 + 44 +0.0 + 45 +-13.4703841816 + 46 +13.4703841816 + 79 +0 + 53 +45.0 + 43 +8.9802561314 + 44 +0.0 + 45 +-13.4703841816 + 46 +13.4703841816 + 79 +0 + 53 +45.0 + 43 +13.4703841844 + 44 +0.0 + 45 +-13.4703841816 + 46 +13.4703841816 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +51 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +420.0 + 20 +0.0 + 10 +520.0 + 20 +0.0 + 10 +520.0 + 20 +100.0 + 10 +420.0 + 20 +100.0 + 0 +TEXT + 5 +52 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +420.0 + 20 +-14.0 + 30 +0.0 + 40 +9.0 + 1 +ANSI34 + 7 +LABEL + 11 +420.0 + 21 +-14.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +53 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI35 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +560.0 + 20 +0.0 + 10 +660.0 + 20 +0.0 + 10 +660.0 + 20 +100.0 + 10 +560.0 + 20 +100.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-4.4901280605 + 46 +4.4901280605 + 79 +0 + 53 +45.0 + 43 +4.490128053 + 44 +0.0 + 45 +-4.4901280605 + 46 +4.4901280605 + 79 +4 + 49 +7.9375 + 49 +-1.5875 + 49 +0.0 + 49 +-1.5875 + 98 +0 + 0 +LWPOLYLINE + 5 +54 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +560.0 + 20 +0.0 + 10 +660.0 + 20 +0.0 + 10 +660.0 + 20 +100.0 + 10 +560.0 + 20 +100.0 + 0 +TEXT + 5 +55 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +560.0 + 20 +-14.0 + 30 +0.0 + 40 +9.0 + 1 +ANSI35 + 7 +LABEL + 11 +560.0 + 21 +-14.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +56 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI36 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +700.0 + 20 +0.0 + 10 +800.0 + 20 +0.0 + 10 +800.0 + 20 +100.0 + 10 +700.0 + 20 +100.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +1.6837980227 + 46 +6.1739260832 + 79 +4 + 49 +7.9375 + 49 +-1.5875 + 49 +0.0 + 49 +-1.5875 + 98 +0 + 0 +LWPOLYLINE + 5 +57 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +700.0 + 20 +0.0 + 10 +800.0 + 20 +0.0 + 10 +800.0 + 20 +100.0 + 10 +700.0 + 20 +100.0 + 0 +TEXT + 5 +58 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +700.0 + 20 +-14.0 + 30 +0.0 + 40 +9.0 + 1 +ANSI36 + 7 +LABEL + 11 +700.0 + 21 +-14.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +59 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI37 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +840.0 + 20 +0.0 + 10 +940.0 + 20 +0.0 + 10 +940.0 + 20 +100.0 + 10 +840.0 + 20 +100.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-2.2450640303 + 46 +2.2450640303 + 79 +0 + 53 +135.0 + 43 +0.0 + 44 +0.0 + 45 +-2.2450640303 + 46 +-2.2450640303 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +5A +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +0.0 + 10 +940.0 + 20 +0.0 + 10 +940.0 + 20 +100.0 + 10 +840.0 + 20 +100.0 + 0 +TEXT + 5 +5B +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +840.0 + 20 +-14.0 + 30 +0.0 + 40 +9.0 + 1 +ANSI37 + 7 +LABEL + 11 +840.0 + 21 +-14.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +5C +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI38 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +980.0 + 20 +0.0 + 10 +1080.0 + 20 +0.0 + 10 +1080.0 + 20 +100.0 + 10 +980.0 + 20 +100.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-2.2450640303 + 46 +2.2450640303 + 79 +0 + 53 +135.0 + 43 +0.0 + 44 +0.0 + 45 +-6.7351920908 + 46 +2.2450640303 + 79 +2 + 49 +7.9375 + 49 +-4.7625 + 98 +0 + 0 +LWPOLYLINE + 5 +5D +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +980.0 + 20 +0.0 + 10 +1080.0 + 20 +0.0 + 10 +1080.0 + 20 +100.0 + 10 +980.0 + 20 +100.0 + 0 +TEXT + 5 +5E +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +980.0 + 20 +-14.0 + 30 +0.0 + 40 +9.0 + 1 +ANSI38 + 7 +LABEL + 11 +980.0 + 21 +-14.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +5F +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-B816 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-165.0 + 10 +100.0 + 20 +-165.0 + 10 +100.0 + 20 +-65.0 + 10 +0.0 + 20 +-65.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +203.2 + 79 +0 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-203.2 + 46 +203.2 + 79 +2 + 49 +203.2 + 49 +-203.2 + 98 +0 + 0 +LWPOLYLINE + 5 +60 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-165.0 + 10 +100.0 + 20 +-165.0 + 10 +100.0 + 20 +-65.0 + 10 +0.0 + 20 +-65.0 + 0 +TEXT + 5 +61 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-179.0 + 30 +0.0 + 40 +9.0 + 1 +AR-B816 + 7 +LABEL + 11 +0.0 + 21 +-179.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +62 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-B816C + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +140.0 + 20 +-165.0 + 10 +240.0 + 20 +-165.0 + 10 +240.0 + 20 +-65.0 + 10 +140.0 + 20 +-65.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +4 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +203.2 + 46 +203.2 + 79 +2 + 49 +396.875 + 49 +-9.525 + 53 +0.0 + 43 +-203.2 + 44 +9.525 + 45 +203.2 + 46 +203.2 + 79 +2 + 49 +396.875 + 49 +-9.525 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-203.2 + 46 +203.2 + 79 +2 + 49 +-212.725 + 49 +193.675 + 53 +90.0 + 43 +-9.525 + 44 +0.0 + 45 +-203.2 + 46 +203.2 + 79 +2 + 49 +-212.725 + 49 +193.675 + 98 +0 + 0 +LWPOLYLINE + 5 +63 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +140.0 + 20 +-165.0 + 10 +240.0 + 20 +-165.0 + 10 +240.0 + 20 +-65.0 + 10 +140.0 + 20 +-65.0 + 0 +TEXT + 5 +64 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +140.0 + 20 +-179.0 + 30 +0.0 + 40 +9.0 + 1 +AR-B816C + 7 +LABEL + 11 +140.0 + 21 +-179.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +65 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-B88 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +280.0 + 20 +-165.0 + 10 +380.0 + 20 +-165.0 + 10 +380.0 + 20 +-65.0 + 10 +280.0 + 20 +-65.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +203.2 + 79 +0 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-101.6 + 46 +203.2 + 79 +2 + 49 +203.2 + 49 +-203.2 + 98 +0 + 0 +LWPOLYLINE + 5 +66 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +280.0 + 20 +-165.0 + 10 +380.0 + 20 +-165.0 + 10 +380.0 + 20 +-65.0 + 10 +280.0 + 20 +-65.0 + 0 +TEXT + 5 +67 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +280.0 + 20 +-179.0 + 30 +0.0 + 40 +9.0 + 1 +AR-B88 + 7 +LABEL + 11 +280.0 + 21 +-179.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +68 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-BRELM + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +420.0 + 20 +-165.0 + 10 +520.0 + 20 +-165.0 + 10 +520.0 + 20 +-65.0 + 10 +420.0 + 20 +-65.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +8 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +135.484 + 79 +2 + 49 +193.675 + 49 +-9.525 + 53 +0.0 + 43 +0.0 + 44 +57.15 + 45 +0.0 + 46 +135.484 + 79 +2 + 49 +193.675 + 49 +-9.525 + 53 +0.0 + 43 +50.8 + 44 +67.7418 + 45 +0.0 + 46 +135.484 + 79 +2 + 49 +92.075 + 49 +-9.525 + 53 +0.0 + 43 +50.8 + 44 +124.892 + 45 +0.0 + 46 +135.484 + 79 +2 + 49 +92.075 + 49 +-9.525 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-203.2 + 46 +0.0 + 79 +2 + 49 +57.15 + 49 +-78.334 + 53 +90.0 + 43 +-9.525 + 44 +0.0 + 45 +-203.2 + 46 +0.0 + 79 +2 + 49 +57.15 + 49 +-78.334 + 53 +90.0 + 43 +50.8 + 44 +67.7418 + 45 +-101.6 + 46 +0.0 + 79 +2 + 49 +57.15 + 49 +-78.334 + 53 +90.0 + 43 +41.275 + 44 +67.7418 + 45 +-101.6 + 46 +0.0 + 79 +2 + 49 +57.15 + 49 +-78.334 + 98 +0 + 0 +LWPOLYLINE + 5 +69 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +420.0 + 20 +-165.0 + 10 +520.0 + 20 +-165.0 + 10 +520.0 + 20 +-65.0 + 10 +420.0 + 20 +-65.0 + 0 +TEXT + 5 +6A +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +420.0 + 20 +-179.0 + 30 +0.0 + 40 +9.0 + 1 +AR-BRELM + 7 +LABEL + 11 +420.0 + 21 +-179.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +6B +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-BRSTD + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +560.0 + 20 +-165.0 + 10 +660.0 + 20 +-165.0 + 10 +660.0 + 20 +-65.0 + 10 +560.0 + 20 +-65.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +67.7418 + 79 +0 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-101.6 + 46 +67.7418 + 79 +2 + 49 +67.7418 + 49 +-67.7418 + 98 +0 + 0 +LWPOLYLINE + 5 +6C +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +560.0 + 20 +-165.0 + 10 +660.0 + 20 +-165.0 + 10 +660.0 + 20 +-65.0 + 10 +560.0 + 20 +-65.0 + 0 +TEXT + 5 +6D +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +560.0 + 20 +-179.0 + 30 +0.0 + 40 +9.0 + 1 +AR-BRSTD + 7 +LABEL + 11 +560.0 + 21 +-179.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +6E +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-CONC + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +700.0 + 20 +-165.0 + 10 +800.0 + 20 +-165.0 + 10 +800.0 + 20 +-65.0 + 10 +700.0 + 20 +-65.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +13 + 53 +50.0 + 43 +0.0 + 44 +0.0 + 45 +182.184668996 + 46 +-15.9390855389 + 79 +2 + 49 +19.05 + 49 +-209.55 + 53 +355.0 + 43 +0.0 + 44 +0.0 + 45 +-35.243421425 + 46 +191.056845239 + 79 +2 + 49 +15.24 + 49 +-167.64058417 + 53 +100.4514447 + 43 +15.182007 + 44 +-1.3282535 + 45 +146.9412470904 + 46 +175.1177519122 + 79 +2 + 49 +16.1900088 + 49 +-178.0902446 + 53 +46.1842 + 43 +0.0 + 44 +50.8 + 45 +271.0790408921 + 46 +-42.0423279327 + 79 +2 + 49 +28.575 + 49 +-314.325 + 53 +96.63555761 + 43 +22.5899 + 44 +47.2965 + 45 +237.4041340515 + 46 +247.4261245977 + 79 +2 + 49 +24.28502314 + 49 +-267.13560816 + 53 +351.18415117 + 43 +0.0 + 44 +50.8 + 45 +237.404134065 + 46 +247.4261245855 + 79 +2 + 49 +22.85996707 + 49 +-251.45973192 + 53 +21.0 + 43 +25.4 + 44 +38.1 + 45 +151.6143912691 + 46 +-102.2651981871 + 79 +2 + 49 +19.05 + 49 +-209.55 + 53 +326.0 + 43 +25.4 + 44 +38.1 + 45 +61.8020283476 + 46 +184.1879661223 + 79 +2 + 49 +15.24 + 49 +-167.64 + 53 +71.451445 + 43 +38.0345326 + 44 +29.5779001 + 45 +213.4164192787 + 46 +81.9227688859 + 79 +2 + 49 +16.1900088 + 49 +-178.0899376 + 53 +37.5 + 43 +0.0 + 44 +0.0 + 45 +3.0886032506 + 46 +84.5550388732 + 79 +6 + 49 +0.0 + 49 +-165.608 + 49 +0.0 + 49 +-170.18 + 49 +0.0 + 49 +-168.275 + 53 +7.5 + 43 +0.0 + 44 +0.0 + 45 +66.8196625103 + 46 +100.1805748181 + 79 +6 + 49 +0.0 + 49 +-97.028 + 49 +0.0 + 49 +-161.798 + 49 +0.0 + 49 +-64.135 + 53 +-32.5 + 43 +-56.642 + 44 +0.0 + 45 +135.5905951669 + 46 +-5.7287439927 + 79 +6 + 49 +0.0 + 49 +-63.5 + 49 +0.0 + 49 +-198.12 + 49 +0.0 + 49 +-262.89 + 53 +-42.5 + 43 +-82.042 + 44 +0.0 + 45 +148.129181386 + 46 +25.4264910333 + 79 +6 + 49 +0.0 + 49 +-82.55 + 49 +0.0 + 49 +-131.572 + 49 +0.0 + 49 +-186.69 + 98 +0 + 0 +LWPOLYLINE + 5 +6F +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +700.0 + 20 +-165.0 + 10 +800.0 + 20 +-165.0 + 10 +800.0 + 20 +-65.0 + 10 +700.0 + 20 +-65.0 + 0 +TEXT + 5 +70 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +700.0 + 20 +-179.0 + 30 +0.0 + 40 +9.0 + 1 +AR-CONC + 7 +LABEL + 11 +700.0 + 21 +-179.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +71 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-HBONE + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +840.0 + 20 +-165.0 + 10 +940.0 + 20 +-165.0 + 10 +940.0 + 20 +-65.0 + 10 +840.0 + 20 +-65.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +143.6840979371 + 79 +2 + 49 +304.8 + 49 +-101.6 + 53 +135.0 + 43 +71.842 + 44 +71.842 + 45 +0.0 + 46 +143.6840979371 + 79 +2 + 49 +304.8 + 49 +-101.6 + 98 +0 + 0 +LWPOLYLINE + 5 +72 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +-165.0 + 10 +940.0 + 20 +-165.0 + 10 +940.0 + 20 +-65.0 + 10 +840.0 + 20 +-65.0 + 0 +TEXT + 5 +73 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +840.0 + 20 +-179.0 + 30 +0.0 + 40 +9.0 + 1 +AR-HBONE + 7 +LABEL + 11 +840.0 + 21 +-179.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +74 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-PARQ1 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +980.0 + 20 +-165.0 + 10 +1080.0 + 20 +-165.0 + 10 +1080.0 + 20 +-65.0 + 10 +980.0 + 20 +-65.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +14 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-304.8 + 46 +304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +90.0 + 43 +50.8 + 44 +0.0 + 45 +-304.8 + 46 +304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +90.0 + 43 +101.6 + 44 +0.0 + 45 +-304.8 + 46 +304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +90.0 + 43 +152.4 + 44 +0.0 + 45 +-304.8 + 46 +304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +90.0 + 43 +203.2 + 44 +0.0 + 45 +-304.8 + 46 +304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +90.0 + 43 +254.0 + 44 +0.0 + 45 +-304.8 + 46 +304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +90.0 + 43 +304.8 + 44 +0.0 + 45 +-304.8 + 46 +304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +0.0 + 43 +0.0 + 44 +304.8 + 45 +304.8 + 46 +-304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +0.0 + 43 +0.0 + 44 +355.6 + 45 +304.8 + 46 +-304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +0.0 + 43 +0.0 + 44 +406.4 + 45 +304.8 + 46 +-304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +0.0 + 43 +0.0 + 44 +457.2 + 45 +304.8 + 46 +-304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +0.0 + 43 +0.0 + 44 +508.0 + 45 +304.8 + 46 +-304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +0.0 + 43 +0.0 + 44 +558.8 + 45 +304.8 + 46 +-304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 53 +0.0 + 43 +0.0 + 44 +609.6 + 45 +304.8 + 46 +-304.8 + 79 +2 + 49 +304.8 + 49 +-304.8 + 98 +0 + 0 +LWPOLYLINE + 5 +75 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +980.0 + 20 +-165.0 + 10 +1080.0 + 20 +-165.0 + 10 +1080.0 + 20 +-65.0 + 10 +980.0 + 20 +-65.0 + 0 +TEXT + 5 +76 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +980.0 + 20 +-179.0 + 30 +0.0 + 40 +9.0 + 1 +AR-PARQ1 + 7 +LABEL + 11 +980.0 + 21 +-179.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +77 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-RROOF + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-330.0 + 10 +100.0 + 20 +-330.0 + 10 +100.0 + 20 +-230.0 + 10 +0.0 + 20 +-230.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +55.88 + 46 +25.4 + 79 +4 + 49 +381.0 + 49 +-50.8 + 49 +127.0 + 49 +-25.4 + 53 +0.0 + 43 +33.782 + 44 +12.7 + 45 +-25.4 + 46 +33.782 + 79 +4 + 49 +76.2 + 49 +-8.382 + 49 +152.4 + 49 +-19.05 + 53 +0.0 + 43 +12.7 + 44 +21.59 + 45 +132.08 + 46 +17.018 + 79 +4 + 49 +203.2 + 49 +-35.56 + 49 +101.6 + 49 +-25.4 + 98 +0 + 0 +LWPOLYLINE + 5 +78 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-330.0 + 10 +100.0 + 20 +-330.0 + 10 +100.0 + 20 +-230.0 + 10 +0.0 + 20 +-230.0 + 0 +TEXT + 5 +79 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-344.0 + 30 +0.0 + 40 +9.0 + 1 +AR-RROOF + 7 +LABEL + 11 +0.0 + 21 +-344.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +7A +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-RSHKE + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +140.0 + 20 +-330.0 + 10 +240.0 + 20 +-330.0 + 10 +240.0 + 20 +-230.0 + 10 +140.0 + 20 +-230.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +9 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +647.7 + 46 +304.8 + 79 +6 + 49 +152.4 + 49 +-127.0 + 49 +177.8 + 49 +-76.2 + 49 +228.6 + 49 +-101.6 + 53 +0.0 + 43 +152.4 + 44 +12.7 + 45 +647.7 + 46 +304.8 + 79 +4 + 49 +127.0 + 49 +-482.6 + 49 +101.6 + 49 +-152.4 + 53 +0.0 + 43 +457.2 + 44 +-19.05 + 45 +647.7 + 46 +304.8 + 79 +2 + 49 +76.2 + 49 +-787.4 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-215.9 + 46 +304.8 + 79 +2 + 49 +292.1 + 49 +-927.1 + 53 +90.0 + 43 +152.4 + 44 +0.0 + 45 +-215.9 + 46 +304.8 + 79 +2 + 49 +285.75 + 49 +-933.45 + 53 +90.0 + 43 +279.4 + 44 +0.0 + 45 +-215.9 + 46 +304.8 + 79 +2 + 49 +266.7 + 49 +-952.5 + 53 +90.0 + 43 +457.2 + 44 +-19.05 + 45 +-215.9 + 46 +304.8 + 79 +2 + 49 +292.1 + 49 +-927.1 + 53 +90.0 + 43 +533.4 + 44 +-19.05 + 45 +-215.9 + 46 +304.8 + 79 +2 + 49 +292.1 + 49 +-927.1 + 53 +90.0 + 43 +762.0 + 44 +0.0 + 45 +-215.9 + 46 +304.8 + 79 +2 + 49 +279.4 + 49 +-939.8 + 98 +0 + 0 +LWPOLYLINE + 5 +7B +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +140.0 + 20 +-330.0 + 10 +240.0 + 20 +-330.0 + 10 +240.0 + 20 +-230.0 + 10 +140.0 + 20 +-230.0 + 0 +TEXT + 5 +7C +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +140.0 + 20 +-344.0 + 30 +0.0 + 40 +9.0 + 1 +AR-RSHKE + 7 +LABEL + 11 +140.0 + 21 +-344.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +7D +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-SAND + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +280.0 + 20 +-330.0 + 10 +380.0 + 20 +-330.0 + 10 +380.0 + 20 +-230.0 + 10 +280.0 + 20 +-230.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +4 + 53 +37.5 + 43 +0.0 + 44 +0.0 + 45 +-1.600031296 + 46 +48.9413237329 + 79 +6 + 49 +0.0 + 49 +-38.608 + 49 +0.0 + 49 +-43.18 + 49 +0.0 + 49 +-41.275 + 53 +7.5 + 43 +0.0 + 44 +0.0 + 45 +44.9523283138 + 46 +71.6825100568 + 79 +6 + 49 +0.0 + 49 +-20.828 + 49 +0.0 + 49 +-34.798 + 49 +0.0 + 49 +-13.335 + 53 +-32.5 + 43 +-31.242 + 44 +0.0 + 45 +79.0992370241 + 46 +0.1437184679 + 79 +6 + 49 +0.0 + 49 +-12.7 + 49 +0.0 + 49 +-45.72 + 49 +0.0 + 49 +-59.69 + 53 +-42.5 + 43 +-31.242 + 44 +0.0 + 45 +76.3556452472 + 46 +22.2929323257 + 79 +6 + 49 +0.0 + 49 +-6.35 + 49 +0.0 + 49 +-29.972 + 49 +0.0 + 49 +-34.29 + 98 +0 + 0 +LWPOLYLINE + 5 +7E +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +280.0 + 20 +-330.0 + 10 +380.0 + 20 +-330.0 + 10 +380.0 + 20 +-230.0 + 10 +280.0 + 20 +-230.0 + 0 +TEXT + 5 +7F +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +280.0 + 20 +-344.0 + 30 +0.0 + 40 +9.0 + 1 +AR-SAND + 7 +LABEL + 11 +280.0 + 21 +-344.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +80 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +BOX + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +420.0 + 20 +-330.0 + 10 +520.0 + 20 +-330.0 + 10 +520.0 + 20 +-230.0 + 10 +420.0 + 20 +-230.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +8 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-25.4 + 46 +0.0 + 79 +0 + 53 +90.0 + 43 +6.35 + 44 +0.0 + 45 +-25.4 + 46 +0.0 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +-6.35 + 49 +6.35 + 53 +0.0 + 43 +0.0 + 44 +6.35 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +-6.35 + 49 +6.35 + 53 +0.0 + 43 +0.0 + 44 +12.7 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +0.0 + 43 +0.0 + 44 +19.05 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +90.0 + 43 +12.7 + 44 +0.0 + 45 +-25.4 + 46 +0.0 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +90.0 + 43 +19.05 + 44 +0.0 + 45 +-25.4 + 46 +0.0 + 79 +2 + 49 +6.35 + 49 +-6.35 + 98 +0 + 0 +LWPOLYLINE + 5 +81 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +420.0 + 20 +-330.0 + 10 +520.0 + 20 +-330.0 + 10 +520.0 + 20 +-230.0 + 10 +420.0 + 20 +-230.0 + 0 +TEXT + 5 +82 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +420.0 + 20 +-344.0 + 30 +0.0 + 40 +9.0 + 1 +BOX + 7 +LABEL + 11 +420.0 + 21 +-344.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +83 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +BRASS + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +560.0 + 20 +-330.0 + 10 +660.0 + 20 +-330.0 + 10 +660.0 + 20 +-230.0 + 10 +560.0 + 20 +-230.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +6.35 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +3.175 + 45 +0.0 + 46 +6.35 + 79 +2 + 49 +3.175 + 49 +-1.5875 + 98 +0 + 0 +LWPOLYLINE + 5 +84 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +560.0 + 20 +-330.0 + 10 +660.0 + 20 +-330.0 + 10 +660.0 + 20 +-230.0 + 10 +560.0 + 20 +-230.0 + 0 +TEXT + 5 +85 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +560.0 + 20 +-344.0 + 30 +0.0 + 40 +9.0 + 1 +BRASS + 7 +LABEL + 11 +560.0 + 21 +-344.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +86 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +BRICK + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +700.0 + 20 +-330.0 + 10 +800.0 + 20 +-330.0 + 10 +800.0 + 20 +-230.0 + 10 +700.0 + 20 +-230.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +6.35 + 79 +0 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-12.7 + 46 +0.0 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +90.0 + 43 +6.35 + 44 +0.0 + 45 +-12.7 + 46 +0.0 + 79 +2 + 49 +-6.35 + 49 +6.35 + 98 +0 + 0 +LWPOLYLINE + 5 +87 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +700.0 + 20 +-330.0 + 10 +800.0 + 20 +-330.0 + 10 +800.0 + 20 +-230.0 + 10 +700.0 + 20 +-230.0 + 0 +TEXT + 5 +88 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +700.0 + 20 +-344.0 + 30 +0.0 + 40 +9.0 + 1 +BRICK + 7 +LABEL + 11 +700.0 + 21 +-344.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +89 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +BRICK_DEMOLITION + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +840.0 + 20 +-330.0 + 10 +940.0 + 20 +-330.0 + 10 +940.0 + 20 +-230.0 + 10 +840.0 + 20 +-230.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-5.3881536726 + 46 +5.3881536726 + 79 +2 + 49 +2.54 + 49 +-2.54 + 53 +45.0 + 43 +1.796034 + 44 +0.0 + 45 +-5.3881536726 + 46 +5.3881536726 + 79 +2 + 49 +2.54 + 49 +-2.54 + 98 +0 + 0 +LWPOLYLINE + 5 +8A +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +-330.0 + 10 +940.0 + 20 +-330.0 + 10 +940.0 + 20 +-230.0 + 10 +840.0 + 20 +-230.0 + 0 +TEXT + 5 +8B +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +840.0 + 20 +-344.0 + 30 +0.0 + 40 +9.0 + 1 +BRICK_DEMOLITION + 7 +LABEL + 11 +840.0 + 21 +-344.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +8C +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +BRICK_EXISTING + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +980.0 + 20 +-330.0 + 10 +1080.0 + 20 +-330.0 + 10 +1080.0 + 20 +-230.0 + 10 +980.0 + 20 +-230.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-7.1842048969 + 46 +7.1842048969 + 79 +0 + 53 +45.0 + 43 +3.5920934 + 44 +0.0 + 45 +-7.1842048969 + 46 +7.1842048969 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +8D +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +980.0 + 20 +-330.0 + 10 +1080.0 + 20 +-330.0 + 10 +1080.0 + 20 +-230.0 + 10 +980.0 + 20 +-230.0 + 0 +TEXT + 5 +8E +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +980.0 + 20 +-344.0 + 30 +0.0 + 40 +9.0 + 1 +BRICK_EXISTING + 7 +LABEL + 11 +980.0 + 21 +-344.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +8F +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +BRICK_FLBOND + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-495.0 + 10 +100.0 + 20 +-495.0 + 10 +100.0 + 20 +-395.0 + 10 +0.0 + 20 +-395.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +8 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +38.1 + 46 +16.9333333291 + 79 +2 + 49 +48.41875 + 49 +-27.78125 + 53 +0.0 + 43 +50.8 + 44 +0.0 + 45 +38.1 + 46 +16.9333333291 + 79 +2 + 49 +23.01875 + 49 +-53.18125 + 53 +0.0 + 43 +0.0 + 44 +14.5520833291 + 45 +38.1 + 46 +16.9333333291 + 79 +2 + 49 +48.41875 + 49 +-27.78125 + 53 +0.0 + 43 +50.8 + 44 +14.5520833291 + 45 +38.1 + 46 +16.9333333291 + 79 +2 + 49 +23.01875 + 49 +-53.18125 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-38.1 + 46 +16.9333333291 + 79 +2 + 49 +14.5520833291 + 49 +-19.3145833291 + 53 +90.0 + 43 +48.41875 + 44 +0.0 + 45 +-38.1 + 46 +16.9333333291 + 79 +2 + 49 +14.5520833291 + 49 +-19.3145833291 + 53 +90.0 + 43 +50.8 + 44 +0.0 + 45 +-38.1 + 46 +16.9333333291 + 79 +2 + 49 +14.5520833291 + 49 +-19.3145833291 + 53 +90.0 + 43 +73.81875 + 44 +0.0 + 45 +-38.1 + 46 +16.9333333291 + 79 +2 + 49 +14.5520833291 + 49 +-19.3145833291 + 98 +0 + 0 +LWPOLYLINE + 5 +90 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-495.0 + 10 +100.0 + 20 +-495.0 + 10 +100.0 + 20 +-395.0 + 10 +0.0 + 20 +-395.0 + 0 +TEXT + 5 +91 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-509.0 + 30 +0.0 + 40 +9.0 + 1 +BRICK_FLBOND + 7 +LABEL + 11 +0.0 + 21 +-509.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +92 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +BRICK_INSULATING + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +140.0 + 20 +-495.0 + 10 +240.0 + 20 +-495.0 + 10 +240.0 + 20 +-395.0 + 10 +140.0 + 20 +-395.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-6.2861792847 + 46 +6.2861792847 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +2.54 + 79 +2 + 49 +0.0 + 49 +-2.54 + 98 +0 + 0 +LWPOLYLINE + 5 +93 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +140.0 + 20 +-495.0 + 10 +240.0 + 20 +-495.0 + 10 +240.0 + 20 +-395.0 + 10 +140.0 + 20 +-395.0 + 0 +TEXT + 5 +94 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +140.0 + 20 +-509.0 + 30 +0.0 + 40 +9.0 + 1 +BRICK_INSULATING + 7 +LABEL + 11 +140.0 + 21 +-509.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +95 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +BRICK_LWEIGHT + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +280.0 + 20 +-495.0 + 10 +380.0 + 20 +-495.0 + 10 +380.0 + 20 +-395.0 + 10 +280.0 + 20 +-395.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-6.2861792847 + 46 +6.2861792847 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.79375 + 46 +1.5875 + 79 +2 + 49 +0.0 + 49 +-1.5875 + 98 +0 + 0 +LWPOLYLINE + 5 +96 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +280.0 + 20 +-495.0 + 10 +380.0 + 20 +-495.0 + 10 +380.0 + 20 +-395.0 + 10 +280.0 + 20 +-395.0 + 0 +TEXT + 5 +97 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +280.0 + 20 +-509.0 + 30 +0.0 + 40 +9.0 + 1 +BRICK_LWEIGHT + 7 +LABEL + 11 +280.0 + 21 +-509.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +98 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +BRICK_PAIRS + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +420.0 + 20 +-495.0 + 10 +520.0 + 20 +-495.0 + 10 +520.0 + 20 +-395.0 + 10 +420.0 + 20 +-395.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +8 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +50.8 + 46 +50.8 + 79 +6 + 49 +48.41875 + 49 +-2.38125 + 49 +23.01875 + 49 +-2.38125 + 49 +23.01875 + 49 +-2.38125 + 53 +0.0 + 43 +0.0 + 44 +23.01875 + 45 +50.8 + 46 +50.8 + 79 +2 + 49 +48.41875 + 49 +-53.18125 + 53 +0.0 + 43 +0.0 + 44 +25.4 + 45 +50.8 + 46 +50.8 + 79 +2 + 49 +48.41875 + 49 +-53.18125 + 53 +0.0 + 43 +0.0 + 44 +48.41875 + 45 +50.8 + 46 +50.8 + 79 +6 + 49 +48.41875 + 49 +-2.38125 + 49 +23.01875 + 49 +-2.38125 + 49 +23.01875 + 49 +-2.38125 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-50.8 + 46 +50.8 + 79 +6 + 49 +23.01875 + 49 +-2.38125 + 49 +23.01875 + 49 +-2.38125 + 49 +48.41875 + 49 +-2.38125 + 53 +90.0 + 43 +23.01875 + 44 +50.8 + 45 +-50.8 + 46 +50.8 + 79 +2 + 49 +48.41875 + 49 +-53.18125 + 53 +90.0 + 43 +25.4 + 44 +50.8 + 45 +-50.8 + 46 +50.8 + 79 +2 + 49 +48.41875 + 49 +-53.18125 + 53 +90.0 + 43 +48.41875 + 44 +0.0 + 45 +-50.8 + 46 +50.8 + 79 +6 + 49 +23.01875 + 49 +-2.38125 + 49 +23.01875 + 49 +-2.38125 + 49 +48.41875 + 49 +-2.38125 + 98 +0 + 0 +LWPOLYLINE + 5 +99 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +420.0 + 20 +-495.0 + 10 +520.0 + 20 +-495.0 + 10 +520.0 + 20 +-395.0 + 10 +420.0 + 20 +-395.0 + 0 +TEXT + 5 +9A +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +420.0 + 20 +-509.0 + 30 +0.0 + 40 +9.0 + 1 +BRICK_PAIRS + 7 +LABEL + 11 +420.0 + 21 +-509.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +9B +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +BRICK_STBOND + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +560.0 + 20 +-495.0 + 10 +660.0 + 20 +-495.0 + 10 +660.0 + 20 +-395.0 + 10 +560.0 + 20 +-395.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +25.4 + 79 +0 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-50.8 + 46 +0.0 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +9C +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +560.0 + 20 +-495.0 + 10 +660.0 + 20 +-495.0 + 10 +660.0 + 20 +-395.0 + 10 +560.0 + 20 +-395.0 + 0 +TEXT + 5 +9D +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +560.0 + 20 +-509.0 + 30 +0.0 + 40 +9.0 + 1 +BRICK_STBOND + 7 +LABEL + 11 +560.0 + 21 +-509.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +9E +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +BRICK_STRBOND + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +700.0 + 20 +-495.0 + 10 +800.0 + 20 +-495.0 + 10 +800.0 + 20 +-395.0 + 10 +700.0 + 20 +-395.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +50.8 + 79 +0 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-101.6 + 46 +50.8 + 79 +2 + 49 +50.8 + 49 +-50.8 + 98 +0 + 0 +LWPOLYLINE + 5 +9F +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +700.0 + 20 +-495.0 + 10 +800.0 + 20 +-495.0 + 10 +800.0 + 20 +-395.0 + 10 +700.0 + 20 +-395.0 + 0 +TEXT + 5 +A0 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +700.0 + 20 +-509.0 + 30 +0.0 + 40 +9.0 + 1 +BRICK_STRBOND + 7 +LABEL + 11 +700.0 + 21 +-509.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +A1 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +CLAY + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +840.0 + 20 +-495.0 + 10 +940.0 + 20 +-495.0 + 10 +940.0 + 20 +-395.0 + 10 +840.0 + 20 +-395.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +4 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +4.7625 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +0.79375 + 45 +0.0 + 46 +4.7625 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +1.5875 + 45 +0.0 + 46 +4.7625 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +3.175 + 45 +0.0 + 46 +4.7625 + 79 +2 + 49 +4.7625 + 49 +-3.175 + 98 +0 + 0 +LWPOLYLINE + 5 +A2 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +-495.0 + 10 +940.0 + 20 +-495.0 + 10 +940.0 + 20 +-395.0 + 10 +840.0 + 20 +-395.0 + 0 +TEXT + 5 +A3 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +840.0 + 20 +-509.0 + 30 +0.0 + 40 +9.0 + 1 +CLAY + 7 +LABEL + 11 +840.0 + 21 +-509.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +A4 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +CONCRETE1 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +980.0 + 20 +-495.0 + 10 +1080.0 + 20 +-495.0 + 10 +1080.0 + 20 +-395.0 + 10 +980.0 + 20 +-395.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +22 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +20.32 + 46 +20.32 + 79 +2 + 49 +2.54 + 49 +-17.78 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-20.32 + 46 +20.32 + 79 +2 + 49 +2.54 + 49 +-17.78 + 53 +135.0 + 43 +2.54 + 44 +0.0 + 45 +-20.3199999659 + 46 +0.0 + 79 +2 + 49 +3.592102544 + 49 +-25.144717808 + 53 +0.0 + 43 +2.54 + 44 +11.43 + 45 +20.32 + 46 +20.32 + 79 +2 + 49 +2.54 + 49 +-17.78 + 53 +45.0 + 43 +3.81 + 44 +10.16 + 45 +0.0 + 46 +20.3199999659 + 79 +2 + 49 +1.796050256 + 49 +-26.940768064 + 53 +135.0 + 43 +3.81 + 44 +10.16 + 45 +-20.3199999659 + 46 +0.0 + 79 +2 + 49 +1.796050256 + 49 +-26.940768064 + 53 +0.0 + 43 +10.16 + 44 +16.51 + 45 +20.32 + 46 +20.32 + 79 +2 + 49 +3.592102544 + 49 +-16.727897456 + 53 +45.0 + 43 +10.16 + 44 +16.51 + 45 +0.0 + 46 +20.3199999659 + 79 +2 + 49 +2.54 + 49 +-26.196820352 + 53 +135.0 + 43 +13.752102544 + 44 +16.51 + 45 +-20.3199999659 + 46 +0.0 + 79 +2 + 49 +2.54 + 49 +-26.196820352 + 53 +90.0 + 43 +13.97 + 44 +5.08 + 45 +-20.32 + 46 +20.32 + 79 +2 + 49 +2.54 + 49 +-17.78 + 53 +45.0 + 43 +13.97 + 44 +5.08 + 45 +0.0 + 46 +20.3199999659 + 79 +2 + 49 +1.796050256 + 49 +-26.940768064 + 53 +135.0 + 43 +15.24 + 44 +6.35 + 45 +-20.3199999659 + 46 +0.0 + 79 +2 + 49 +1.796050256 + 49 +-26.940768064 + 53 +0.0 + 43 +2.54 + 44 +5.08 + 45 +20.32 + 46 +20.32 + 79 +2 + 49 +1.27 + 49 +-17.018 + 53 +0.0 + 43 +17.78 + 44 +10.16 + 45 +20.32 + 46 +20.32 + 79 +2 + 49 +1.27 + 49 +-17.018 + 53 +90.0 + 43 +11.43 + 44 +12.7 + 45 +-20.32 + 46 +20.32 + 79 +2 + 49 +1.27 + 49 +-17.018 + 53 +135.0 + 43 +13.97 + 44 +1.27 + 45 +-20.3199999659 + 46 +0.0 + 79 +2 + 49 +1.796050256 + 49 +-26.940768064 + 53 +135.0 + 43 +5.08 + 44 +15.24 + 45 +-20.3199999659 + 46 +0.0 + 79 +2 + 49 +1.796050256 + 49 +-26.940768064 + 53 +45.0 + 43 +9.525 + 44 +6.6675 + 45 +0.0 + 46 +20.3199999659 + 79 +2 + 49 +1.796050256 + 49 +-26.940768064 + 53 +90.0 + 43 +6.985 + 44 +2.54 + 45 +-20.32 + 46 +20.32 + 79 +2 + 49 +0.3175 + 49 +-20.0025 + 53 +90.0 + 43 +7.9375 + 44 +11.1125 + 45 +-20.32 + 46 +20.32 + 79 +2 + 49 +0.3175 + 49 +-20.0025 + 53 +90.0 + 43 +17.4625 + 44 +14.605 + 45 +-20.32 + 46 +20.32 + 79 +2 + 49 +0.3175 + 49 +-20.0025 + 53 +90.0 + 43 +17.78 + 44 +3.81 + 45 +-20.32 + 46 +20.32 + 79 +2 + 49 +0.3175 + 49 +-20.0025 + 98 +0 + 0 +LWPOLYLINE + 5 +A5 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +980.0 + 20 +-495.0 + 10 +1080.0 + 20 +-495.0 + 10 +1080.0 + 20 +-395.0 + 10 +980.0 + 20 +-395.0 + 0 +TEXT + 5 +A6 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +980.0 + 20 +-509.0 + 30 +0.0 + 40 +9.0 + 1 +CONCRETE1 + 7 +LABEL + 11 +980.0 + 21 +-509.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +A7 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +CONCRETE2 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-660.0 + 10 +100.0 + 20 +-660.0 + 10 +100.0 + 20 +-560.0 + 10 +0.0 + 20 +-560.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +13 + 53 +50.0 + 43 +0.0 + 44 +0.0 + 45 +14.5747269104 + 46 +-1.2751233828 + 79 +2 + 49 +1.524 + 49 +-16.764 + 53 +355.0 + 43 +0.0 + 44 +0.0 + 45 +-2.819427099 + 46 +15.2845441568 + 79 +2 + 49 +1.2192 + 49 +-13.4112 + 53 +100.4514 + 43 +1.2145605376 + 44 +-0.1062601888 + 45 +11.7553106364 + 46 +14.0094114947 + 79 +2 + 49 +1.2952006608 + 49 +-14.2472077158 + 53 +46.1842 + 43 +0.0 + 44 +4.064 + 45 +21.6863381081 + 46 +-3.3633463712 + 79 +2 + 49 +2.286 + 49 +-25.146 + 53 +96.6356 + 43 +1.8071946584 + 44 +3.7837200018 + 45 +18.9923461767 + 46 +19.7940751367 + 79 +2 + 49 +1.9428010522 + 49 +-21.37080816 + 53 +351.1842 + 43 +0.0 + 44 +4.064 + 45 +18.9923307251 + 46 +19.7940899708 + 79 +2 + 49 +1.8288 + 49 +-20.1168 + 53 +21.0 + 43 +2.032 + 44 +3.048 + 45 +12.129151299 + 46 +-8.1812158583 + 79 +2 + 49 +1.524 + 49 +-16.764 + 53 +326.0 + 43 +2.032 + 44 +3.048 + 45 +4.9441675446 + 46 +14.7350489154 + 79 +2 + 49 +1.2192 + 49 +-13.4112 + 53 +71.4514 + 43 +3.0427621746 + 44 +2.3662313661 + 45 +17.0733238128 + 46 +6.5538196931 + 79 +2 + 49 +1.2952006608 + 49 +-14.2472077158 + 53 +37.5 + 43 +0.0 + 44 +0.0 + 45 +0.24708826 + 46 +6.7644031099 + 79 +6 + 49 +0.0 + 49 +-13.24864 + 49 +0.0 + 49 +-13.6144 + 49 +0.0 + 49 +-13.462 + 53 +7.5 + 43 +0.0 + 44 +0.0 + 45 +5.3455730008 + 46 +8.0144459854 + 79 +6 + 49 +0.0 + 49 +-7.76224 + 49 +0.0 + 49 +-12.94384 + 49 +0.0 + 49 +-5.1308 + 53 +-32.5 + 43 +-4.53136 + 44 +0.0 + 45 +10.847271903 + 46 +-0.4583149936 + 79 +6 + 49 +0.0 + 49 +-5.08 + 49 +0.0 + 49 +-15.8496 + 49 +0.0 + 49 +-21.0312 + 53 +-42.5 + 43 +-6.56336 + 44 +0.0 + 45 +11.850342961 + 46 +2.034133241 + 79 +6 + 49 +0.0 + 49 +-6.604 + 49 +0.0 + 49 +-10.52576 + 49 +0.0 + 49 +-14.9352 + 98 +0 + 0 +LWPOLYLINE + 5 +A8 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-660.0 + 10 +100.0 + 20 +-660.0 + 10 +100.0 + 20 +-560.0 + 10 +0.0 + 20 +-560.0 + 0 +TEXT + 5 +A9 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-674.0 + 30 +0.0 + 40 +9.0 + 1 +CONCRETE2 + 7 +LABEL + 11 +0.0 + 21 +-674.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +AA +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +CONCRETE3 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +140.0 + 20 +-660.0 + 10 +240.0 + 20 +-660.0 + 10 +240.0 + 20 +-560.0 + 10 +140.0 + 20 +-560.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +304 + 53 +82.88 + 43 +97.10721498 + 44 +59.2083144 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.03725418 + 49 +-136.48436 + 53 +97.13 + 43 +97.10660538 + 44 +59.2448904 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.04934458 + 49 +-136.4722696 + 53 +116.57 + 43 +97.09453022 + 44 +59.29154258 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +135.0 + 43 +97.06356 + 44 +59.33695778 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +172.88 + 43 +97.01943258 + 44 +59.3792564 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +172.88 + 43 +96.9621632 + 44 +59.3875368 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +187.13 + 43 +96.92463978 + 44 +59.38655382 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.05259578 + 49 +-136.4690184 + 53 +225.0 + 43 +96.8702152 + 44 +59.3801708 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.06072378 + 49 +-23.88639622 + 53 +243.44 + 43 +96.82142942 + 44 +59.3422232 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +262.88 + 43 +96.79022298 + 44 +59.29440262 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +262.88 + 43 +96.78295858 + 44 +59.2425536 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +277.13 + 43 +96.78366978 + 44 +59.20499462 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.0483108 + 49 +-136.47330338 + 53 +296.57 + 43 +96.79555698 + 44 +59.1593432 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +315.0 + 43 +96.8265272 + 44 +59.11391022 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +352.88 + 43 +96.87065462 + 44 +59.07162938 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +7.13 + 43 +96.96544742 + 44 +59.0642964 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.0521208 + 49 +-136.46949338 + 53 +45.0 + 43 +97.0198212 + 44 +59.07066418 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.0608076 + 49 +-23.8863124 + 53 +63.44 + 43 +97.06865778 + 44 +59.1086448 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +82.88 + 43 +97.09986422 + 44 +59.15646538 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +82.88 + 43 +87.67045458 + 44 +53.3422352 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.03725418 + 49 +-136.48436 + 53 +97.13 + 43 +87.66984498 + 44 +53.37879342 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.04934458 + 49 +-136.4722696 + 53 +116.57 + 43 +87.65776982 + 44 +53.4254456 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +135.0 + 43 +87.6267996 + 44 +53.47087858 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +172.88 + 43 +87.58267218 + 44 +53.51315942 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +172.88 + 43 +87.5254028 + 44 +53.52143982 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +187.13 + 43 +87.48787938 + 44 +53.52045938 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.05259578 + 49 +-136.4690184 + 53 +225.0 + 43 +87.4334548 + 44 +53.51407382 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.06072378 + 49 +-23.88639622 + 53 +243.44 + 43 +87.38466902 + 44 +53.47612622 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +262.88 + 43 +87.35346258 + 44 +53.42830818 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +262.88 + 43 +87.34619818 + 44 +53.37645662 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +277.13 + 43 +87.34690938 + 44 +53.33890018 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.0483108 + 49 +-136.47330338 + 53 +296.57 + 43 +87.35879658 + 44 +53.29324622 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +315.0 + 43 +87.3897668 + 44 +53.24781578 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +352.88 + 43 +87.43389422 + 44 +53.2055324 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +7.13 + 43 +87.52868702 + 44 +53.19819942 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.0521208 + 49 +-136.46949338 + 53 +45.0 + 43 +87.5830608 + 44 +53.2045672 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.0608076 + 49 +-23.8863124 + 53 +63.44 + 43 +87.63189738 + 44 +53.24254782 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +82.88 + 43 +87.66310382 + 44 +53.29038618 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +82.88 + 43 +93.68222818 + 44 +52.93331298 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +63.44 + 43 +93.6510192 + 44 +52.8854924 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +45.0 + 43 +93.60218262 + 44 +52.847494 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.0608076 + 49 +-23.8863124 + 53 +7.13 + 43 +93.54781138 + 44 +52.84112622 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.0521208 + 49 +-136.46949338 + 53 +352.88 + 43 +93.45301858 + 44 +52.84847698 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +315.0 + 43 +93.40888862 + 44 +52.89075782 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +296.57 + 43 +93.3779184 + 44 +52.93617302 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +277.13 + 43 +93.3660312 + 44 +52.98182698 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.0483108 + 49 +-136.47330338 + 53 +262.88 + 43 +93.36532 + 44 +53.01938342 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +262.88 + 43 +93.3725844 + 44 +53.07125022 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +243.44 + 43 +93.40379338 + 44 +53.1190708 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +225.0 + 43 +93.45257662 + 44 +53.15700062 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.06072378 + 49 +-23.88639622 + 53 +187.13 + 43 +93.5070012 + 44 +53.16340142 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.05259578 + 49 +-136.4690184 + 53 +172.88 + 43 +93.54452462 + 44 +53.16436662 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +172.88 + 43 +93.601794 + 44 +53.15608622 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +135.0 + 43 +93.64592142 + 44 +53.11380538 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +116.57 + 43 +93.67689418 + 44 +53.0683724 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +97.13 + 43 +93.6889668 + 44 +53.02172022 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.04934458 + 49 +-136.4722696 + 53 +82.88 + 43 +93.6895764 + 44 +52.985162 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.03725418 + 49 +-136.48436 + 53 +82.88 + 43 +89.09138138 + 44 +65.02255982 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +63.44 + 43 +89.06015462 + 44 +64.97474178 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +45.0 + 43 +89.01132058 + 44 +64.93675862 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.0608076 + 49 +-23.8863124 + 53 +7.13 + 43 +88.95696458 + 44 +64.93039338 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.0521208 + 49 +-136.46949338 + 53 +352.88 + 43 +88.862154 + 44 +64.93772382 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +315.0 + 43 +88.81802658 + 44 +64.9800072 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +296.57 + 43 +88.78705382 + 44 +65.0254224 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +277.13 + 43 +88.7751844 + 44 +65.07107382 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.0483108 + 49 +-136.47330338 + 53 +262.88 + 43 +88.77445542 + 44 +65.10865058 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +262.88 + 43 +88.78171982 + 44 +65.1604996 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +243.44 + 43 +88.81294658 + 44 +65.20832018 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +225.0 + 43 +88.86171458 + 44 +65.24626778 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.06072378 + 49 +-23.88639622 + 53 +187.13 + 43 +88.9161544 + 44 +65.2526508 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.05259578 + 49 +-136.4690184 + 53 +172.88 + 43 +88.95366258 + 44 +65.253616 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +172.88 + 43 +89.0109472 + 44 +65.2453356 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +135.0 + 43 +89.05507462 + 44 +65.20305222 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +116.57 + 43 +89.08604738 + 44 +65.15763702 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +97.13 + 43 +89.09810222 + 44 +65.11098738 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.04934458 + 49 +-136.4722696 + 53 +82.88 + 43 +89.0987296 + 44 +65.07441138 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.03725418 + 49 +-136.48436 + 53 +82.88 + 43 +88.11877982 + 44 +63.97348902 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.15551658 + 49 +-136.3660976 + 53 +97.13 + 43 +88.11622458 + 44 +64.12612778 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.20597622 + 49 +-136.31563542 + 53 +116.57 + 43 +88.06583098 + 44 +64.32089498 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.23506938 + 49 +-37.62955898 + 53 +135.0 + 43 +87.93656022 + 44 +64.51053138 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.24807418 + 49 +-23.69904582 + 53 +172.88 + 43 +87.75230862 + 44 +64.6870436 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.24306022 + 49 +-136.27855142 + 53 +172.88 + 43 +87.51319302 + 44 +64.72162062 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.16085058 + 49 +-136.3607636 + 53 +187.13 + 43 +87.35657662 + 44 +64.71755662 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.21959062 + 49 +-136.30202102 + 53 +225.0 + 43 +87.12934822 + 44 +64.69088662 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.25350978 + 49 +-23.69361022 + 53 +243.44 + 43 +86.92572658 + 44 +64.53249222 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.23410418 + 49 +-37.63052418 + 53 +262.88 + 43 +86.79542458 + 44 +64.33284822 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.21999702 + 49 +-136.30161462 + 53 +262.88 + 43 +86.76506142 + 44 +64.11637418 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.16085058 + 49 +-136.3607636 + 53 +277.13 + 43 +86.7680764 + 44 +63.95955458 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.20170902 + 49 +-136.31990262 + 53 +296.57 + 43 +86.81769022 + 44 +63.768986 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.23506938 + 49 +-37.62955898 + 53 +315.0 + 43 +86.94696098 + 44 +63.5793496 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.24807418 + 49 +-23.69904582 + 53 +352.88 + 43 +87.13121258 + 44 +63.4028196 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.24306022 + 49 +-136.27855142 + 53 +7.13 + 43 +87.52695982 + 44 +63.37220498 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.21760942 + 49 +-136.30400222 + 53 +45.0 + 43 +87.75393422 + 44 +63.39877338 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.2538476 + 49 +-23.6932724 + 53 +63.44 + 43 +87.95779462 + 44 +63.55737098 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.23410418 + 49 +-37.63052418 + 53 +82.88 + 43 +88.0881144 + 44 +63.75701498 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.21999702 + 49 +-136.30161462 + 53 +82.88 + 43 +87.3229648 + 44 +65.74639378 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.21999702 + 49 +-136.30161462 + 53 +63.44 + 43 +87.1926628 + 44 +65.54674978 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.23410418 + 49 +-37.63052418 + 53 +45.0 + 43 +86.98878462 + 44 +65.38815218 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.2538476 + 49 +-23.6932724 + 53 +7.13 + 43 +86.76181022 + 44 +65.361566 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.21760942 + 49 +-136.30400222 + 53 +352.88 + 43 +86.36606298 + 44 +65.3921984 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.24306022 + 49 +-136.27855142 + 53 +315.0 + 43 +86.18182662 + 44 +65.56871062 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.24807418 + 49 +-23.69904582 + 53 +296.57 + 43 +86.05254062 + 44 +65.75834702 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.23506938 + 49 +-37.62955898 + 53 +277.13 + 43 +86.00294458 + 44 +65.94893338 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.20170902 + 49 +-136.31990262 + 53 +262.88 + 43 +85.9999296 + 44 +66.1057352 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.16085058 + 49 +-136.3607636 + 53 +262.88 + 43 +86.03027498 + 44 +66.32222702 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.21999702 + 49 +-136.30161462 + 53 +243.44 + 43 +86.16057698 + 44 +66.52187102 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.23410418 + 49 +-37.63052418 + 53 +225.0 + 43 +86.36419862 + 44 +66.68025018 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.25350978 + 49 +-23.69361022 + 53 +187.13 + 43 +86.5914448 + 44 +66.70692018 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.21959062 + 49 +-136.30202102 + 53 +172.88 + 43 +86.7480612 + 44 +66.71099942 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.16085058 + 49 +-136.3607636 + 53 +172.88 + 43 +86.9871768 + 44 +66.6764224 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.24306022 + 49 +-136.27855142 + 53 +135.0 + 43 +87.17141062 + 44 +66.4998924 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.24807418 + 49 +-23.69904582 + 53 +116.57 + 43 +87.30069662 + 44 +66.310256 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.23506938 + 49 +-37.62955898 + 53 +97.13 + 43 +87.35107498 + 44 +66.1154888 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.20597622 + 49 +-136.31563542 + 53 +82.88 + 43 +87.353648 + 44 +65.96285258 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.15551658 + 49 +-136.3660976 + 53 +82.88 + 43 +94.74125578 + 44 +62.99714858 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.52391818 + 49 +-135.997696 + 53 +63.44 + 43 +94.43093382 + 44 +62.52167582 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.55751222 + 49 +-37.3071136 + 53 +45.0 + 43 +93.94542298 + 44 +62.14397782 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.60453778 + 49 +-23.34258222 + 53 +7.13 + 43 +93.40487542 + 44 +62.08068102 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.51824382 + 49 +-136.00336782 + 53 +352.88 + 43 +92.46236778 + 44 +62.15361458 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.578866 + 49 +-135.94274818 + 53 +315.0 + 43 +92.0235904 + 44 +62.5740176 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.59077098 + 49 +-23.35634902 + 53 +296.57 + 43 +91.71570938 + 44 +63.0256296 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.559816 + 49 +-37.30480982 + 53 +277.13 + 43 +91.5975816 + 44 +63.47950982 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.4803648 + 49 +-136.04124938 + 53 +262.88 + 43 +91.59040102 + 44 +63.85294062 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.38306502 + 49 +-136.13854662 + 53 +262.88 + 43 +91.66267418 + 44 +64.36850982 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.52391818 + 49 +-135.997696 + 53 +243.44 + 43 +91.97301138 + 44 +64.84398258 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.55751222 + 49 +-37.3071136 + 53 +225.0 + 43 +92.4579304 + 44 +65.22117258 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.603758 + 49 +-23.343362 + 53 +187.13 + 43 +92.99912058 + 44 +65.28468782 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.52296822 + 49 +-135.99864342 + 53 +172.88 + 43 +93.37209418 + 44 +65.29439062 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.38306502 + 49 +-136.13854662 + 53 +172.88 + 43 +93.94156218 + 44 +65.21204382 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.578866 + 49 +-135.94274818 + 53 +135.0 + 43 +94.38033702 + 44 +64.7916408 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.59077098 + 49 +-23.35634902 + 53 +116.57 + 43 +94.68822058 + 44 +64.3400288 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.559816 + 49 +-37.30480982 + 53 +97.13 + 43 +94.80822542 + 44 +63.876174 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.49054258 + 49 +-136.0310716 + 53 +82.88 + 43 +94.81432142 + 44 +63.51266698 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.37036502 + 49 +-136.15124662 + 53 +82.88 + 43 +99.5581956 + 44 +54.0248856 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.37036502 + 49 +-136.15124662 + 53 +97.13 + 43 +99.5520996 + 44 +54.3884104 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.49054258 + 49 +-136.0310716 + 53 +116.57 + 43 +99.43211 + 44 +54.8522652 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.559816 + 49 +-37.30480982 + 53 +135.0 + 43 +99.12422898 + 44 +55.3038772 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.59077098 + 49 +-23.35634902 + 53 +172.88 + 43 +98.6854516 + 44 +55.72428022 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.578866 + 49 +-135.94274818 + 53 +172.88 + 43 +98.1159836 + 44 +55.80661178 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.38306502 + 49 +-136.13854662 + 53 +187.13 + 43 +97.74301 + 44 +55.79692422 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.52296822 + 49 +-135.99864342 + 53 +225.0 + 43 +97.20181982 + 44 +55.73340898 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.603758 + 49 +-23.343362 + 53 +243.44 + 43 +96.7169008 + 44 +55.3562012 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.55751222 + 49 +-37.3071136 + 53 +262.88 + 43 +96.4065636 + 44 +54.88073098 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.52391818 + 49 +-135.997696 + 53 +262.88 + 43 +96.33429298 + 44 +54.36517702 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.38306502 + 49 +-136.13854662 + 53 +277.13 + 43 +96.34147102 + 44 +53.99174622 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.4803648 + 49 +-136.04124938 + 53 +296.57 + 43 +96.4595988 + 44 +53.53784822 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.559816 + 49 +-37.30480982 + 53 +315.0 + 43 +96.76747982 + 44 +53.08623622 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.59077098 + 49 +-23.35634902 + 53 +352.88 + 43 +97.2062572 + 44 +52.6658332 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.578866 + 49 +-135.94274818 + 53 +7.13 + 43 +98.1487496 + 44 +52.59291742 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.51824382 + 49 +-136.00336782 + 53 +45.0 + 43 +98.68929462 + 44 +52.65619898 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.60453778 + 49 +-23.34258222 + 53 +63.44 + 43 +99.174808 + 44 +53.03391222 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.55751222 + 49 +-37.3071136 + 53 +82.88 + 43 +99.4851452 + 44 +53.50938498 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.52391818 + 49 +-135.997696 + 53 +82.88 + 43 +100.58544018 + 44 +60.18634902 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.21999702 + 49 +-136.30161462 + 53 +63.44 + 43 +100.4551204 + 44 +59.98670502 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.23410418 + 49 +-37.63052418 + 53 +45.0 + 43 +100.25126 + 44 +59.82810742 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.2538476 + 49 +-23.6932724 + 53 +7.13 + 43 +100.0242856 + 44 +59.80153902 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.21760942 + 49 +-136.30400222 + 53 +352.88 + 43 +99.62853582 + 44 +59.83215618 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.24306022 + 49 +-136.27855142 + 53 +315.0 + 43 +99.444302 + 44 +60.00868618 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.24807418 + 49 +-23.69904582 + 53 +296.57 + 43 +99.315016 + 44 +60.1983048 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.23506938 + 49 +-37.62955898 + 53 +277.13 + 43 +99.26541742 + 44 +60.38888862 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.20170902 + 49 +-136.31990262 + 53 +262.88 + 43 +99.26240498 + 44 +60.54570822 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.16085058 + 49 +-136.3607636 + 53 +262.88 + 43 +99.29274782 + 44 +60.7621848 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.21999702 + 49 +-136.30161462 + 53 +243.44 + 43 +99.42304982 + 44 +60.9618288 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.23410418 + 49 +-37.63052418 + 53 +225.0 + 43 +99.626674 + 44 +61.1202232 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.25350978 + 49 +-23.69361022 + 53 +187.13 + 43 +99.85392018 + 44 +61.1468932 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.21959062 + 49 +-136.30202102 + 53 +172.88 + 43 +100.01053658 + 44 +61.1509572 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.16085058 + 49 +-136.3607636 + 53 +172.88 + 43 +100.24965218 + 44 +61.11638018 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.24306022 + 49 +-136.27855142 + 53 +135.0 + 43 +100.433886 + 44 +60.93986542 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.24807418 + 49 +-23.69904582 + 53 +116.57 + 43 +100.563172 + 44 +60.75022902 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.23506938 + 49 +-37.62955898 + 53 +97.13 + 43 +100.61354782 + 44 +60.55544658 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.20597622 + 49 +-136.31563542 + 53 +82.88 + 43 +100.6161056 + 44 +60.40280782 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.15551658 + 49 +-136.3660976 + 53 +82.88 + 43 +97.50794062 + 44 +65.78770942 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +63.44 + 43 +97.47673418 + 44 +65.73989138 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +45.0 + 43 +97.4278976 + 44 +65.70189298 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.0608076 + 49 +-23.8863124 + 53 +7.13 + 43 +97.37352382 + 44 +65.6955252 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.0521208 + 49 +-136.46949338 + 53 +352.88 + 43 +97.27873102 + 44 +65.70285818 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +315.0 + 43 +97.2346036 + 44 +65.7451568 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +296.57 + 43 +97.20363338 + 44 +65.790572 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +277.13 + 43 +97.19174618 + 44 +65.83622342 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.0483108 + 49 +-136.47330338 + 53 +262.88 + 43 +97.19103498 + 44 +65.8737824 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +262.88 + 43 +97.19829938 + 44 +65.9256492 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +243.44 + 43 +97.22950582 + 44 +65.97346978 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +225.0 + 43 +97.2782916 + 44 +66.0113996 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.06072378 + 49 +-23.88639622 + 53 +187.13 + 43 +97.33271618 + 44 +66.01778262 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.05259578 + 49 +-136.4690184 + 53 +172.88 + 43 +97.3702396 + 44 +66.0187656 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +172.88 + 43 +97.42750898 + 44 +66.0104852 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +135.0 + 43 +97.4716364 + 44 +65.96820182 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +116.57 + 43 +97.50260662 + 44 +65.92277138 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +97.13 + 43 +97.51468178 + 44 +65.8761192 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.04934458 + 49 +-136.4722696 + 53 +82.88 + 43 +97.51529138 + 44 +65.83956098 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.03725418 + 49 +-136.48436 + 53 +82.88 + 43 +98.2182948 + 44 +64.2727696 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.15922498 + 49 +-136.3623892 + 53 +63.44 + 43 +98.12399222 + 44 +64.12827662 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.16943578 + 49 +-37.69519258 + 53 +45.0 + 43 +97.97641822 + 44 +64.01346862 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.18372582 + 49 +-23.76339418 + 53 +7.13 + 43 +97.8121488 + 44 +63.99425098 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.15749778 + 49 +-136.3641164 + 53 +352.88 + 43 +97.52570538 + 44 +64.01639978 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.17593818 + 49 +-136.345676 + 53 +315.0 + 43 +97.3923376 + 44 +64.14417702 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.17954498 + 49 +-23.76757502 + 53 +296.57 + 43 +97.298764 + 44 +64.28142338 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.17014698 + 49 +-37.69448138 + 53 +277.13 + 43 +97.26286618 + 44 +64.4193784 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.1459992 + 49 +-136.37561498 + 53 +262.88 + 43 +97.26069702 + 44 +64.5328656 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.11641582 + 49 +-136.40519582 + 53 +262.88 + 43 +97.2826604 + 44 +64.68956582 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.15922498 + 49 +-136.3623892 + 53 +243.44 + 43 +97.37697822 + 44 +64.8340588 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.16943578 + 49 +-37.69519258 + 53 +225.0 + 43 +97.52434902 + 44 +64.94869662 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.1834896 + 49 +-23.7636304 + 53 +187.13 + 43 +97.68882418 + 44 +64.96800062 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.15893542 + 49 +-136.36267622 + 53 +172.88 + 43 +97.80217422 + 44 +64.9709648 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.11641582 + 49 +-136.40519582 + 53 +172.88 + 43 +97.97524982 + 44 +64.94593818 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.17593818 + 49 +-136.345676 + 53 +135.0 + 43 +98.1086176 + 44 +64.8181584 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.17954498 + 49 +-23.76757502 + 53 +116.57 + 43 +98.2021912 + 44 +64.68091458 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.17014698 + 49 +-37.69448138 + 53 +97.13 + 43 +98.23864782 + 44 +64.5399268 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.14908022 + 49 +-136.37253142 + 53 +82.88 + 43 +98.24051218 + 44 +64.42945458 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.11255502 + 49 +-136.40905662 + 53 +82.88 + 43 +94.03588 + 44 +58.51547098 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.15551658 + 49 +-136.3660976 + 53 +97.13 + 43 +94.03332222 + 44 +58.6681072 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.20597622 + 49 +-136.31563542 + 53 +116.57 + 43 +93.9829464 + 44 +58.8628744 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.23506938 + 49 +-37.62955898 + 53 +135.0 + 43 +93.8536604 + 44 +59.0525108 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.24807418 + 49 +-23.69904582 + 53 +172.88 + 43 +93.66942658 + 44 +59.2290408 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.24306022 + 49 +-136.27855142 + 53 +172.88 + 43 +93.4302932 + 44 +59.26360258 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.16085058 + 49 +-136.3607636 + 53 +187.13 + 43 +93.27369458 + 44 +59.25953858 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.21959062 + 49 +-136.30202102 + 53 +225.0 + 43 +93.0464484 + 44 +59.23286858 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.25350978 + 49 +-23.69361022 + 53 +243.44 + 43 +92.84282422 + 44 +59.07447418 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.23410418 + 49 +-37.63052418 + 53 +262.88 + 43 +92.71252222 + 44 +58.87483018 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.21999702 + 49 +-136.30161462 + 53 +262.88 + 43 +92.68217938 + 44 +58.6583536 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.16085058 + 49 +-136.3607636 + 53 +277.13 + 43 +92.68519182 + 44 +58.50155178 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.20170902 + 49 +-136.31990262 + 53 +296.57 + 43 +92.7347904 + 44 +58.31096542 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.23506938 + 49 +-37.62955898 + 53 +315.0 + 43 +92.86405862 + 44 +58.12132902 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.24807418 + 49 +-23.69904582 + 53 +352.88 + 43 +93.04831022 + 44 +57.94479902 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.24306022 + 49 +-136.27855142 + 53 +7.13 + 43 +93.44406 + 44 +57.9141844 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.21760942 + 49 +-136.30400222 + 53 +45.0 + 43 +93.6710344 + 44 +57.9407528 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.2538476 + 49 +-23.6932724 + 53 +63.44 + 43 +93.8748948 + 44 +58.0993504 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.23410418 + 49 +-37.63052418 + 53 +82.88 + 43 +94.00521458 + 44 +58.29901218 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.21999702 + 49 +-136.30161462 + 53 +82.88 + 43 +90.7421096 + 44 +59.22648302 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.11255502 + 49 +-136.40905662 + 53 +97.13 + 43 +90.74024778 + 44 +59.33695778 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.14908022 + 49 +-136.37253142 + 53 +116.57 + 43 +90.70378862 + 44 +59.47794302 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.17014698 + 49 +-37.69448138 + 53 +135.0 + 43 +90.61021502 + 44 +59.61518938 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.17954498 + 49 +-23.76757502 + 53 +172.88 + 43 +90.47686502 + 44 +59.74296662 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.17593818 + 49 +-136.345676 + 53 +172.88 + 43 +90.30378942 + 44 +59.767978 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.11641582 + 49 +-136.40519582 + 53 +187.13 + 43 +90.1904216 + 44 +59.7650316 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.15893542 + 49 +-136.36267622 + 53 +225.0 + 43 +90.02594898 + 44 +59.7457276 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.1834896 + 49 +-23.7636304 + 53 +243.44 + 43 +89.87857818 + 44 +59.63108978 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.16943578 + 49 +-37.69519258 + 53 +262.88 + 43 +89.78425782 + 44 +59.4865968 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.15922498 + 49 +-136.3623892 + 53 +262.88 + 43 +89.76229698 + 44 +59.32989658 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.11641582 + 49 +-136.40519582 + 53 +277.13 + 43 +89.7644636 + 44 +59.21640938 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.1459992 + 49 +-136.37561498 + 53 +296.57 + 43 +89.8003792 + 44 +59.07845182 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.17014698 + 49 +-37.69448138 + 53 +315.0 + 43 +89.8939528 + 44 +58.941208 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.17954498 + 49 +-23.76757502 + 53 +352.88 + 43 +90.0273028 + 44 +58.81342822 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.17593818 + 49 +-136.345676 + 53 +7.13 + 43 +90.31374622 + 44 +58.79126418 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.15749778 + 49 +-136.3641164 + 53 +45.0 + 43 +90.47803342 + 44 +58.8104996 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.18372582 + 49 +-23.76339418 + 53 +63.44 + 43 +90.62559218 + 44 +58.9253076 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.16943578 + 49 +-37.69519258 + 53 +82.88 + 43 +90.71991 + 44 +59.06980058 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.15922498 + 49 +-136.3623892 + 53 +82.88 + 43 +88.04749218 + 44 +58.09938342 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.21413978 + 49 +-136.3074744 + 53 +97.13 + 43 +88.0439692 + 44 +58.30954302 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.28359862 + 49 +-136.23801302 + 53 +116.57 + 43 +87.97459418 + 44 +58.57771622 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.32366458 + 49 +-37.54096378 + 53 +135.0 + 43 +87.79659098 + 44 +58.83882822 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.34156142 + 49 +-23.60555858 + 53 +172.88 + 43 +87.54291102 + 44 +59.0818732 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.3346704 + 49 +-136.18694378 + 53 +172.88 + 43 +87.21367622 + 44 +59.12949058 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.22147022 + 49 +-136.30014142 + 53 +187.13 + 43 +86.998048 + 44 +59.1238848 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.3023616 + 49 +-136.21925258 + 53 +225.0 + 43 +86.68515302 + 44 +59.0871564 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.34906458 + 49 +-23.59805542 + 53 +243.44 + 43 +86.40478782 + 44 +58.869072 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.322326 + 49 +-37.54229982 + 53 +262.88 + 43 +86.22538 + 44 +58.59417542 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.30290262 + 49 +-136.21870902 + 53 +262.88 + 43 +86.18358938 + 44 +58.29611658 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.22147022 + 49 +-136.30014142 + 53 +277.13 + 43 +86.1877372 + 44 +58.08021658 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.2777236 + 49 +-136.24389058 + 53 +296.57 + 43 +86.25603018 + 44 +57.81779902 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.32366458 + 49 +-37.54096378 + 53 +315.0 + 43 +86.43403338 + 44 +57.5567048 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.34156142 + 49 +-23.60555858 + 53 +352.88 + 43 +86.6877108 + 44 +57.31364458 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.3346704 + 49 +-136.18694378 + 53 +7.13 + 43 +87.23262462 + 44 +57.27148058 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.2996184 + 49 +-136.22199578 + 53 +45.0 + 43 +87.54514622 + 44 +57.30807182 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.349504 + 49 +-23.597616 + 53 +63.44 + 43 +87.825834 + 44 +57.52644578 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.322326 + 49 +-37.54229982 + 53 +82.88 + 43 +88.0052596 + 44 +57.80133982 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.30290262 + 49 +-136.21870902 + 53 +82.88 + 43 +90.0168888 + 44 +60.63658942 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.03725418 + 49 +-136.48436 + 53 +97.13 + 43 +90.0162792 + 44 +60.67315018 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.04934458 + 49 +-136.4722696 + 53 +116.57 + 43 +90.00420658 + 44 +60.71979982 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +135.0 + 43 +89.9732516 + 44 +60.7652328 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +172.88 + 43 +89.9291064 + 44 +60.80751618 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +172.88 + 43 +89.87183702 + 44 +60.81579658 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +187.13 + 43 +89.8343136 + 44 +60.8148136 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.05259578 + 49 +-136.4690184 + 53 +225.0 + 43 +89.77988902 + 44 +60.80843058 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.06072378 + 49 +-23.88639622 + 53 +243.44 + 43 +89.73110578 + 44 +60.77049822 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +262.88 + 43 +89.6998968 + 44 +60.7226624 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +262.88 + 43 +89.6926324 + 44 +60.67081338 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.03852418 + 49 +-136.48309 + 53 +277.13 + 43 +89.6933436 + 44 +60.6332544 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.0483108 + 49 +-136.47330338 + 53 +296.57 + 43 +89.7052308 + 44 +60.58760298 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.05630418 + 49 +-37.80832418 + 53 +315.0 + 43 +89.73620102 + 44 +60.54218778 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.05941822 + 49 +-23.88770178 + 53 +352.88 + 43 +89.78033098 + 44 +60.49988662 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.0582168 + 49 +-136.46339738 + 53 +7.13 + 43 +89.87512378 + 44 +60.49255618 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.0521208 + 49 +-136.46949338 + 53 +45.0 + 43 +89.92949502 + 44 +60.49892142 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.0608076 + 49 +-23.8863124 + 53 +63.44 + 43 +89.9783316 + 44 +60.53691982 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.0560832 + 49 +-37.80854262 + 53 +82.88 + 43 +90.00954058 + 44 +60.5847404 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.05269738 + 49 +-136.4689168 + 53 +82.88 + 43 +91.272614 + 44 +55.4477428 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.52391818 + 49 +-135.997696 + 53 +63.44 + 43 +90.9622768 + 44 +54.97227258 + 45 +-0.0014916558 + 46 +16.9328188651 + 79 +2 + 49 +0.55751222 + 49 +-37.3071136 + 53 +45.0 + 43 +90.47676342 + 44 +54.5945568 + 45 +0.0 + 46 +16.9331709419 + 79 +2 + 49 +0.60453778 + 49 +-23.34258222 + 53 +7.13 + 43 +89.9362184 + 44 +54.53127778 + 45 +118.5322702695 + 46 +16.9431028479 + 79 +2 + 49 +0.51824382 + 49 +-136.00336782 + 53 +352.88 + 43 +88.993726 + 44 +54.6042088 + 45 +118.5352255934 + 46 +-16.9224148061 + 79 +2 + 49 +0.578866 + 49 +-135.94274818 + 53 +315.0 + 43 +88.55494862 + 44 +55.02461182 + 45 +16.9331709419 + 46 +-0.0 + 79 +2 + 49 +0.59077098 + 49 +-23.35634902 + 53 +296.57 + 43 +88.2470676 + 44 +55.47622382 + 45 +16.9342802744 + 46 +-16.9313563251 + 79 +2 + 49 +0.559816 + 49 +-37.30480982 + 53 +277.13 + 43 +88.12893982 + 44 +55.93010658 + 45 +16.9431028479 + 46 +-118.5322702695 + 79 +2 + 49 +0.4803648 + 49 +-136.04124938 + 53 +262.88 + 43 +88.12176178 + 44 +56.30353738 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.38306502 + 49 +-136.13854662 + 53 +262.88 + 43 +88.1940324 + 44 +56.8190888 + 45 +0.0008534187 + 46 +-16.9336313627 + 79 +2 + 49 +0.52391818 + 49 +-135.997696 + 53 +243.44 + 43 +88.5043696 + 44 +57.2945768 + 45 +0.0014916558 + 46 +-16.9328188651 + 79 +2 + 49 +0.55751222 + 49 +-37.3071136 + 53 +225.0 + 43 +88.98928862 + 44 +57.6717668 + 45 +-0.0 + 46 +-16.9331709419 + 79 +2 + 49 +0.603758 + 49 +-23.343362 + 53 +187.13 + 43 +89.5304788 + 44 +57.73528458 + 45 +-118.5322702695 + 46 +-16.9431028479 + 79 +2 + 49 +0.52296822 + 49 +-135.99864342 + 53 +172.88 + 43 +89.9034524 + 44 +57.74498738 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.38306502 + 49 +-136.13854662 + 53 +172.88 + 43 +90.4729204 + 44 +57.66264058 + 45 +-118.5352255934 + 46 +16.9224148061 + 79 +2 + 49 +0.578866 + 49 +-135.94274818 + 53 +135.0 + 43 +90.91169778 + 44 +57.24223502 + 45 +-16.9331709419 + 46 +0.0 + 79 +2 + 49 +0.59077098 + 49 +-23.35634902 + 53 +116.57 + 43 +91.2195788 + 44 +56.79062302 + 45 +-16.9342802744 + 46 +16.9313563251 + 79 +2 + 49 +0.559816 + 49 +-37.30480982 + 53 +97.13 + 43 +91.3395684 + 44 +56.32676822 + 45 +-16.9431028479 + 46 +118.5322702695 + 79 +2 + 49 +0.49054258 + 49 +-136.0310716 + 53 +82.88 + 43 +91.3456644 + 44 +55.96324342 + 45 +-0.0008534187 + 46 +16.9336313627 + 79 +2 + 49 +0.37036502 + 49 +-136.15124662 + 98 +0 + 0 +LWPOLYLINE + 5 +AB +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +140.0 + 20 +-660.0 + 10 +240.0 + 20 +-660.0 + 10 +240.0 + 20 +-560.0 + 10 +140.0 + 20 +-560.0 + 0 +TEXT + 5 +AC +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +140.0 + 20 +-674.0 + 30 +0.0 + 40 +9.0 + 1 +CONCRETE3 + 7 +LABEL + 11 +140.0 + 21 +-674.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +AD +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +CORK + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +280.0 + 20 +-660.0 + 10 +380.0 + 20 +-660.0 + 10 +380.0 + 20 +-560.0 + 10 +280.0 + 20 +-560.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +4 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +3.81 + 79 +0 + 53 +135.0 + 43 +1.905 + 44 +-1.905 + 45 +-7.6199999872 + 46 +-7.6199999872 + 79 +2 + 49 +5.3881536941 + 49 +-5.3881536941 + 53 +135.0 + 43 +2.8575 + 44 +-1.905 + 45 +-7.6199999872 + 46 +-7.6199999872 + 79 +2 + 49 +5.3881536941 + 49 +-5.3881536941 + 53 +135.0 + 43 +3.81 + 44 +-1.905 + 45 +-7.6199999872 + 46 +-7.6199999872 + 79 +2 + 49 +5.3881536941 + 49 +-5.3881536941 + 98 +0 + 0 +LWPOLYLINE + 5 +AE +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +280.0 + 20 +-660.0 + 10 +380.0 + 20 +-660.0 + 10 +380.0 + 20 +-560.0 + 10 +280.0 + 20 +-560.0 + 0 +TEXT + 5 +AF +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +280.0 + 20 +-674.0 + 30 +0.0 + 40 +9.0 + 1 +CORK + 7 +LABEL + 11 +280.0 + 21 +-674.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +B0 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +CROSS + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +420.0 + 20 +-660.0 + 10 +520.0 + 20 +-660.0 + 10 +520.0 + 20 +-560.0 + 10 +420.0 + 20 +-560.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +6.35 + 46 +6.35 + 79 +2 + 49 +3.175 + 49 +-9.525 + 53 +90.0 + 43 +1.5875 + 44 +-1.5875 + 45 +-6.35 + 46 +6.35 + 79 +2 + 49 +3.175 + 49 +-9.525 + 98 +0 + 0 +LWPOLYLINE + 5 +B1 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +420.0 + 20 +-660.0 + 10 +520.0 + 20 +-660.0 + 10 +520.0 + 20 +-560.0 + 10 +420.0 + 20 +-560.0 + 0 +TEXT + 5 +B2 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +420.0 + 20 +-674.0 + 30 +0.0 + 40 +9.0 + 1 +CROSS + 7 +LABEL + 11 +420.0 + 21 +-674.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +B3 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +CROSSES + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +560.0 + 20 +-660.0 + 10 +660.0 + 20 +-660.0 + 10 +660.0 + 20 +-560.0 + 10 +560.0 + 20 +-560.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +-4.48945 + 44 +0.0 + 45 +-8.9802561211 + 46 +8.9802561211 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +135.0 + 43 +0.0 + 44 +0.0 + 45 +-8.9802561211 + 46 +-8.9802561211 + 79 +2 + 49 +6.35 + 49 +-6.35 + 98 +0 + 0 +LWPOLYLINE + 5 +B4 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +560.0 + 20 +-660.0 + 10 +660.0 + 20 +-660.0 + 10 +660.0 + 20 +-560.0 + 10 +560.0 + 20 +-560.0 + 0 +TEXT + 5 +B5 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +560.0 + 20 +-674.0 + 30 +0.0 + 40 +9.0 + 1 +CROSSES + 7 +LABEL + 11 +560.0 + 21 +-674.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +B6 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +DOLMIT + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +700.0 + 20 +-660.0 + 10 +800.0 + 20 +-660.0 + 10 +800.0 + 20 +-560.0 + 10 +700.0 + 20 +-560.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +6.35 + 79 +0 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-12.6999913435 + 46 +12.6999913435 + 79 +2 + 49 +8.9802561211 + 49 +-17.9605122421 + 98 +0 + 0 +LWPOLYLINE + 5 +B7 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +700.0 + 20 +-660.0 + 10 +800.0 + 20 +-660.0 + 10 +800.0 + 20 +-560.0 + 10 +700.0 + 20 +-560.0 + 0 +TEXT + 5 +B8 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +700.0 + 20 +-674.0 + 30 +0.0 + 40 +9.0 + 1 +DOLMIT + 7 +LABEL + 11 +700.0 + 21 +-674.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +B9 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +DOTS + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +840.0 + 20 +-660.0 + 10 +940.0 + 20 +-660.0 + 10 +940.0 + 20 +-560.0 + 10 +840.0 + 20 +-560.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +1 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.79375 + 46 +1.5875 + 79 +2 + 49 +0.0 + 49 +-1.5875 + 98 +0 + 0 +LWPOLYLINE + 5 +BA +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +-660.0 + 10 +940.0 + 20 +-660.0 + 10 +940.0 + 20 +-560.0 + 10 +840.0 + 20 +-560.0 + 0 +TEXT + 5 +BB +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +840.0 + 20 +-674.0 + 30 +0.0 + 40 +9.0 + 1 +DOTS + 7 +LABEL + 11 +840.0 + 21 +-674.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +BC +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +DOTS1 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +980.0 + 20 +-660.0 + 10 +1080.0 + 20 +-660.0 + 10 +1080.0 + 20 +-560.0 + 10 +980.0 + 20 +-560.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +1 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.79375 + 46 +1.5875 + 79 +2 + 49 +0.0 + 49 +-1.5875 + 98 +0 + 0 +LWPOLYLINE + 5 +BD +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +980.0 + 20 +-660.0 + 10 +1080.0 + 20 +-660.0 + 10 +1080.0 + 20 +-560.0 + 10 +980.0 + 20 +-560.0 + 0 +TEXT + 5 +BE +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +980.0 + 20 +-674.0 + 30 +0.0 + 40 +9.0 + 1 +DOTS1 + 7 +LABEL + 11 +980.0 + 21 +-674.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +BF +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +DOTS2 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-825.0 + 10 +100.0 + 20 +-825.0 + 10 +100.0 + 20 +-725.0 + 10 +0.0 + 20 +-725.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +17 + 53 +0.0 + 43 +1.016 + 44 +0.508 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +9.144 + 44 +1.016 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +4.572 + 44 +6.604 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +10.16 + 44 +10.668 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +3.556 + 44 +12.192 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +5.588 + 44 +18.288 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +2.032 + 44 +22.86 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +10.16 + 44 +22.352 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +16.256 + 44 +23.368 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +19.304 + 44 +17.272 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +24.384 + 44 +16.764 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +24.384 + 44 +7.62 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +19.812 + 44 +4.572 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +12.7 + 44 +6.096 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +17.272 + 44 +10.668 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +12.7 + 44 +15.24 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 53 +0.0 + 43 +23.368 + 44 +1.016 + 45 +0.0 + 46 +25.4 + 79 +2 + 49 +0.0 + 49 +-25.4 + 98 +0 + 0 +LWPOLYLINE + 5 +C0 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-825.0 + 10 +100.0 + 20 +-825.0 + 10 +100.0 + 20 +-725.0 + 10 +0.0 + 20 +-725.0 + 0 +TEXT + 5 +C1 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-839.0 + 30 +0.0 + 40 +9.0 + 1 +DOTS2 + 7 +LABEL + 11 +0.0 + 21 +-839.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +C2 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +EARTH + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +140.0 + 20 +-825.0 + 10 +240.0 + 20 +-825.0 + 10 +240.0 + 20 +-725.0 + 10 +140.0 + 20 +-725.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +6 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +0.0 + 43 +0.0 + 44 +2.38125 + 45 +6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +0.0 + 43 +0.0 + 44 +4.7625 + 45 +6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +90.0 + 43 +0.79375 + 44 +5.55625 + 45 +-6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +90.0 + 43 +3.175 + 44 +5.55625 + 45 +-6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +90.0 + 43 +5.55625 + 44 +5.55625 + 45 +-6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 98 +0 + 0 +LWPOLYLINE + 5 +C3 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +140.0 + 20 +-825.0 + 10 +240.0 + 20 +-825.0 + 10 +240.0 + 20 +-725.0 + 10 +140.0 + 20 +-725.0 + 0 +TEXT + 5 +C4 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +140.0 + 20 +-839.0 + 30 +0.0 + 40 +9.0 + 1 +EARTH + 7 +LABEL + 11 +140.0 + 21 +-839.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +C5 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +EARTH1 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +280.0 + 20 +-825.0 + 10 +380.0 + 20 +-825.0 + 10 +380.0 + 20 +-725.0 + 10 +280.0 + 20 +-725.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +6 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +0.0 + 43 +0.0 + 44 +2.38125 + 45 +6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +0.0 + 43 +0.0 + 44 +4.7625 + 45 +6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +90.0 + 43 +0.79375 + 44 +5.55625 + 45 +-6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +90.0 + 43 +3.175 + 44 +5.55625 + 45 +-6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +90.0 + 43 +5.55625 + 44 +5.55625 + 45 +-6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 98 +0 + 0 +LWPOLYLINE + 5 +C6 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +280.0 + 20 +-825.0 + 10 +380.0 + 20 +-825.0 + 10 +380.0 + 20 +-725.0 + 10 +280.0 + 20 +-725.0 + 0 +TEXT + 5 +C7 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +280.0 + 20 +-839.0 + 30 +0.0 + 40 +9.0 + 1 +EARTH1 + 7 +LABEL + 11 +280.0 + 21 +-839.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +C8 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +EARTH2 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +420.0 + 20 +-825.0 + 10 +520.0 + 20 +-825.0 + 10 +520.0 + 20 +-725.0 + 10 +420.0 + 20 +-725.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +12 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +13.4703841816 + 79 +2 + 49 +9.525 + 49 +-9.525 + 53 +45.0 + 43 +-1.3470384159 + 44 +1.3470384159 + 45 +0.0 + 46 +13.4703841816 + 79 +2 + 49 +9.525 + 49 +-9.525 + 53 +45.0 + 43 +-2.6940768128 + 44 +2.6940768128 + 45 +0.0 + 46 +13.4703841816 + 79 +2 + 49 +9.525 + 49 +-9.525 + 53 +45.0 + 43 +-4.0411152668 + 44 +4.0411152668 + 45 +0.0 + 46 +13.4703841816 + 79 +2 + 49 +9.525 + 49 +-9.525 + 53 +45.0 + 43 +-5.388153435 + 44 +5.388153435 + 45 +0.0 + 46 +13.4703841816 + 79 +2 + 49 +9.525 + 49 +-9.525 + 53 +45.0 + 43 +-6.73519227 + 44 +6.73519227 + 45 +0.0 + 46 +13.4703841816 + 79 +2 + 49 +9.525 + 49 +-9.525 + 53 +135.0 + 43 +0.0 + 44 +0.0 + 45 +-13.4703841816 + 46 +0.0 + 79 +2 + 49 +9.525 + 49 +-9.525 + 53 +135.0 + 43 +-1.3470384159 + 44 +-1.3470384159 + 45 +-13.4703841816 + 46 +0.0 + 79 +2 + 49 +9.525 + 49 +-9.525 + 53 +135.0 + 43 +-2.6940768128 + 44 +-2.6940768128 + 45 +-13.4703841816 + 46 +0.0 + 79 +2 + 49 +9.525 + 49 +-9.525 + 53 +135.0 + 43 +-4.0411152668 + 44 +-4.0411152668 + 45 +-13.4703841816 + 46 +0.0 + 79 +2 + 49 +9.525 + 49 +-9.525 + 53 +135.0 + 43 +-5.388153435 + 44 +-5.388153435 + 45 +-13.4703841816 + 46 +0.0 + 79 +2 + 49 +9.525 + 49 +-9.525 + 53 +135.0 + 43 +-6.73519227 + 44 +-6.73519227 + 45 +-13.4703841816 + 46 +0.0 + 79 +2 + 49 +9.525 + 49 +-9.525 + 98 +0 + 0 +LWPOLYLINE + 5 +C9 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +420.0 + 20 +-825.0 + 10 +520.0 + 20 +-825.0 + 10 +520.0 + 20 +-725.0 + 10 +420.0 + 20 +-725.0 + 0 +TEXT + 5 +CA +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +420.0 + 20 +-839.0 + 30 +0.0 + 40 +9.0 + 1 +EARTH2 + 7 +LABEL + 11 +420.0 + 21 +-839.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +CB +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ESCHER + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +560.0 + 20 +-825.0 + 10 +660.0 + 20 +-825.0 + 10 +660.0 + 20 +-725.0 + 10 +560.0 + 20 +-725.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +21 + 53 +60.0 + 43 +0.0 + 44 +0.0 + 45 +-30.4799999881 + 46 +-6.9e-09 + 79 +2 + 49 +27.94 + 49 +-2.54 + 53 +180.0 + 43 +0.0 + 44 +0.0 + 45 +15.24 + 46 +-26.3964542936 + 79 +2 + 49 +27.94 + 49 +-2.54 + 53 +300.0 + 43 +0.0 + 44 +0.0 + 45 +30.4799999881 + 46 +-6.9e-09 + 79 +2 + 49 +27.94 + 49 +-2.54 + 53 +60.0 + 43 +2.54 + 44 +0.0 + 45 +-30.4799999881 + 46 +-6.9e-09 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +300.0 + 43 +2.54 + 44 +0.0 + 45 +30.4799999881 + 46 +-6.9e-09 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +60.0 + 43 +-1.27 + 44 +2.199704516 + 45 +-30.4799999881 + 46 +-6.9e-09 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +180.0 + 43 +-1.27 + 44 +2.199704516 + 45 +15.24 + 46 +-26.3964542936 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +300.0 + 43 +-1.27 + 44 +-2.199704516 + 45 +30.4799999881 + 46 +-6.9e-09 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +180.0 + 43 +-1.27 + 44 +-2.199704516 + 45 +15.24 + 46 +-26.3964542936 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +60.0 + 43 +-10.16 + 44 +0.0 + 45 +-30.4799999881 + 46 +-6.9e-09 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +300.0 + 43 +-10.16 + 44 +0.0 + 45 +30.4799999881 + 46 +-6.9e-09 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +60.0 + 43 +5.08 + 44 +-8.7988180894 + 45 +-30.4799999881 + 46 +-6.9e-09 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +180.0 + 43 +5.08 + 44 +-8.7988180894 + 45 +15.24 + 46 +-26.3964542936 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +300.0 + 43 +5.08 + 44 +8.7988180894 + 45 +30.4799999881 + 46 +-6.9e-09 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +180.0 + 43 +5.08 + 44 +8.7988180894 + 45 +15.24 + 46 +-26.3964542936 + 79 +2 + 49 +5.08 + 49 +-25.4 + 53 +0.0 + 43 +5.08 + 44 +4.3994090574 + 45 +-15.24 + 46 +26.3964542936 + 79 +2 + 49 +17.78 + 49 +-12.7 + 53 +0.0 + 43 +5.08 + 44 +-4.3994090574 + 45 +-15.24 + 46 +26.3964542936 + 79 +2 + 49 +17.78 + 49 +-12.7 + 53 +120.0 + 43 +1.27 + 44 +6.5991135734 + 45 +-30.4799999881 + 46 +6.9e-09 + 79 +2 + 49 +17.78 + 49 +-12.7 + 53 +120.0 + 43 +-6.35 + 44 +2.199704516 + 45 +-30.4799999881 + 46 +6.9e-09 + 79 +2 + 49 +17.78 + 49 +-12.7 + 53 +240.0 + 43 +-6.35 + 44 +-2.199704516 + 45 +15.2399999881 + 46 +-26.3964543005 + 79 +2 + 49 +17.78 + 49 +-12.7 + 53 +240.0 + 43 +1.27 + 44 +-6.5991135734 + 45 +15.2399999881 + 46 +-26.3964543005 + 79 +2 + 49 +17.78 + 49 +-12.7 + 98 +0 + 0 +LWPOLYLINE + 5 +CC +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +560.0 + 20 +-825.0 + 10 +660.0 + 20 +-825.0 + 10 +660.0 + 20 +-725.0 + 10 +560.0 + 20 +-725.0 + 0 +TEXT + 5 +CD +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +560.0 + 20 +-839.0 + 30 +0.0 + 40 +9.0 + 1 +ESCHER + 7 +LABEL + 11 +560.0 + 21 +-839.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +CE +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +GRASS + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +700.0 + 20 +-825.0 + 10 +800.0 + 20 +-825.0 + 10 +800.0 + 20 +-725.0 + 10 +700.0 + 20 +-725.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-17.96051224 + 46 +17.96051224 + 79 +2 + 49 +4.7625 + 49 +-31.15852448 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-17.9605122421 + 46 +17.9605122421 + 79 +2 + 49 +4.7625 + 49 +-20.6375 + 53 +135.0 + 43 +0.0 + 44 +0.0 + 45 +-17.9605122421 + 46 +-17.9605122421 + 79 +2 + 49 +4.7625 + 49 +-20.6375 + 98 +0 + 0 +LWPOLYLINE + 5 +CF +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +700.0 + 20 +-825.0 + 10 +800.0 + 20 +-825.0 + 10 +800.0 + 20 +-725.0 + 10 +700.0 + 20 +-725.0 + 0 +TEXT + 5 +D0 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +700.0 + 20 +-839.0 + 30 +0.0 + 40 +9.0 + 1 +GRASS + 7 +LABEL + 11 +700.0 + 21 +-839.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +D1 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +GRASS1 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +840.0 + 20 +-825.0 + 10 +940.0 + 20 +-825.0 + 10 +940.0 + 20 +-725.0 + 10 +840.0 + 20 +-725.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-14.3684097899 + 46 +14.3684097899 + 79 +2 + 49 +3.81 + 49 +-24.9268196002 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-14.3684097937 + 46 +14.3684097937 + 79 +2 + 49 +3.81 + 49 +-16.51 + 53 +135.0 + 43 +0.0 + 44 +0.0 + 45 +-14.3684097937 + 46 +-14.3684097937 + 79 +2 + 49 +3.81 + 49 +-16.51 + 98 +0 + 0 +LWPOLYLINE + 5 +D2 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +-825.0 + 10 +940.0 + 20 +-825.0 + 10 +940.0 + 20 +-725.0 + 10 +840.0 + 20 +-725.0 + 0 +TEXT + 5 +D3 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +840.0 + 20 +-839.0 + 30 +0.0 + 40 +9.0 + 1 +GRASS1 + 7 +LABEL + 11 +840.0 + 21 +-839.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +D4 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +GRASS2 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +980.0 + 20 +-825.0 + 10 +1080.0 + 20 +-825.0 + 10 +1080.0 + 20 +-725.0 + 10 +980.0 + 20 +-725.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +6 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +10.16 + 46 +17.597636189 + 79 +2 + 49 +2.54 + 49 +-17.78 + 53 +90.0 + 43 +1.27 + 44 +0.0 + 45 +-10.16 + 46 +17.597636189 + 79 +2 + 49 +1.27 + 49 +-33.9252723779 + 53 +90.0 + 43 +1.5875 + 44 +0.0 + 45 +-10.16 + 46 +17.597636189 + 79 +2 + 49 +1.016 + 49 +-34.1792723779 + 53 +90.0 + 43 +0.9525 + 44 +0.0 + 45 +-10.16 + 46 +17.597636189 + 79 +2 + 49 +1.016 + 49 +-34.1792723779 + 53 +60.0 + 43 +1.905 + 44 +0.0 + 45 +-10.1599999862 + 46 +17.5976361969 + 79 +2 + 49 +0.8128 + 49 +-19.5072 + 53 +120.0 + 43 +0.635 + 44 +0.0 + 45 +-20.3199999862 + 46 +8e-09 + 79 +2 + 49 +0.8128 + 49 +-19.5072 + 98 +0 + 0 +LWPOLYLINE + 5 +D5 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +980.0 + 20 +-825.0 + 10 +1080.0 + 20 +-825.0 + 10 +1080.0 + 20 +-725.0 + 10 +980.0 + 20 +-725.0 + 0 +TEXT + 5 +D6 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +980.0 + 20 +-839.0 + 30 +0.0 + 40 +9.0 + 1 +GRASS2 + 7 +LABEL + 11 +980.0 + 21 +-839.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +D7 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +GRAVEL + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-990.0 + 10 +100.0 + 20 +-990.0 + 10 +100.0 + 20 +-890.0 + 10 +0.0 + 20 +-890.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +41 + 53 +228.0127875 + 43 +18.288 + 44 +25.4 + 45 +-203.200000016 + 46 +-228.5999999858 + 79 +2 + 49 +3.4172144 + 49 +-338.3048363956 + 53 +184.969741 + 43 +16.002 + 44 +22.86 + 45 +304.7999998794 + 46 +25.400001447 + 79 +2 + 49 +5.8640472 + 49 +-580.5404889352 + 53 +132.5104471 + 43 +10.16 + 44 +22.352 + 45 +254.0000001073 + 46 +-279.3999999025 + 79 +2 + 49 +4.1348152 + 49 +-409.347227941 + 53 +267.273689 + 43 +0.254 + 44 +16.002 + 45 +25.4000000532 + 46 +507.9999999973 + 79 +2 + 49 +5.3400452 + 49 +-528.6643742574 + 53 +292.83365418 + 43 +0.0 + 44 +10.668 + 45 +-127.0000000106 + 46 +304.7999999956 + 79 +2 + 49 +5.236337 + 49 +-518.3980774534 + 53 +357.273689 + 43 +2.032 + 44 +5.842 + 45 +-507.9999999973 + 46 +25.4000000532 + 79 +2 + 49 +5.3400452 + 49 +-528.6643742574 + 53 +37.69424047 + 43 +7.366 + 44 +5.588 + 45 +-330.1999999854 + 46 +-254.000000019 + 79 +2 + 49 +7.0619366 + 49 +-699.1311531425 + 53 +72.25532837 + 43 +12.954 + 44 +9.906 + 45 +177.8000000478 + 46 +558.7999999848 + 79 +2 + 49 +6.6671952 + 49 +-660.0525660191 + 53 +121.42956562 + 43 +14.986 + 44 +16.256 + 45 +-203.2000000288 + 46 +330.1999999823 + 79 +2 + 49 +5.35813 + 49 +-530.4554569871 + 53 +175.2363583 + 43 +12.192 + 44 +20.828 + 45 +279.399999996 + 46 +-25.4000000439 + 79 +2 + 49 +6.1171328 + 49 +-299.7393695 + 53 +222.3974378 + 43 +6.096 + 44 +21.336 + 45 +-304.7999999902 + 46 +-279.4000000106 + 79 +2 + 49 +7.9107792 + 49 +-783.1677251218 + 53 +138.81407483 + 43 +25.4 + 44 +15.748 + 45 +-177.7999999893 + 46 +152.4000000124 + 79 +2 + 49 +2.7000454 + 49 +-267.3056582434 + 53 +171.4692344 + 43 +23.368 + 44 +17.526 + 45 +330.2000000089 + 46 +-50.7999999424 + 79 +2 + 49 +5.1368198 + 49 +-508.5463899704 + 53 +225.0 + 43 +18.288 + 44 +18.288 + 45 +-0.0 + 46 +-25.4 + 79 +2 + 49 +3.5920934 + 49 +-32.3289310843 + 53 +203.19859051 + 43 +16.51 + 44 +21.336 + 45 +127.0000000035 + 46 +50.7999999911 + 79 +2 + 49 +1.9344132 + 49 +-191.5062236889 + 53 +291.80140949 + 43 +14.732 + 44 +20.574 + 45 +-25.4000000053 + 46 +76.1999999982 + 79 +2 + 49 +2.7356562 + 49 +-134.0475299 + 53 +30.96375653 + 43 +15.748 + 44 +18.034 + 45 +76.2000000019 + 46 +50.7999999972 + 79 +2 + 49 +4.4431966 + 49 +-143.6629815291 + 53 +161.56505118 + 43 +19.558 + 44 +20.32 + 45 +50.8000000013 + 46 +-25.3999999973 + 79 +2 + 49 +3.2128714 + 49 +-77.1089811683 + 53 +16.389540334 + 43 +0.0 + 44 +20.574 + 45 +254.0 + 46 +76.2 + 79 +2 + 49 +4.50088 + 49 +-445.5882667254 + 53 +70.34617594 + 43 +4.318 + 44 +21.844 + 45 +-101.6000000093 + 46 +-279.3999999967 + 79 +2 + 49 +3.7759894 + 49 +-373.822156782 + 53 +293.19859051 + 43 +19.558 + 44 +25.4 + 45 +-50.7999999911 + 46 +127.0000000036 + 79 +2 + 49 +3.868801 + 49 +-189.5718358889 + 53 +343.61045967 + 43 +21.082 + 44 +21.844 + 45 +-254.0000000053 + 46 +76.1999999822 + 79 +2 + 49 +4.50088 + 49 +-445.5882667254 + 53 +339.44395478 + 43 +0.0 + 44 +4.826 + 45 +-127.0 + 46 +50.8 + 79 +2 + 49 +4.340352 + 49 +-212.6773431311 + 53 +294.7751406 + 43 +4.064 + 44 +3.302 + 45 +-127.0000001512 + 46 +279.3999999313 + 79 +2 + 49 +3.6367212 + 49 +-360.0359338072 + 53 +66.80140949 + 43 +19.812 + 44 +0.0 + 45 +50.799999992 + 46 +127.0000000032 + 79 +2 + 49 +3.868801 + 49 +-189.5718358889 + 53 +17.35402464 + 43 +21.336 + 44 +3.556 + 45 +-330.1999999934 + 46 +-101.6000000213 + 79 +2 + 49 +4.2578274 + 49 +-421.523759802 + 53 +69.44395478 + 43 +7.366 + 44 +0.0 + 45 +-50.8000000009 + 46 +-126.9999999996 + 79 +2 + 49 +2.170176 + 49 +-214.8475191311 + 53 +101.309932474 + 43 +18.288 + 44 +0.0 + 45 +-25.4 + 46 +101.6 + 79 +2 + 49 +1.295146 + 49 +-128.2199496453 + 53 +165.963756532 + 43 +18.034 + 44 +1.27 + 45 +76.2 + 46 +-25.4 + 79 +2 + 49 +5.236337 + 49 +-99.4905458907 + 53 +186.00900596 + 43 +12.954 + 44 +2.54 + 45 +253.9999999987 + 46 +25.4000000133 + 79 +2 + 49 +4.85267 + 49 +-480.4136486334 + 53 +303.69006753 + 43 +15.748 + 44 +15.748 + 45 +-25.4000000035 + 46 +50.7999999982 + 79 +2 + 49 +3.6632388 + 49 +-87.9177635968 + 53 +353.15722659 + 43 +17.78 + 44 +12.7 + 45 +431.8000000027 + 46 +-50.7999999774 + 79 +2 + 49 +6.3955676 + 49 +-633.1600906503 + 53 +60.9453959 + 43 +24.13 + 44 +11.938 + 45 +-101.6000000028 + 46 +-177.7999999984 + 79 +2 + 49 +2.6150824 + 49 +-258.8939231811 + 53 +90.0 + 43 +25.4 + 44 +14.224 + 45 +-25.4 + 46 +25.4 + 79 +2 + 49 +1.524 + 49 +-23.876 + 53 +120.25643716 + 43 +12.446 + 44 +3.302 + 45 +101.5999999876 + 46 +-177.8000000071 + 79 +2 + 49 +3.5286696 + 49 +-349.339407732 + 53 +48.0127875 + 43 +10.668 + 44 +6.35 + 45 +203.2000000168 + 46 +228.5999999851 + 79 +2 + 49 +6.8344288 + 49 +-334.8876219957 + 53 +0.0 + 43 +15.24 + 44 +11.43 + 45 +25.4 + 46 +25.4 + 79 +2 + 49 +6.604 + 49 +-18.796 + 53 +325.3048465 + 43 +21.844 + 44 +11.43 + 45 +254.0000000962 + 46 +-177.7999998625 + 79 +2 + 49 +4.0160956 + 49 +-397.5931672414 + 53 +254.0546041 + 43 +25.146 + 44 +9.144 + 45 +-25.3999999982 + 46 +-101.6000000004 + 79 +2 + 49 +3.6982908 + 49 +-181.2165003877 + 53 +207.64597536 + 43 +24.13 + 44 +5.588 + 45 +-482.6000000177 + 46 +-253.9999999663 + 79 +2 + 49 +6.021451 + 49 +-596.1246442294 + 53 +175.42607874 + 43 +18.796 + 44 +2.794 + 45 +-330.2 + 46 +25.4 + 79 +2 + 49 +6.3702946 + 49 +-630.6584645624 + 98 +0 + 0 +LWPOLYLINE + 5 +D8 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-990.0 + 10 +100.0 + 20 +-990.0 + 10 +100.0 + 20 +-890.0 + 10 +0.0 + 20 +-890.0 + 0 +TEXT + 5 +D9 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-1004.0 + 30 +0.0 + 40 +9.0 + 1 +GRAVEL + 7 +LABEL + 11 +0.0 + 21 +-1004.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +DA +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +GRAVEL1 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +140.0 + 20 +-990.0 + 10 +240.0 + 20 +-990.0 + 10 +240.0 + 20 +-890.0 + 10 +140.0 + 20 +-890.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +41 + 53 +228.0128 + 43 +12.9600000032 + 44 +17.9999999816 + 45 +-143.9999681763 + 46 +-162.000024158 + 79 +2 + 49 +2.4216479939 + 49 +-239.7435839968 + 53 +184.9697 + 43 +11.3399999971 + 44 +16.2000000155 + 45 +216.0000189102 + 46 +17.9998435066 + 79 +2 + 49 +4.1556239824 + 49 +-411.4066499867 + 53 +132.5104 + 43 +7.2000000018 + 44 +15.840000004 + 45 +179.9998329469 + 46 +-198.0001561228 + 79 +2 + 49 +2.9301840101 + 49 +-290.0885759914 + 53 +267.2737 + 43 +0.1800000058 + 44 +11.3399999971 + 45 +17.9999283207 + 46 +360.0000052976 + 79 +2 + 49 +3.7842839935 + 49 +-374.6440439896 + 53 +292.8337 + 43 +0.0 + 44 +7.5600000133 + 45 +-90.0001782992 + 46 +215.999935404 + 79 +2 + 49 +3.7107900079 + 49 +-367.3687139784 + 53 +357.2737 + 43 +1.4400000004 + 44 +4.1399999953 + 45 +-360.0000052976 + 46 +17.9999283207 + 79 +2 + 49 +3.7842839935 + 49 +-374.6440439896 + 53 +37.6942 + 43 +5.2199999842 + 44 +3.9599999896 + 45 +-234.0001322119 + 46 +-179.9998272812 + 79 +2 + 49 +5.0045219899 + 49 +-495.4472817984 + 53 +72.2553 + 43 +9.1800000194 + 44 +7.019999996 + 45 +126.0001937207 + 46 +395.9999321528 + 79 +2 + 49 +4.724783987 + 49 +-467.7537780288 + 53 +121.4296 + 43 +10.6200000198 + 44 +11.5200000029 + 45 +-144.0001482242 + 46 +233.9999106564 + 79 +2 + 49 +3.7970999953 + 49 +-375.9133139885 + 53 +175.2364 + 43 +8.6400000022 + 44 +14.7600000151 + 45 +198.0000170247 + 46 +-17.9998475922 + 79 +2 + 49 +4.3349759986 + 49 +-212.4137339982 + 53 +222.3974 + 43 +4.3200000011 + 44 +15.1199999809 + 45 +-216.0001323074 + 46 +-197.9998574727 + 79 +2 + 49 +5.6060640076 + 49 +-555.0007501944 + 53 +138.8141 + 43 +17.9999999816 + 44 +11.1599999914 + 45 +-126.0000530418 + 46 +107.9999516683 + 79 +2 + 49 +1.9134179816 + 49 +-189.4291919867 + 53 +171.4692 + 43 +16.5599999813 + 44 +12.419999986 + 45 +233.9999691401 + 46 +-36.0001423904 + 79 +2 + 49 +3.6402659935 + 49 +-360.3871980151 + 53 +225.0 + 43 +12.9600000032 + 44 +12.9600000032 + 45 +-0.0 + 46 +-18.000005591 + 79 +2 + 49 +2.5455779975 + 49 +-22.9102560184 + 53 +203.1986 + 43 +11.7000000086 + 44 +15.1199999809 + 45 +89.9999951667 + 46 +36.0000238407 + 79 +2 + 49 +1.3708440198 + 49 +-135.7130699906 + 53 +291.8014 + 43 +10.440000014 + 44 +14.5800000094 + 45 +-17.9999983704 + 46 +54.0000049026 + 79 +2 + 49 +1.9386540043 + 49 +-94.9943160054 + 53 +30.9638 + 43 +11.1599999914 + 44 +12.7799999975 + 45 +53.9999644169 + 46 +36.0000446951 + 79 +2 + 49 +3.1487219982 + 49 +-101.8084140155 + 53 +161.5651 + 43 +13.8599999863 + 44 +14.4000000036 + 45 +36.0000078261 + 46 +-17.9999712785 + 79 +2 + 49 +2.2768379863 + 49 +-54.644165987 + 53 +16.3895 + 43 +0.0 + 44 +14.5800000094 + 45 +180.0000395482 + 46 +53.999868792 + 79 +2 + 49 +3.1896000216 + 49 +-315.7712100108 + 53 +70.3462 + 43 +3.0600000065 + 44 +15.4799999924 + 45 +-71.9999144577 + 46 +-198.0000384368 + 79 +2 + 49 +2.6758980112 + 49 +-264.913343995 + 53 +293.1986 + 43 +13.8599999863 + 44 +17.9999999816 + 45 +-36.0000238407 + 46 +89.9999951667 + 79 +2 + 49 +2.7416699802 + 49 +-134.3422439845 + 53 +343.6105 + 43 +14.9400000209 + 44 +15.4799999924 + 45 +-180.0000395482 + 46 +53.999868792 + 79 +2 + 49 +3.1896000216 + 49 +-315.7712100108 + 53 +339.444 + 43 +0.0 + 44 +3.420000018 + 45 +-90.000033183 + 46 +35.9999279355 + 79 +2 + 49 +3.0758400205 + 49 +-150.7162320086 + 53 +294.7751 + 43 +2.8800000007 + 44 +2.3399999834 + 45 +-89.9998594132 + 46 +198.0000615975 + 79 +2 + 49 +2.5772039845 + 49 +-255.1435739892 + 53 +66.8014 + 43 +14.0399999921 + 44 +0.0 + 45 +36.0000238407 + 46 +89.9999951667 + 79 +2 + 49 +2.7416699802 + 49 +-134.3422439845 + 53 +17.354 + 43 +15.1199999809 + 44 +2.5199999892 + 45 +-234.0000363497 + 46 +-71.9999010651 + 79 +2 + 49 +3.017358014 + 49 +-298.7176319971 + 53 +69.444 + 43 +5.2199999842 + 44 +0.0 + 45 +-35.9999279355 + 46 +-90.000033183 + 79 +2 + 49 +1.5379199874 + 49 +-152.254151996 + 53 +101.3099 + 43 +12.9600000032 + 44 +0.0 + 45 +-17.9999573944 + 46 +72.0000135294 + 79 +2 + 49 +0.9178199932 + 49 +-90.8645219942 + 53 +165.9638 + 43 +12.7799999975 + 44 +0.8999999831 + 45 +54.0000098409 + 46 +-17.9999650276 + 79 +2 + 49 +3.7107900079 + 49 +-70.5050999903 + 53 +186.009 + 43 +9.1800000194 + 44 +1.8000000119 + 45 +179.9999954963 + 46 +17.9999876948 + 79 +2 + 49 +3.4388999802 + 49 +-340.4506140022 + 53 +303.6901 + 43 +11.1599999914 + 44 +11.1599999914 + 45 +-18.0000240412 + 46 +35.9999920382 + 79 +2 + 49 +2.5959960018 + 49 +-62.3039220112 + 53 +353.1572 + 43 +12.5999999917 + 44 +9.0000000137 + 45 +305.9999885795 + 46 +-36.0001439522 + 79 +2 + 49 +4.5322919971 + 49 +-448.6961339953 + 53 +60.9454 + 43 +17.0999999986 + 44 +8.4599999964 + 45 +-72.0000005012 + 46 +-126.0000069224 + 79 +2 + 49 +1.8532079878 + 49 +-183.4681320216 + 53 +90.0 + 43 +17.9999999816 + 44 +10.0800000025 + 45 +-17.9999999816 + 46 +17.9999999816 + 79 +2 + 49 +1.0799999888 + 49 +-16.9199999928 + 53 +120.2564 + 43 +8.8200000079 + 44 +2.3399999834 + 45 +71.9999079614 + 46 +-126.0000441964 + 79 +2 + 49 +2.5006319914 + 49 +-247.5633600209 + 53 +48.0128 + 43 +7.5600000133 + 44 +4.5000000068 + 45 +143.9999681763 + 46 +162.000024158 + 79 +2 + 49 +4.8432959878 + 49 +-237.3219360029 + 53 +0.0 + 43 +10.7999999798 + 44 +8.0999999849 + 45 +17.9999999816 + 46 +17.9999999816 + 79 +2 + 49 +4.6800000126 + 49 +-13.3200000148 + 53 +325.3048 + 43 +15.4799999924 + 44 +8.0999999849 + 45 +-179.9998966718 + 46 +126.0001549797 + 79 +2 + 49 +2.8460519863 + 49 +-281.7589319903 + 53 +254.0546 + 43 +17.8200000216 + 44 +6.4799999788 + 45 +-17.9999980057 + 46 +-72.0000022974 + 79 +2 + 49 +2.6208359978 + 49 +-128.4211439852 + 53 +207.646 + 43 +17.0999999986 + 44 +3.9599999896 + 45 +-341.999924501 + 46 +-180.0001388421 + 79 +2 + 49 +4.2671699924 + 49 +-422.4505320137 + 53 +175.4261 + 43 +13.320007142 + 44 +1.980001628 + 45 +-233.9997863523 + 46 +17.9999001623 + 79 +2 + 49 +4.51438391 + 49 +-446.9228933 + 98 +0 + 0 +LWPOLYLINE + 5 +DB +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +140.0 + 20 +-990.0 + 10 +240.0 + 20 +-990.0 + 10 +240.0 + 20 +-890.0 + 10 +140.0 + 20 +-890.0 + 0 +TEXT + 5 +DC +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +140.0 + 20 +-1004.0 + 30 +0.0 + 40 +9.0 + 1 +GRAVEL1 + 7 +LABEL + 11 +140.0 + 21 +-1004.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +DD +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +HEX + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +280.0 + 20 +-990.0 + 10 +380.0 + 20 +-990.0 + 10 +380.0 + 20 +-890.0 + 10 +280.0 + 20 +-890.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +5.4992613154 + 79 +2 + 49 +3.175 + 49 +-6.35 + 53 +120.0 + 43 +0.0 + 44 +0.0 + 45 +-4.7625000012 + 46 +-2.7496306577 + 79 +2 + 49 +3.175 + 49 +-6.35 + 53 +60.0 + 43 +3.175 + 44 +0.0 + 45 +-4.7625000012 + 46 +2.7496306577 + 79 +2 + 49 +3.175 + 49 +-6.35 + 98 +0 + 0 +LWPOLYLINE + 5 +DE +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +280.0 + 20 +-990.0 + 10 +380.0 + 20 +-990.0 + 10 +380.0 + 20 +-890.0 + 10 +280.0 + 20 +-890.0 + 0 +TEXT + 5 +DF +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +280.0 + 20 +-1004.0 + 30 +0.0 + 40 +9.0 + 1 +HEX + 7 +LABEL + 11 +280.0 + 21 +-1004.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +E0 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +HEXAGONS + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +420.0 + 20 +-990.0 + 10 +520.0 + 20 +-990.0 + 10 +520.0 + 20 +-890.0 + 10 +420.0 + 20 +-890.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +6.5991135785 + 79 +2 + 49 +3.81 + 49 +-7.62 + 53 +120.0 + 43 +0.0 + 44 +0.0 + 45 +-5.7150000014 + 46 +-3.2995567892 + 79 +2 + 49 +3.81 + 49 +-7.62 + 53 +60.0 + 43 +3.81 + 44 +0.0 + 45 +-5.7150000014 + 46 +3.2995567892 + 79 +2 + 49 +3.81 + 49 +-7.62 + 98 +0 + 0 +LWPOLYLINE + 5 +E1 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +420.0 + 20 +-990.0 + 10 +520.0 + 20 +-990.0 + 10 +520.0 + 20 +-890.0 + 10 +420.0 + 20 +-890.0 + 0 +TEXT + 5 +E2 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +420.0 + 20 +-1004.0 + 30 +0.0 + 40 +9.0 + 1 +HEXAGONS + 7 +LABEL + 11 +420.0 + 21 +-1004.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +E3 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +HONEY + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +560.0 + 20 +-990.0 + 10 +660.0 + 20 +-990.0 + 10 +660.0 + 20 +-890.0 + 10 +560.0 + 20 +-890.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +4.7625 + 46 +2.749630645 + 79 +2 + 49 +3.175 + 49 +-6.35 + 53 +120.0 + 43 +0.0 + 44 +0.0 + 45 +-4.7624999896 + 46 +2.749630663 + 79 +2 + 49 +3.175 + 49 +-6.35 + 53 +60.0 + 43 +0.0 + 44 +0.0 + 45 +1.04e-08 + 46 +5.499261308 + 79 +2 + 49 +-6.35 + 49 +3.175 + 98 +0 + 0 +LWPOLYLINE + 5 +E4 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +560.0 + 20 +-990.0 + 10 +660.0 + 20 +-990.0 + 10 +660.0 + 20 +-890.0 + 10 +560.0 + 20 +-890.0 + 0 +TEXT + 5 +E5 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +560.0 + 20 +-1004.0 + 30 +0.0 + 40 +9.0 + 1 +HONEY + 7 +LABEL + 11 +560.0 + 21 +-1004.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +E6 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +HONEYCOMB + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +700.0 + 20 +-990.0 + 10 +800.0 + 20 +-990.0 + 10 +800.0 + 20 +-890.0 + 10 +700.0 + 20 +-890.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +5.715 + 46 +3.299556774 + 79 +2 + 49 +3.81 + 49 +-7.62 + 53 +120.0 + 43 +0.0 + 44 +0.0 + 45 +-5.7149999875 + 46 +3.2995567956 + 79 +2 + 49 +3.81 + 49 +-7.62 + 53 +60.0 + 43 +0.0 + 44 +0.0 + 45 +1.25e-08 + 46 +6.5991135696 + 79 +2 + 49 +-7.62 + 49 +3.81 + 98 +0 + 0 +LWPOLYLINE + 5 +E7 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +700.0 + 20 +-990.0 + 10 +800.0 + 20 +-990.0 + 10 +800.0 + 20 +-890.0 + 10 +700.0 + 20 +-890.0 + 0 +TEXT + 5 +E8 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +700.0 + 20 +-1004.0 + 30 +0.0 + 40 +9.0 + 1 +HONEYCOMB + 7 +LABEL + 11 +700.0 + 21 +-1004.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +E9 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +INSUL + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +840.0 + 20 +-990.0 + 10 +940.0 + 20 +-990.0 + 10 +940.0 + 20 +-890.0 + 10 +840.0 + 20 +-890.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +9.525 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +3.175 + 45 +0.0 + 46 +9.525 + 79 +2 + 49 +3.175 + 49 +-3.175 + 53 +0.0 + 43 +0.0 + 44 +6.35 + 45 +0.0 + 46 +9.525 + 79 +2 + 49 +3.175 + 49 +-3.175 + 98 +0 + 0 +LWPOLYLINE + 5 +EA +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +-990.0 + 10 +940.0 + 20 +-990.0 + 10 +940.0 + 20 +-890.0 + 10 +840.0 + 20 +-890.0 + 0 +TEXT + 5 +EB +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +840.0 + 20 +-1004.0 + 30 +0.0 + 40 +9.0 + 1 +INSUL + 7 +LABEL + 11 +840.0 + 21 +-1004.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +EC +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +INSULATION + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +980.0 + 20 +-990.0 + 10 +1080.0 + 20 +-990.0 + 10 +1080.0 + 20 +-890.0 + 10 +980.0 + 20 +-890.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-2.5144717139 + 46 +2.5144717139 + 79 +0 + 53 +135.0 + 43 +0.0 + 44 +0.0 + 45 +-2.5144717139 + 46 +-2.5144717139 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +ED +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +980.0 + 20 +-990.0 + 10 +1080.0 + 20 +-990.0 + 10 +1080.0 + 20 +-890.0 + 10 +980.0 + 20 +-890.0 + 0 +TEXT + 5 +EE +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +980.0 + 20 +-1004.0 + 30 +0.0 + 40 +9.0 + 1 +INSULATION + 7 +LABEL + 11 +980.0 + 21 +-1004.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +EF +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +LINE + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-1155.0 + 10 +100.0 + 20 +-1155.0 + 10 +100.0 + 20 +-1055.0 + 10 +0.0 + 20 +-1055.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +1 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +3.175 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +F0 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-1155.0 + 10 +100.0 + 20 +-1155.0 + 10 +100.0 + 20 +-1055.0 + 10 +0.0 + 20 +-1055.0 + 0 +TEXT + 5 +F1 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-1169.0 + 30 +0.0 + 40 +9.0 + 1 +LINE + 7 +LABEL + 11 +0.0 + 21 +-1169.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +F2 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +LINES + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +140.0 + 20 +-1155.0 + 10 +240.0 + 20 +-1155.0 + 10 +240.0 + 20 +-1055.0 + 10 +140.0 + 20 +-1055.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +1 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +2.54 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +F3 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +140.0 + 20 +-1155.0 + 10 +240.0 + 20 +-1155.0 + 10 +240.0 + 20 +-1055.0 + 10 +140.0 + 20 +-1055.0 + 0 +TEXT + 5 +F4 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +140.0 + 20 +-1169.0 + 30 +0.0 + 40 +9.0 + 1 +LINES + 7 +LABEL + 11 +140.0 + 21 +-1169.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +F5 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +MUDST + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +280.0 + 20 +-1155.0 + 10 +380.0 + 20 +-1155.0 + 10 +380.0 + 20 +-1055.0 + 10 +280.0 + 20 +-1055.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +1 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +12.7 + 46 +6.35 + 79 +6 + 49 +6.35 + 49 +-6.35 + 49 +0.0 + 49 +-6.35 + 49 +0.0 + 49 +-6.35 + 98 +0 + 0 +LWPOLYLINE + 5 +F6 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +280.0 + 20 +-1155.0 + 10 +380.0 + 20 +-1155.0 + 10 +380.0 + 20 +-1055.0 + 10 +280.0 + 20 +-1055.0 + 0 +TEXT + 5 +F7 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +280.0 + 20 +-1169.0 + 30 +0.0 + 40 +9.0 + 1 +MUDST + 7 +LABEL + 11 +280.0 + 21 +-1169.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +F8 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +NET + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +420.0 + 20 +-1155.0 + 10 +520.0 + 20 +-1155.0 + 10 +520.0 + 20 +-1055.0 + 10 +420.0 + 20 +-1055.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +3.175 + 79 +0 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-3.175 + 46 +0.0 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +F9 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +420.0 + 20 +-1155.0 + 10 +520.0 + 20 +-1155.0 + 10 +520.0 + 20 +-1055.0 + 10 +420.0 + 20 +-1055.0 + 0 +TEXT + 5 +FA +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +420.0 + 20 +-1169.0 + 30 +0.0 + 40 +9.0 + 1 +NET + 7 +LABEL + 11 +420.0 + 21 +-1169.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +FB +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +NET3 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +560.0 + 20 +-1155.0 + 10 +660.0 + 20 +-1155.0 + 10 +660.0 + 20 +-1055.0 + 10 +560.0 + 20 +-1055.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +3.175 + 79 +0 + 53 +60.0 + 43 +0.0 + 44 +0.0 + 45 +-2.749630657 + 46 +1.5875 + 79 +0 + 53 +120.0 + 43 +0.0 + 44 +0.0 + 45 +-2.749630657 + 46 +-1.5875 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +FC +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +560.0 + 20 +-1155.0 + 10 +660.0 + 20 +-1155.0 + 10 +660.0 + 20 +-1055.0 + 10 +560.0 + 20 +-1055.0 + 0 +TEXT + 5 +FD +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +560.0 + 20 +-1169.0 + 30 +0.0 + 40 +9.0 + 1 +NET3 + 7 +LABEL + 11 +560.0 + 21 +-1169.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +FE +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +PLAST + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +700.0 + 20 +-1155.0 + 10 +800.0 + 20 +-1155.0 + 10 +800.0 + 20 +-1055.0 + 10 +700.0 + 20 +-1055.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +6.35 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +0.79375 + 45 +0.0 + 46 +6.35 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +1.5875 + 45 +0.0 + 46 +6.35 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +FF +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +700.0 + 20 +-1155.0 + 10 +800.0 + 20 +-1155.0 + 10 +800.0 + 20 +-1055.0 + 10 +700.0 + 20 +-1055.0 + 0 +TEXT + 5 +100 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +700.0 + 20 +-1169.0 + 30 +0.0 + 40 +9.0 + 1 +PLAST + 7 +LABEL + 11 +700.0 + 21 +-1169.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +101 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +PLASTI + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +840.0 + 20 +-1155.0 + 10 +940.0 + 20 +-1155.0 + 10 +940.0 + 20 +-1055.0 + 10 +840.0 + 20 +-1055.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +4 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +6.35 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +0.79375 + 45 +0.0 + 46 +6.35 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +1.5875 + 45 +0.0 + 46 +6.35 + 79 +0 + 53 +0.0 + 43 +0.0 + 44 +3.96875 + 45 +0.0 + 46 +6.35 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +102 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +-1155.0 + 10 +940.0 + 20 +-1155.0 + 10 +940.0 + 20 +-1055.0 + 10 +840.0 + 20 +-1055.0 + 0 +TEXT + 5 +103 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +840.0 + 20 +-1169.0 + 30 +0.0 + 40 +9.0 + 1 +PLASTI + 7 +LABEL + 11 +840.0 + 21 +-1169.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +104 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SQUARE + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +980.0 + 20 +-1155.0 + 10 +1080.0 + 20 +-1155.0 + 10 +1080.0 + 20 +-1055.0 + 10 +980.0 + 20 +-1055.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +3.175 + 79 +2 + 49 +3.175 + 49 +-3.175 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-3.175 + 46 +0.0 + 79 +2 + 49 +3.175 + 49 +-3.175 + 98 +0 + 0 +LWPOLYLINE + 5 +105 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +980.0 + 20 +-1155.0 + 10 +1080.0 + 20 +-1155.0 + 10 +1080.0 + 20 +-1055.0 + 10 +980.0 + 20 +-1055.0 + 0 +TEXT + 5 +106 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +980.0 + 20 +-1169.0 + 30 +0.0 + 40 +9.0 + 1 +SQUARE + 7 +LABEL + 11 +980.0 + 21 +-1169.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +107 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SQUARES + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-1320.0 + 10 +100.0 + 20 +-1320.0 + 10 +100.0 + 20 +-1220.0 + 10 +0.0 + 20 +-1220.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +3.81 + 79 +2 + 49 +3.81 + 49 +-3.81 + 53 +90.0 + 43 +0.0 + 44 +0.0 + 45 +-3.81 + 46 +0.0 + 79 +2 + 49 +3.81 + 49 +-3.81 + 98 +0 + 0 +LWPOLYLINE + 5 +108 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-1320.0 + 10 +100.0 + 20 +-1320.0 + 10 +100.0 + 20 +-1220.0 + 10 +0.0 + 20 +-1220.0 + 0 +TEXT + 5 +109 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-1334.0 + 30 +0.0 + 40 +9.0 + 1 +SQUARES + 7 +LABEL + 11 +0.0 + 21 +-1334.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +10A +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +STARS + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +140.0 + 20 +-1320.0 + 10 +240.0 + 20 +-1320.0 + 10 +240.0 + 20 +-1220.0 + 10 +140.0 + 20 +-1220.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +5.4992613154 + 79 +2 + 49 +3.175 + 49 +-3.175 + 53 +60.0 + 43 +0.0 + 44 +0.0 + 45 +-4.7625000012 + 46 +2.7496306577 + 79 +2 + 49 +3.175 + 49 +-3.175 + 53 +120.0 + 43 +1.5875 + 44 +2.7496306704 + 45 +-4.7625000012 + 46 +-2.7496306577 + 79 +2 + 49 +3.175 + 49 +-3.175 + 98 +0 + 0 +LWPOLYLINE + 5 +10B +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +140.0 + 20 +-1320.0 + 10 +240.0 + 20 +-1320.0 + 10 +240.0 + 20 +-1220.0 + 10 +140.0 + 20 +-1220.0 + 0 +TEXT + 5 +10C +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +140.0 + 20 +-1334.0 + 30 +0.0 + 40 +9.0 + 1 +STARS + 7 +LABEL + 11 +140.0 + 21 +-1334.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +10D +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +STEEL + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +280.0 + 20 +-1320.0 + 10 +380.0 + 20 +-1320.0 + 10 +380.0 + 20 +-1220.0 + 10 +280.0 + 20 +-1220.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +8 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-5.3881536726 + 46 +5.3881536726 + 79 +0 + 53 +45.0 + 43 +4.318 + 44 +0.0 + 45 +-5.3881536726 + 46 +5.3881536726 + 79 +0 + 53 +45.0 + 43 +4.572 + 44 +0.0 + 45 +-5.3881536726 + 46 +5.3881536726 + 79 +0 + 53 +45.0 + 43 +4.826 + 44 +0.0 + 45 +-5.3881536726 + 46 +5.3881536726 + 79 +0 + 53 +45.0 + 43 +5.08 + 44 +0.0 + 45 +-5.3881536726 + 46 +5.3881536726 + 79 +0 + 53 +45.0 + 43 +5.334 + 44 +0.0 + 45 +-5.3881536726 + 46 +5.3881536726 + 79 +0 + 53 +45.0 + 43 +5.588 + 44 +0.0 + 45 +-5.3881536726 + 46 +5.3881536726 + 79 +0 + 53 +45.0 + 43 +5.842 + 44 +0.0 + 45 +-5.3881536726 + 46 +5.3881536726 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +10E +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +280.0 + 20 +-1320.0 + 10 +380.0 + 20 +-1320.0 + 10 +380.0 + 20 +-1220.0 + 10 +280.0 + 20 +-1220.0 + 0 +TEXT + 5 +10F +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +280.0 + 20 +-1334.0 + 30 +0.0 + 40 +9.0 + 1 +STEEL + 7 +LABEL + 11 +280.0 + 21 +-1334.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +110 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SWAMP + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +420.0 + 20 +-1320.0 + 10 +520.0 + 20 +-1320.0 + 10 +520.0 + 20 +-1220.0 + 10 +420.0 + 20 +-1220.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +6 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +12.7 + 46 +21.9970452362 + 79 +2 + 49 +3.175 + 49 +-22.225 + 53 +90.0 + 43 +1.5875 + 44 +0.0 + 45 +-12.7 + 46 +21.9970452362 + 79 +2 + 49 +1.5875 + 49 +-42.4065904724 + 53 +90.0 + 43 +1.984375 + 44 +0.0 + 45 +-12.7 + 46 +21.9970452362 + 79 +2 + 49 +1.27 + 49 +-42.7240904724 + 53 +90.0 + 43 +1.190625 + 44 +0.0 + 45 +-12.7 + 46 +21.9970452362 + 79 +2 + 49 +1.27 + 49 +-42.7240904724 + 53 +60.0 + 43 +2.38125 + 44 +0.0 + 45 +-12.6999999827 + 46 +21.9970452462 + 79 +2 + 49 +1.016 + 49 +-24.384 + 53 +120.0 + 43 +0.79375 + 44 +0.0 + 45 +-25.3999999827 + 46 +1e-08 + 79 +2 + 49 +1.016 + 49 +-24.384 + 98 +0 + 0 +LWPOLYLINE + 5 +111 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +420.0 + 20 +-1320.0 + 10 +520.0 + 20 +-1320.0 + 10 +520.0 + 20 +-1220.0 + 10 +420.0 + 20 +-1220.0 + 0 +TEXT + 5 +112 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +420.0 + 20 +-1334.0 + 30 +0.0 + 40 +9.0 + 1 +SWAMP + 7 +LABEL + 11 +420.0 + 21 +-1334.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +113 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +TRIANG + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +560.0 + 20 +-1320.0 + 10 +660.0 + 20 +-1320.0 + 10 +660.0 + 20 +-1220.0 + 10 +560.0 + 20 +-1220.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +60.0 + 43 +0.0 + 44 +0.0 + 45 +-4.7624999908 + 46 +8.2488919657 + 79 +2 + 49 +4.7625 + 49 +-4.7625 + 53 +120.0 + 43 +0.0 + 44 +0.0 + 45 +-9.5249999908 + 46 +5.3e-09 + 79 +2 + 49 +4.7625 + 49 +-4.7625 + 53 +0.0 + 43 +-2.38125 + 44 +4.1244459802 + 45 +4.7625 + 46 +8.2488919604 + 79 +2 + 49 +4.7625 + 49 +-4.7625 + 98 +0 + 0 +LWPOLYLINE + 5 +114 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +560.0 + 20 +-1320.0 + 10 +660.0 + 20 +-1320.0 + 10 +660.0 + 20 +-1220.0 + 10 +560.0 + 20 +-1220.0 + 0 +TEXT + 5 +115 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +560.0 + 20 +-1334.0 + 30 +0.0 + 40 +9.0 + 1 +TRIANG + 7 +LABEL + 11 +560.0 + 21 +-1334.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +116 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +TRIANGLES + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +700.0 + 20 +-1320.0 + 10 +800.0 + 20 +-1320.0 + 10 +800.0 + 20 +-1220.0 + 10 +700.0 + 20 +-1220.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +60.0 + 43 +0.0 + 44 +0.0 + 45 +-5.7149999889 + 46 +9.8986703589 + 79 +2 + 49 +5.715 + 49 +-5.715 + 53 +120.0 + 43 +0.0 + 44 +0.0 + 45 +-11.4299999889 + 46 +6.4e-09 + 79 +2 + 49 +5.715 + 49 +-5.715 + 53 +0.0 + 43 +-2.8575 + 44 +4.9493351762 + 45 +5.715 + 46 +9.8986703525 + 79 +2 + 49 +5.715 + 49 +-5.715 + 98 +0 + 0 +LWPOLYLINE + 5 +117 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +700.0 + 20 +-1320.0 + 10 +800.0 + 20 +-1320.0 + 10 +800.0 + 20 +-1220.0 + 10 +700.0 + 20 +-1220.0 + 0 +TEXT + 5 +118 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +700.0 + 20 +-1334.0 + 30 +0.0 + 40 +9.0 + 1 +TRIANGLES + 7 +LABEL + 11 +700.0 + 21 +-1334.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +119 +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ZIGZAG + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +840.0 + 20 +-1320.0 + 10 +940.0 + 20 +-1320.0 + 10 +940.0 + 20 +-1220.0 + 10 +840.0 + 20 +-1220.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +2 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 53 +90.0 + 43 +6.35 + 44 +0.0 + 45 +-6.35 + 46 +6.35 + 79 +2 + 49 +6.35 + 49 +-6.35 + 98 +0 + 0 +LWPOLYLINE + 5 +11A +330 +17 +100 +AcDbEntity + 8 +PATTERNS + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +-1320.0 + 10 +940.0 + 20 +-1320.0 + 10 +940.0 + 20 +-1220.0 + 10 +840.0 + 20 +-1220.0 + 0 +TEXT + 5 +11B +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +840.0 + 20 +-1334.0 + 30 +0.0 + 40 +9.0 + 1 +ZIGZAG + 7 +LABEL + 11 +840.0 + 21 +-1334.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +11C +330 +17 +100 +AcDbEntity + 8 +GRADIENTS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-1585.0 + 10 +100.0 + 20 +-1585.0 + 10 +100.0 + 20 +-1485.0 + 10 +0.0 + 20 +-1485.0 + 97 +0 + 75 +0 + 76 +1 + 98 +0 +450 +1 +451 +0 +460 +0.0 +461 +0.0 +452 +0 +462 +0.0 +453 +2 +463 +0 +421 +16768080 +463 +1 +421 +1326220 +470 +LINEAR + 0 +TEXT + 5 +11D +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-1599.0 + 30 +0.0 + 40 +9.0 + 1 +linear + 7 +LABEL + 11 +0.0 + 21 +-1599.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +11E +330 +17 +100 +AcDbEntity + 8 +GRADIENTS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +140.0 + 20 +-1585.0 + 10 +240.0 + 20 +-1585.0 + 10 +240.0 + 20 +-1485.0 + 10 +140.0 + 20 +-1485.0 + 97 +0 + 75 +0 + 76 +1 + 98 +0 +450 +1 +451 +0 +460 +0.5235987755982988 +461 +0.0 +452 +0 +462 +0.0 +453 +2 +463 +0 +421 +16768080 +463 +1 +421 +1326220 +470 +CYLINDER + 0 +TEXT + 5 +11F +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +140.0 + 20 +-1599.0 + 30 +0.0 + 40 +9.0 + 1 +cylinder + 7 +LABEL + 11 +140.0 + 21 +-1599.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +120 +330 +17 +100 +AcDbEntity + 8 +GRADIENTS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +280.0 + 20 +-1585.0 + 10 +380.0 + 20 +-1585.0 + 10 +380.0 + 20 +-1485.0 + 10 +280.0 + 20 +-1485.0 + 97 +0 + 75 +0 + 76 +1 + 98 +0 +450 +1 +451 +0 +460 +0.0 +461 +0.0 +452 +0 +462 +0.0 +453 +2 +463 +0 +421 +16768080 +463 +1 +421 +1326220 +470 +INVCYLINDER + 0 +TEXT + 5 +121 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +280.0 + 20 +-1599.0 + 30 +0.0 + 40 +9.0 + 1 +invcylinder + 7 +LABEL + 11 +280.0 + 21 +-1599.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +122 +330 +17 +100 +AcDbEntity + 8 +GRADIENTS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +420.0 + 20 +-1585.0 + 10 +520.0 + 20 +-1585.0 + 10 +520.0 + 20 +-1485.0 + 10 +420.0 + 20 +-1485.0 + 97 +0 + 75 +0 + 76 +1 + 98 +0 +450 +1 +451 +0 +460 +0.5235987755982988 +461 +0.0 +452 +0 +462 +0.0 +453 +2 +463 +0 +421 +16768080 +463 +1 +421 +1326220 +470 +SPHERICAL + 0 +TEXT + 5 +123 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +420.0 + 20 +-1599.0 + 30 +0.0 + 40 +9.0 + 1 +spherical + 7 +LABEL + 11 +420.0 + 21 +-1599.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +124 +330 +17 +100 +AcDbEntity + 8 +GRADIENTS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +560.0 + 20 +-1585.0 + 10 +660.0 + 20 +-1585.0 + 10 +660.0 + 20 +-1485.0 + 10 +560.0 + 20 +-1485.0 + 97 +0 + 75 +0 + 76 +1 + 98 +0 +450 +1 +451 +0 +460 +0.0 +461 +0.0 +452 +0 +462 +0.0 +453 +2 +463 +0 +421 +16768080 +463 +1 +421 +1326220 +470 +INVSPHERICAL + 0 +TEXT + 5 +125 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +560.0 + 20 +-1599.0 + 30 +0.0 + 40 +9.0 + 1 +invspherical + 7 +LABEL + 11 +560.0 + 21 +-1599.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +126 +330 +17 +100 +AcDbEntity + 8 +GRADIENTS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +700.0 + 20 +-1585.0 + 10 +800.0 + 20 +-1585.0 + 10 +800.0 + 20 +-1485.0 + 10 +700.0 + 20 +-1485.0 + 97 +0 + 75 +0 + 76 +1 + 98 +0 +450 +1 +451 +0 +460 +0.5235987755982988 +461 +0.0 +452 +0 +462 +0.0 +453 +2 +463 +0 +421 +16768080 +463 +1 +421 +1326220 +470 +HEMISPHERICAL + 0 +TEXT + 5 +127 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +700.0 + 20 +-1599.0 + 30 +0.0 + 40 +9.0 + 1 +hemispherical + 7 +LABEL + 11 +700.0 + 21 +-1599.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +128 +330 +17 +100 +AcDbEntity + 8 +GRADIENTS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +840.0 + 20 +-1585.0 + 10 +940.0 + 20 +-1585.0 + 10 +940.0 + 20 +-1485.0 + 10 +840.0 + 20 +-1485.0 + 97 +0 + 75 +0 + 76 +1 + 98 +0 +450 +1 +451 +0 +460 +0.0 +461 +0.0 +452 +0 +462 +0.0 +453 +2 +463 +0 +421 +16768080 +463 +1 +421 +1326220 +470 +INVHEMISPHERICAL + 0 +TEXT + 5 +129 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +840.0 + 20 +-1599.0 + 30 +0.0 + 40 +9.0 + 1 +invhemispherical + 7 +LABEL + 11 +840.0 + 21 +-1599.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +12A +330 +17 +100 +AcDbEntity + 8 +GRADIENTS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +980.0 + 20 +-1585.0 + 10 +1080.0 + 20 +-1585.0 + 10 +1080.0 + 20 +-1485.0 + 10 +980.0 + 20 +-1485.0 + 97 +0 + 75 +0 + 76 +1 + 98 +0 +450 +1 +451 +0 +460 +0.5235987755982988 +461 +0.0 +452 +0 +462 +0.0 +453 +2 +463 +0 +421 +16768080 +463 +1 +421 +1326220 +470 +CURVED + 0 +TEXT + 5 +12B +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +980.0 + 20 +-1599.0 + 30 +0.0 + 40 +9.0 + 1 +curved + 7 +LABEL + 11 +980.0 + 21 +-1599.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +12C +330 +17 +100 +AcDbEntity + 8 +GRADIENTS + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-1750.0 + 10 +100.0 + 20 +-1750.0 + 10 +100.0 + 20 +-1650.0 + 10 +0.0 + 20 +-1650.0 + 97 +0 + 75 +0 + 76 +1 + 98 +0 +450 +1 +451 +0 +460 +0.0 +461 +0.0 +452 +0 +462 +0.0 +453 +2 +463 +0 +421 +16768080 +463 +1 +421 +1326220 +470 +INVCURVED + 0 +TEXT + 5 +12D +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-1764.0 + 30 +0.0 + 40 +9.0 + 1 +invcurved + 7 +LABEL + 11 +0.0 + 21 +-1764.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +12E +330 +17 +100 +AcDbEntity + 8 +ISLANDS + 62 +1 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +3 + 92 +19 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-2015.0 + 10 +200.0 + 20 +-2015.0 + 10 +200.0 + 20 +-1815.0 + 10 +0.0 + 20 +-1815.0 + 97 +0 + 92 +16 + 93 +1 + 72 +2 + 10 +100.0 + 20 +-1915.0 + 40 +70 + 50 +0 + 51 +360 + 73 +1 + 97 +0 + 92 +18 + 72 +0 + 73 +1 + 93 +3 + 10 +75.0 + 20 +-1935.0 + 10 +125.0 + 20 +-1935.0 + 10 +100.0 + 20 +-1887.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.4 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-3.1430896424 + 46 +3.1430896424 + 79 +0 + 98 +0 + 0 +TEXT + 5 +12F +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +0.0 + 20 +-2029.0 + 30 +0.0 + 40 +9.0 + 1 +normal: nested islands + 7 +LABEL + 11 +0.0 + 21 +-2029.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +130 +330 +17 +100 +AcDbEntity + 8 +ISLANDS + 62 +1 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +3 + 92 +19 + 72 +0 + 73 +1 + 93 +4 + 10 +240.0 + 20 +-2015.0 + 10 +440.0 + 20 +-2015.0 + 10 +440.0 + 20 +-1815.0 + 10 +240.0 + 20 +-1815.0 + 97 +0 + 92 +16 + 93 +1 + 72 +2 + 10 +340.0 + 20 +-1915.0 + 40 +70 + 50 +0 + 51 +360 + 73 +1 + 97 +0 + 92 +18 + 72 +0 + 73 +1 + 93 +3 + 10 +315.0 + 20 +-1935.0 + 10 +365.0 + 20 +-1935.0 + 10 +340.0 + 20 +-1887.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.4 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-3.1430896424 + 46 +3.1430896424 + 79 +0 + 98 +0 + 0 +TEXT + 5 +131 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +240.0 + 20 +-2029.0 + 30 +0.0 + 40 +9.0 + 1 +outer only + 7 +LABEL + 11 +240.0 + 21 +-2029.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +132 +330 +17 +100 +AcDbEntity + 8 +ISLANDS + 62 +1 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +3 + 92 +19 + 72 +0 + 73 +1 + 93 +4 + 10 +480.0 + 20 +-2015.0 + 10 +680.0 + 20 +-2015.0 + 10 +680.0 + 20 +-1815.0 + 10 +480.0 + 20 +-1815.0 + 97 +0 + 92 +16 + 93 +1 + 72 +2 + 10 +580.0 + 20 +-1915.0 + 40 +70 + 50 +0 + 51 +360 + 73 +1 + 97 +0 + 92 +18 + 72 +0 + 73 +1 + 93 +3 + 10 +555.0 + 20 +-1935.0 + 10 +605.0 + 20 +-1935.0 + 10 +580.0 + 20 +-1887.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.4 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-3.1430896424 + 46 +3.1430896424 + 79 +0 + 98 +0 + 0 +TEXT + 5 +133 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +480.0 + 20 +-2029.0 + 30 +0.0 + 40 +9.0 + 1 +ignore: all filled + 7 +LABEL + 11 +480.0 + 21 +-2029.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +134 +330 +17 +100 +AcDbEntity + 8 +EDGES + 62 +3 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +HONEY + 70 +0 + 71 +0 + 91 +1 + 92 +1 + 93 +5 + 72 +1 + 10 +720.0 + 20 +-2015.0 + 11 +880.0 + 21 +-2015.0 + 72 +2 + 10 +880.0 + 20 +-1975.0 + 40 +40 + 50 +270 + 51 +90 + 73 +1 + 72 +1 + 10 +880.0 + 20 +-1935.0 + 11 +840.0 + 21 +-1935.0 + 72 +4 + 94 +3 + 73 +0 + 74 +0 + 95 +8 + 96 +0 + 40 +0.0 + 40 +0.0 + 40 +0.0 + 40 +0.0 + 40 +-3.0 + 40 +-3.0 + 40 +-3.0 + 40 +-3.0 + 97 +5 + 11 +840.0 + 21 +-1935.0 + 11 +820.0 + 21 +-1875.0 + 11 +780.0 + 21 +-1975.0 + 11 +760.0 + 21 +-1895.0 + 11 +720.0 + 21 +-1915.0 + 72 +1 + 10 +720.0 + 20 +-1915.0 + 11 +720.0 + 21 +-2015.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +1.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +4.7625 + 46 +2.749630645 + 79 +2 + 49 +3.175 + 49 +-6.35 + 53 +120.0 + 43 +0.0 + 44 +0.0 + 45 +-4.7624999896 + 46 +2.749630663 + 79 +2 + 49 +3.175 + 49 +-6.35 + 53 +60.0 + 43 +0.0 + 44 +0.0 + 45 +1.04e-08 + 46 +5.499261308 + 79 +2 + 49 +-6.35 + 49 +3.175 + 98 +0 + 0 +TEXT + 5 +135 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +720.0 + 20 +-2029.0 + 30 +0.0 + 40 +9.0 + 1 +edges: line, arc, spline + 7 +LABEL + 11 +720.0 + 21 +-2029.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +136 +330 +17 +100 +AcDbEntity + 8 +EDGES + 62 +6 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +1 + 93 +1 + 72 +3 + 10 +1010.0 + 20 +-1945.0 + 11 +70.0 + 21 +0.0 + 40 +0.55 + 50 +0 + 51 +360 + 73 +1 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +TEXT + 5 +137 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +940.0 + 20 +-2029.0 + 30 +0.0 + 40 +9.0 + 1 +ellipse, solid + 7 +LABEL + 11 +940.0 + 21 +-2029.0 + 31 +0.0 +100 +AcDbText + 0 +HATCH + 5 +138 +330 +17 +100 +AcDbEntity + 8 +EDGES + 62 +2 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI37 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +1120.0 + 20 +-2015.0 + 10 +1260.0 + 20 +-2015.0 + 10 +1260.0 + 20 +-1875.0 + 10 +1120.0 + 20 +-1875.0 + 97 +0 + 75 +1 + 76 +1 + 52 +15.0 + 41 +2.5 + 77 +0 + 78 +2 + 53 +60.0 + 43 +0.0 + 44 +0.0 + 45 +-6.8740766426 + 46 +3.9687500001 + 79 +0 + 53 +150.0 + 43 +0.0 + 44 +0.0 + 45 +-3.9687500001 + 46 +-6.8740766426 + 79 +0 + 98 +0 + 0 +TEXT + 5 +139 +330 +17 +100 +AcDbEntity + 8 +LABELS +100 +AcDbText + 10 +1120.0 + 20 +-2029.0 + 30 +0.0 + 40 +9.0 + 1 +angle 15, scale 2.5 + 7 +LABEL + 11 +1120.0 + 21 +-2029.0 + 31 +0.0 +100 +AcDbText + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +A +330 +0 +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ACAD_COLOR +350 +B + 3 +ACAD_GROUP +350 +C + 3 +ACAD_LAYOUT +350 +D + 3 +ACAD_MATERIAL +350 +E + 3 +ACAD_MLEADERSTYLE +350 +F + 3 +ACAD_MLINESTYLE +350 +10 + 3 +ACAD_PLOTSETTINGS +350 +11 + 3 +ACAD_PLOTSTYLENAME +350 +12 + 3 +ACAD_SCALELIST +350 +14 + 3 +ACAD_TABLESTYLE +350 +15 + 3 +ACAD_VISUALSTYLE +350 +16 + 3 +EZDXF_META +350 +2D + 0 +DICTIONARY + 5 +B +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +C +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +D +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Model +350 +1A + 3 +Layout1 +350 +1E + 0 +DICTIONARY + 5 +E +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ByBlock +350 +1F + 3 +ByLayer +350 +20 + 3 +Global +350 +21 + 0 +DICTIONARY + 5 +F +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +2C + 0 +DICTIONARY + 5 +10 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +22 + 0 +DICTIONARY + 5 +11 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +ACDBDICTIONARYWDFLT + 5 +12 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Normal +350 +13 +100 +AcDbDictionaryWithDefault +340 +13 + 0 +ACDBPLACEHOLDER + 5 +13 +330 +12 + 0 +DICTIONARY + 5 +14 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +15 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +16 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +LAYOUT + 5 +1A +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +1024 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 +1 + 71 +0 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +17 + 0 +LAYOUT + 5 +1E +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +0 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 +1 + 71 +1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +1B + 0 +MATERIAL + 5 +1F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByBlock + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +20 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByLayer + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +21 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +Global + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MLINESTYLE + 5 +22 +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMlineStyle + 2 +Standard + 70 +0 + 3 + + 62 +256 + 51 +90.0 + 52 +90.0 + 71 +2 + 49 +0.5 + 62 +256 + 6 +BYLAYER + 49 +-0.5 + 62 +256 + 6 +BYLAYER + 0 +MLEADERSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +F +102 +} +330 +F +100 +AcDbMLeaderStyle +179 +2 +170 +2 +171 +1 +172 +0 + 90 +2 + 40 +0.0 + 41 +0.0 +173 +1 + 91 +-1056964608 + 92 +-2 +290 +1 + 42 +2.0 +291 +1 + 43 +8.0 + 3 +Standard + 44 +4.0 +300 + +342 +29 +174 +1 +175 +1 +176 +0 +178 +1 + 93 +-1056964608 + 45 +4.0 +292 +0 +297 +0 + 46 +4.0 + 94 +-1056964608 + 47 +1.0 + 49 +1.0 +140 +1.0 +294 +1 +141 +0.0 +177 +0 +142 +1.0 +295 +0 +296 +0 +143 +3.75 +271 +0 +272 +9 +273 +9 + 0 +DICTIONARY + 5 +2D +330 +A +100 +AcDbDictionary +281 +1 + 3 +CREATED_BY_EZDXF +350 +2E + 3 +WRITTEN_BY_EZDXF +350 +13D + 0 +DICTIONARYVAR + 5 +2E +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +DICTIONARYVAR + 5 +13D +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +ENDSEC + 0 +EOF diff --git a/crates/exav-viewer/demo/examples/files/cad/house-elevations.dxf b/crates/exav-viewer/demo/examples/files/cad/house-elevations.dxf new file mode 100644 index 0000000..e22260b --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/cad/house-elevations.dxf @@ -0,0 +1,18904 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1032 + 9 +$ACADMAINTVER + 90 +4 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$LASTSAVEDBY + 1 +ezdxf + 9 +$REQUIREDVERSIONS +160 +0 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$EXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 +0 + 9 +$REGENMODE + 70 +1 + 9 +$FILLMODE + 70 +1 + 9 +$QTEXTMODE + 70 +0 + 9 +$MIRRTEXT + 70 +1 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 +1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 +256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 +0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 +0 + 9 +$DIMLIM + 70 +0 + 9 +$DIMTIH + 70 +0 + 9 +$DIMTOH + 70 +0 + 9 +$DIMSE1 + 70 +0 + 9 +$DIMSE2 + 70 +0 + 9 +$DIMTAD + 70 +1 + 9 +$DIMZIN + 70 +8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 +1 + 9 +$DIMSHO + 70 +1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 +0 + 9 +$DIMALTD + 70 +3 + 9 +$DIMALTF + 40 +0.03937007874 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 +1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 +0 + 9 +$DIMSOXD + 70 +0 + 9 +$DIMSAH + 70 +0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 +0 + 9 +$DIMCLRE + 70 +0 + 9 +$DIMCLRT + 70 +0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 +0 + 9 +$DIMSD1 + 70 +0 + 9 +$DIMSD2 + 70 +0 + 9 +$DIMTOLJ + 70 +0 + 9 +$DIMTZIN + 70 +8 + 9 +$DIMALTZ + 70 +0 + 9 +$DIMALTTZ + 70 +0 + 9 +$DIMUPT + 70 +0 + 9 +$DIMDEC + 70 +2 + 9 +$DIMTDEC + 70 +2 + 9 +$DIMALTU + 70 +2 + 9 +$DIMALTTD + 70 +3 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 +0 + 9 +$DIMADEC + 70 +0 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 +0 + 9 +$DIMDSEP + 70 +44 + 9 +$DIMATFIT + 70 +3 + 9 +$DIMFRAC + 70 +0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 +2 + 9 +$DIMLWD + 70 +-2 + 9 +$DIMLWE + 70 +-2 + 9 +$DIMTMOVE + 70 +0 + 9 +$DIMFXL + 40 +1.0 + 9 +$DIMFXLON + 70 +0 + 9 +$DIMJOGANG + 40 +0.785398163397 + 9 +$DIMTFILL + 70 +0 + 9 +$DIMTFILLCLR + 70 +0 + 9 +$DIMARCSYM + 70 +0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$DIMTXTDIRECTION + 70 +0 + 9 +$LUNITS + 70 +2 + 9 +$LUPREC + 70 +4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 +0 + 9 +$AUPREC + 70 +2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 +0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 +0 + 9 +$TDCREATE + 40 +2451545.0 + 9 +$TDUCREATE + 40 +2451545.0 + 9 +$TDUPDATE + 40 +2451545.0 + 9 +$TDUUPDATE + 40 +2451545.0 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 +1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 +0 + 9 +$PDMODE + 70 +0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 +0 + 9 +$SPLINETYPE + 70 +6 + 9 +$SPLINESEGS + 70 +8 + 9 +$HANDSEED + 5 +23A + 9 +$SURFTAB1 + 70 +6 + 9 +$SURFTAB2 + 70 +6 + 9 +$SURFTYPE + 70 +6 + 9 +$SURFU + 70 +6 + 9 +$SURFV + 70 +6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 +0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 +0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 +0 + 9 +$USERI2 + 70 +0 + 9 +$USERI3 + 70 +0 + 9 +$USERI4 + 70 +0 + 9 +$USERI5 + 70 +0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 +1 + 9 +$SHADEDGE + 70 +3 + 9 +$SHADEDIF + 70 +70 + 9 +$TILEMODE + 70 +1 + 9 +$MAXACTVP + 70 +64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 +0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 +0 + 9 +$VISRETAIN + 70 +1 + 9 +$PLINEGEN + 70 +0 + 9 +$PSLTSCALE + 70 +1 + 9 +$TREEDEPTH + 70 +3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 +0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 +1 + 9 +$MEASUREMENT + 70 +1 + 9 +$CELWEIGHT +370 +-1 + 9 +$ENDCAPS +280 +0 + 9 +$JOINSTYLE +280 +0 + 9 +$LWDISPLAY +290 +0 + 9 +$INSUNITS + 70 +4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 +1 + 9 +$CEPSNTYPE +380 +0 + 9 +$PSTYLEMODE +290 +1 + 9 +$FINGERPRINTGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$VERSIONGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$EXTNAMES +290 +1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 +0 + 9 +$SORTENTS +280 +127 + 9 +$INDEXCTL +280 +0 + 9 +$HIDETEXT +280 +1 + 9 +$XCLIPFRAME +280 +1 + 9 +$HALOGAP +280 +0 + 9 +$OBSCOLOR + 70 +257 + 9 +$OBSLTYPE +280 +0 + 9 +$INTERSECTIONDISPLAY +280 +0 + 9 +$INTERSECTIONCOLOR + 70 +257 + 9 +$DIMASSOC +280 +2 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 +0 + 9 +$LENSLENGTH + 40 +50.0 + 9 +$CAMERAHEIGHT + 40 +0.0 + 9 +$STEPSPERSEC + 40 +24.0 + 9 +$STEPSIZE + 40 +100.0 + 9 +$3DDWFPREC + 40 +2.0 + 9 +$PSOLWIDTH + 40 +0.005 + 9 +$PSOLHEIGHT + 40 +0.08 + 9 +$LOFTANG1 + 40 +1.570796326795 + 9 +$LOFTANG2 + 40 +1.570796326795 + 9 +$LOFTMAG1 + 40 +0.0 + 9 +$LOFTMAG2 + 40 +0.0 + 9 +$LOFTPARAM + 70 +7 + 9 +$LOFTNORMALS +280 +1 + 9 +$LATITUDE + 40 +37.795 + 9 +$LONGITUDE + 40 +-122.394 + 9 +$NORTHDIRECTION + 40 +0.0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 +1 + 9 +$TILEMODELIGHTSYNCH +280 +1 + 9 +$CMATERIAL +347 +20 + 9 +$SOLIDHIST +280 +0 + 9 +$SHOWHIST +280 +1 + 9 +$DWFFRAME +280 +2 + 9 +$DGNFRAME +280 +2 + 9 +$REALWORLDSCALE +290 +1 + 9 +$INTERFERECOLOR + 62 +256 + 9 +$CSHADOW +280 +0 + 9 +$SHADOWPLANELOCATION + 40 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +CELLSTYLEMAP + 2 +AcDbCellStyleMap + 3 +ObjectDBX Classes + 90 +1152 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MENTALRAYRENDERSETTINGS + 2 +AcDbMentalRayRenderSettings + 3 +SCENEOE + 90 +1024 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBDETAILVIEWSTYLE + 2 +AcDbDetailViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBSECTIONVIEWSTYLE + 2 +AcDbSectionViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +RASTERVARIABLES + 2 +AcDbRasterVariables + 3 +ISM + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 +1 + 0 +VPORT + 5 +236 +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +20684.586738111186 + 22 +-5270.0 + 13 +0.0 + 23 +0.0 + 14 +0.5 + 24 +0.5 + 15 +0.5 + 25 +0.5 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +29358.0 + 41 +1.34 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +1000 + 73 +1 + 74 +3 + 75 +0 + 76 +0 + 77 +0 + 78 +0 +281 +0 + 65 +1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 +21 + 0 +LTYPE + 5 +24 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +25 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +26 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +2F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 +0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +5.08 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +30 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 +0 + 3 +Center (2x) ________ __ ________ __ ________ + 72 +65 + 73 +4 + 40 +8.89 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 +0 + 3 +Center (.5x) ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +2.54 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +32 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 +0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 +65 + 73 +2 + 40 +1.524 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +33 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 +0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ____ + 72 +65 + 73 +2 + 40 +3.048 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +34 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 +0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 +65 + 73 +2 + 40 +0.762 + 49 +0.635 + 74 +0 + 49 +-0.127 + 74 +0 + 0 +LTYPE + 5 +35 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM + 70 +0 + 3 +Phantom ______ __ __ ______ __ __ ______ + 72 +65 + 73 +6 + 40 +6.35 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOMX2 + 70 +0 + 3 +Phantom (2x)____________ ____ ____ ____________ + 72 +65 + 73 +6 + 40 +10.795 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +37 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 +0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___ + 72 +65 + 73 +6 + 40 +3.175 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +38 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 +0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 +65 + 73 +4 + 40 +3.556 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +39 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 +0 + 3 +Dash dot (2x) ____ . ____ . ____ . ____ + 72 +65 + 73 +4 + 40 +6.096 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 +0 + 3 +Dash dot (.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +4 + 40 +1.778 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 +0 + 3 +Dot . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.508 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 +0 + 3 +Dot (2x) . . . . . . . . + 72 +65 + 73 +2 + 40 +1.016 + 49 +0.0 + 74 +0 + 49 +-1.016 + 74 +0 + 0 +LTYPE + 5 +3D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 +0 + 3 +Dot (.5) . . . . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.254 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 +0 + 3 +Divide __ . . __ . . __ . . __ . . __ . . __ + 72 +65 + 73 +6 + 40 +4.064 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 +0 + 3 +Divide (2x) ____ . . ____ . . ____ . . ____ + 72 +65 + 73 +6 + 40 +6.604 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +40 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 +0 + 3 +Divide(.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +6 + 40 +2.032 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 +14 + 0 +LAYER + 5 +27 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 62 +7 + 6 +Continuous +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +28 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Defpoints + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +41 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +E-GROUND + 70 +0 + 62 +3 + 6 +Continuous +370 +50 +390 +13 +347 +21 + 0 +LAYER + 5 +42 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +E-WALL + 70 +0 + 62 +7 + 6 +Continuous +370 +35 +390 +13 +347 +21 + 0 +LAYER + 5 +43 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +E-RENDER + 70 +0 + 62 +8 + 6 +Continuous +370 +9 +390 +13 +347 +21 + 0 +LAYER + 5 +44 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +E-PLINTH + 70 +0 + 62 +8 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +45 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +E-ROOF + 70 +0 + 62 +1 + 6 +Continuous +370 +35 +390 +13 +347 +21 + 0 +LAYER + 5 +46 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +E-FLOOR + 70 +0 + 62 +9 + 6 +DASHDOT +370 +9 +390 +13 +347 +21 + 0 +LAYER + 5 +47 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +E-DOOR + 70 +0 + 62 +30 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +48 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +E-STEP + 70 +0 + 62 +8 + 6 +Continuous +370 +18 +390 +13 +347 +21 + 0 +LAYER + 5 +49 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-WIND + 70 +0 + 62 +5 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +4A +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-ANNO + 70 +0 + 62 +2 + 6 +Continuous +370 +18 +390 +13 +347 +21 + 0 +LAYER + 5 +4B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-DIMS + 70 +0 + 62 +3 + 6 +Continuous +370 +13 +390 +13 +347 +21 + 0 +LAYER + 5 +4C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-FIXT + 70 +0 + 62 +4 + 6 +Continuous +370 +18 +390 +13 +347 +21 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 +3 + 0 +STYLE + 5 +29 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +4D +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +ARCH-TEXT + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +STYLE + 5 +4E +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +ARCH-TITLE + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +times.ttf + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 +3 + 0 +APPID + 5 +2A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 +0 + 0 +APPID + 5 +237 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +HATCHBACKGROUNDCOLOR + 70 +0 + 0 +APPID + 5 +238 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +EZDXF + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +4 +330 +0 +100 +AcDbSymbolTable + 70 +2 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +2B +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 +0 + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +0 +177 +0 +178 +0 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +371 +-2 +372 +-2 + 0 +DIMSTYLE +105 +4F +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ELEV50 + 70 +0 + 40 +1.0 + 41 +128.0 + 42 +128.0 + 43 +3.75 + 44 +96.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +160.0 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +48.0 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +3 +177 +3 +178 +2 +179 +2 +271 +0 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +340 +4D +371 +-2 +372 +-2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 +26 + 0 +BLOCK_RECORD + 5 +17 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +1A + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +50 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +DOOR +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +57 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +WINDOW +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +60 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +BED +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +67 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +TABLE +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +73 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +SOFA +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +7B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +WC +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +80 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +SINK +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +86 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +BATH +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +8B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +AXIS +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +90 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +NORTH +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +96 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +LEVEL +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +D9 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D1 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +DE +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_CLOSEDFILLED +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +EC +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D2 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +FB +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D3 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +138 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D4 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +147 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D5 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +156 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D6 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +193 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D7 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1A2 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D8 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1B1 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D9 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1E9 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D10 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1F8 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D11 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +207 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D12 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +18 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +19 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +51 +330 +50 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +DOOR + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +DOOR + 1 + + 0 +LINE + 5 +53 +330 +50 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +900.0 + 31 +0.0 + 0 +ARC + 5 +54 +330 +50 +100 +AcDbEntity + 8 +A-DOOR + 6 +DASHED +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +900.0 +100 +AcDbArc + 50 +0.0 + 51 +90.0 + 0 +LWPOLYLINE + 5 +55 +330 +50 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +900.0 + 20 +0.0 + 10 +900.0 + 20 +40.0 + 10 +0.0 + 20 +40.0 + 0 +ATTDEF + 5 +56 +330 +50 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +350.0 + 20 +-330.0 + 30 +0.0 + 40 +110.0 + 1 +D-000 +100 +AcDbAttributeDefinition + 3 + + 2 +TAG + 70 +0 + 71 +1 + 72 +0 + 0 +ENDBLK + 5 +52 +330 +50 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +58 +330 +57 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +WINDOW + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +WINDOW + 1 + + 0 +LINE + 5 +5A +330 +57 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +1.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +5B +330 +57 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.35 + 30 +0.0 + 11 +1.0 + 21 +0.35 + 31 +0.0 + 0 +LINE + 5 +5C +330 +57 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.65 + 30 +0.0 + 11 +1.0 + 21 +0.65 + 31 +0.0 + 0 +LINE + 5 +5D +330 +57 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +1.0 + 30 +0.0 + 11 +1.0 + 21 +1.0 + 31 +0.0 + 0 +LINE + 5 +5E +330 +57 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +1.0 + 31 +0.0 + 0 +LINE + 5 +5F +330 +57 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +1.0 + 20 +0.0 + 30 +0.0 + 11 +1.0 + 21 +1.0 + 31 +0.0 + 0 +ENDBLK + 5 +59 +330 +57 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +61 +330 +60 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +BED + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +BED + 1 + + 0 +LWPOLYLINE + 5 +63 +330 +60 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1600.0 + 20 +0.0 + 10 +1600.0 + 20 +2000.0 + 10 +0.0 + 20 +2000.0 + 0 +LWPOLYLINE + 5 +64 +330 +60 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +80.0 + 20 +1300.0 + 10 +760.0 + 20 +1300.0 + 10 +760.0 + 20 +1920.0 + 10 +80.0 + 20 +1920.0 + 0 +LWPOLYLINE + 5 +65 +330 +60 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +1300.0 + 10 +1520.0 + 20 +1300.0 + 10 +1520.0 + 20 +1920.0 + 10 +840.0 + 20 +1920.0 + 0 +LINE + 5 +66 +330 +60 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbLine + 10 +0.0 + 20 +1200.0 + 30 +0.0 + 11 +1600.0 + 21 +1200.0 + 31 +0.0 + 0 +ENDBLK + 5 +62 +330 +60 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +68 +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +TABLE + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +TABLE + 1 + + 0 +LWPOLYLINE + 5 +6A +330 +67 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1800.0 + 20 +0.0 + 10 +1800.0 + 20 +900.0 + 10 +0.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +6B +330 +67 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +-450.0 + 10 +550.0 + 20 +-450.0 + 10 +550.0 + 20 +-50.0 + 10 +150.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +6C +330 +67 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +950.0 + 10 +550.0 + 20 +950.0 + 10 +550.0 + 20 +1350.0 + 10 +150.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +6D +330 +67 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +600.0 + 20 +-450.0 + 10 +1000.0 + 20 +-450.0 + 10 +1000.0 + 20 +-50.0 + 10 +600.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +6E +330 +67 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +600.0 + 20 +950.0 + 10 +1000.0 + 20 +950.0 + 10 +1000.0 + 20 +1350.0 + 10 +600.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +6F +330 +67 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1050.0 + 20 +-450.0 + 10 +1450.0 + 20 +-450.0 + 10 +1450.0 + 20 +-50.0 + 10 +1050.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +70 +330 +67 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1050.0 + 20 +950.0 + 10 +1450.0 + 20 +950.0 + 10 +1450.0 + 20 +1350.0 + 10 +1050.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +71 +330 +67 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1500.0 + 20 +-450.0 + 10 +1900.0 + 20 +-450.0 + 10 +1900.0 + 20 +-50.0 + 10 +1500.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +72 +330 +67 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1500.0 + 20 +950.0 + 10 +1900.0 + 20 +950.0 + 10 +1900.0 + 20 +1350.0 + 10 +1500.0 + 20 +1350.0 + 0 +ENDBLK + 5 +69 +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +74 +330 +73 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +SOFA + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +SOFA + 1 + + 0 +LWPOLYLINE + 5 +76 +330 +73 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +2200.0 + 20 +0.0 + 10 +2200.0 + 20 +950.0 + 10 +0.0 + 20 +950.0 + 0 +LWPOLYLINE + 5 +77 +330 +73 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +2200.0 + 20 +0.0 + 10 +2200.0 + 20 +250.0 + 10 +0.0 + 20 +250.0 + 0 +LWPOLYLINE + 5 +78 +330 +73 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +120.0 + 20 +300.0 + 10 +720.0 + 20 +300.0 + 10 +720.0 + 20 +900.0 + 10 +120.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +79 +330 +73 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +770.0 + 20 +300.0 + 10 +1370.0 + 20 +300.0 + 10 +1370.0 + 20 +900.0 + 10 +770.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +7A +330 +73 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1420.0 + 20 +300.0 + 10 +2020.0 + 20 +300.0 + 10 +2020.0 + 20 +900.0 + 10 +1420.0 + 20 +900.0 + 0 +ENDBLK + 5 +75 +330 +73 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +7C +330 +7B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +WC + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +WC + 1 + + 0 +LWPOLYLINE + 5 +7E +330 +7B +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +400.0 + 20 +0.0 + 10 +400.0 + 20 +200.0 + 10 +0.0 + 20 +200.0 + 0 +ELLIPSE + 5 +7F +330 +7B +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbEllipse + 10 +200.0 + 20 +-250.0 + 30 +0.0 + 11 +0.0 + 21 +230.0 + 31 +0.0 + 40 +0.8 + 41 +0.0 + 42 +6.283185307179586 + 0 +ENDBLK + 5 +7D +330 +7B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +81 +330 +80 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +SINK + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +SINK + 1 + + 0 +LWPOLYLINE + 5 +83 +330 +80 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +600.0 + 20 +0.0 + 10 +600.0 + 20 +450.0 + 10 +0.0 + 20 +450.0 + 0 +CIRCLE + 5 +84 +330 +80 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbCircle + 10 +300.0 + 20 +225.0 + 30 +0.0 + 40 +160.0 + 0 +CIRCLE + 5 +85 +330 +80 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbCircle + 10 +300.0 + 20 +225.0 + 30 +0.0 + 40 +25.0 + 0 +ENDBLK + 5 +82 +330 +80 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +87 +330 +86 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +BATH + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +BATH + 1 + + 0 +LWPOLYLINE + 5 +89 +330 +86 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1700.0 + 20 +0.0 + 10 +1700.0 + 20 +750.0 + 10 +0.0 + 20 +750.0 + 0 +LWPOLYLINE + 5 +8A +330 +86 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +5 + 70 +1 + 10 +100.0 + 20 +100.0 + 10 +1500.0 + 20 +100.0 + 10 +1600.0 + 20 +375.0 + 10 +1500.0 + 20 +650.0 + 10 +100.0 + 20 +650.0 + 0 +ENDBLK + 5 +88 +330 +86 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8C +330 +8B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +AXIS + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +AXIS + 1 + + 0 +CIRCLE + 5 +8E +330 +8B +100 +AcDbEntity + 8 +A-GRID +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +300.0 + 0 +ATTDEF + 5 +8F +330 +8B +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +300.0 + 1 +A + 72 +4 + 11 +0.0 + 21 +0.0 + 31 +0.0 +100 +AcDbAttributeDefinition + 3 + + 2 +ID + 70 +0 + 71 +1 + 72 +0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +8D +330 +8B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +91 +330 +90 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +NORTH + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +NORTH + 1 + + 0 +CIRCLE + 5 +93 +330 +90 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +500.0 + 0 +SOLID + 5 +94 +330 +90 +100 +AcDbEntity + 8 +A-ANNO + 62 +7 +100 +AcDbTrace + 10 +0.0 + 20 +650.0 + 30 +0.0 + 11 +-170.0 + 21 +-400.0 + 31 +0.0 + 12 +0.0 + 22 +-200.0 + 32 +0.0 + 13 +170.0 + 23 +-400.0 + 33 +0.0 + 0 +TEXT + 5 +95 +330 +90 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +0.0 + 20 +800.0 + 30 +0.0 + 40 +300.0 + 1 +N + 72 +1 + 11 +0.0 + 21 +800.0 + 31 +0.0 +100 +AcDbText + 73 +1 + 0 +ENDBLK + 5 +92 +330 +90 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +97 +330 +96 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +LEVEL + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +LEVEL + 1 + + 0 +LWPOLYLINE + 5 +99 +330 +96 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbPolyline + 90 +3 + 70 +1 + 10 +-250.0 + 20 +250.0 + 10 +0.0 + 20 +0.0 + 10 +250.0 + 20 +250.0 + 0 +LINE + 5 +9A +330 +96 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbLine + 10 +-250.0 + 20 +250.0 + 30 +0.0 + 11 +900.0 + 21 +250.0 + 31 +0.0 + 0 +ATTDEF + 5 +9B +330 +96 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +320.0 + 20 +290.0 + 30 +0.0 + 40 +120.0 + 1 ++0.00 +100 +AcDbAttributeDefinition + 3 + + 2 +H + 70 +0 + 71 +1 + 72 +0 + 0 +ENDBLK + 5 +98 +330 +96 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +DA +330 +D9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D1 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D1 + 1 + + 0 +LINE + 5 +DC +330 +D9 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-128.0 + 20 +0.0 + 30 +0.0 + 11 +-1996.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +DD +330 +D9 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-128.0 + 20 +5400.0 + 30 +0.0 + 11 +-1996.0 + 21 +5400.0 + 31 +0.0 + 0 +INSERT + 5 +E2 +330 +D9 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-1900.0 + 20 +0.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +270.0 + 0 +INSERT + 5 +E4 +330 +D9 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-1900.0 + 20 +5400.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +90.0 + 0 +LINE + 5 +E6 +330 +D9 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-1900.0 + 20 +128.0 + 30 +0.0 + 11 +-1900.0 + 21 +5272.0 + 31 +0.0 + 0 +MTEXT + 5 +E7 +330 +D9 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +-2028.0 + 20 +2700.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +5400 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +E8 +330 +D9 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-1900.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +E9 +330 +D9 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +EA +330 +D9 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +5400.0 + 30 +0.0 + 0 +ENDBLK + 5 +DB +330 +D9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +DF +330 +DE +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_CLOSEDFILLED + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_CLOSEDFILLED + 1 + + 0 +SOLID + 5 +E1 +330 +DE +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 +0 +100 +AcDbTrace + 10 +-1.0 + 20 +0.16439898372402537 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 12 +-1.0 + 22 +-0.16439898372402537 + 32 +0.0 + 13 +-1.0 + 23 +-0.16439898372402537 + 33 +0.0 + 0 +ENDBLK + 5 +E0 +330 +DE +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +ED +330 +EC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D2 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D2 + 1 + + 0 +LINE + 5 +EF +330 +EC +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-128.0 + 20 +5400.0 + 30 +0.0 + 11 +-1996.0 + 21 +5400.0 + 31 +0.0 + 0 +LINE + 5 +F0 +330 +EC +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-128.0 + 20 +8300.0 + 30 +0.0 + 11 +-1996.0 + 21 +8300.0 + 31 +0.0 + 0 +INSERT + 5 +F1 +330 +EC +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-1900.0 + 20 +5400.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +270.0 + 0 +INSERT + 5 +F3 +330 +EC +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-1900.0 + 20 +8300.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +90.0 + 0 +LINE + 5 +F5 +330 +EC +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-1900.0 + 20 +5528.0 + 30 +0.0 + 11 +-1900.0 + 21 +8172.0 + 31 +0.0 + 0 +MTEXT + 5 +F6 +330 +EC +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +-2028.0 + 20 +6850.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +2900 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +F7 +330 +EC +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-1900.0 + 20 +5400.0 + 30 +0.0 + 0 +POINT + 5 +F8 +330 +EC +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +5400.0 + 30 +0.0 + 0 +POINT + 5 +F9 +330 +EC +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +8300.0 + 30 +0.0 + 0 +ENDBLK + 5 +EE +330 +EC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +FC +330 +FB +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D3 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D3 + 1 + + 0 +LINE + 5 +FE +330 +FB +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +-128.0 + 30 +0.0 + 11 +0.0 + 21 +-1196.0 + 31 +0.0 + 0 +LINE + 5 +FF +330 +FB +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +10000.0 + 20 +-128.0 + 30 +0.0 + 11 +10000.0 + 21 +-1196.0 + 31 +0.0 + 0 +INSERT + 5 +100 +330 +FB +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +-1100.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +180.0 + 0 +INSERT + 5 +102 +330 +FB +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +10000.0 + 20 +-1100.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 0 +LINE + 5 +104 +330 +FB +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +128.0 + 20 +-1100.0 + 30 +0.0 + 11 +9872.0 + 21 +-1100.0 + 31 +0.0 + 0 +MTEXT + 5 +105 +330 +FB +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +5000.0 + 20 +-972.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +10000 + 7 +ARCH-TEXT + 0 +POINT + 5 +106 +330 +FB +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-1100.0 + 30 +0.0 + 0 +POINT + 5 +107 +330 +FB +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +108 +330 +FB +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +10000.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +FD +330 +FB +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +139 +330 +138 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D4 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D4 + 1 + + 0 +LINE + 5 +13B +330 +138 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +15872.0 + 20 +0.0 + 30 +0.0 + 11 +14004.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +13C +330 +138 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +15872.0 + 20 +5400.0 + 30 +0.0 + 11 +14004.0 + 21 +5400.0 + 31 +0.0 + 0 +INSERT + 5 +13D +330 +138 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +14100.0 + 20 +0.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +270.0 + 0 +INSERT + 5 +13F +330 +138 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +14100.0 + 20 +5400.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +90.0 + 0 +LINE + 5 +141 +330 +138 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +14100.0 + 20 +128.0 + 30 +0.0 + 11 +14100.0 + 21 +5272.0 + 31 +0.0 + 0 +MTEXT + 5 +142 +330 +138 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +13972.0 + 20 +2700.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +5400 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +143 +330 +138 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +14100.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +144 +330 +138 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +145 +330 +138 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +5400.0 + 30 +0.0 + 0 +ENDBLK + 5 +13A +330 +138 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +148 +330 +147 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D5 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D5 + 1 + + 0 +LINE + 5 +14A +330 +147 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +15872.0 + 20 +5400.0 + 30 +0.0 + 11 +14004.0 + 21 +5400.0 + 31 +0.0 + 0 +LINE + 5 +14B +330 +147 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +15872.0 + 20 +8300.0 + 30 +0.0 + 11 +14004.0 + 21 +8300.0 + 31 +0.0 + 0 +INSERT + 5 +14C +330 +147 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +14100.0 + 20 +5400.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +270.0 + 0 +INSERT + 5 +14E +330 +147 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +14100.0 + 20 +8300.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +90.0 + 0 +LINE + 5 +150 +330 +147 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +14100.0 + 20 +5528.0 + 30 +0.0 + 11 +14100.0 + 21 +8172.0 + 31 +0.0 + 0 +MTEXT + 5 +151 +330 +147 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +13972.0 + 20 +6850.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +2900 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +152 +330 +147 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +14100.0 + 20 +5400.0 + 30 +0.0 + 0 +POINT + 5 +153 +330 +147 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +5400.0 + 30 +0.0 + 0 +POINT + 5 +154 +330 +147 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +8300.0 + 30 +0.0 + 0 +ENDBLK + 5 +149 +330 +147 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +157 +330 +156 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D6 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D6 + 1 + + 0 +LINE + 5 +159 +330 +156 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +16000.0 + 20 +-128.0 + 30 +0.0 + 11 +16000.0 + 21 +-1196.0 + 31 +0.0 + 0 +LINE + 5 +15A +330 +156 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +24000.0 + 20 +-128.0 + 30 +0.0 + 11 +24000.0 + 21 +-1196.0 + 31 +0.0 + 0 +INSERT + 5 +15B +330 +156 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +16000.0 + 20 +-1100.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +180.0 + 0 +INSERT + 5 +15D +330 +156 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +24000.0 + 20 +-1100.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 0 +LINE + 5 +15F +330 +156 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +16128.0 + 20 +-1100.0 + 30 +0.0 + 11 +23872.0 + 21 +-1100.0 + 31 +0.0 + 0 +MTEXT + 5 +160 +330 +156 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +20000.0 + 20 +-972.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +8000 + 7 +ARCH-TEXT + 0 +POINT + 5 +161 +330 +156 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +-1100.0 + 30 +0.0 + 0 +POINT + 5 +162 +330 +156 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +163 +330 +156 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +24000.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +158 +330 +156 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +194 +330 +193 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D7 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D7 + 1 + + 0 +LINE + 5 +196 +330 +193 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-128.0 + 20 +-17000.0 + 30 +0.0 + 11 +-1996.0 + 21 +-17000.0 + 31 +0.0 + 0 +LINE + 5 +197 +330 +193 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-128.0 + 20 +-11600.0 + 30 +0.0 + 11 +-1996.0 + 21 +-11600.0 + 31 +0.0 + 0 +INSERT + 5 +198 +330 +193 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-1900.0 + 20 +-17000.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +270.0 + 0 +INSERT + 5 +19A +330 +193 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-1900.0 + 20 +-11600.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +90.0 + 0 +LINE + 5 +19C +330 +193 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-1900.0 + 20 +-16872.0 + 30 +0.0 + 11 +-1900.0 + 21 +-11728.0 + 31 +0.0 + 0 +MTEXT + 5 +19D +330 +193 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +-2028.0 + 20 +-14300.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +5400 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +19E +330 +193 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-1900.0 + 20 +-17000.0 + 30 +0.0 + 0 +POINT + 5 +19F +330 +193 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-17000.0 + 30 +0.0 + 0 +POINT + 5 +1A0 +330 +193 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-11600.0 + 30 +0.0 + 0 +ENDBLK + 5 +195 +330 +193 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1A3 +330 +1A2 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D8 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D8 + 1 + + 0 +LINE + 5 +1A5 +330 +1A2 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-128.0 + 20 +-11600.0 + 30 +0.0 + 11 +-1996.0 + 21 +-11600.0 + 31 +0.0 + 0 +LINE + 5 +1A6 +330 +1A2 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-128.0 + 20 +-8700.0 + 30 +0.0 + 11 +-1996.0 + 21 +-8700.0 + 31 +0.0 + 0 +INSERT + 5 +1A7 +330 +1A2 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-1900.0 + 20 +-11600.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +270.0 + 0 +INSERT + 5 +1A9 +330 +1A2 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-1900.0 + 20 +-8700.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +90.0 + 0 +LINE + 5 +1AB +330 +1A2 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-1900.0 + 20 +-11472.0 + 30 +0.0 + 11 +-1900.0 + 21 +-8828.0 + 31 +0.0 + 0 +MTEXT + 5 +1AC +330 +1A2 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +-2028.0 + 20 +-10150.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +2900 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +1AD +330 +1A2 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-1900.0 + 20 +-11600.0 + 30 +0.0 + 0 +POINT + 5 +1AE +330 +1A2 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-11600.0 + 30 +0.0 + 0 +POINT + 5 +1AF +330 +1A2 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-8700.0 + 30 +0.0 + 0 +ENDBLK + 5 +1A4 +330 +1A2 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1B2 +330 +1B1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D9 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D9 + 1 + + 0 +LINE + 5 +1B4 +330 +1B1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +-17128.0 + 30 +0.0 + 11 +0.0 + 21 +-18196.0 + 31 +0.0 + 0 +LINE + 5 +1B5 +330 +1B1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +10000.0 + 20 +-17128.0 + 30 +0.0 + 11 +10000.0 + 21 +-18196.0 + 31 +0.0 + 0 +INSERT + 5 +1B6 +330 +1B1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +-18100.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +180.0 + 0 +INSERT + 5 +1B8 +330 +1B1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +10000.0 + 20 +-18100.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 0 +LINE + 5 +1BA +330 +1B1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +128.0 + 20 +-18100.0 + 30 +0.0 + 11 +9872.0 + 21 +-18100.0 + 31 +0.0 + 0 +MTEXT + 5 +1BB +330 +1B1 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +5000.0 + 20 +-17972.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +10000 + 7 +ARCH-TEXT + 0 +POINT + 5 +1BC +330 +1B1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-18100.0 + 30 +0.0 + 0 +POINT + 5 +1BD +330 +1B1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-17000.0 + 30 +0.0 + 0 +POINT + 5 +1BE +330 +1B1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +10000.0 + 20 +-17000.0 + 30 +0.0 + 0 +ENDBLK + 5 +1B3 +330 +1B1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1EA +330 +1E9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D10 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D10 + 1 + + 0 +LINE + 5 +1EC +330 +1E9 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +15872.0 + 20 +-17000.0 + 30 +0.0 + 11 +14004.0 + 21 +-17000.0 + 31 +0.0 + 0 +LINE + 5 +1ED +330 +1E9 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +15872.0 + 20 +-11600.0 + 30 +0.0 + 11 +14004.0 + 21 +-11600.0 + 31 +0.0 + 0 +INSERT + 5 +1EE +330 +1E9 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +14100.0 + 20 +-17000.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +270.0 + 0 +INSERT + 5 +1F0 +330 +1E9 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +14100.0 + 20 +-11600.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +90.0 + 0 +LINE + 5 +1F2 +330 +1E9 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +14100.0 + 20 +-16872.0 + 30 +0.0 + 11 +14100.0 + 21 +-11728.0 + 31 +0.0 + 0 +MTEXT + 5 +1F3 +330 +1E9 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +13972.0 + 20 +-14300.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +5400 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +1F4 +330 +1E9 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +14100.0 + 20 +-17000.0 + 30 +0.0 + 0 +POINT + 5 +1F5 +330 +1E9 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +-17000.0 + 30 +0.0 + 0 +POINT + 5 +1F6 +330 +1E9 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +-11600.0 + 30 +0.0 + 0 +ENDBLK + 5 +1EB +330 +1E9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1F9 +330 +1F8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D11 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D11 + 1 + + 0 +LINE + 5 +1FB +330 +1F8 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +15872.0 + 20 +-11600.0 + 30 +0.0 + 11 +14004.0 + 21 +-11600.0 + 31 +0.0 + 0 +LINE + 5 +1FC +330 +1F8 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +15872.0 + 20 +-8700.0 + 30 +0.0 + 11 +14004.0 + 21 +-8700.0 + 31 +0.0 + 0 +INSERT + 5 +1FD +330 +1F8 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +14100.0 + 20 +-11600.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +270.0 + 0 +INSERT + 5 +1FF +330 +1F8 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +14100.0 + 20 +-8700.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +90.0 + 0 +LINE + 5 +201 +330 +1F8 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +14100.0 + 20 +-11472.0 + 30 +0.0 + 11 +14100.0 + 21 +-8828.0 + 31 +0.0 + 0 +MTEXT + 5 +202 +330 +1F8 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +13972.0 + 20 +-10150.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +2900 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +203 +330 +1F8 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +14100.0 + 20 +-11600.0 + 30 +0.0 + 0 +POINT + 5 +204 +330 +1F8 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +-11600.0 + 30 +0.0 + 0 +POINT + 5 +205 +330 +1F8 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +-8700.0 + 30 +0.0 + 0 +ENDBLK + 5 +1FA +330 +1F8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +208 +330 +207 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D12 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D12 + 1 + + 0 +LINE + 5 +20A +330 +207 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +16000.0 + 20 +-17128.0 + 30 +0.0 + 11 +16000.0 + 21 +-18196.0 + 31 +0.0 + 0 +LINE + 5 +20B +330 +207 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +24000.0 + 20 +-17128.0 + 30 +0.0 + 11 +24000.0 + 21 +-18196.0 + 31 +0.0 + 0 +INSERT + 5 +20C +330 +207 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +16000.0 + 20 +-18100.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 50 +180.0 + 0 +INSERT + 5 +20E +330 +207 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +24000.0 + 20 +-18100.0 + 30 +0.0 + 41 +128.0 + 42 +128.0 + 0 +LINE + 5 +210 +330 +207 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +16128.0 + 20 +-18100.0 + 30 +0.0 + 11 +23872.0 + 21 +-18100.0 + 31 +0.0 + 0 +MTEXT + 5 +211 +330 +207 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +20000.0 + 20 +-17972.0 + 30 +0.0 + 40 +160.0 + 71 +5 + 1 +8000 + 7 +ARCH-TEXT + 0 +POINT + 5 +212 +330 +207 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +-18100.0 + 30 +0.0 + 0 +POINT + 5 +213 +330 +207 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +16000.0 + 20 +-17000.0 + 30 +0.0 + 0 +POINT + 5 +214 +330 +207 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +24000.0 + 20 +-17000.0 + 30 +0.0 + 0 +ENDBLK + 5 +209 +330 +207 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LWPOLYLINE + 5 +9C +330 +17 +100 +AcDbEntity + 8 +E-GROUND +370 +70 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +-1500.0 + 20 +0.0 + 10 +11500.0 + 20 +0.0 + 0 +HATCH + 5 +9D +330 +17 +100 +AcDbEntity + 8 +E-GROUND + 62 +3 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +EARTH + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +-1500.0 + 20 +-600.0 + 10 +11500.0 + 20 +-600.0 + 10 +11500.0 + 20 +0.0 + 10 +-1500.0 + 20 +0.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +60.0 + 77 +0 + 78 +6 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +0.0 + 43 +0.0 + 44 +142.875 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +0.0 + 43 +0.0 + 44 +285.75 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +47.625 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +190.5 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +333.375 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 98 +0 + 0 +LWPOLYLINE + 5 +9E +330 +17 +100 +AcDbEntity + 8 +E-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +10000.0 + 20 +0.0 + 10 +10000.0 + 20 +5400.0 + 10 +0.0 + 20 +5400.0 + 0 +HATCH + 5 +9F +330 +17 +100 +AcDbEntity + 8 +E-RENDER + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-SAND + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +0.0 + 10 +10000.0 + 20 +0.0 + 10 +10000.0 + 20 +5400.0 + 10 +0.0 + 20 +5400.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +15.0 + 77 +0 + 78 +4 + 53 +37.5 + 43 +0.0 + 44 +0.0 + 45 +-24.00046944 + 46 +734.1198559935 + 79 +6 + 49 +0.0 + 49 +-579.12 + 49 +0.0 + 49 +-647.7 + 49 +0.0 + 49 +-619.125 + 53 +7.5 + 43 +0.0 + 44 +0.0 + 45 +674.284924707 + 46 +1075.237650852 + 79 +6 + 49 +0.0 + 49 +-312.42 + 49 +0.0 + 49 +-521.97 + 49 +0.0 + 49 +-200.025 + 53 +-32.5 + 43 +-468.63 + 44 +0.0 + 45 +1186.4885553615 + 46 +2.1557770185 + 79 +6 + 49 +0.0 + 49 +-190.5 + 49 +0.0 + 49 +-685.8 + 49 +0.0 + 49 +-895.35 + 53 +-42.5 + 43 +-468.63 + 44 +0.0 + 45 +1145.334678708 + 46 +334.3939848855 + 79 +6 + 49 +0.0 + 49 +-95.25 + 49 +0.0 + 49 +-449.58 + 49 +0.0 + 49 +-514.35 + 98 +0 + 0 +LWPOLYLINE + 5 +A0 +330 +17 +100 +AcDbEntity + 8 +E-PLINTH +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +10000.0 + 20 +0.0 + 10 +10000.0 + 20 +450.0 + 10 +0.0 + 20 +450.0 + 0 +LWPOLYLINE + 5 +A1 +330 +17 +100 +AcDbEntity + 8 +E-ROOF +370 +50 +100 +AcDbPolyline + 90 +3 + 70 +1 + 10 +-450.0 + 20 +5400.0 + 10 +5000.0 + 20 +8300.0 + 10 +10450.0 + 20 +5400.0 + 0 +HATCH + 5 +A2 +330 +17 +100 +AcDbEntity + 8 +E-ROOF + 62 +1 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-RROOF + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +3 + 10 +-450.0 + 20 +5400.0 + 10 +5000.0 + 20 +8300.0 + 10 +10450.0 + 20 +5400.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +60.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +3352.8 + 46 +1524.0 + 79 +4 + 49 +22860.0 + 49 +-3048.0 + 49 +7620.0 + 49 +-1524.0 + 53 +0.0 + 43 +2026.92 + 44 +762.0 + 45 +-1524.0 + 46 +2026.92 + 79 +4 + 49 +4572.0 + 49 +-502.92 + 49 +9144.0 + 49 +-1143.0 + 53 +0.0 + 43 +762.0 + 44 +1295.4 + 45 +7924.8 + 46 +1021.08 + 79 +4 + 49 +12192.0 + 49 +-2133.6 + 49 +6096.0 + 49 +-1524.0 + 98 +0 + 0 +LINE + 5 +A3 +330 +17 +100 +AcDbEntity + 8 +E-FLOOR + 6 +DASHDOT +100 +AcDbLine + 10 +0.0 + 20 +2700.0 + 30 +0.0 + 11 +10000.0 + 21 +2700.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +A4 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3600.0 + 20 +1100.0 + 10 +4500.0 + 20 +1100.0 + 10 +4500.0 + 20 +2400.0 + 10 +3600.0 + 20 +2400.0 + 0 +LWPOLYLINE + 5 +A5 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3660.0 + 20 +1160.0 + 10 +4440.0 + 20 +1160.0 + 10 +4440.0 + 20 +2340.0 + 10 +3660.0 + 20 +2340.0 + 0 +LINE + 5 +A6 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +4050.0 + 20 +1160.0 + 30 +0.0 + 11 +4050.0 + 21 +2340.0 + 31 +0.0 + 0 +HATCH + 5 +A7 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +3660.0 + 20 +1160.0 + 10 +4440.0 + 20 +1160.0 + 10 +4440.0 + 20 +2340.0 + 10 +3660.0 + 20 +2340.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +A8 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3520.0 + 20 +1010.0 + 10 +4580.0 + 20 +1010.0 + 10 +4580.0 + 20 +1100.0 + 10 +3520.0 + 20 +1100.0 + 0 +LWPOLYLINE + 5 +A9 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6200.0 + 20 +1100.0 + 10 +7100.0 + 20 +1100.0 + 10 +7100.0 + 20 +2400.0 + 10 +6200.0 + 20 +2400.0 + 0 +LWPOLYLINE + 5 +AA +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6260.0 + 20 +1160.0 + 10 +7040.0 + 20 +1160.0 + 10 +7040.0 + 20 +2340.0 + 10 +6260.0 + 20 +2340.0 + 0 +LINE + 5 +AB +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +6650.0 + 20 +1160.0 + 30 +0.0 + 11 +6650.0 + 21 +2340.0 + 31 +0.0 + 0 +HATCH + 5 +AC +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6260.0 + 20 +1160.0 + 10 +7040.0 + 20 +1160.0 + 10 +7040.0 + 20 +2340.0 + 10 +6260.0 + 20 +2340.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +AD +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6120.0 + 20 +1010.0 + 10 +7180.0 + 20 +1010.0 + 10 +7180.0 + 20 +1100.0 + 10 +6120.0 + 20 +1100.0 + 0 +LWPOLYLINE + 5 +AE +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +8200.0 + 20 +1100.0 + 10 +9400.0 + 20 +1100.0 + 10 +9400.0 + 20 +2400.0 + 10 +8200.0 + 20 +2400.0 + 0 +LWPOLYLINE + 5 +AF +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +8260.0 + 20 +1160.0 + 10 +9340.0 + 20 +1160.0 + 10 +9340.0 + 20 +2340.0 + 10 +8260.0 + 20 +2340.0 + 0 +LINE + 5 +B0 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +8800.0 + 20 +1160.0 + 30 +0.0 + 11 +8800.0 + 21 +2340.0 + 31 +0.0 + 0 +HATCH + 5 +B1 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +8260.0 + 20 +1160.0 + 10 +9340.0 + 20 +1160.0 + 10 +9340.0 + 20 +2340.0 + 10 +8260.0 + 20 +2340.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +B2 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +8120.0 + 20 +1010.0 + 10 +9480.0 + 20 +1010.0 + 10 +9480.0 + 20 +1100.0 + 10 +8120.0 + 20 +1100.0 + 0 +LWPOLYLINE + 5 +B3 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +800.0 + 20 +3400.0 + 10 +1800.0 + 20 +3400.0 + 10 +1800.0 + 20 +4800.0 + 10 +800.0 + 20 +4800.0 + 0 +LWPOLYLINE + 5 +B4 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +860.0 + 20 +3460.0 + 10 +1740.0 + 20 +3460.0 + 10 +1740.0 + 20 +4740.0 + 10 +860.0 + 20 +4740.0 + 0 +LINE + 5 +B5 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +1300.0 + 20 +3460.0 + 30 +0.0 + 11 +1300.0 + 21 +4740.0 + 31 +0.0 + 0 +HATCH + 5 +B6 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +860.0 + 20 +3460.0 + 10 +1740.0 + 20 +3460.0 + 10 +1740.0 + 20 +4740.0 + 10 +860.0 + 20 +4740.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +B7 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +720.0 + 20 +3310.0 + 10 +1880.0 + 20 +3310.0 + 10 +1880.0 + 20 +3400.0 + 10 +720.0 + 20 +3400.0 + 0 +LWPOLYLINE + 5 +B8 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3600.0 + 20 +3400.0 + 10 +4500.0 + 20 +3400.0 + 10 +4500.0 + 20 +4800.0 + 10 +3600.0 + 20 +4800.0 + 0 +LWPOLYLINE + 5 +B9 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3660.0 + 20 +3460.0 + 10 +4440.0 + 20 +3460.0 + 10 +4440.0 + 20 +4740.0 + 10 +3660.0 + 20 +4740.0 + 0 +LINE + 5 +BA +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +4050.0 + 20 +3460.0 + 30 +0.0 + 11 +4050.0 + 21 +4740.0 + 31 +0.0 + 0 +HATCH + 5 +BB +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +3660.0 + 20 +3460.0 + 10 +4440.0 + 20 +3460.0 + 10 +4440.0 + 20 +4740.0 + 10 +3660.0 + 20 +4740.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +BC +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3520.0 + 20 +3310.0 + 10 +4580.0 + 20 +3310.0 + 10 +4580.0 + 20 +3400.0 + 10 +3520.0 + 20 +3400.0 + 0 +LWPOLYLINE + 5 +BD +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6200.0 + 20 +3400.0 + 10 +7100.0 + 20 +3400.0 + 10 +7100.0 + 20 +4800.0 + 10 +6200.0 + 20 +4800.0 + 0 +LWPOLYLINE + 5 +BE +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6260.0 + 20 +3460.0 + 10 +7040.0 + 20 +3460.0 + 10 +7040.0 + 20 +4740.0 + 10 +6260.0 + 20 +4740.0 + 0 +LINE + 5 +BF +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +6650.0 + 20 +3460.0 + 30 +0.0 + 11 +6650.0 + 21 +4740.0 + 31 +0.0 + 0 +HATCH + 5 +C0 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6260.0 + 20 +3460.0 + 10 +7040.0 + 20 +3460.0 + 10 +7040.0 + 20 +4740.0 + 10 +6260.0 + 20 +4740.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +C1 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6120.0 + 20 +3310.0 + 10 +7180.0 + 20 +3310.0 + 10 +7180.0 + 20 +3400.0 + 10 +6120.0 + 20 +3400.0 + 0 +LWPOLYLINE + 5 +C2 +330 +17 +100 +AcDbEntity + 8 +E-DOOR +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1400.0 + 20 +0.0 + 10 +2900.0 + 20 +0.0 + 10 +2900.0 + 20 +2300.0 + 10 +1400.0 + 20 +2300.0 + 0 +LWPOLYLINE + 5 +C3 +330 +17 +100 +AcDbEntity + 8 +E-DOOR +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1500.0 + 20 +100.0 + 10 +2800.0 + 20 +100.0 + 10 +2800.0 + 20 +2200.0 + 10 +1500.0 + 20 +2200.0 + 0 +CIRCLE + 5 +C4 +330 +17 +100 +AcDbEntity + 8 +E-DOOR +100 +AcDbCircle + 10 +2700.0 + 20 +1000.0 + 30 +0.0 + 40 +40.0 + 0 +LWPOLYLINE + 5 +C5 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1250.0 + 20 +300.0 + 10 +3050.0 + 20 +300.0 + 10 +3050.0 + 20 +450.0 + 10 +1250.0 + 20 +450.0 + 0 +LWPOLYLINE + 5 +C6 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1130.0 + 20 +150.0 + 10 +3170.0 + 20 +150.0 + 10 +3170.0 + 20 +300.0 + 10 +1130.0 + 20 +300.0 + 0 +LWPOLYLINE + 5 +C7 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1010.0 + 20 +0.0 + 10 +3290.0 + 20 +0.0 + 10 +3290.0 + 20 +150.0 + 10 +1010.0 + 20 +150.0 + 0 +INSERT + 5 +C8 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +11900.0 + 20 +0.0 + 30 +0.0 + 0 +ATTRIB + 5 +CA +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +12220.0 + 20 +290.0 + 30 +0.0 + 40 +120.0 + 1 ++0.00 + 11 +12220.0 + 21 +290.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +12220.0 + 21 +290.0 + 31 +0.0 + 0 +SEQEND + 5 +C9 +330 +C8 +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +CB +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +10000.0 + 20 +0.0 + 30 +0.0 + 11 +11900.0 + 21 +0.0 + 31 +0.0 + 0 +INSERT + 5 +CC +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +11900.0 + 20 +2700.0 + 30 +0.0 + 0 +ATTRIB + 5 +CE +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +12220.0 + 20 +2990.0 + 30 +0.0 + 40 +120.0 + 1 ++2.70 + 11 +12220.0 + 21 +2990.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +12220.0 + 21 +2990.0 + 31 +0.0 + 0 +SEQEND + 5 +CD +330 +CC +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +CF +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +10000.0 + 20 +2700.0 + 30 +0.0 + 11 +11900.0 + 21 +2700.0 + 31 +0.0 + 0 +INSERT + 5 +D0 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +11900.0 + 20 +5400.0 + 30 +0.0 + 0 +ATTRIB + 5 +D2 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +12220.0 + 20 +5690.0 + 30 +0.0 + 40 +120.0 + 1 ++5.40 + 11 +12220.0 + 21 +5690.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +12220.0 + 21 +5690.0 + 31 +0.0 + 0 +SEQEND + 5 +D1 +330 +D0 +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +D3 +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +10000.0 + 20 +5400.0 + 30 +0.0 + 11 +11900.0 + 21 +5400.0 + 31 +0.0 + 0 +INSERT + 5 +D4 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +11900.0 + 20 +8300.0 + 30 +0.0 + 0 +ATTRIB + 5 +D6 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +12220.0 + 20 +8590.0 + 30 +0.0 + 40 +120.0 + 1 ++8.30 + 11 +12220.0 + 21 +8590.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +12220.0 + 21 +8590.0 + 31 +0.0 + 0 +SEQEND + 5 +D5 +330 +D4 +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +D7 +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +10000.0 + 20 +8300.0 + 30 +0.0 + 11 +11900.0 + 21 +8300.0 + 31 +0.0 + 0 +DIMENSION + 5 +D8 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D1 + 3 +ELEV50 + 10 +-1900.0 + 20 +0.0 + 30 +0.0 + 11 +-2028.0 + 21 +2700.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +0.0 + 24 +5400.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +EB +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D2 + 3 +ELEV50 + 10 +-1900.0 + 20 +5400.0 + 30 +0.0 + 11 +-2028.0 + 21 +6850.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +5400.0 + 33 +0.0 + 14 +0.0 + 24 +8300.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +FA +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D3 + 3 +ELEV50 + 10 +0.0 + 20 +-1100.0 + 30 +0.0 + 11 +5000.0 + 21 +-972.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +10000.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +TEXT + 5 +109 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +0.0 + 20 +-2100.0 + 30 +0.0 + 40 +300.0 + 1 +SOUTH ELEVATION 1:50 + 7 +ARCH-TITLE + 11 +0.0 + 21 +-2100.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +10A +330 +17 +100 +AcDbEntity + 8 +A-ANNO +370 +70 +100 +AcDbLine + 10 +0.0 + 20 +-2250.0 + 30 +0.0 + 11 +3600.0 + 21 +-2250.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +10B +330 +17 +100 +AcDbEntity + 8 +E-GROUND +370 +70 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +14500.0 + 20 +0.0 + 10 +25500.0 + 20 +0.0 + 0 +HATCH + 5 +10C +330 +17 +100 +AcDbEntity + 8 +E-GROUND + 62 +3 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +EARTH + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +14500.0 + 20 +-600.0 + 10 +25500.0 + 20 +-600.0 + 10 +25500.0 + 20 +0.0 + 10 +14500.0 + 20 +0.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +60.0 + 77 +0 + 78 +6 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +0.0 + 43 +0.0 + 44 +142.875 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +0.0 + 43 +0.0 + 44 +285.75 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +47.625 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +190.5 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +333.375 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 98 +0 + 0 +LWPOLYLINE + 5 +10D +330 +17 +100 +AcDbEntity + 8 +E-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +16000.0 + 20 +0.0 + 10 +24000.0 + 20 +0.0 + 10 +24000.0 + 20 +5400.0 + 10 +16000.0 + 20 +5400.0 + 0 +HATCH + 5 +10E +330 +17 +100 +AcDbEntity + 8 +E-RENDER + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-SAND + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +16000.0 + 20 +0.0 + 10 +24000.0 + 20 +0.0 + 10 +24000.0 + 20 +5400.0 + 10 +16000.0 + 20 +5400.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +15.0 + 77 +0 + 78 +4 + 53 +37.5 + 43 +0.0 + 44 +0.0 + 45 +-24.00046944 + 46 +734.1198559935 + 79 +6 + 49 +0.0 + 49 +-579.12 + 49 +0.0 + 49 +-647.7 + 49 +0.0 + 49 +-619.125 + 53 +7.5 + 43 +0.0 + 44 +0.0 + 45 +674.284924707 + 46 +1075.237650852 + 79 +6 + 49 +0.0 + 49 +-312.42 + 49 +0.0 + 49 +-521.97 + 49 +0.0 + 49 +-200.025 + 53 +-32.5 + 43 +-468.63 + 44 +0.0 + 45 +1186.4885553615 + 46 +2.1557770185 + 79 +6 + 49 +0.0 + 49 +-190.5 + 49 +0.0 + 49 +-685.8 + 49 +0.0 + 49 +-895.35 + 53 +-42.5 + 43 +-468.63 + 44 +0.0 + 45 +1145.334678708 + 46 +334.3939848855 + 79 +6 + 49 +0.0 + 49 +-95.25 + 49 +0.0 + 49 +-449.58 + 49 +0.0 + 49 +-514.35 + 98 +0 + 0 +LWPOLYLINE + 5 +10F +330 +17 +100 +AcDbEntity + 8 +E-PLINTH +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +16000.0 + 20 +0.0 + 10 +24000.0 + 20 +0.0 + 10 +24000.0 + 20 +450.0 + 10 +16000.0 + 20 +450.0 + 0 +LWPOLYLINE + 5 +110 +330 +17 +100 +AcDbEntity + 8 +E-ROOF +370 +50 +100 +AcDbPolyline + 90 +3 + 70 +1 + 10 +15550.0 + 20 +5400.0 + 10 +20000.0 + 20 +8300.0 + 10 +24450.0 + 20 +5400.0 + 0 +HATCH + 5 +111 +330 +17 +100 +AcDbEntity + 8 +E-ROOF + 62 +1 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-RROOF + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +3 + 10 +15550.0 + 20 +5400.0 + 10 +20000.0 + 20 +8300.0 + 10 +24450.0 + 20 +5400.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +60.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +3352.8 + 46 +1524.0 + 79 +4 + 49 +22860.0 + 49 +-3048.0 + 49 +7620.0 + 49 +-1524.0 + 53 +0.0 + 43 +2026.92 + 44 +762.0 + 45 +-1524.0 + 46 +2026.92 + 79 +4 + 49 +4572.0 + 49 +-502.92 + 49 +9144.0 + 49 +-1143.0 + 53 +0.0 + 43 +762.0 + 44 +1295.4 + 45 +7924.8 + 46 +1021.08 + 79 +4 + 49 +12192.0 + 49 +-2133.6 + 49 +6096.0 + 49 +-1524.0 + 98 +0 + 0 +LINE + 5 +112 +330 +17 +100 +AcDbEntity + 8 +E-FLOOR + 6 +DASHDOT +100 +AcDbLine + 10 +16000.0 + 20 +2700.0 + 30 +0.0 + 11 +24000.0 + 21 +2700.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +113 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +17500.0 + 20 +1100.0 + 10 +18800.0 + 20 +1100.0 + 10 +18800.0 + 20 +2400.0 + 10 +17500.0 + 20 +2400.0 + 0 +LWPOLYLINE + 5 +114 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +17560.0 + 20 +1160.0 + 10 +18740.0 + 20 +1160.0 + 10 +18740.0 + 20 +2340.0 + 10 +17560.0 + 20 +2340.0 + 0 +LINE + 5 +115 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +18150.0 + 20 +1160.0 + 30 +0.0 + 11 +18150.0 + 21 +2340.0 + 31 +0.0 + 0 +HATCH + 5 +116 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +17560.0 + 20 +1160.0 + 10 +18740.0 + 20 +1160.0 + 10 +18740.0 + 20 +2340.0 + 10 +17560.0 + 20 +2340.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +117 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +17420.0 + 20 +1010.0 + 10 +18880.0 + 20 +1010.0 + 10 +18880.0 + 20 +1100.0 + 10 +17420.0 + 20 +1100.0 + 0 +LWPOLYLINE + 5 +118 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +20800.0 + 20 +1100.0 + 10 +22100.0 + 20 +1100.0 + 10 +22100.0 + 20 +2400.0 + 10 +20800.0 + 20 +2400.0 + 0 +LWPOLYLINE + 5 +119 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +20860.0 + 20 +1160.0 + 10 +22040.0 + 20 +1160.0 + 10 +22040.0 + 20 +2340.0 + 10 +20860.0 + 20 +2340.0 + 0 +LINE + 5 +11A +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +21450.0 + 20 +1160.0 + 30 +0.0 + 11 +21450.0 + 21 +2340.0 + 31 +0.0 + 0 +HATCH + 5 +11B +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +20860.0 + 20 +1160.0 + 10 +22040.0 + 20 +1160.0 + 10 +22040.0 + 20 +2340.0 + 10 +20860.0 + 20 +2340.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +11C +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +20720.0 + 20 +1010.0 + 10 +22180.0 + 20 +1010.0 + 10 +22180.0 + 20 +1100.0 + 10 +20720.0 + 20 +1100.0 + 0 +LWPOLYLINE + 5 +11D +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +17500.0 + 20 +3400.0 + 10 +18800.0 + 20 +3400.0 + 10 +18800.0 + 20 +4800.0 + 10 +17500.0 + 20 +4800.0 + 0 +LWPOLYLINE + 5 +11E +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +17560.0 + 20 +3460.0 + 10 +18740.0 + 20 +3460.0 + 10 +18740.0 + 20 +4740.0 + 10 +17560.0 + 20 +4740.0 + 0 +LINE + 5 +11F +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +18150.0 + 20 +3460.0 + 30 +0.0 + 11 +18150.0 + 21 +4740.0 + 31 +0.0 + 0 +HATCH + 5 +120 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +17560.0 + 20 +3460.0 + 10 +18740.0 + 20 +3460.0 + 10 +18740.0 + 20 +4740.0 + 10 +17560.0 + 20 +4740.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +121 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +17420.0 + 20 +3310.0 + 10 +18880.0 + 20 +3310.0 + 10 +18880.0 + 20 +3400.0 + 10 +17420.0 + 20 +3400.0 + 0 +LWPOLYLINE + 5 +122 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +20800.0 + 20 +3400.0 + 10 +22100.0 + 20 +3400.0 + 10 +22100.0 + 20 +4800.0 + 10 +20800.0 + 20 +4800.0 + 0 +LWPOLYLINE + 5 +123 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +20860.0 + 20 +3460.0 + 10 +22040.0 + 20 +3460.0 + 10 +22040.0 + 20 +4740.0 + 10 +20860.0 + 20 +4740.0 + 0 +LINE + 5 +124 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +21450.0 + 20 +3460.0 + 30 +0.0 + 11 +21450.0 + 21 +4740.0 + 31 +0.0 + 0 +HATCH + 5 +125 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +20860.0 + 20 +3460.0 + 10 +22040.0 + 20 +3460.0 + 10 +22040.0 + 20 +4740.0 + 10 +20860.0 + 20 +4740.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +126 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +20720.0 + 20 +3310.0 + 10 +22180.0 + 20 +3310.0 + 10 +22180.0 + 20 +3400.0 + 10 +20720.0 + 20 +3400.0 + 0 +INSERT + 5 +127 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +25900.0 + 20 +0.0 + 30 +0.0 + 0 +ATTRIB + 5 +129 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +26220.0 + 20 +290.0 + 30 +0.0 + 40 +120.0 + 1 ++0.00 + 11 +26220.0 + 21 +290.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +26220.0 + 21 +290.0 + 31 +0.0 + 0 +SEQEND + 5 +128 +330 +127 +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +12A +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +24000.0 + 20 +0.0 + 30 +0.0 + 11 +25900.0 + 21 +0.0 + 31 +0.0 + 0 +INSERT + 5 +12B +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +25900.0 + 20 +2700.0 + 30 +0.0 + 0 +ATTRIB + 5 +12D +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +26220.0 + 20 +2990.0 + 30 +0.0 + 40 +120.0 + 1 ++2.70 + 11 +26220.0 + 21 +2990.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +26220.0 + 21 +2990.0 + 31 +0.0 + 0 +SEQEND + 5 +12C +330 +12B +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +12E +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +24000.0 + 20 +2700.0 + 30 +0.0 + 11 +25900.0 + 21 +2700.0 + 31 +0.0 + 0 +INSERT + 5 +12F +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +25900.0 + 20 +5400.0 + 30 +0.0 + 0 +ATTRIB + 5 +131 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +26220.0 + 20 +5690.0 + 30 +0.0 + 40 +120.0 + 1 ++5.40 + 11 +26220.0 + 21 +5690.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +26220.0 + 21 +5690.0 + 31 +0.0 + 0 +SEQEND + 5 +130 +330 +12F +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +132 +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +24000.0 + 20 +5400.0 + 30 +0.0 + 11 +25900.0 + 21 +5400.0 + 31 +0.0 + 0 +INSERT + 5 +133 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +25900.0 + 20 +8300.0 + 30 +0.0 + 0 +ATTRIB + 5 +135 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +26220.0 + 20 +8590.0 + 30 +0.0 + 40 +120.0 + 1 ++8.30 + 11 +26220.0 + 21 +8590.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +26220.0 + 21 +8590.0 + 31 +0.0 + 0 +SEQEND + 5 +134 +330 +133 +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +136 +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +24000.0 + 20 +8300.0 + 30 +0.0 + 11 +25900.0 + 21 +8300.0 + 31 +0.0 + 0 +DIMENSION + 5 +137 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D4 + 3 +ELEV50 + 10 +14100.0 + 20 +0.0 + 30 +0.0 + 11 +13972.0 + 21 +2700.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +16000.0 + 23 +0.0 + 33 +0.0 + 14 +16000.0 + 24 +5400.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +146 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D5 + 3 +ELEV50 + 10 +14100.0 + 20 +5400.0 + 30 +0.0 + 11 +13972.0 + 21 +6850.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +16000.0 + 23 +5400.0 + 33 +0.0 + 14 +16000.0 + 24 +8300.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +155 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D6 + 3 +ELEV50 + 10 +16000.0 + 20 +-1100.0 + 30 +0.0 + 11 +20000.0 + 21 +-972.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +16000.0 + 23 +0.0 + 33 +0.0 + 14 +24000.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +TEXT + 5 +164 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +16000.0 + 20 +-2100.0 + 30 +0.0 + 40 +300.0 + 1 +EAST ELEVATION 1:50 + 7 +ARCH-TITLE + 11 +16000.0 + 21 +-2100.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +165 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +370 +70 +100 +AcDbLine + 10 +16000.0 + 20 +-2250.0 + 30 +0.0 + 11 +19600.0 + 21 +-2250.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +166 +330 +17 +100 +AcDbEntity + 8 +E-GROUND +370 +70 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +-1500.0 + 20 +-17000.0 + 10 +11500.0 + 20 +-17000.0 + 0 +HATCH + 5 +167 +330 +17 +100 +AcDbEntity + 8 +E-GROUND + 62 +3 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +EARTH + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +-1500.0 + 20 +-17600.0 + 10 +11500.0 + 20 +-17600.0 + 10 +11500.0 + 20 +-17000.0 + 10 +-1500.0 + 20 +-17000.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +60.0 + 77 +0 + 78 +6 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +0.0 + 43 +0.0 + 44 +142.875 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +0.0 + 43 +0.0 + 44 +285.75 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +47.625 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +190.5 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +333.375 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 98 +0 + 0 +LWPOLYLINE + 5 +168 +330 +17 +100 +AcDbEntity + 8 +E-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-17000.0 + 10 +10000.0 + 20 +-17000.0 + 10 +10000.0 + 20 +-11600.0 + 10 +0.0 + 20 +-11600.0 + 0 +HATCH + 5 +169 +330 +17 +100 +AcDbEntity + 8 +E-RENDER + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-SAND + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-17000.0 + 10 +10000.0 + 20 +-17000.0 + 10 +10000.0 + 20 +-11600.0 + 10 +0.0 + 20 +-11600.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +15.0 + 77 +0 + 78 +4 + 53 +37.5 + 43 +0.0 + 44 +0.0 + 45 +-24.00046944 + 46 +734.1198559935 + 79 +6 + 49 +0.0 + 49 +-579.12 + 49 +0.0 + 49 +-647.7 + 49 +0.0 + 49 +-619.125 + 53 +7.5 + 43 +0.0 + 44 +0.0 + 45 +674.284924707 + 46 +1075.237650852 + 79 +6 + 49 +0.0 + 49 +-312.42 + 49 +0.0 + 49 +-521.97 + 49 +0.0 + 49 +-200.025 + 53 +-32.5 + 43 +-468.63 + 44 +0.0 + 45 +1186.4885553615 + 46 +2.1557770185 + 79 +6 + 49 +0.0 + 49 +-190.5 + 49 +0.0 + 49 +-685.8 + 49 +0.0 + 49 +-895.35 + 53 +-42.5 + 43 +-468.63 + 44 +0.0 + 45 +1145.334678708 + 46 +334.3939848855 + 79 +6 + 49 +0.0 + 49 +-95.25 + 49 +0.0 + 49 +-449.58 + 49 +0.0 + 49 +-514.35 + 98 +0 + 0 +LWPOLYLINE + 5 +16A +330 +17 +100 +AcDbEntity + 8 +E-PLINTH +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-17000.0 + 10 +10000.0 + 20 +-17000.0 + 10 +10000.0 + 20 +-16550.0 + 10 +0.0 + 20 +-16550.0 + 0 +LWPOLYLINE + 5 +16B +330 +17 +100 +AcDbEntity + 8 +E-ROOF +370 +50 +100 +AcDbPolyline + 90 +3 + 70 +1 + 10 +-450.0 + 20 +-11600.0 + 10 +5000.0 + 20 +-8700.0 + 10 +10450.0 + 20 +-11600.0 + 0 +HATCH + 5 +16C +330 +17 +100 +AcDbEntity + 8 +E-ROOF + 62 +1 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-RROOF + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +3 + 10 +-450.0 + 20 +-11600.0 + 10 +5000.0 + 20 +-8700.0 + 10 +10450.0 + 20 +-11600.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +60.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +3352.8 + 46 +1524.0 + 79 +4 + 49 +22860.0 + 49 +-3048.0 + 49 +7620.0 + 49 +-1524.0 + 53 +0.0 + 43 +2026.92 + 44 +762.0 + 45 +-1524.0 + 46 +2026.92 + 79 +4 + 49 +4572.0 + 49 +-502.92 + 49 +9144.0 + 49 +-1143.0 + 53 +0.0 + 43 +762.0 + 44 +1295.4 + 45 +7924.8 + 46 +1021.08 + 79 +4 + 49 +12192.0 + 49 +-2133.6 + 49 +6096.0 + 49 +-1524.0 + 98 +0 + 0 +LINE + 5 +16D +330 +17 +100 +AcDbEntity + 8 +E-FLOOR + 6 +DASHDOT +100 +AcDbLine + 10 +0.0 + 20 +-14300.0 + 30 +0.0 + 11 +10000.0 + 21 +-14300.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +16E +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1200.0 + 20 +-15900.0 + 10 +2600.0 + 20 +-15900.0 + 10 +2600.0 + 20 +-14600.0 + 10 +1200.0 + 20 +-14600.0 + 0 +LWPOLYLINE + 5 +16F +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1260.0 + 20 +-15840.0 + 10 +2540.0 + 20 +-15840.0 + 10 +2540.0 + 20 +-14660.0 + 10 +1260.0 + 20 +-14660.0 + 0 +LINE + 5 +170 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +1900.0 + 20 +-15840.0 + 30 +0.0 + 11 +1900.0 + 21 +-14660.0 + 31 +0.0 + 0 +HATCH + 5 +171 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +1260.0 + 20 +-15840.0 + 10 +2540.0 + 20 +-15840.0 + 10 +2540.0 + 20 +-14660.0 + 10 +1260.0 + 20 +-14660.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +172 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1120.0 + 20 +-15990.0 + 10 +2680.0 + 20 +-15990.0 + 10 +2680.0 + 20 +-15900.0 + 10 +1120.0 + 20 +-15900.0 + 0 +LWPOLYLINE + 5 +173 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3600.0 + 20 +-15900.0 + 10 +5200.0 + 20 +-15900.0 + 10 +5200.0 + 20 +-14600.0 + 10 +3600.0 + 20 +-14600.0 + 0 +LWPOLYLINE + 5 +174 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3660.0 + 20 +-15840.0 + 10 +5140.0 + 20 +-15840.0 + 10 +5140.0 + 20 +-14660.0 + 10 +3660.0 + 20 +-14660.0 + 0 +LINE + 5 +175 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +4400.0 + 20 +-15840.0 + 30 +0.0 + 11 +4400.0 + 21 +-14660.0 + 31 +0.0 + 0 +HATCH + 5 +176 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +3660.0 + 20 +-15840.0 + 10 +5140.0 + 20 +-15840.0 + 10 +5140.0 + 20 +-14660.0 + 10 +3660.0 + 20 +-14660.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +177 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3520.0 + 20 +-15990.0 + 10 +5280.0 + 20 +-15990.0 + 10 +5280.0 + 20 +-15900.0 + 10 +3520.0 + 20 +-15900.0 + 0 +LWPOLYLINE + 5 +178 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6600.0 + 20 +-15900.0 + 10 +7800.0 + 20 +-15900.0 + 10 +7800.0 + 20 +-14600.0 + 10 +6600.0 + 20 +-14600.0 + 0 +LWPOLYLINE + 5 +179 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6660.0 + 20 +-15840.0 + 10 +7740.0 + 20 +-15840.0 + 10 +7740.0 + 20 +-14660.0 + 10 +6660.0 + 20 +-14660.0 + 0 +LINE + 5 +17A +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +7200.0 + 20 +-15840.0 + 30 +0.0 + 11 +7200.0 + 21 +-14660.0 + 31 +0.0 + 0 +HATCH + 5 +17B +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6660.0 + 20 +-15840.0 + 10 +7740.0 + 20 +-15840.0 + 10 +7740.0 + 20 +-14660.0 + 10 +6660.0 + 20 +-14660.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +17C +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6520.0 + 20 +-15990.0 + 10 +7880.0 + 20 +-15990.0 + 10 +7880.0 + 20 +-15900.0 + 10 +6520.0 + 20 +-15900.0 + 0 +LWPOLYLINE + 5 +17D +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3600.0 + 20 +-13600.0 + 10 +5200.0 + 20 +-13600.0 + 10 +5200.0 + 20 +-12200.0 + 10 +3600.0 + 20 +-12200.0 + 0 +LWPOLYLINE + 5 +17E +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3660.0 + 20 +-13540.0 + 10 +5140.0 + 20 +-13540.0 + 10 +5140.0 + 20 +-12260.0 + 10 +3660.0 + 20 +-12260.0 + 0 +LINE + 5 +17F +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +4400.0 + 20 +-13540.0 + 30 +0.0 + 11 +4400.0 + 21 +-12260.0 + 31 +0.0 + 0 +HATCH + 5 +180 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +3660.0 + 20 +-13540.0 + 10 +5140.0 + 20 +-13540.0 + 10 +5140.0 + 20 +-12260.0 + 10 +3660.0 + 20 +-12260.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +181 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3520.0 + 20 +-13690.0 + 10 +5280.0 + 20 +-13690.0 + 10 +5280.0 + 20 +-13600.0 + 10 +3520.0 + 20 +-13600.0 + 0 +INSERT + 5 +182 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +11900.0 + 20 +-17000.0 + 30 +0.0 + 0 +ATTRIB + 5 +184 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +12220.0 + 20 +-16710.0 + 30 +0.0 + 40 +120.0 + 1 ++0.00 + 11 +12220.0 + 21 +-16710.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +12220.0 + 21 +-16710.0 + 31 +0.0 + 0 +SEQEND + 5 +183 +330 +182 +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +185 +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +10000.0 + 20 +-17000.0 + 30 +0.0 + 11 +11900.0 + 21 +-17000.0 + 31 +0.0 + 0 +INSERT + 5 +186 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +11900.0 + 20 +-14300.0 + 30 +0.0 + 0 +ATTRIB + 5 +188 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +12220.0 + 20 +-14010.0 + 30 +0.0 + 40 +120.0 + 1 ++2.70 + 11 +12220.0 + 21 +-14010.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +12220.0 + 21 +-14010.0 + 31 +0.0 + 0 +SEQEND + 5 +187 +330 +186 +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +189 +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +10000.0 + 20 +-14300.0 + 30 +0.0 + 11 +11900.0 + 21 +-14300.0 + 31 +0.0 + 0 +INSERT + 5 +18A +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +11900.0 + 20 +-11600.0 + 30 +0.0 + 0 +ATTRIB + 5 +18C +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +12220.0 + 20 +-11310.0 + 30 +0.0 + 40 +120.0 + 1 ++5.40 + 11 +12220.0 + 21 +-11310.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +12220.0 + 21 +-11310.0 + 31 +0.0 + 0 +SEQEND + 5 +18B +330 +18A +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +18D +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +10000.0 + 20 +-11600.0 + 30 +0.0 + 11 +11900.0 + 21 +-11600.0 + 31 +0.0 + 0 +INSERT + 5 +18E +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +11900.0 + 20 +-8700.0 + 30 +0.0 + 0 +ATTRIB + 5 +190 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +12220.0 + 20 +-8410.0 + 30 +0.0 + 40 +120.0 + 1 ++8.30 + 11 +12220.0 + 21 +-8410.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +12220.0 + 21 +-8410.0 + 31 +0.0 + 0 +SEQEND + 5 +18F +330 +18E +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +191 +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +10000.0 + 20 +-8700.0 + 30 +0.0 + 11 +11900.0 + 21 +-8700.0 + 31 +0.0 + 0 +DIMENSION + 5 +192 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D7 + 3 +ELEV50 + 10 +-1900.0 + 20 +-17000.0 + 30 +0.0 + 11 +-2028.0 + 21 +-14300.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +-17000.0 + 33 +0.0 + 14 +0.0 + 24 +-11600.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1A1 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D8 + 3 +ELEV50 + 10 +-1900.0 + 20 +-11600.0 + 30 +0.0 + 11 +-2028.0 + 21 +-10150.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +-11600.0 + 33 +0.0 + 14 +0.0 + 24 +-8700.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1B0 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D9 + 3 +ELEV50 + 10 +0.0 + 20 +-18100.0 + 30 +0.0 + 11 +5000.0 + 21 +-17972.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +-17000.0 + 33 +0.0 + 14 +10000.0 + 24 +-17000.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +TEXT + 5 +1BF +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +0.0 + 20 +-19100.0 + 30 +0.0 + 40 +300.0 + 1 +NORTH ELEVATION 1:50 + 7 +ARCH-TITLE + 11 +0.0 + 21 +-19100.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +1C0 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +370 +70 +100 +AcDbLine + 10 +0.0 + 20 +-19250.0 + 30 +0.0 + 11 +3600.0 + 21 +-19250.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +1C1 +330 +17 +100 +AcDbEntity + 8 +E-GROUND +370 +70 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +14500.0 + 20 +-17000.0 + 10 +25500.0 + 20 +-17000.0 + 0 +HATCH + 5 +1C2 +330 +17 +100 +AcDbEntity + 8 +E-GROUND + 62 +3 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +EARTH + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +14500.0 + 20 +-17600.0 + 10 +25500.0 + 20 +-17600.0 + 10 +25500.0 + 20 +-17000.0 + 10 +14500.0 + 20 +-17000.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +60.0 + 77 +0 + 78 +6 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +0.0 + 43 +0.0 + 44 +142.875 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +0.0 + 43 +0.0 + 44 +285.75 + 45 +381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +47.625 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +190.5 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 53 +90.0 + 43 +333.375 + 44 +333.375 + 45 +-381.0 + 46 +381.0 + 79 +2 + 49 +381.0 + 49 +-381.0 + 98 +0 + 0 +LWPOLYLINE + 5 +1C3 +330 +17 +100 +AcDbEntity + 8 +E-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +16000.0 + 20 +-17000.0 + 10 +24000.0 + 20 +-17000.0 + 10 +24000.0 + 20 +-11600.0 + 10 +16000.0 + 20 +-11600.0 + 0 +HATCH + 5 +1C4 +330 +17 +100 +AcDbEntity + 8 +E-RENDER + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-SAND + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +16000.0 + 20 +-17000.0 + 10 +24000.0 + 20 +-17000.0 + 10 +24000.0 + 20 +-11600.0 + 10 +16000.0 + 20 +-11600.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +15.0 + 77 +0 + 78 +4 + 53 +37.5 + 43 +0.0 + 44 +0.0 + 45 +-24.00046944 + 46 +734.1198559935 + 79 +6 + 49 +0.0 + 49 +-579.12 + 49 +0.0 + 49 +-647.7 + 49 +0.0 + 49 +-619.125 + 53 +7.5 + 43 +0.0 + 44 +0.0 + 45 +674.284924707 + 46 +1075.237650852 + 79 +6 + 49 +0.0 + 49 +-312.42 + 49 +0.0 + 49 +-521.97 + 49 +0.0 + 49 +-200.025 + 53 +-32.5 + 43 +-468.63 + 44 +0.0 + 45 +1186.4885553615 + 46 +2.1557770185 + 79 +6 + 49 +0.0 + 49 +-190.5 + 49 +0.0 + 49 +-685.8 + 49 +0.0 + 49 +-895.35 + 53 +-42.5 + 43 +-468.63 + 44 +0.0 + 45 +1145.334678708 + 46 +334.3939848855 + 79 +6 + 49 +0.0 + 49 +-95.25 + 49 +0.0 + 49 +-449.58 + 49 +0.0 + 49 +-514.35 + 98 +0 + 0 +LWPOLYLINE + 5 +1C5 +330 +17 +100 +AcDbEntity + 8 +E-PLINTH +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +16000.0 + 20 +-17000.0 + 10 +24000.0 + 20 +-17000.0 + 10 +24000.0 + 20 +-16550.0 + 10 +16000.0 + 20 +-16550.0 + 0 +LWPOLYLINE + 5 +1C6 +330 +17 +100 +AcDbEntity + 8 +E-ROOF +370 +50 +100 +AcDbPolyline + 90 +3 + 70 +1 + 10 +15550.0 + 20 +-11600.0 + 10 +20000.0 + 20 +-8700.0 + 10 +24450.0 + 20 +-11600.0 + 0 +HATCH + 5 +1C7 +330 +17 +100 +AcDbEntity + 8 +E-ROOF + 62 +1 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +AR-RROOF + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +3 + 10 +15550.0 + 20 +-11600.0 + 10 +20000.0 + 20 +-8700.0 + 10 +24450.0 + 20 +-11600.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +60.0 + 77 +0 + 78 +3 + 53 +0.0 + 43 +0.0 + 44 +0.0 + 45 +3352.8 + 46 +1524.0 + 79 +4 + 49 +22860.0 + 49 +-3048.0 + 49 +7620.0 + 49 +-1524.0 + 53 +0.0 + 43 +2026.92 + 44 +762.0 + 45 +-1524.0 + 46 +2026.92 + 79 +4 + 49 +4572.0 + 49 +-502.92 + 49 +9144.0 + 49 +-1143.0 + 53 +0.0 + 43 +762.0 + 44 +1295.4 + 45 +7924.8 + 46 +1021.08 + 79 +4 + 49 +12192.0 + 49 +-2133.6 + 49 +6096.0 + 49 +-1524.0 + 98 +0 + 0 +LINE + 5 +1C8 +330 +17 +100 +AcDbEntity + 8 +E-FLOOR + 6 +DASHDOT +100 +AcDbLine + 10 +16000.0 + 20 +-14300.0 + 30 +0.0 + 11 +24000.0 + 21 +-14300.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +1C9 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +17600.0 + 20 +-15900.0 + 10 +19000.0 + 20 +-15900.0 + 10 +19000.0 + 20 +-14600.0 + 10 +17600.0 + 20 +-14600.0 + 0 +LWPOLYLINE + 5 +1CA +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +17660.0 + 20 +-15840.0 + 10 +18940.0 + 20 +-15840.0 + 10 +18940.0 + 20 +-14660.0 + 10 +17660.0 + 20 +-14660.0 + 0 +LINE + 5 +1CB +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +18300.0 + 20 +-15840.0 + 30 +0.0 + 11 +18300.0 + 21 +-14660.0 + 31 +0.0 + 0 +HATCH + 5 +1CC +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +17660.0 + 20 +-15840.0 + 10 +18940.0 + 20 +-15840.0 + 10 +18940.0 + 20 +-14660.0 + 10 +17660.0 + 20 +-14660.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +1CD +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +17520.0 + 20 +-15990.0 + 10 +19080.0 + 20 +-15990.0 + 10 +19080.0 + 20 +-15900.0 + 10 +17520.0 + 20 +-15900.0 + 0 +LWPOLYLINE + 5 +1CE +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +21000.0 + 20 +-15900.0 + 10 +22400.0 + 20 +-15900.0 + 10 +22400.0 + 20 +-14600.0 + 10 +21000.0 + 20 +-14600.0 + 0 +LWPOLYLINE + 5 +1CF +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +21060.0 + 20 +-15840.0 + 10 +22340.0 + 20 +-15840.0 + 10 +22340.0 + 20 +-14660.0 + 10 +21060.0 + 20 +-14660.0 + 0 +LINE + 5 +1D0 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +21700.0 + 20 +-15840.0 + 30 +0.0 + 11 +21700.0 + 21 +-14660.0 + 31 +0.0 + 0 +HATCH + 5 +1D1 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +21060.0 + 20 +-15840.0 + 10 +22340.0 + 20 +-15840.0 + 10 +22340.0 + 20 +-14660.0 + 10 +21060.0 + 20 +-14660.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +1D2 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +20920.0 + 20 +-15990.0 + 10 +22480.0 + 20 +-15990.0 + 10 +22480.0 + 20 +-15900.0 + 10 +20920.0 + 20 +-15900.0 + 0 +LWPOLYLINE + 5 +1D3 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +19000.0 + 20 +-13600.0 + 10 +20200.0 + 20 +-13600.0 + 10 +20200.0 + 20 +-12200.0 + 10 +19000.0 + 20 +-12200.0 + 0 +LWPOLYLINE + 5 +1D4 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +19060.0 + 20 +-13540.0 + 10 +20140.0 + 20 +-13540.0 + 10 +20140.0 + 20 +-12260.0 + 10 +19060.0 + 20 +-12260.0 + 0 +LINE + 5 +1D5 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +19600.0 + 20 +-13540.0 + 30 +0.0 + 11 +19600.0 + 21 +-12260.0 + 31 +0.0 + 0 +HATCH + 5 +1D6 +330 +17 +100 +AcDbEntity + 8 +A-WIND + 62 +5 +440 +33554534 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +19060.0 + 20 +-13540.0 + 10 +20140.0 + 20 +-13540.0 + 10 +20140.0 + 20 +-12260.0 + 10 +19060.0 + 20 +-12260.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +1D7 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +18920.0 + 20 +-13690.0 + 10 +20280.0 + 20 +-13690.0 + 10 +20280.0 + 20 +-13600.0 + 10 +18920.0 + 20 +-13600.0 + 0 +INSERT + 5 +1D8 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +25900.0 + 20 +-17000.0 + 30 +0.0 + 0 +ATTRIB + 5 +1DA +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +26220.0 + 20 +-16710.0 + 30 +0.0 + 40 +120.0 + 1 ++0.00 + 11 +26220.0 + 21 +-16710.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +26220.0 + 21 +-16710.0 + 31 +0.0 + 0 +SEQEND + 5 +1D9 +330 +1D8 +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +1DB +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +24000.0 + 20 +-17000.0 + 30 +0.0 + 11 +25900.0 + 21 +-17000.0 + 31 +0.0 + 0 +INSERT + 5 +1DC +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +25900.0 + 20 +-14300.0 + 30 +0.0 + 0 +ATTRIB + 5 +1DE +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +26220.0 + 20 +-14010.0 + 30 +0.0 + 40 +120.0 + 1 ++2.70 + 11 +26220.0 + 21 +-14010.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +26220.0 + 21 +-14010.0 + 31 +0.0 + 0 +SEQEND + 5 +1DD +330 +1DC +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +1DF +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +24000.0 + 20 +-14300.0 + 30 +0.0 + 11 +25900.0 + 21 +-14300.0 + 31 +0.0 + 0 +INSERT + 5 +1E0 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +25900.0 + 20 +-11600.0 + 30 +0.0 + 0 +ATTRIB + 5 +1E2 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +26220.0 + 20 +-11310.0 + 30 +0.0 + 40 +120.0 + 1 ++5.40 + 11 +26220.0 + 21 +-11310.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +26220.0 + 21 +-11310.0 + 31 +0.0 + 0 +SEQEND + 5 +1E1 +330 +1E0 +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +1E3 +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +24000.0 + 20 +-11600.0 + 30 +0.0 + 11 +25900.0 + 21 +-11600.0 + 31 +0.0 + 0 +INSERT + 5 +1E4 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +25900.0 + 20 +-8700.0 + 30 +0.0 + 0 +ATTRIB + 5 +1E6 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +26220.0 + 20 +-8410.0 + 30 +0.0 + 40 +120.0 + 1 ++8.30 + 11 +26220.0 + 21 +-8410.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +26220.0 + 21 +-8410.0 + 31 +0.0 + 0 +SEQEND + 5 +1E5 +330 +1E4 +100 +AcDbEntity + 8 +A-ANNO + 0 +LINE + 5 +1E7 +330 +17 +100 +AcDbEntity + 8 +A-ANNO + 6 +DASHED +100 +AcDbLine + 10 +24000.0 + 20 +-8700.0 + 30 +0.0 + 11 +25900.0 + 21 +-8700.0 + 31 +0.0 + 0 +DIMENSION + 5 +1E8 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D10 + 3 +ELEV50 + 10 +14100.0 + 20 +-17000.0 + 30 +0.0 + 11 +13972.0 + 21 +-14300.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +16000.0 + 23 +-17000.0 + 33 +0.0 + 14 +16000.0 + 24 +-11600.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1F7 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D11 + 3 +ELEV50 + 10 +14100.0 + 20 +-11600.0 + 30 +0.0 + 11 +13972.0 + 21 +-10150.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +16000.0 + 23 +-11600.0 + 33 +0.0 + 14 +16000.0 + 24 +-8700.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +206 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D12 + 3 +ELEV50 + 10 +16000.0 + 20 +-18100.0 + 30 +0.0 + 11 +20000.0 + 21 +-17972.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +16000.0 + 23 +-17000.0 + 33 +0.0 + 14 +24000.0 + 24 +-17000.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +TEXT + 5 +215 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +16000.0 + 20 +-19100.0 + 30 +0.0 + 40 +300.0 + 1 +WEST ELEVATION 1:50 + 7 +ARCH-TITLE + 11 +16000.0 + 21 +-19100.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +216 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +370 +70 +100 +AcDbLine + 10 +16000.0 + 20 +-19250.0 + 30 +0.0 + 11 +19600.0 + 21 +-19250.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +217 +330 +17 +100 +AcDbEntity + 8 +E-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +32000.0 + 20 +0.0 + 10 +32300.0 + 20 +0.0 + 10 +32300.0 + 20 +5400.0 + 10 +32000.0 + 20 +5400.0 + 0 +HATCH + 5 +218 +330 +17 +100 +AcDbEntity + 8 +E-WALL + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +32000.0 + 20 +0.0 + 10 +32300.0 + 20 +0.0 + 10 +32300.0 + 20 +5400.0 + 10 +32000.0 + 20 +5400.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +60.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-134.703841818 + 46 +134.703841818 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +219 +330 +17 +100 +AcDbEntity + 8 +E-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +41700.0 + 20 +0.0 + 10 +42000.0 + 20 +0.0 + 10 +42000.0 + 20 +5400.0 + 10 +41700.0 + 20 +5400.0 + 0 +HATCH + 5 +21A +330 +17 +100 +AcDbEntity + 8 +E-WALL + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +41700.0 + 20 +0.0 + 10 +42000.0 + 20 +0.0 + 10 +42000.0 + 20 +5400.0 + 10 +41700.0 + 20 +5400.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +60.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-134.703841818 + 46 +134.703841818 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +21B +330 +17 +100 +AcDbEntity + 8 +E-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +32000.0 + 20 +-300.0 + 10 +42000.0 + 20 +-300.0 + 10 +42000.0 + 20 +0.0 + 10 +32000.0 + 20 +0.0 + 0 +LWPOLYLINE + 5 +21C +330 +17 +100 +AcDbEntity + 8 +E-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +32000.0 + 20 +2600.0 + 10 +42000.0 + 20 +2600.0 + 10 +42000.0 + 20 +2900.0 + 10 +32000.0 + 20 +2900.0 + 0 +LWPOLYLINE + 5 +21D +330 +17 +100 +AcDbEntity + 8 +E-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +32000.0 + 20 +5000.0 + 10 +42000.0 + 20 +5000.0 + 10 +42000.0 + 20 +5300.0 + 10 +32000.0 + 20 +5300.0 + 0 +LWPOLYLINE + 5 +21E +330 +17 +100 +AcDbEntity + 8 +E-ROOF +370 +50 +100 +AcDbPolyline + 90 +6 + 70 +1 + 10 +31550.0 + 20 +5400.0 + 10 +37000.0 + 20 +8300.0 + 10 +42450.0 + 20 +5400.0 + 10 +42450.0 + 20 +5250.0 + 10 +37000.0 + 20 +8150.0 + 10 +31550.0 + 20 +5250.0 + 0 +HATCH + 5 +21F +330 +17 +100 +AcDbEntity + 8 +E-ROOF + 62 +1 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +6 + 10 +31550.0 + 20 +5400.0 + 10 +37000.0 + 20 +8300.0 + 10 +42450.0 + 20 +5400.0 + 10 +42450.0 + 20 +5250.0 + 10 +37000.0 + 20 +8150.0 + 10 +31550.0 + 20 +5250.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +220 +330 +17 +100 +AcDbEntity + 8 +E-GROUND +370 +70 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +30500.0 + 20 +-300.0 + 10 +43500.0 + 20 +-300.0 + 0 +LINE + 5 +221 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +38300.0 + 20 +0.0 + 30 +0.0 + 11 +38600.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +222 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +38600.0 + 20 +0.0 + 30 +0.0 + 11 +38600.0 + 21 +270.0 + 31 +0.0 + 0 +LINE + 5 +223 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +38600.0 + 20 +270.0 + 30 +0.0 + 11 +38900.0 + 21 +270.0 + 31 +0.0 + 0 +LINE + 5 +224 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +38900.0 + 20 +270.0 + 30 +0.0 + 11 +38900.0 + 21 +540.0 + 31 +0.0 + 0 +LINE + 5 +225 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +38900.0 + 20 +540.0 + 30 +0.0 + 11 +39200.0 + 21 +540.0 + 31 +0.0 + 0 +LINE + 5 +226 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +39200.0 + 20 +540.0 + 30 +0.0 + 11 +39200.0 + 21 +810.0 + 31 +0.0 + 0 +LINE + 5 +227 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +39200.0 + 20 +810.0 + 30 +0.0 + 11 +39500.0 + 21 +810.0 + 31 +0.0 + 0 +LINE + 5 +228 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +39500.0 + 20 +810.0 + 30 +0.0 + 11 +39500.0 + 21 +1080.0 + 31 +0.0 + 0 +LINE + 5 +229 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +39500.0 + 20 +1080.0 + 30 +0.0 + 11 +39800.0 + 21 +1080.0 + 31 +0.0 + 0 +LINE + 5 +22A +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +39800.0 + 20 +1080.0 + 30 +0.0 + 11 +39800.0 + 21 +1350.0 + 31 +0.0 + 0 +LINE + 5 +22B +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +39800.0 + 20 +1350.0 + 30 +0.0 + 11 +40100.0 + 21 +1350.0 + 31 +0.0 + 0 +LINE + 5 +22C +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +40100.0 + 20 +1350.0 + 30 +0.0 + 11 +40100.0 + 21 +1620.0 + 31 +0.0 + 0 +LINE + 5 +22D +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +40100.0 + 20 +1620.0 + 30 +0.0 + 11 +40400.0 + 21 +1620.0 + 31 +0.0 + 0 +LINE + 5 +22E +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +40400.0 + 20 +1620.0 + 30 +0.0 + 11 +40400.0 + 21 +1890.0 + 31 +0.0 + 0 +LINE + 5 +22F +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +40400.0 + 20 +1890.0 + 30 +0.0 + 11 +40700.0 + 21 +1890.0 + 31 +0.0 + 0 +LINE + 5 +230 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +40700.0 + 20 +1890.0 + 30 +0.0 + 11 +40700.0 + 21 +2160.0 + 31 +0.0 + 0 +LINE + 5 +231 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +40700.0 + 20 +2160.0 + 30 +0.0 + 11 +41000.0 + 21 +2160.0 + 31 +0.0 + 0 +LINE + 5 +232 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +41000.0 + 20 +2160.0 + 30 +0.0 + 11 +41000.0 + 21 +2430.0 + 31 +0.0 + 0 +LINE + 5 +233 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +41000.0 + 20 +2430.0 + 30 +0.0 + 11 +41300.0 + 21 +2430.0 + 31 +0.0 + 0 +LINE + 5 +234 +330 +17 +100 +AcDbEntity + 8 +E-STEP +100 +AcDbLine + 10 +41300.0 + 20 +2430.0 + 30 +0.0 + 11 +41300.0 + 21 +2700.0 + 31 +0.0 + 0 +TEXT + 5 +235 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +32000.0 + 20 +-2100.0 + 30 +0.0 + 40 +300.0 + 1 +SECTION A-A 1:50 + 7 +ARCH-TITLE + 11 +32000.0 + 21 +-2100.0 + 31 +0.0 +100 +AcDbText + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +A +330 +0 +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ACAD_COLOR +350 +B + 3 +ACAD_GROUP +350 +C + 3 +ACAD_LAYOUT +350 +D + 3 +ACAD_MATERIAL +350 +E + 3 +ACAD_MLEADERSTYLE +350 +F + 3 +ACAD_MLINESTYLE +350 +10 + 3 +ACAD_PLOTSETTINGS +350 +11 + 3 +ACAD_PLOTSTYLENAME +350 +12 + 3 +ACAD_SCALELIST +350 +14 + 3 +ACAD_TABLESTYLE +350 +15 + 3 +ACAD_VISUALSTYLE +350 +16 + 3 +EZDXF_META +350 +2D + 0 +DICTIONARY + 5 +B +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +C +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +D +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Model +350 +1A + 3 +Layout1 +350 +1E + 0 +DICTIONARY + 5 +E +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ByBlock +350 +1F + 3 +ByLayer +350 +20 + 3 +Global +350 +21 + 0 +DICTIONARY + 5 +F +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +2C + 0 +DICTIONARY + 5 +10 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +22 + 0 +DICTIONARY + 5 +11 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +ACDBDICTIONARYWDFLT + 5 +12 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Normal +350 +13 +100 +AcDbDictionaryWithDefault +340 +13 + 0 +ACDBPLACEHOLDER + 5 +13 +330 +12 + 0 +DICTIONARY + 5 +14 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +15 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +16 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +LAYOUT + 5 +1A +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +1024 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 +1 + 71 +0 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +17 + 0 +LAYOUT + 5 +1E +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +0 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 +1 + 71 +1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +1B + 0 +MATERIAL + 5 +1F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByBlock + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +20 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByLayer + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +21 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +Global + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MLINESTYLE + 5 +22 +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMlineStyle + 2 +Standard + 70 +0 + 3 + + 62 +256 + 51 +90.0 + 52 +90.0 + 71 +2 + 49 +0.5 + 62 +256 + 6 +BYLAYER + 49 +-0.5 + 62 +256 + 6 +BYLAYER + 0 +MLEADERSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +F +102 +} +330 +F +100 +AcDbMLeaderStyle +179 +2 +170 +2 +171 +1 +172 +0 + 90 +2 + 40 +0.0 + 41 +0.0 +173 +1 + 91 +-1056964608 + 92 +-2 +290 +1 + 42 +2.0 +291 +1 + 43 +8.0 + 3 +Standard + 44 +4.0 +300 + +342 +29 +174 +1 +175 +1 +176 +0 +178 +1 + 93 +-1056964608 + 45 +4.0 +292 +0 +297 +0 + 46 +4.0 + 94 +-1056964608 + 47 +1.0 + 49 +1.0 +140 +1.0 +294 +1 +141 +0.0 +177 +0 +142 +1.0 +295 +0 +296 +0 +143 +3.75 +271 +0 +272 +9 +273 +9 + 0 +DICTIONARY + 5 +2D +330 +A +100 +AcDbDictionary +281 +1 + 3 +CREATED_BY_EZDXF +350 +2E + 3 +WRITTEN_BY_EZDXF +350 +239 + 0 +DICTIONARYVAR + 5 +2E +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +DICTIONARYVAR + 5 +239 +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +ENDSEC + 0 +EOF diff --git a/crates/exav-viewer/demo/examples/files/cad/house-plan-r2000.dxf b/crates/exav-viewer/demo/examples/files/cad/house-plan-r2000.dxf new file mode 100644 index 0000000..281a730 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/cad/house-plan-r2000.dxf @@ -0,0 +1,16378 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1015 + 9 +$ACADMAINTVER + 70 +6 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$EXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 +0 + 9 +$REGENMODE + 70 +1 + 9 +$FILLMODE + 70 +1 + 9 +$QTEXTMODE + 70 +0 + 9 +$MIRRTEXT + 70 +1 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 +1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 +256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 +0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 +0 + 9 +$DIMLIM + 70 +0 + 9 +$DIMTIH + 70 +0 + 9 +$DIMTOH + 70 +0 + 9 +$DIMSE1 + 70 +0 + 9 +$DIMSE2 + 70 +0 + 9 +$DIMTAD + 70 +1 + 9 +$DIMZIN + 70 +8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 +1 + 9 +$DIMSHO + 70 +1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 +0 + 9 +$DIMALTD + 70 +3 + 9 +$DIMALTF + 40 +0.03937007874 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 +1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 +0 + 9 +$DIMSOXD + 70 +0 + 9 +$DIMSAH + 70 +0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 +0 + 9 +$DIMCLRE + 70 +0 + 9 +$DIMCLRT + 70 +0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 +0 + 9 +$DIMSD1 + 70 +0 + 9 +$DIMSD2 + 70 +0 + 9 +$DIMTOLJ + 70 +0 + 9 +$DIMTZIN + 70 +8 + 9 +$DIMALTZ + 70 +0 + 9 +$DIMALTTZ + 70 +0 + 9 +$DIMUPT + 70 +0 + 9 +$DIMDEC + 70 +2 + 9 +$DIMTDEC + 70 +2 + 9 +$DIMALTU + 70 +2 + 9 +$DIMALTTD + 70 +3 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 +0 + 9 +$DIMADEC + 70 +0 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 +0 + 9 +$DIMDSEP + 70 +44 + 9 +$DIMATFIT + 70 +3 + 9 +$DIMFRAC + 70 +0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 +2 + 9 +$DIMLWD + 70 +-2 + 9 +$DIMLWE + 70 +-2 + 9 +$DIMTMOVE + 70 +0 + 9 +$LUNITS + 70 +2 + 9 +$LUPREC + 70 +4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 +0 + 9 +$AUPREC + 70 +2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 +0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 +0 + 9 +$TDCREATE + 40 +2451545.0 + 9 +$TDUCREATE + 40 +2451545.0 + 9 +$TDUPDATE + 40 +2451545.0 + 9 +$TDUUPDATE + 40 +2451545.0 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 +1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 +0 + 9 +$PDMODE + 70 +0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 +0 + 9 +$SPLINETYPE + 70 +6 + 9 +$SPLINESEGS + 70 +8 + 9 +$HANDSEED + 5 +218 + 9 +$SURFTAB1 + 70 +6 + 9 +$SURFTAB2 + 70 +6 + 9 +$SURFTYPE + 70 +6 + 9 +$SURFU + 70 +6 + 9 +$SURFV + 70 +6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 +0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 +0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 +0 + 9 +$USERI2 + 70 +0 + 9 +$USERI3 + 70 +0 + 9 +$USERI4 + 70 +0 + 9 +$USERI5 + 70 +0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 +1 + 9 +$SHADEDGE + 70 +3 + 9 +$SHADEDIF + 70 +70 + 9 +$TILEMODE + 70 +1 + 9 +$MAXACTVP + 70 +64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 +0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 +0 + 9 +$VISRETAIN + 70 +1 + 9 +$PLINEGEN + 70 +0 + 9 +$PSLTSCALE + 70 +1 + 9 +$TREEDEPTH + 70 +3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 +0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 +1 + 9 +$MEASUREMENT + 70 +1 + 9 +$CELWEIGHT +370 +-1 + 9 +$ENDCAPS +280 +0 + 9 +$JOINSTYLE +280 +0 + 9 +$LWDISPLAY +290 +0 + 9 +$INSUNITS + 70 +4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 +1 + 9 +$CEPSNTYPE +380 +0 + 9 +$PSTYLEMODE +290 +1 + 9 +$FINGERPRINTGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$VERSIONGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$EXTNAMES +290 +1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 +0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 +1153 +280 +0 +281 +0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 +4095 +280 +0 +281 +0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 +1153 +280 +0 +281 +0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 +1153 +280 +0 +281 +0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 +4095 +280 +0 +281 +0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 +4095 +280 +0 +281 +0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +CELLSTYLEMAP + 2 +AcDbCellStyleMap + 3 +ObjectDBX Classes + 90 +1152 +280 +0 +281 +0 + 0 +CLASS + 1 +MENTALRAYRENDERSETTINGS + 2 +AcDbMentalRayRenderSettings + 3 +SCENEOE + 90 +1024 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBDETAILVIEWSTYLE + 2 +AcDbDetailViewStyle + 3 +ObjectDBX Classes + 90 +1025 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBSECTIONVIEWSTYLE + 2 +AcDbSectionViewStyle + 3 +ObjectDBX Classes + 90 +1025 +280 +0 +281 +0 + 0 +CLASS + 1 +RASTERVARIABLES + 2 +AcDbRasterVariables + 3 +ISM + 90 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 +0 +280 +0 +281 +0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 +1 + 0 +VPORT + 5 +214 +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +5835.463185876482 + 22 +2324.253181513731 + 13 +0.0 + 23 +0.0 + 14 +0.5 + 24 +0.5 + 15 +0.5 + 25 +0.5 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +15878.827193569996 + 41 +1.34 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +1000 + 73 +1 + 74 +3 + 75 +0 + 76 +0 + 77 +0 + 78 +0 +281 +0 + 65 +1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 +21 + 0 +LTYPE + 5 +24 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +25 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +26 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +2F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 +0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +5.08 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +30 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 +0 + 3 +Center (2x) ________ __ ________ __ ________ + 72 +65 + 73 +4 + 40 +8.89 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 +0 + 3 +Center (.5x) ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +2.54 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +32 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 +0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 +65 + 73 +2 + 40 +1.524 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +33 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 +0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ____ + 72 +65 + 73 +2 + 40 +3.048 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +34 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 +0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 +65 + 73 +2 + 40 +0.762 + 49 +0.635 + 74 +0 + 49 +-0.127 + 74 +0 + 0 +LTYPE + 5 +35 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM + 70 +0 + 3 +Phantom ______ __ __ ______ __ __ ______ + 72 +65 + 73 +6 + 40 +6.35 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOMX2 + 70 +0 + 3 +Phantom (2x)____________ ____ ____ ____________ + 72 +65 + 73 +6 + 40 +10.795 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +37 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 +0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___ + 72 +65 + 73 +6 + 40 +3.175 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +38 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 +0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 +65 + 73 +4 + 40 +3.556 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +39 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 +0 + 3 +Dash dot (2x) ____ . ____ . ____ . ____ + 72 +65 + 73 +4 + 40 +6.096 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 +0 + 3 +Dash dot (.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +4 + 40 +1.778 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 +0 + 3 +Dot . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.508 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 +0 + 3 +Dot (2x) . . . . . . . . + 72 +65 + 73 +2 + 40 +1.016 + 49 +0.0 + 74 +0 + 49 +-1.016 + 74 +0 + 0 +LTYPE + 5 +3D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 +0 + 3 +Dot (.5) . . . . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.254 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 +0 + 3 +Divide __ . . __ . . __ . . __ . . __ . . __ + 72 +65 + 73 +6 + 40 +4.064 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 +0 + 3 +Divide (2x) ____ . . ____ . . ____ . . ____ + 72 +65 + 73 +6 + 40 +6.604 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +40 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 +0 + 3 +Divide(.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +6 + 40 +2.032 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 +17 + 0 +LAYER + 5 +27 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 62 +7 + 6 +Continuous +370 +-3 +390 +13 + 0 +LAYER + 5 +28 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Defpoints + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +-3 +390 +13 + 0 +LAYER + 5 +41 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-WALL + 70 +0 + 62 +7 + 6 +Continuous +370 +50 +390 +13 + 0 +LAYER + 5 +42 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-WALL-PAT + 70 +0 + 62 +8 + 6 +Continuous +370 +9 +390 +13 + 0 +LAYER + 5 +43 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-DOOR + 70 +0 + 62 +3 + 6 +Continuous +370 +25 +390 +13 + 0 +LAYER + 5 +44 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-WIND + 70 +0 + 62 +5 + 6 +Continuous +370 +25 +390 +13 + 0 +LAYER + 5 +45 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-FURN + 70 +0 + 62 +9 + 6 +Continuous +370 +13 +390 +13 + 0 +LAYER + 5 +46 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-FIXT + 70 +0 + 62 +4 + 6 +Continuous +370 +18 +390 +13 + 0 +LAYER + 5 +47 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-GRID + 70 +0 + 62 +1 + 6 +CENTER +370 +9 +390 +13 + 0 +LAYER + 5 +48 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-ANNO + 70 +0 + 62 +2 + 6 +Continuous +370 +18 +390 +13 + 0 +LAYER + 5 +49 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-DIMS + 70 +0 + 62 +3 + 6 +Continuous +370 +13 +390 +13 + 0 +LAYER + 5 +4A +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-AREA + 70 +0 + 62 +6 + 6 +Continuous +370 +9 +390 +13 + 0 +LAYER + 5 +4B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-FLOR + 70 +0 + 62 +252 + 6 +Continuous +370 +9 +390 +13 + 0 +LAYER + 5 +4C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-SLAB + 70 +0 + 62 +254 + 6 +Continuous +370 +9 +390 +13 + 0 +LAYER + 5 +4D +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-STAIR + 70 +0 + 62 +30 + 6 +Continuous +370 +18 +390 +13 + 0 +LAYER + 5 +4E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-SHEET + 70 +0 + 62 +7 + 6 +Continuous +370 +35 +390 +13 + 0 +LAYER + 5 +4F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-VPORT + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +9 +390 +13 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 +4 + 0 +STYLE + 5 +29 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +50 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +ARCH-TEXT + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +STYLE + 5 +51 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +ARCH-TITLE + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +times.ttf + 4 + + 0 +STYLE + 5 +52 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +ARCH-NOTE + 70 +0 + 40 +0.0 + 41 +0.9 + 50 +15.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 +3 + 0 +APPID + 5 +2A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 +0 + 0 +APPID + 5 +215 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +HATCHBACKGROUNDCOLOR + 70 +0 + 0 +APPID + 5 +216 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +EZDXF + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +4 +330 +0 +100 +AcDbSymbolTable + 70 +2 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +2B +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 +0 + 3 + + 4 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 +148 +0.0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +0 +177 +0 +178 +0 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +371 +-2 +372 +-2 + 0 +DIMSTYLE +105 +53 +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +PLAN50 + 70 +0 + 3 + + 4 + + 40 +1.0 + 41 +176.0 + 42 +176.0 + 43 +3.75 + 44 +132.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +220.0 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +66.0 +148 +0.0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +3 +177 +3 +178 +2 +179 +2 +271 +0 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +340 +50 +371 +-2 +372 +-2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 +25 + 0 +BLOCK_RECORD + 5 +17 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +1A + 0 +BLOCK_RECORD + 5 +1B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 0 +BLOCK_RECORD + 5 +54 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +DOOR +340 +0 + 0 +BLOCK_RECORD + 5 +5B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +WINDOW +340 +0 + 0 +BLOCK_RECORD + 5 +64 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +BED +340 +0 + 0 +BLOCK_RECORD + 5 +6B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +TABLE +340 +0 + 0 +BLOCK_RECORD + 5 +77 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +SOFA +340 +0 + 0 +BLOCK_RECORD + 5 +7F +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +WC +340 +0 + 0 +BLOCK_RECORD + 5 +84 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +SINK +340 +0 + 0 +BLOCK_RECORD + 5 +8A +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +BATH +340 +0 + 0 +BLOCK_RECORD + 5 +8F +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +AXIS +340 +0 + 0 +BLOCK_RECORD + 5 +94 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +NORTH +340 +0 + 0 +BLOCK_RECORD + 5 +9A +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +LEVEL +340 +0 + 0 +BLOCK_RECORD + 5 +163 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D1 +340 +0 + 0 +BLOCK_RECORD + 5 +168 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_CLOSEDFILLED +340 +0 + 0 +BLOCK_RECORD + 5 +176 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D2 +340 +0 + 0 +BLOCK_RECORD + 5 +185 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D3 +340 +0 + 0 +BLOCK_RECORD + 5 +194 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D4 +340 +0 + 0 +BLOCK_RECORD + 5 +1A3 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D5 +340 +0 + 0 +BLOCK_RECORD + 5 +1B2 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D6 +340 +0 + 0 +BLOCK_RECORD + 5 +1C1 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D7 +340 +0 + 0 +BLOCK_RECORD + 5 +1D1 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D8 +340 +0 + 0 +BLOCK_RECORD + 5 +1E1 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D9 +340 +0 + 0 +BLOCK_RECORD + 5 +1F4 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D10 +340 +0 + 0 +BLOCK_RECORD + 5 +206 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space0 +340 +209 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +18 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +19 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +55 +330 +54 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +DOOR + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +DOOR + 1 + + 0 +LINE + 5 +57 +330 +54 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +900.0 + 31 +0.0 + 0 +ARC + 5 +58 +330 +54 +100 +AcDbEntity + 8 +A-DOOR + 6 +DASHED +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +900.0 +100 +AcDbArc + 50 +0.0 + 51 +90.0 + 0 +LWPOLYLINE + 5 +59 +330 +54 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +900.0 + 20 +0.0 + 10 +900.0 + 20 +40.0 + 10 +0.0 + 20 +40.0 + 0 +ATTDEF + 5 +5A +330 +54 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +350.0 + 20 +-330.0 + 30 +0.0 + 40 +110.0 + 1 +D-000 +100 +AcDbAttributeDefinition + 3 + + 2 +TAG + 70 +0 + 0 +ENDBLK + 5 +56 +330 +54 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +5C +330 +5B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +WINDOW + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +WINDOW + 1 + + 0 +LINE + 5 +5E +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +1.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +5F +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.35 + 30 +0.0 + 11 +1.0 + 21 +0.35 + 31 +0.0 + 0 +LINE + 5 +60 +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.65 + 30 +0.0 + 11 +1.0 + 21 +0.65 + 31 +0.0 + 0 +LINE + 5 +61 +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +1.0 + 30 +0.0 + 11 +1.0 + 21 +1.0 + 31 +0.0 + 0 +LINE + 5 +62 +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +1.0 + 31 +0.0 + 0 +LINE + 5 +63 +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +1.0 + 20 +0.0 + 30 +0.0 + 11 +1.0 + 21 +1.0 + 31 +0.0 + 0 +ENDBLK + 5 +5D +330 +5B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +65 +330 +64 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +BED + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +BED + 1 + + 0 +LWPOLYLINE + 5 +67 +330 +64 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1600.0 + 20 +0.0 + 10 +1600.0 + 20 +2000.0 + 10 +0.0 + 20 +2000.0 + 0 +LWPOLYLINE + 5 +68 +330 +64 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +80.0 + 20 +1300.0 + 10 +760.0 + 20 +1300.0 + 10 +760.0 + 20 +1920.0 + 10 +80.0 + 20 +1920.0 + 0 +LWPOLYLINE + 5 +69 +330 +64 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +1300.0 + 10 +1520.0 + 20 +1300.0 + 10 +1520.0 + 20 +1920.0 + 10 +840.0 + 20 +1920.0 + 0 +LINE + 5 +6A +330 +64 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbLine + 10 +0.0 + 20 +1200.0 + 30 +0.0 + 11 +1600.0 + 21 +1200.0 + 31 +0.0 + 0 +ENDBLK + 5 +66 +330 +64 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +6C +330 +6B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +TABLE + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +TABLE + 1 + + 0 +LWPOLYLINE + 5 +6E +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1800.0 + 20 +0.0 + 10 +1800.0 + 20 +900.0 + 10 +0.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +6F +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +-450.0 + 10 +550.0 + 20 +-450.0 + 10 +550.0 + 20 +-50.0 + 10 +150.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +70 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +950.0 + 10 +550.0 + 20 +950.0 + 10 +550.0 + 20 +1350.0 + 10 +150.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +71 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +600.0 + 20 +-450.0 + 10 +1000.0 + 20 +-450.0 + 10 +1000.0 + 20 +-50.0 + 10 +600.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +72 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +600.0 + 20 +950.0 + 10 +1000.0 + 20 +950.0 + 10 +1000.0 + 20 +1350.0 + 10 +600.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +73 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1050.0 + 20 +-450.0 + 10 +1450.0 + 20 +-450.0 + 10 +1450.0 + 20 +-50.0 + 10 +1050.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +74 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1050.0 + 20 +950.0 + 10 +1450.0 + 20 +950.0 + 10 +1450.0 + 20 +1350.0 + 10 +1050.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +75 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1500.0 + 20 +-450.0 + 10 +1900.0 + 20 +-450.0 + 10 +1900.0 + 20 +-50.0 + 10 +1500.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +76 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1500.0 + 20 +950.0 + 10 +1900.0 + 20 +950.0 + 10 +1900.0 + 20 +1350.0 + 10 +1500.0 + 20 +1350.0 + 0 +ENDBLK + 5 +6D +330 +6B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +78 +330 +77 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +SOFA + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +SOFA + 1 + + 0 +LWPOLYLINE + 5 +7A +330 +77 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +2200.0 + 20 +0.0 + 10 +2200.0 + 20 +950.0 + 10 +0.0 + 20 +950.0 + 0 +LWPOLYLINE + 5 +7B +330 +77 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +2200.0 + 20 +0.0 + 10 +2200.0 + 20 +250.0 + 10 +0.0 + 20 +250.0 + 0 +LWPOLYLINE + 5 +7C +330 +77 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +120.0 + 20 +300.0 + 10 +720.0 + 20 +300.0 + 10 +720.0 + 20 +900.0 + 10 +120.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +7D +330 +77 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +770.0 + 20 +300.0 + 10 +1370.0 + 20 +300.0 + 10 +1370.0 + 20 +900.0 + 10 +770.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +7E +330 +77 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1420.0 + 20 +300.0 + 10 +2020.0 + 20 +300.0 + 10 +2020.0 + 20 +900.0 + 10 +1420.0 + 20 +900.0 + 0 +ENDBLK + 5 +79 +330 +77 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +80 +330 +7F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +WC + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +WC + 1 + + 0 +LWPOLYLINE + 5 +82 +330 +7F +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +400.0 + 20 +0.0 + 10 +400.0 + 20 +200.0 + 10 +0.0 + 20 +200.0 + 0 +ELLIPSE + 5 +83 +330 +7F +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbEllipse + 10 +200.0 + 20 +-250.0 + 30 +0.0 + 11 +0.0 + 21 +230.0 + 31 +0.0 + 40 +0.8 + 41 +0.0 + 42 +6.283185307179586 + 0 +ENDBLK + 5 +81 +330 +7F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +85 +330 +84 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +SINK + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +SINK + 1 + + 0 +LWPOLYLINE + 5 +87 +330 +84 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +600.0 + 20 +0.0 + 10 +600.0 + 20 +450.0 + 10 +0.0 + 20 +450.0 + 0 +CIRCLE + 5 +88 +330 +84 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbCircle + 10 +300.0 + 20 +225.0 + 30 +0.0 + 40 +160.0 + 0 +CIRCLE + 5 +89 +330 +84 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbCircle + 10 +300.0 + 20 +225.0 + 30 +0.0 + 40 +25.0 + 0 +ENDBLK + 5 +86 +330 +84 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8B +330 +8A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +BATH + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +BATH + 1 + + 0 +LWPOLYLINE + 5 +8D +330 +8A +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1700.0 + 20 +0.0 + 10 +1700.0 + 20 +750.0 + 10 +0.0 + 20 +750.0 + 0 +LWPOLYLINE + 5 +8E +330 +8A +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +5 + 70 +1 + 10 +100.0 + 20 +100.0 + 10 +1500.0 + 20 +100.0 + 10 +1600.0 + 20 +375.0 + 10 +1500.0 + 20 +650.0 + 10 +100.0 + 20 +650.0 + 0 +ENDBLK + 5 +8C +330 +8A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +90 +330 +8F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +AXIS + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +AXIS + 1 + + 0 +CIRCLE + 5 +92 +330 +8F +100 +AcDbEntity + 8 +A-GRID +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +300.0 + 0 +ATTDEF + 5 +93 +330 +8F +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +300.0 + 1 +A + 72 +4 + 11 +0.0 + 21 +0.0 + 31 +0.0 +100 +AcDbAttributeDefinition + 3 + + 2 +ID + 70 +0 + 0 +ENDBLK + 5 +91 +330 +8F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +95 +330 +94 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +NORTH + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +NORTH + 1 + + 0 +CIRCLE + 5 +97 +330 +94 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +500.0 + 0 +SOLID + 5 +98 +330 +94 +100 +AcDbEntity + 8 +A-ANNO + 62 +7 +100 +AcDbTrace + 10 +0.0 + 20 +650.0 + 30 +0.0 + 11 +-170.0 + 21 +-400.0 + 31 +0.0 + 12 +0.0 + 22 +-200.0 + 32 +0.0 + 13 +170.0 + 23 +-400.0 + 33 +0.0 + 0 +TEXT + 5 +99 +330 +94 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +0.0 + 20 +800.0 + 30 +0.0 + 40 +300.0 + 1 +N + 72 +1 + 11 +0.0 + 21 +800.0 + 31 +0.0 +100 +AcDbText + 73 +1 + 0 +ENDBLK + 5 +96 +330 +94 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +9B +330 +9A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +LEVEL + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +LEVEL + 1 + + 0 +LWPOLYLINE + 5 +9D +330 +9A +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbPolyline + 90 +3 + 70 +1 + 10 +-250.0 + 20 +250.0 + 10 +0.0 + 20 +0.0 + 10 +250.0 + 20 +250.0 + 0 +LINE + 5 +9E +330 +9A +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbLine + 10 +-250.0 + 20 +250.0 + 30 +0.0 + 11 +900.0 + 21 +250.0 + 31 +0.0 + 0 +ATTDEF + 5 +9F +330 +9A +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +320.0 + 20 +290.0 + 30 +0.0 + 40 +120.0 + 1 ++0.00 +100 +AcDbAttributeDefinition + 3 + + 2 +H + 70 +0 + 0 +ENDBLK + 5 +9C +330 +9A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +164 +330 +163 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D1 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D1 + 1 + + 0 +LINE + 5 +166 +330 +163 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +-176.0 + 30 +0.0 + 11 +0.0 + 21 +-3232.0 + 31 +0.0 + 0 +LINE + 5 +167 +330 +163 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +10000.0 + 20 +-176.0 + 30 +0.0 + 11 +10000.0 + 21 +-3232.0 + 31 +0.0 + 0 +INSERT + 5 +16C +330 +163 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +-3100.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +180.0 + 0 +INSERT + 5 +16E +330 +163 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +10000.0 + 20 +-3100.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 0 +LINE + 5 +170 +330 +163 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +176.0 + 20 +-3100.0 + 30 +0.0 + 11 +9824.0 + 21 +-3100.0 + 31 +0.0 + 0 +MTEXT + 5 +171 +330 +163 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +5000.0 + 20 +-2924.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +10000 + 7 +ARCH-TEXT + 0 +POINT + 5 +172 +330 +163 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-3100.0 + 30 +0.0 + 0 +POINT + 5 +173 +330 +163 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +174 +330 +163 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +10000.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +165 +330 +163 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +169 +330 +168 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_CLOSEDFILLED + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_CLOSEDFILLED + 1 + + 0 +SOLID + 5 +16B +330 +168 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 +0 +100 +AcDbTrace + 10 +-1.0 + 20 +0.16439898372402537 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 12 +-1.0 + 22 +-0.16439898372402537 + 32 +0.0 + 13 +-1.0 + 23 +-0.16439898372402537 + 33 +0.0 + 0 +ENDBLK + 5 +16A +330 +168 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +177 +330 +176 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D2 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D2 + 1 + + 0 +LINE + 5 +179 +330 +176 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +-176.0 + 30 +0.0 + 11 +0.0 + 21 +-2732.0 + 31 +0.0 + 0 +LINE + 5 +17A +330 +176 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +3500.0 + 20 +-176.0 + 30 +0.0 + 11 +3500.0 + 21 +-2732.0 + 31 +0.0 + 0 +INSERT + 5 +17B +330 +176 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +180.0 + 0 +INSERT + 5 +17D +330 +176 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +3500.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 0 +LINE + 5 +17F +330 +176 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +176.0 + 20 +-2600.0 + 30 +0.0 + 11 +3324.0 + 21 +-2600.0 + 31 +0.0 + 0 +MTEXT + 5 +180 +330 +176 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +1750.0 + 20 +-2424.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +3500 + 7 +ARCH-TEXT + 0 +POINT + 5 +181 +330 +176 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-2600.0 + 30 +0.0 + 0 +POINT + 5 +182 +330 +176 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +183 +330 +176 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +3500.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +178 +330 +176 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +186 +330 +185 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D3 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D3 + 1 + + 0 +LINE + 5 +188 +330 +185 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +3500.0 + 20 +-176.0 + 30 +0.0 + 11 +3500.0 + 21 +-2732.0 + 31 +0.0 + 0 +LINE + 5 +189 +330 +185 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +6200.0 + 20 +-176.0 + 30 +0.0 + 11 +6200.0 + 21 +-2732.0 + 31 +0.0 + 0 +INSERT + 5 +18A +330 +185 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +3500.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +180.0 + 0 +INSERT + 5 +18C +330 +185 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +6200.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 0 +LINE + 5 +18E +330 +185 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +3676.0 + 20 +-2600.0 + 30 +0.0 + 11 +6024.0 + 21 +-2600.0 + 31 +0.0 + 0 +MTEXT + 5 +18F +330 +185 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +4850.0 + 20 +-2424.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +2700 + 7 +ARCH-TEXT + 0 +POINT + 5 +190 +330 +185 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +3500.0 + 20 +-2600.0 + 30 +0.0 + 0 +POINT + 5 +191 +330 +185 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +3500.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +192 +330 +185 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +6200.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +187 +330 +185 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +195 +330 +194 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D4 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D4 + 1 + + 0 +LINE + 5 +197 +330 +194 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +6200.0 + 20 +-176.0 + 30 +0.0 + 11 +6200.0 + 21 +-2732.0 + 31 +0.0 + 0 +LINE + 5 +198 +330 +194 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +10000.0 + 20 +-176.0 + 30 +0.0 + 11 +10000.0 + 21 +-2732.0 + 31 +0.0 + 0 +INSERT + 5 +199 +330 +194 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +6200.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +180.0 + 0 +INSERT + 5 +19B +330 +194 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +10000.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 0 +LINE + 5 +19D +330 +194 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +6376.0 + 20 +-2600.0 + 30 +0.0 + 11 +9824.0 + 21 +-2600.0 + 31 +0.0 + 0 +MTEXT + 5 +19E +330 +194 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +8100.0 + 20 +-2424.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +3800 + 7 +ARCH-TEXT + 0 +POINT + 5 +19F +330 +194 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +6200.0 + 20 +-2600.0 + 30 +0.0 + 0 +POINT + 5 +1A0 +330 +194 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +6200.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +1A1 +330 +194 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +10000.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +196 +330 +194 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1A4 +330 +1A3 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D5 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D5 + 1 + + 0 +LINE + 5 +1A6 +330 +1A3 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +0.0 + 30 +0.0 + 11 +-3232.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +1A7 +330 +1A3 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +8000.0 + 30 +0.0 + 11 +-3232.0 + 21 +8000.0 + 31 +0.0 + 0 +INSERT + 5 +1A8 +330 +1A3 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-3100.0 + 20 +0.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +270.0 + 0 +INSERT + 5 +1AA +330 +1A3 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-3100.0 + 20 +8000.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +90.0 + 0 +LINE + 5 +1AC +330 +1A3 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-3100.0 + 20 +176.0 + 30 +0.0 + 11 +-3100.0 + 21 +7824.0 + 31 +0.0 + 0 +MTEXT + 5 +1AD +330 +1A3 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +-3276.0 + 20 +4000.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +8000 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +1AE +330 +1A3 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-3100.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +1AF +330 +1A3 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +1B0 +330 +1A3 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +8000.0 + 30 +0.0 + 0 +ENDBLK + 5 +1A5 +330 +1A3 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1B3 +330 +1B2 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D6 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D6 + 1 + + 0 +LINE + 5 +1B5 +330 +1B2 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +0.0 + 30 +0.0 + 11 +-2732.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +1B6 +330 +1B2 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +4200.0 + 30 +0.0 + 11 +-2732.0 + 21 +4200.0 + 31 +0.0 + 0 +INSERT + 5 +1B7 +330 +1B2 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-2600.0 + 20 +0.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +270.0 + 0 +INSERT + 5 +1B9 +330 +1B2 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-2600.0 + 20 +4200.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +90.0 + 0 +LINE + 5 +1BB +330 +1B2 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-2600.0 + 20 +176.0 + 30 +0.0 + 11 +-2600.0 + 21 +4024.0 + 31 +0.0 + 0 +MTEXT + 5 +1BC +330 +1B2 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +-2776.0 + 20 +2100.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +4200 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +1BD +330 +1B2 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-2600.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +1BE +330 +1B2 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +1BF +330 +1B2 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +4200.0 + 30 +0.0 + 0 +ENDBLK + 5 +1B4 +330 +1B2 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C2 +330 +1C1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D7 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D7 + 1 + + 0 +LINE + 5 +1C4 +330 +1C1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +4200.0 + 30 +0.0 + 11 +-2732.0 + 21 +4200.0 + 31 +0.0 + 0 +LINE + 5 +1C5 +330 +1C1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +8000.0 + 30 +0.0 + 11 +-2732.0 + 21 +8000.0 + 31 +0.0 + 0 +INSERT + 5 +1C6 +330 +1C1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-2600.0 + 20 +4200.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +270.0 + 0 +INSERT + 5 +1C8 +330 +1C1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-2600.0 + 20 +8000.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +90.0 + 0 +LINE + 5 +1CA +330 +1C1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-2600.0 + 20 +4376.0 + 30 +0.0 + 11 +-2600.0 + 21 +7824.0 + 31 +0.0 + 0 +MTEXT + 5 +1CB +330 +1C1 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +-2776.0 + 20 +6100.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +3800 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +1CC +330 +1C1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-2600.0 + 20 +4200.0 + 30 +0.0 + 0 +POINT + 5 +1CD +330 +1C1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +4200.0 + 30 +0.0 + 0 +POINT + 5 +1CE +330 +1C1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +8000.0 + 30 +0.0 + 0 +ENDBLK + 5 +1C3 +330 +1C1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1D2 +330 +1D1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D8 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D8 + 1 + + 0 +LINE + 5 +1D4 +330 +1D1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +11624.450793488832 + 20 +375.54920651116765 + 30 +0.0 + 11 +12088.312841947207 + 21 +-88.31284194720743 + 31 +0.0 + 0 +LINE + 5 +1D5 +330 +1D1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +14624.450793488832 + 20 +3375.5492065111675 + 30 +0.0 + 11 +15088.312841947207 + 21 +2911.6871580527927 + 31 +0.0 + 0 +INSERT + 5 +1D6 +330 +1D1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +11994.974746830583 + 20 +5.025253169416828 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +225.0 + 0 +INSERT + 5 +1D8 +330 +1D1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +14994.974746830583 + 20 +3005.025253169417 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +45.0 + 0 +LINE + 5 +1DA +330 +1D1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +12119.425540319415 + 20 +129.47604665824917 + 30 +0.0 + 11 +14870.523953341752 + 21 +2880.5744596805844 + 31 +0.0 + 0 +MTEXT + 5 +1DB +330 +1D1 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +13370.523953341752 + 20 +1629.4760466582493 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +4243 + 7 +ARCH-TEXT + 50 +45.0 + 0 +POINT + 5 +1DC +330 +1D1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +11994.974746830583 + 20 +5.025253169416828 + 30 +0.0 + 0 +POINT + 5 +1DD +330 +1D1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 0 +POINT + 5 +1DE +330 +1D1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +14500.0 + 20 +3500.0 + 30 +0.0 + 0 +ENDBLK + 5 +1D3 +330 +1D1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1E2 +330 +1E1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D9 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D9 + 1 + + 0 +LINE + 5 +1E4 +330 +1E1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +11676.0 + 20 +500.0 + 30 +0.0 + 11 +12456.621125123533 + 21 +500.0 + 31 +0.0 + 0 +LINE + 5 +1E5 +330 +1E1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +11624.450793488832 + 20 +624.4507934888323 + 30 +0.0 + 11 +12176.433284601155 + 21 +1176.4332846011544 + 31 +0.0 + 0 +INSERT + 5 +1E6 +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +12324.621125123533 + 20 +500.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +443.88564221369427 + 0 +INSERT + 5 +1E8 +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +12083.09518948453 + 20 +1083.0951894845302 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +321.11435778630573 + 0 +MTEXT + 5 +1EA +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +12546.405475591537 + 20 +933.4353397314832 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +45° + 7 +ARCH-TEXT + 50 +-67.5 + 0 +ARC + 5 +1EB +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbCircle + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 40 +824.6211251235321 +100 +AcDbArc + 50 +0.0 + 51 +45.0 + 0 +ARC + 5 +1EC +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbCircle + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 40 +824.6211251235321 +100 +AcDbArc + 50 +-24.45743114522284 + 51 +-12.22871557261142 + 0 +ARC + 5 +1ED +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbCircle + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 40 +824.6211251235321 +100 +AcDbArc + 50 +57.22871557261142 + 51 +69.45743114522284 + 0 +POINT + 5 +1EE +330 +1E1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +14500.0 + 20 +500.0 + 30 +0.0 + 0 +POINT + 5 +1EF +330 +1E1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 0 +POINT + 5 +1F0 +330 +1E1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +14500.0 + 20 +3500.0 + 30 +0.0 + 0 +POINT + 5 +1F1 +330 +1E1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 0 +POINT + 5 +1F2 +330 +1E1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +12300.0 + 20 +700.0 + 30 +0.0 + 0 +ENDBLK + 5 +1E3 +330 +1E1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1F5 +330 +1F4 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D10 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D10 + 1 + + 0 +INSERT + 5 +1F7 +330 +1F4 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +6911.396103067893 + 20 +2336.396103067893 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +225.0 + 0 +LINE + 5 +1F9 +330 +1F4 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +6275.0 + 20 +1700.0 + 30 +0.0 + 11 +6911.396103067893 + 21 +2336.396103067893 + 31 +0.0 + 0 +LINE + 5 +1FA +330 +1F4 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +7035.846896556725 + 20 +2460.8468965567254 + 30 +0.0 + 11 +7704.7699115591995 + 21 +3129.7699115591995 + 31 +0.0 + 0 +MTEXT + 5 +1FB +330 +1F4 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +7269.192134348285 + 20 +2943.093721325951 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +R900 + 7 +ARCH-TEXT + 50 +45.0 + 0 +POINT + 5 +1FC +330 +1F4 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +6275.0 + 20 +1700.0 + 30 +0.0 + 0 +POINT + 5 +1FD +330 +1F4 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +6911.396103067893 + 20 +2336.396103067893 + 30 +0.0 + 0 +ENDBLK + 5 +1F6 +330 +1F4 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +207 +330 +206 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space0 + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space0 + 1 + + 0 +VIEWPORT + 5 +20A +330 +206 +100 +AcDbEntity + 67 +1 + 8 +VIEWPORTS +100 +AcDbViewport + 10 +200.0 + 20 +138.5 + 30 +0.0 + 40 +462.00000000000006 + 41 +326.70000000000005 + 68 +1 + 69 +1 + 12 +200.0 + 22 +138.5 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 45 +326.70000000000005 + 50 +0.0 + 51 +0.0 + 72 +100 + 90 +557088 + 1 + +281 +0 + 71 +0 + 74 +0 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +LWPOLYLINE + 5 +20B +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +10.0 + 20 +10.0 + 10 +410.0 + 20 +10.0 + 10 +410.0 + 20 +287.0 + 10 +10.0 + 20 +287.0 + 0 +LWPOLYLINE + 5 +20C +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +5.0 + 20 +5.0 + 10 +415.0 + 20 +5.0 + 10 +415.0 + 20 +292.0 + 10 +5.0 + 20 +292.0 + 0 +LWPOLYLINE + 5 +20D +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +260.0 + 20 +10.0 + 10 +410.0 + 20 +10.0 + 10 +410.0 + 20 +60.0 + 10 +260.0 + 20 +60.0 + 0 +LINE + 5 +20E +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbLine + 10 +260.0 + 20 +35.0 + 30 +0.0 + 11 +410.0 + 21 +35.0 + 31 +0.0 + 0 +LINE + 5 +20F +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbLine + 10 +335.0 + 20 +10.0 + 30 +0.0 + 11 +335.0 + 21 +35.0 + 31 +0.0 + 0 +TEXT + 5 +210 +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbText + 10 +265.0 + 20 +45.0 + 30 +0.0 + 40 +7.0 + 1 +HOUSE, GROUND FLOOR + 7 +ARCH-TITLE + 11 +265.0 + 21 +45.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +211 +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbText + 10 +265.0 + 20 +18.0 + 30 +0.0 + 40 +4.0 + 1 +Scale 1:50 + 7 +ARCH-TEXT + 11 +265.0 + 21 +18.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +212 +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbText + 10 +340.0 + 20 +18.0 + 30 +0.0 + 40 +4.0 + 1 +Sheet A-101 + 7 +ARCH-TEXT + 11 +340.0 + 21 +18.0 + 31 +0.0 +100 +AcDbText + 0 +VIEWPORT + 5 +213 +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-VPORT +100 +AcDbViewport + 10 +135.0 + 20 +160.0 + 30 +0.0 + 40 +250.0 + 41 +200.0 + 68 +1 + 69 +3 + 12 +5000.0 + 22 +3400.0 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 45 +10000.0 + 50 +0.0 + 51 +0.0 + 72 +100 + 90 +0 + 1 + +281 +0 + 71 +0 + 74 +0 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDBLK + 5 +208 +330 +206 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +HATCH + 5 +A0 +330 +17 +100 +AcDbEntity + 8 +A-SLAB + 62 +254 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +0.0 + 10 +10000.0 + 20 +0.0 + 10 +10000.0 + 20 +8000.0 + 10 +0.0 + 20 +8000.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +A1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +150.0 + 10 +1400.0 + 20 +150.0 + 10 +1400.0 + 20 +-150.0 + 10 +0.0 + 20 +-150.0 + 0 +HATCH + 5 +A2 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +150.0 + 10 +1400.0 + 20 +150.0 + 10 +1400.0 + 20 +-150.0 + 10 +0.0 + 20 +-150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +A3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +2900.0 + 20 +150.0 + 10 +3600.0 + 20 +150.0 + 10 +3600.0 + 20 +-150.0 + 10 +2900.0 + 20 +-150.0 + 0 +HATCH + 5 +A4 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +2900.0 + 20 +150.0 + 10 +3600.0 + 20 +150.0 + 10 +3600.0 + 20 +-150.0 + 10 +2900.0 + 20 +-150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +A5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +4500.0 + 20 +150.0 + 10 +6200.0 + 20 +150.0 + 10 +6200.0 + 20 +-150.0 + 10 +4500.0 + 20 +-150.0 + 0 +HATCH + 5 +A6 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +4500.0 + 20 +150.0 + 10 +6200.0 + 20 +150.0 + 10 +6200.0 + 20 +-150.0 + 10 +4500.0 + 20 +-150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +A7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +7100.0 + 20 +150.0 + 10 +8200.0 + 20 +150.0 + 10 +8200.0 + 20 +-150.0 + 10 +7100.0 + 20 +-150.0 + 0 +HATCH + 5 +A8 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +7100.0 + 20 +150.0 + 10 +8200.0 + 20 +150.0 + 10 +8200.0 + 20 +-150.0 + 10 +7100.0 + 20 +-150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +A9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +9400.0 + 20 +150.0 + 10 +10000.0 + 20 +150.0 + 10 +10000.0 + 20 +-150.0 + 10 +9400.0 + 20 +-150.0 + 0 +HATCH + 5 +AA +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +9400.0 + 20 +150.0 + 10 +10000.0 + 20 +150.0 + 10 +10000.0 + 20 +-150.0 + 10 +9400.0 + 20 +-150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +AB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +1400.0 + 20 +150.0 + 30 +0.0 + 11 +1400.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +AC +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +2900.0 + 20 +150.0 + 30 +0.0 + 11 +2900.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +AD +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +3600.0 + 20 +150.0 + 30 +0.0 + 11 +3600.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +AE +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +4500.0 + 20 +150.0 + 30 +0.0 + 11 +4500.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +AF +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6200.0 + 20 +150.0 + 30 +0.0 + 11 +6200.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +B0 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +7100.0 + 20 +150.0 + 30 +0.0 + 11 +7100.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +B1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +8200.0 + 20 +150.0 + 30 +0.0 + 11 +8200.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +B2 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +9400.0 + 20 +150.0 + 30 +0.0 + 11 +9400.0 + 21 +-150.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +B3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +9850.0 + 20 +0.0 + 10 +9850.0 + 20 +1500.0 + 10 +10150.0 + 20 +1500.0 + 10 +10150.0 + 20 +0.0 + 0 +HATCH + 5 +B4 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +9850.0 + 20 +0.0 + 10 +9850.0 + 20 +1500.0 + 10 +10150.0 + 20 +1500.0 + 10 +10150.0 + 20 +0.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +B5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +9850.0 + 20 +2800.0 + 10 +9850.0 + 20 +4800.0 + 10 +10150.0 + 20 +4800.0 + 10 +10150.0 + 20 +2800.0 + 0 +HATCH + 5 +B6 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +9850.0 + 20 +2800.0 + 10 +9850.0 + 20 +4800.0 + 10 +10150.0 + 20 +4800.0 + 10 +10150.0 + 20 +2800.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +B7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +9850.0 + 20 +6100.0 + 10 +9850.0 + 20 +8000.0 + 10 +10150.0 + 20 +8000.0 + 10 +10150.0 + 20 +6100.0 + 0 +HATCH + 5 +B8 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +9850.0 + 20 +6100.0 + 10 +9850.0 + 20 +8000.0 + 10 +10150.0 + 20 +8000.0 + 10 +10150.0 + 20 +6100.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +B9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +9850.0 + 20 +1500.0 + 30 +0.0 + 11 +10150.0 + 21 +1500.0 + 31 +0.0 + 0 +LINE + 5 +BA +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +9850.0 + 20 +2800.0 + 30 +0.0 + 11 +10150.0 + 21 +2800.0 + 31 +0.0 + 0 +LINE + 5 +BB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +9850.0 + 20 +4800.0 + 30 +0.0 + 11 +10150.0 + 21 +4800.0 + 31 +0.0 + 0 +LINE + 5 +BC +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +9850.0 + 20 +6100.0 + 30 +0.0 + 11 +10150.0 + 21 +6100.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +BD +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +10000.0 + 20 +7850.0 + 10 +8800.0 + 20 +7850.0 + 10 +8800.0 + 20 +8150.0 + 10 +10000.0 + 20 +8150.0 + 0 +HATCH + 5 +BE +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +10000.0 + 20 +7850.0 + 10 +8800.0 + 20 +7850.0 + 10 +8800.0 + 20 +8150.0 + 10 +10000.0 + 20 +8150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +BF +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +7400.0 + 20 +7850.0 + 10 +6400.0 + 20 +7850.0 + 10 +6400.0 + 20 +8150.0 + 10 +7400.0 + 20 +8150.0 + 0 +HATCH + 5 +C0 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +7400.0 + 20 +7850.0 + 10 +6400.0 + 20 +7850.0 + 10 +6400.0 + 20 +8150.0 + 10 +7400.0 + 20 +8150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +C1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +4800.0 + 20 +7850.0 + 10 +3400.0 + 20 +7850.0 + 10 +3400.0 + 20 +8150.0 + 10 +4800.0 + 20 +8150.0 + 0 +HATCH + 5 +C2 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +4800.0 + 20 +7850.0 + 10 +3400.0 + 20 +7850.0 + 10 +3400.0 + 20 +8150.0 + 10 +4800.0 + 20 +8150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +C3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +2200.0 + 20 +7850.0 + 10 +0.0 + 20 +7850.0 + 10 +0.0 + 20 +8150.0 + 10 +2200.0 + 20 +8150.0 + 0 +HATCH + 5 +C4 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +2200.0 + 20 +7850.0 + 10 +0.0 + 20 +7850.0 + 10 +0.0 + 20 +8150.0 + 10 +2200.0 + 20 +8150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +C5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +8800.0 + 20 +7850.0 + 30 +0.0 + 11 +8800.0 + 21 +8150.0 + 31 +0.0 + 0 +LINE + 5 +C6 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +7400.0 + 20 +7850.0 + 30 +0.0 + 11 +7400.0 + 21 +8150.0 + 31 +0.0 + 0 +LINE + 5 +C7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6400.0 + 20 +7850.0 + 30 +0.0 + 11 +6400.0 + 21 +8150.0 + 31 +0.0 + 0 +LINE + 5 +C8 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +4800.0 + 20 +7850.0 + 30 +0.0 + 11 +4800.0 + 21 +8150.0 + 31 +0.0 + 0 +LINE + 5 +C9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +3400.0 + 20 +7850.0 + 30 +0.0 + 11 +3400.0 + 21 +8150.0 + 31 +0.0 + 0 +LINE + 5 +CA +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +2200.0 + 20 +7850.0 + 30 +0.0 + 11 +2200.0 + 21 +8150.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +CB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +8000.0 + 10 +150.0 + 20 +6400.0 + 10 +-150.0 + 20 +6400.0 + 10 +-150.0 + 20 +8000.0 + 0 +HATCH + 5 +CC +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +150.0 + 20 +8000.0 + 10 +150.0 + 20 +6400.0 + 10 +-150.0 + 20 +6400.0 + 10 +-150.0 + 20 +8000.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +CD +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +5000.0 + 10 +150.0 + 20 +3000.0 + 10 +-150.0 + 20 +3000.0 + 10 +-150.0 + 20 +5000.0 + 0 +HATCH + 5 +CE +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +150.0 + 20 +5000.0 + 10 +150.0 + 20 +3000.0 + 10 +-150.0 + 20 +3000.0 + 10 +-150.0 + 20 +5000.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +CF +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +1600.0 + 10 +150.0 + 20 +0.0 + 10 +-150.0 + 20 +0.0 + 10 +-150.0 + 20 +1600.0 + 0 +HATCH + 5 +D0 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +150.0 + 20 +1600.0 + 10 +150.0 + 20 +0.0 + 10 +-150.0 + 20 +0.0 + 10 +-150.0 + 20 +1600.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +D1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +150.0 + 20 +6400.0 + 30 +0.0 + 11 +-150.0 + 21 +6400.0 + 31 +0.0 + 0 +LINE + 5 +D2 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +150.0 + 20 +5000.0 + 30 +0.0 + 11 +-150.0 + 21 +5000.0 + 31 +0.0 + 0 +LINE + 5 +D3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +150.0 + 20 +3000.0 + 30 +0.0 + 11 +-150.0 + 21 +3000.0 + 31 +0.0 + 0 +LINE + 5 +D4 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +150.0 + 20 +1600.0 + 30 +0.0 + 11 +-150.0 + 21 +1600.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +D5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +4275.0 + 10 +600.0 + 20 +4275.0 + 10 +600.0 + 20 +4125.0 + 10 +0.0 + 20 +4125.0 + 0 +HATCH + 5 +D6 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +4275.0 + 10 +600.0 + 20 +4275.0 + 10 +600.0 + 20 +4125.0 + 10 +0.0 + 20 +4125.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +D7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1500.0 + 20 +4275.0 + 10 +2700.0 + 20 +4275.0 + 10 +2700.0 + 20 +4125.0 + 10 +1500.0 + 20 +4125.0 + 0 +HATCH + 5 +D8 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +1500.0 + 20 +4275.0 + 10 +2700.0 + 20 +4275.0 + 10 +2700.0 + 20 +4125.0 + 10 +1500.0 + 20 +4125.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +D9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3600.0 + 20 +4275.0 + 10 +4800.0 + 20 +4275.0 + 10 +4800.0 + 20 +4125.0 + 10 +3600.0 + 20 +4125.0 + 0 +HATCH + 5 +DA +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +3600.0 + 20 +4275.0 + 10 +4800.0 + 20 +4275.0 + 10 +4800.0 + 20 +4125.0 + 10 +3600.0 + 20 +4125.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +DB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +5700.0 + 20 +4275.0 + 10 +6200.0 + 20 +4275.0 + 10 +6200.0 + 20 +4125.0 + 10 +5700.0 + 20 +4125.0 + 0 +HATCH + 5 +DC +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +5700.0 + 20 +4275.0 + 10 +6200.0 + 20 +4275.0 + 10 +6200.0 + 20 +4125.0 + 10 +5700.0 + 20 +4125.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +DD +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +600.0 + 20 +4275.0 + 30 +0.0 + 11 +600.0 + 21 +4125.0 + 31 +0.0 + 0 +LINE + 5 +DE +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +1500.0 + 20 +4275.0 + 30 +0.0 + 11 +1500.0 + 21 +4125.0 + 31 +0.0 + 0 +LINE + 5 +DF +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +2700.0 + 20 +4275.0 + 30 +0.0 + 11 +2700.0 + 21 +4125.0 + 31 +0.0 + 0 +LINE + 5 +E0 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +3600.0 + 20 +4275.0 + 30 +0.0 + 11 +3600.0 + 21 +4125.0 + 31 +0.0 + 0 +LINE + 5 +E1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +4800.0 + 20 +4275.0 + 30 +0.0 + 11 +4800.0 + 21 +4125.0 + 31 +0.0 + 0 +LINE + 5 +E2 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +5700.0 + 20 +4275.0 + 30 +0.0 + 11 +5700.0 + 21 +4125.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +E3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6125.0 + 20 +0.0 + 10 +6125.0 + 20 +1700.0 + 10 +6275.0 + 20 +1700.0 + 10 +6275.0 + 20 +0.0 + 0 +HATCH + 5 +E4 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6125.0 + 20 +0.0 + 10 +6125.0 + 20 +1700.0 + 10 +6275.0 + 20 +1700.0 + 10 +6275.0 + 20 +0.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +E5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6125.0 + 20 +2600.0 + 10 +6125.0 + 20 +4200.0 + 10 +6275.0 + 20 +4200.0 + 10 +6275.0 + 20 +2600.0 + 0 +HATCH + 5 +E6 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6125.0 + 20 +2600.0 + 10 +6125.0 + 20 +4200.0 + 10 +6275.0 + 20 +4200.0 + 10 +6275.0 + 20 +2600.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +E7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6125.0 + 20 +1700.0 + 30 +0.0 + 11 +6275.0 + 21 +1700.0 + 31 +0.0 + 0 +LINE + 5 +E8 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6125.0 + 20 +2600.0 + 30 +0.0 + 11 +6275.0 + 21 +2600.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +E9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6125.0 + 20 +4200.0 + 10 +6125.0 + 20 +6300.0 + 10 +6275.0 + 20 +6300.0 + 10 +6275.0 + 20 +4200.0 + 0 +HATCH + 5 +EA +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6125.0 + 20 +4200.0 + 10 +6125.0 + 20 +6300.0 + 10 +6275.0 + 20 +6300.0 + 10 +6275.0 + 20 +4200.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +EB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6125.0 + 20 +7200.0 + 10 +6125.0 + 20 +8000.0 + 10 +6275.0 + 20 +8000.0 + 10 +6275.0 + 20 +7200.0 + 0 +HATCH + 5 +EC +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6125.0 + 20 +7200.0 + 10 +6125.0 + 20 +8000.0 + 10 +6275.0 + 20 +8000.0 + 10 +6275.0 + 20 +7200.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +ED +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6125.0 + 20 +6300.0 + 30 +0.0 + 11 +6275.0 + 21 +6300.0 + 31 +0.0 + 0 +LINE + 5 +EE +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6125.0 + 20 +7200.0 + 30 +0.0 + 11 +6275.0 + 21 +7200.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +EF +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3425.0 + 20 +0.0 + 10 +3425.0 + 20 +2400.0 + 10 +3575.0 + 20 +2400.0 + 10 +3575.0 + 20 +0.0 + 0 +HATCH + 5 +F0 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +3425.0 + 20 +0.0 + 10 +3425.0 + 20 +2400.0 + 10 +3575.0 + 20 +2400.0 + 10 +3575.0 + 20 +0.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +F1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3425.0 + 20 +3300.0 + 10 +3425.0 + 20 +4200.0 + 10 +3575.0 + 20 +4200.0 + 10 +3575.0 + 20 +3300.0 + 0 +HATCH + 5 +F2 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +3425.0 + 20 +3300.0 + 10 +3425.0 + 20 +4200.0 + 10 +3575.0 + 20 +4200.0 + 10 +3575.0 + 20 +3300.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +F3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +3425.0 + 20 +2400.0 + 30 +0.0 + 11 +3575.0 + 21 +2400.0 + 31 +0.0 + 0 +LINE + 5 +F4 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +3425.0 + 20 +3300.0 + 30 +0.0 + 11 +3575.0 + 21 +3300.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +F5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6200.0 + 20 +4275.0 + 10 +10000.0 + 20 +4275.0 + 10 +10000.0 + 20 +4125.0 + 10 +6200.0 + 20 +4125.0 + 0 +HATCH + 5 +F6 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6200.0 + 20 +4275.0 + 10 +10000.0 + 20 +4275.0 + 10 +10000.0 + 20 +4125.0 + 10 +6200.0 + 20 +4125.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +F7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +8125.0 + 20 +4200.0 + 10 +8125.0 + 20 +5800.0 + 10 +8275.0 + 20 +5800.0 + 10 +8275.0 + 20 +4200.0 + 0 +HATCH + 5 +F8 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +8125.0 + 20 +4200.0 + 10 +8125.0 + 20 +5800.0 + 10 +8275.0 + 20 +5800.0 + 10 +8275.0 + 20 +4200.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +F9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +8125.0 + 20 +6700.0 + 10 +8125.0 + 20 +8000.0 + 10 +8275.0 + 20 +8000.0 + 10 +8275.0 + 20 +6700.0 + 0 +HATCH + 5 +FA +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +8125.0 + 20 +6700.0 + 10 +8125.0 + 20 +8000.0 + 10 +8275.0 + 20 +8000.0 + 10 +8275.0 + 20 +6700.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +FB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +8125.0 + 20 +5800.0 + 30 +0.0 + 11 +8275.0 + 21 +5800.0 + 31 +0.0 + 0 +LINE + 5 +FC +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +8125.0 + 20 +6700.0 + 30 +0.0 + 11 +8275.0 + 21 +6700.0 + 31 +0.0 + 0 +INSERT + 5 +FD +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +1700.0 + 20 +150.0 + 30 +0.0 + 0 +ATTRIB + 5 +FF +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +2050.0 + 20 +-180.0 + 30 +0.0 + 40 +110.0 + 1 +D-101 + 11 +2050.0 + 21 +-180.0 + 31 +0.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 0 +SEQEND + 5 +FE +330 +FD +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +100 +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +6275.0 + 20 +1700.0 + 30 +0.0 + 50 +90.0 + 0 +ATTRIB + 5 +102 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +6605.0 + 20 +2050.0 + 30 +0.0 + 40 +110.0 + 1 +D-102 + 50 +90.0 + 11 +6605.0 + 21 +2050.0 + 31 +0.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 0 +SEQEND + 5 +101 +330 +100 +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +103 +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +3575.0 + 20 +2400.0 + 30 +0.0 + 50 +90.0 + 0 +ATTRIB + 5 +105 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +3905.0 + 20 +2750.0 + 30 +0.0 + 40 +110.0 + 1 +D-103 + 50 +90.0 + 11 +3905.0 + 21 +2750.0 + 31 +0.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 0 +SEQEND + 5 +104 +330 +103 +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +106 +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +700.0 + 20 +4275.0 + 30 +0.0 + 42 +-1.0 + 0 +ATTRIB + 5 +108 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +-1050.0 + 20 +4605.0 + 30 +0.0 + 40 +110.0 + 1 +D-104 + 50 +180.0 + 11 +-1050.0 + 21 +4605.0 + 31 +0.0 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 0 +SEQEND + 5 +107 +330 +106 +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +109 +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +2800.0 + 20 +4275.0 + 30 +0.0 + 0 +ATTRIB + 5 +10B +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +3150.0 + 20 +3945.0 + 30 +0.0 + 40 +110.0 + 1 +D-105 + 11 +3150.0 + 21 +3945.0 + 31 +0.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 0 +SEQEND + 5 +10A +330 +109 +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +10C +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +4900.0 + 20 +4275.0 + 30 +0.0 + 42 +-1.0 + 0 +ATTRIB + 5 +10E +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +-5250.0 + 20 +4605.0 + 30 +0.0 + 40 +110.0 + 1 +D-106 + 50 +180.0 + 11 +-5250.0 + 21 +4605.0 + 31 +0.0 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 0 +SEQEND + 5 +10D +330 +10C +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +10F +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +8275.0 + 20 +5800.0 + 30 +0.0 + 50 +90.0 + 0 +ATTRIB + 5 +111 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +8605.0 + 20 +6150.0 + 30 +0.0 + 40 +110.0 + 1 +D-107 + 50 +90.0 + 11 +8605.0 + 21 +6150.0 + 31 +0.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 0 +SEQEND + 5 +110 +330 +10F +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +112 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +3600.0 + 20 +-150.0 + 30 +0.0 + 41 +900.0 + 42 +300.0 + 0 +INSERT + 5 +114 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +6200.0 + 20 +-150.0 + 30 +0.0 + 41 +900.0 + 42 +300.0 + 0 +INSERT + 5 +116 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +8200.0 + 20 +-150.0 + 30 +0.0 + 41 +1200.0 + 42 +300.0 + 0 +INSERT + 5 +118 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +10150.0 + 20 +4800.0 + 30 +0.0 + 41 +1300.0 + 42 +300.0 + 50 +90.0 + 0 +INSERT + 5 +11A +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +1200.0 + 20 +7850.0 + 30 +0.0 + 41 +1400.0 + 42 +300.0 + 0 +INSERT + 5 +11C +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +3600.0 + 20 +7850.0 + 30 +0.0 + 41 +1600.0 + 42 +300.0 + 0 +INSERT + 5 +11E +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +6600.0 + 20 +7850.0 + 30 +0.0 + 41 +1200.0 + 42 +300.0 + 0 +INSERT + 5 +120 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +150.0 + 20 +5000.0 + 30 +0.0 + 41 +1400.0 + 42 +300.0 + 50 +90.0 + 0 +INSERT + 5 +122 +330 +17 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbBlockReference + 2 +SOFA + 10 +1200.0 + 20 +6900.0 + 30 +0.0 + 0 +INSERT + 5 +124 +330 +17 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbBlockReference + 2 +TABLE + 10 +3900.0 + 20 +5300.0 + 30 +0.0 + 0 +INSERT + 5 +126 +330 +17 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbBlockReference + 2 +BED + 10 +4300.0 + 20 +400.0 + 30 +0.0 + 0 +INSERT + 5 +128 +330 +17 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbBlockReference + 2 +BED + 10 +500.0 + 20 +600.0 + 30 +0.0 + 41 +0.8 + 42 +0.9 + 0 +INSERT + 5 +12A +330 +17 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbBlockReference + 2 +BATH + 10 +6800.0 + 20 +300.0 + 30 +0.0 + 0 +INSERT + 5 +12C +330 +17 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbBlockReference + 2 +WC + 10 +8300.0 + 20 +3200.0 + 30 +0.0 + 50 +90.0 + 0 +INSERT + 5 +12E +330 +17 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbBlockReference + 2 +SINK + 10 +6500.0 + 20 +3350.0 + 30 +0.0 + 0 +LINE + 5 +130 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +4400.0 + 30 +0.0 + 11 +7400.0 + 21 +4400.0 + 31 +0.0 + 0 +LINE + 5 +131 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +4680.0 + 30 +0.0 + 11 +7400.0 + 21 +4680.0 + 31 +0.0 + 0 +LINE + 5 +132 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +4960.0 + 30 +0.0 + 11 +7400.0 + 21 +4960.0 + 31 +0.0 + 0 +LINE + 5 +133 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +5240.0 + 30 +0.0 + 11 +7400.0 + 21 +5240.0 + 31 +0.0 + 0 +LINE + 5 +134 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +5520.0 + 30 +0.0 + 11 +7400.0 + 21 +5520.0 + 31 +0.0 + 0 +LINE + 5 +135 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +5800.0 + 30 +0.0 + 11 +7400.0 + 21 +5800.0 + 31 +0.0 + 0 +LINE + 5 +136 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +6080.0 + 30 +0.0 + 11 +7400.0 + 21 +6080.0 + 31 +0.0 + 0 +LINE + 5 +137 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +6360.0 + 30 +0.0 + 11 +7400.0 + 21 +6360.0 + 31 +0.0 + 0 +LINE + 5 +138 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +6640.0 + 30 +0.0 + 11 +7400.0 + 21 +6640.0 + 31 +0.0 + 0 +LINE + 5 +139 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +6920.0 + 30 +0.0 + 11 +7400.0 + 21 +6920.0 + 31 +0.0 + 0 +LINE + 5 +13A +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +7200.0 + 30 +0.0 + 11 +7400.0 + 21 +7200.0 + 31 +0.0 + 0 +LINE + 5 +13B +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +7480.0 + 30 +0.0 + 11 +7400.0 + 21 +7480.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +13C +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6400.0 + 20 +4400.0 + 10 +7400.0 + 20 +4400.0 + 10 +7400.0 + 20 +7760.0 + 10 +6400.0 + 20 +7760.0 + 0 +LWPOLYLINE + 5 +13D +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +6900.0 + 20 +4500.0 + 10 +6900.0 + 20 +7700.0 + 0 +LEADER + 5 +13E +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLeader + 3 +Standard + 73 +3 + 76 +3 + 10 +6900.0 + 20 +7700.0 + 30 +0.0 + 10 +6820.0 + 20 +7400.0 + 30 +0.0 + 10 +6980.0 + 20 +7400.0 + 30 +0.0 + 0 +TEXT + 5 +13F +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbText + 10 +6950.0 + 20 +4600.0 + 30 +0.0 + 40 +150.0 + 1 +UP + 7 +ARCH-TEXT + 11 +6950.0 + 21 +4600.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +140 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +0.0 + 20 +-1700.0 + 30 +0.0 + 11 +0.0 + 21 +9200.0 + 31 +0.0 + 0 +INSERT + 5 +141 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +0.0 + 20 +-2000.0 + 30 +0.0 + 0 +ATTRIB + 5 +143 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +0.0 + 20 +-2000.0 + 30 +0.0 + 40 +300.0 + 1 +1 + 72 +4 + 11 +0.0 + 21 +-2000.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 0 +SEQEND + 5 +142 +330 +141 +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +144 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +3500.0 + 20 +-1700.0 + 30 +0.0 + 11 +3500.0 + 21 +9200.0 + 31 +0.0 + 0 +INSERT + 5 +145 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +3500.0 + 20 +-2000.0 + 30 +0.0 + 0 +ATTRIB + 5 +147 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +3500.0 + 20 +-2000.0 + 30 +0.0 + 40 +300.0 + 1 +2 + 72 +4 + 11 +3500.0 + 21 +-2000.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 0 +SEQEND + 5 +146 +330 +145 +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +148 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +6200.0 + 20 +-1700.0 + 30 +0.0 + 11 +6200.0 + 21 +9200.0 + 31 +0.0 + 0 +INSERT + 5 +149 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +6200.0 + 20 +-2000.0 + 30 +0.0 + 0 +ATTRIB + 5 +14B +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +6200.0 + 20 +-2000.0 + 30 +0.0 + 40 +300.0 + 1 +3 + 72 +4 + 11 +6200.0 + 21 +-2000.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 0 +SEQEND + 5 +14A +330 +149 +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +14C +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +10000.0 + 20 +-1700.0 + 30 +0.0 + 11 +10000.0 + 21 +9200.0 + 31 +0.0 + 0 +INSERT + 5 +14D +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +10000.0 + 20 +-2000.0 + 30 +0.0 + 0 +ATTRIB + 5 +14F +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +10000.0 + 20 +-2000.0 + 30 +0.0 + 40 +300.0 + 1 +4 + 72 +4 + 11 +10000.0 + 21 +-2000.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 0 +SEQEND + 5 +14E +330 +14D +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +150 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +-1700.0 + 20 +0.0 + 30 +0.0 + 11 +11200.0 + 21 +0.0 + 31 +0.0 + 0 +INSERT + 5 +151 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +-2000.0 + 20 +0.0 + 30 +0.0 + 0 +ATTRIB + 5 +153 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +-2000.0 + 20 +0.0 + 30 +0.0 + 40 +300.0 + 1 +A + 72 +4 + 11 +-2000.0 + 21 +0.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 0 +SEQEND + 5 +152 +330 +151 +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +154 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +-1700.0 + 20 +4200.0 + 30 +0.0 + 11 +11200.0 + 21 +4200.0 + 31 +0.0 + 0 +INSERT + 5 +155 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +-2000.0 + 20 +4200.0 + 30 +0.0 + 0 +ATTRIB + 5 +157 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +-2000.0 + 20 +4200.0 + 30 +0.0 + 40 +300.0 + 1 +B + 72 +4 + 11 +-2000.0 + 21 +4200.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 0 +SEQEND + 5 +156 +330 +155 +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +158 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +-1700.0 + 20 +8000.0 + 30 +0.0 + 11 +11200.0 + 21 +8000.0 + 31 +0.0 + 0 +INSERT + 5 +159 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +-2000.0 + 20 +8000.0 + 30 +0.0 + 0 +ATTRIB + 5 +15B +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +-2000.0 + 20 +8000.0 + 30 +0.0 + 40 +300.0 + 1 +C + 72 +4 + 11 +-2000.0 + 21 +8000.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 0 +SEQEND + 5 +15A +330 +159 +100 +AcDbEntity + 8 +A-GRID + 0 +MTEXT + 5 +15C +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +1750.0 + 20 +2100.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;BEDROOM 1\P\fArial|b0;14.7 m² + 7 +ARCH-TEXT + 0 +MTEXT + 5 +15D +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +4850.0 + 20 +2100.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;BEDROOM 2\P\fArial|b0;11.3 m² + 7 +ARCH-TEXT + 0 +MTEXT + 5 +15E +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +7500.0 + 20 +2100.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;BATH\P\fArial|b0;16.0 m² + 7 +ARCH-TEXT + 0 +MTEXT + 5 +15F +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +3100.0 + 20 +6100.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;LIVING ROOM\P\fArial|b0;23.6 m² + 7 +ARCH-TEXT + 0 +MTEXT + 5 +160 +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +7150.0 + 20 +6100.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;KITCHEN\P\fArial|b0;14.4 m² + 7 +ARCH-TEXT + 0 +MTEXT + 5 +161 +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +1500.0 + 20 +4650.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;HALL + 7 +ARCH-TEXT + 0 +DIMENSION + 5 +162 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension + 2 +*D1 + 3 +PLAN50 + 10 +0.0 + 20 +-3100.0 + 30 +0.0 + 11 +5000.0 + 21 +-2924.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +10000.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +175 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension + 2 +*D2 + 3 +PLAN50 + 10 +0.0 + 20 +-2600.0 + 30 +0.0 + 11 +1750.0 + 21 +-2424.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +3500.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +184 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension + 2 +*D3 + 3 +PLAN50 + 10 +3500.0 + 20 +-2600.0 + 30 +0.0 + 11 +4850.0 + 21 +-2424.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +3500.0 + 23 +0.0 + 33 +0.0 + 14 +6200.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +193 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension + 2 +*D4 + 3 +PLAN50 + 10 +6200.0 + 20 +-2600.0 + 30 +0.0 + 11 +8100.0 + 21 +-2424.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +6200.0 + 23 +0.0 + 33 +0.0 + 14 +10000.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1A2 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension + 2 +*D5 + 3 +PLAN50 + 10 +-3100.0 + 20 +0.0 + 30 +0.0 + 11 +-3276.0 + 21 +4000.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +0.0 + 24 +8000.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1B1 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension + 2 +*D6 + 3 +PLAN50 + 10 +-2600.0 + 20 +0.0 + 30 +0.0 + 11 +-2776.0 + 21 +2100.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +0.0 + 24 +4200.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1C0 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension + 2 +*D7 + 3 +PLAN50 + 10 +-2600.0 + 20 +4200.0 + 30 +0.0 + 11 +-2776.0 + 21 +6100.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +4200.0 + 33 +0.0 + 14 +0.0 + 24 +8000.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +LWPOLYLINE + 5 +1CF +330 +17 +100 +AcDbEntity + 8 +A-WALL + 6 +DASHED +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +11500.0 + 20 +500.0 + 10 +14500.0 + 20 +3500.0 + 0 +DIMENSION + 5 +1D0 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension + 2 +*D8 + 3 +PLAN50 + 10 +11994.974746830583 + 20 +5.025253169416828 + 30 +0.0 + 11 +13370.523953341752 + 21 +1629.4760466582493 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +11500.0 + 23 +500.0 + 33 +0.0 + 14 +14500.0 + 24 +3500.0 + 34 +0.0 + 50 +45.0 +100 +AcDbRotatedDimension + 0 +LINE + 5 +1DF +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 11 +14500.0 + 21 +500.0 + 31 +0.0 + 0 +DIMENSION + 5 +1E0 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension + 2 +*D9 + 3 +PLAN50 + 10 +14500.0 + 20 +500.0 + 30 +0.0 + 11 +12546.405475591537 + 21 +933.4353397314832 + 31 +0.0 + 70 +34 + 71 +5 + 1 +<> +100 +AcDb2LineAngularDimension + 13 +11500.0 + 23 +500.0 + 33 +0.0 + 14 +14500.0 + 24 +3500.0 + 34 +0.0 + 15 +11500.0 + 25 +500.0 + 35 +0.0 + 16 +12300.0 + 26 +700.0 + 36 +0.0 + 0 +DIMENSION + 5 +1F3 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension + 2 +*D10 + 3 +PLAN50 + 10 +6275.0 + 20 +1700.0 + 30 +0.0 + 11 +7269.192134348285 + 21 +2943.093721325951 + 31 +0.0 + 70 +36 + 71 +5 + 1 +<> +100 +AcDbRadialDimension + 15 +6911.396103067893 + 25 +2336.396103067893 + 35 +0.0 + 0 +INSERT + 5 +1FE +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 2 +NORTH + 10 +12200.0 + 20 +8700.0 + 30 +0.0 + 0 +INSERT + 5 +200 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +5000.0 + 20 +3400.0 + 30 +0.0 + 0 +ATTRIB + 5 +202 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +5320.0 + 20 +3690.0 + 30 +0.0 + 40 +120.0 + 1 +±0.00 + 11 +5320.0 + 21 +3690.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 0 +SEQEND + 5 +201 +330 +200 +100 +AcDbEntity + 8 +A-ANNO + 0 +TEXT + 5 +203 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +0.0 + 20 +-4700.0 + 30 +0.0 + 40 +330.0 + 1 +GROUND FLOOR PLAN 1:50 + 7 +ARCH-TITLE + 11 +0.0 + 21 +-4700.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +204 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +370 +70 +100 +AcDbLine + 10 +0.0 + 20 +-4900.0 + 30 +0.0 + 11 +4500.0 + 21 +-4900.0 + 31 +0.0 + 0 +TEXT + 5 +205 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +0.0 + 20 +-5200.0 + 30 +0.0 + 40 +130.0 + 1 +Drawn for the exav demo. Dimensions in millimetres. + 7 +ARCH-NOTE + 11 +0.0 + 21 +-5200.0 + 31 +0.0 +100 +AcDbText + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +A +330 +0 +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ACAD_COLOR +350 +B + 3 +ACAD_GROUP +350 +C + 3 +ACAD_LAYOUT +350 +D + 3 +ACAD_MATERIAL +350 +E + 3 +ACAD_MLEADERSTYLE +350 +F + 3 +ACAD_MLINESTYLE +350 +10 + 3 +ACAD_PLOTSETTINGS +350 +11 + 3 +ACAD_PLOTSTYLENAME +350 +12 + 3 +ACAD_SCALELIST +350 +14 + 3 +ACAD_TABLESTYLE +350 +15 + 3 +ACAD_VISUALSTYLE +350 +16 + 3 +EZDXF_META +350 +2D + 0 +DICTIONARY + 5 +B +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +C +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +D +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Model +350 +1A + 3 +Layout1 +350 +1E + 3 +A3 Plan +350 +209 + 0 +DICTIONARY + 5 +E +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ByBlock +350 +1F + 3 +ByLayer +350 +20 + 3 +Global +350 +21 + 0 +DICTIONARY + 5 +F +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +2C + 0 +DICTIONARY + 5 +10 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +22 + 0 +DICTIONARY + 5 +11 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +ACDBDICTIONARYWDFLT + 5 +12 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Normal +350 +13 +100 +AcDbDictionaryWithDefault +340 +13 + 0 +ACDBPLACEHOLDER + 5 +13 +330 +12 + 0 +DICTIONARY + 5 +14 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +15 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +16 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +LAYOUT + 5 +1A +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +1024 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 +1 + 71 +0 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +17 + 0 +LAYOUT + 5 +1E +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +0 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 +1 + 71 +1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +1B + 0 +MATERIAL + 5 +1F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByBlock + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +20 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByLayer + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +21 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +Global + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MLINESTYLE + 5 +22 +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMlineStyle + 2 +Standard + 70 +0 + 3 + + 62 +256 + 51 +90.0 + 52 +90.0 + 71 +2 + 49 +0.5 + 62 +256 + 6 +BYLAYER + 49 +-0.5 + 62 +256 + 6 +BYLAYER + 0 +MLEADERSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +F +102 +} +330 +F +100 +AcDbMLeaderStyle +179 +2 +170 +2 +171 +1 +172 +0 + 90 +2 + 40 +0.0 + 41 +0.0 +173 +1 + 91 +-1056964608 + 92 +-2 +290 +1 + 42 +2.0 +291 +1 + 43 +8.0 + 3 +Standard + 44 +4.0 +300 + +342 +29 +174 +1 +175 +1 +176 +0 +178 +1 + 93 +-1056964608 + 45 +4.0 +292 +0 +297 +0 + 46 +4.0 + 94 +-1056964608 + 47 +1.0 + 49 +1.0 +140 +1.0 +294 +1 +141 +0.0 +177 +0 +142 +1.0 +295 +0 +296 +0 +143 +3.75 +271 +0 +272 +9 +273 +9 + 0 +DICTIONARY + 5 +2D +330 +A +100 +AcDbDictionary +281 +1 + 3 +CREATED_BY_EZDXF +350 +2E + 3 +WRITTEN_BY_EZDXF +350 +217 + 0 +DICTIONARYVAR + 5 +2E +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +LAYOUT + 5 +209 +330 +D +100 +AcDbPlotSettings + 1 + + 2 +DWG to PDF.pc3 + 4 +ezdxf_(420.00_x_297.00_MM) + 6 + + 40 +10.0 + 41 +10.0 + 42 +10.0 + 43 +10.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +672 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +A3 Plan + 70 +1 + 71 +3 + 10 +-10.0 + 20 +-10.0 + 11 +410.0 + 21 +287.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +206 +331 +20A + 0 +DICTIONARYVAR + 5 +217 +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +ENDSEC + 0 +EOF diff --git a/crates/exav-viewer/demo/examples/files/cad/house-plan.dxf b/crates/exav-viewer/demo/examples/files/cad/house-plan.dxf new file mode 100644 index 0000000..6cdcec3 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/cad/house-plan.dxf @@ -0,0 +1,17000 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1032 + 9 +$ACADMAINTVER + 90 +4 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$LASTSAVEDBY + 1 +ezdxf + 9 +$REQUIREDVERSIONS +160 +0 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$EXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 +0 + 9 +$REGENMODE + 70 +1 + 9 +$FILLMODE + 70 +1 + 9 +$QTEXTMODE + 70 +0 + 9 +$MIRRTEXT + 70 +1 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 +1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 +256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 +0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 +0 + 9 +$DIMLIM + 70 +0 + 9 +$DIMTIH + 70 +0 + 9 +$DIMTOH + 70 +0 + 9 +$DIMSE1 + 70 +0 + 9 +$DIMSE2 + 70 +0 + 9 +$DIMTAD + 70 +1 + 9 +$DIMZIN + 70 +8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 +1 + 9 +$DIMSHO + 70 +1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 +0 + 9 +$DIMALTD + 70 +3 + 9 +$DIMALTF + 40 +0.03937007874 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 +1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 +0 + 9 +$DIMSOXD + 70 +0 + 9 +$DIMSAH + 70 +0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 +0 + 9 +$DIMCLRE + 70 +0 + 9 +$DIMCLRT + 70 +0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 +0 + 9 +$DIMSD1 + 70 +0 + 9 +$DIMSD2 + 70 +0 + 9 +$DIMTOLJ + 70 +0 + 9 +$DIMTZIN + 70 +8 + 9 +$DIMALTZ + 70 +0 + 9 +$DIMALTTZ + 70 +0 + 9 +$DIMUPT + 70 +0 + 9 +$DIMDEC + 70 +2 + 9 +$DIMTDEC + 70 +2 + 9 +$DIMALTU + 70 +2 + 9 +$DIMALTTD + 70 +3 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 +0 + 9 +$DIMADEC + 70 +0 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 +0 + 9 +$DIMDSEP + 70 +44 + 9 +$DIMATFIT + 70 +3 + 9 +$DIMFRAC + 70 +0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 +2 + 9 +$DIMLWD + 70 +-2 + 9 +$DIMLWE + 70 +-2 + 9 +$DIMTMOVE + 70 +0 + 9 +$DIMFXL + 40 +1.0 + 9 +$DIMFXLON + 70 +0 + 9 +$DIMJOGANG + 40 +0.785398163397 + 9 +$DIMTFILL + 70 +0 + 9 +$DIMTFILLCLR + 70 +0 + 9 +$DIMARCSYM + 70 +0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$DIMTXTDIRECTION + 70 +0 + 9 +$LUNITS + 70 +2 + 9 +$LUPREC + 70 +4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 +0 + 9 +$AUPREC + 70 +2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 +0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 +0 + 9 +$TDCREATE + 40 +2451545.0 + 9 +$TDUCREATE + 40 +2451545.0 + 9 +$TDUPDATE + 40 +2451545.0 + 9 +$TDUUPDATE + 40 +2451545.0 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 +1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 +0 + 9 +$PDMODE + 70 +0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 +0 + 9 +$SPLINETYPE + 70 +6 + 9 +$SPLINESEGS + 70 +8 + 9 +$HANDSEED + 5 +218 + 9 +$SURFTAB1 + 70 +6 + 9 +$SURFTAB2 + 70 +6 + 9 +$SURFTYPE + 70 +6 + 9 +$SURFU + 70 +6 + 9 +$SURFV + 70 +6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 +0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 +0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 +0 + 9 +$USERI2 + 70 +0 + 9 +$USERI3 + 70 +0 + 9 +$USERI4 + 70 +0 + 9 +$USERI5 + 70 +0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 +1 + 9 +$SHADEDGE + 70 +3 + 9 +$SHADEDIF + 70 +70 + 9 +$TILEMODE + 70 +1 + 9 +$MAXACTVP + 70 +64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 +0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 +0 + 9 +$VISRETAIN + 70 +1 + 9 +$PLINEGEN + 70 +0 + 9 +$PSLTSCALE + 70 +1 + 9 +$TREEDEPTH + 70 +3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 +0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 +1 + 9 +$MEASUREMENT + 70 +1 + 9 +$CELWEIGHT +370 +-1 + 9 +$ENDCAPS +280 +0 + 9 +$JOINSTYLE +280 +0 + 9 +$LWDISPLAY +290 +0 + 9 +$INSUNITS + 70 +4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 +1 + 9 +$CEPSNTYPE +380 +0 + 9 +$PSTYLEMODE +290 +1 + 9 +$FINGERPRINTGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$VERSIONGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$EXTNAMES +290 +1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 +0 + 9 +$SORTENTS +280 +127 + 9 +$INDEXCTL +280 +0 + 9 +$HIDETEXT +280 +1 + 9 +$XCLIPFRAME +280 +1 + 9 +$HALOGAP +280 +0 + 9 +$OBSCOLOR + 70 +257 + 9 +$OBSLTYPE +280 +0 + 9 +$INTERSECTIONDISPLAY +280 +0 + 9 +$INTERSECTIONCOLOR + 70 +257 + 9 +$DIMASSOC +280 +2 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 +0 + 9 +$LENSLENGTH + 40 +50.0 + 9 +$CAMERAHEIGHT + 40 +0.0 + 9 +$STEPSPERSEC + 40 +24.0 + 9 +$STEPSIZE + 40 +100.0 + 9 +$3DDWFPREC + 40 +2.0 + 9 +$PSOLWIDTH + 40 +0.005 + 9 +$PSOLHEIGHT + 40 +0.08 + 9 +$LOFTANG1 + 40 +1.570796326795 + 9 +$LOFTANG2 + 40 +1.570796326795 + 9 +$LOFTMAG1 + 40 +0.0 + 9 +$LOFTMAG2 + 40 +0.0 + 9 +$LOFTPARAM + 70 +7 + 9 +$LOFTNORMALS +280 +1 + 9 +$LATITUDE + 40 +37.795 + 9 +$LONGITUDE + 40 +-122.394 + 9 +$NORTHDIRECTION + 40 +0.0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 +1 + 9 +$TILEMODELIGHTSYNCH +280 +1 + 9 +$CMATERIAL +347 +20 + 9 +$SOLIDHIST +280 +0 + 9 +$SHOWHIST +280 +1 + 9 +$DWFFRAME +280 +2 + 9 +$DGNFRAME +280 +2 + 9 +$REALWORLDSCALE +290 +1 + 9 +$INTERFERECOLOR + 62 +256 + 9 +$CSHADOW +280 +0 + 9 +$SHADOWPLANELOCATION + 40 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +CELLSTYLEMAP + 2 +AcDbCellStyleMap + 3 +ObjectDBX Classes + 90 +1152 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MENTALRAYRENDERSETTINGS + 2 +AcDbMentalRayRenderSettings + 3 +SCENEOE + 90 +1024 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBDETAILVIEWSTYLE + 2 +AcDbDetailViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBSECTIONVIEWSTYLE + 2 +AcDbSectionViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +RASTERVARIABLES + 2 +AcDbRasterVariables + 3 +ISM + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 +1 + 0 +VPORT + 5 +214 +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +5835.463185876482 + 22 +2324.253181513731 + 13 +0.0 + 23 +0.0 + 14 +0.5 + 24 +0.5 + 15 +0.5 + 25 +0.5 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +15878.827193569996 + 41 +1.34 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +1000 + 73 +1 + 74 +3 + 75 +0 + 76 +0 + 77 +0 + 78 +0 +281 +0 + 65 +1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 +21 + 0 +LTYPE + 5 +24 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +25 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +26 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +2F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 +0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +5.08 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +30 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 +0 + 3 +Center (2x) ________ __ ________ __ ________ + 72 +65 + 73 +4 + 40 +8.89 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 +0 + 3 +Center (.5x) ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +2.54 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +32 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 +0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 +65 + 73 +2 + 40 +1.524 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +33 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 +0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ____ + 72 +65 + 73 +2 + 40 +3.048 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +34 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 +0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 +65 + 73 +2 + 40 +0.762 + 49 +0.635 + 74 +0 + 49 +-0.127 + 74 +0 + 0 +LTYPE + 5 +35 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM + 70 +0 + 3 +Phantom ______ __ __ ______ __ __ ______ + 72 +65 + 73 +6 + 40 +6.35 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOMX2 + 70 +0 + 3 +Phantom (2x)____________ ____ ____ ____________ + 72 +65 + 73 +6 + 40 +10.795 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +37 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 +0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___ + 72 +65 + 73 +6 + 40 +3.175 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +38 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 +0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 +65 + 73 +4 + 40 +3.556 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +39 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 +0 + 3 +Dash dot (2x) ____ . ____ . ____ . ____ + 72 +65 + 73 +4 + 40 +6.096 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 +0 + 3 +Dash dot (.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +4 + 40 +1.778 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 +0 + 3 +Dot . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.508 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 +0 + 3 +Dot (2x) . . . . . . . . + 72 +65 + 73 +2 + 40 +1.016 + 49 +0.0 + 74 +0 + 49 +-1.016 + 74 +0 + 0 +LTYPE + 5 +3D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 +0 + 3 +Dot (.5) . . . . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.254 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 +0 + 3 +Divide __ . . __ . . __ . . __ . . __ . . __ + 72 +65 + 73 +6 + 40 +4.064 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 +0 + 3 +Divide (2x) ____ . . ____ . . ____ . . ____ + 72 +65 + 73 +6 + 40 +6.604 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +40 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 +0 + 3 +Divide(.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +6 + 40 +2.032 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 +17 + 0 +LAYER + 5 +27 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 62 +7 + 6 +Continuous +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +28 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Defpoints + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +41 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-WALL + 70 +0 + 62 +7 + 6 +Continuous +370 +50 +390 +13 +347 +21 + 0 +LAYER + 5 +42 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-WALL-PAT + 70 +0 + 62 +8 + 6 +Continuous +370 +9 +390 +13 +347 +21 + 0 +LAYER + 5 +43 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-DOOR + 70 +0 + 62 +3 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +44 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-WIND + 70 +0 + 62 +5 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +45 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-FURN + 70 +0 + 62 +9 + 6 +Continuous +370 +13 +390 +13 +347 +21 + 0 +LAYER + 5 +46 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-FIXT + 70 +0 + 62 +4 + 6 +Continuous +370 +18 +390 +13 +347 +21 + 0 +LAYER + 5 +47 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-GRID + 70 +0 + 62 +1 + 6 +CENTER +370 +9 +390 +13 +347 +21 + 0 +LAYER + 5 +48 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-ANNO + 70 +0 + 62 +2 + 6 +Continuous +370 +18 +390 +13 +347 +21 + 0 +LAYER + 5 +49 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-DIMS + 70 +0 + 62 +3 + 6 +Continuous +370 +13 +390 +13 +347 +21 + 0 +LAYER + 5 +4A +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-AREA + 70 +0 + 62 +6 + 6 +Continuous +370 +9 +390 +13 +347 +21 + 0 +LAYER + 5 +4B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-FLOR + 70 +0 + 62 +252 + 6 +Continuous +370 +9 +390 +13 +347 +21 + 0 +LAYER + 5 +4C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-SLAB + 70 +0 + 62 +254 + 6 +Continuous +370 +9 +390 +13 +347 +21 + 0 +LAYER + 5 +4D +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-STAIR + 70 +0 + 62 +30 + 6 +Continuous +370 +18 +390 +13 +347 +21 + 0 +LAYER + 5 +4E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-SHEET + 70 +0 + 62 +7 + 6 +Continuous +370 +35 +390 +13 +347 +21 + 0 +LAYER + 5 +4F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +A-VPORT + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +9 +390 +13 +347 +21 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 +4 + 0 +STYLE + 5 +29 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +50 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +ARCH-TEXT + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +STYLE + 5 +51 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +ARCH-TITLE + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +times.ttf + 4 + + 0 +STYLE + 5 +52 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +ARCH-NOTE + 70 +0 + 40 +0.0 + 41 +0.9 + 50 +15.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 +3 + 0 +APPID + 5 +2A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 +0 + 0 +APPID + 5 +215 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +HATCHBACKGROUNDCOLOR + 70 +0 + 0 +APPID + 5 +216 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +EZDXF + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +4 +330 +0 +100 +AcDbSymbolTable + 70 +2 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +2B +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 +0 + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +0 +177 +0 +178 +0 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +371 +-2 +372 +-2 + 0 +DIMSTYLE +105 +53 +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +PLAN50 + 70 +0 + 40 +1.0 + 41 +176.0 + 42 +176.0 + 43 +3.75 + 44 +132.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +220.0 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +66.0 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +3 +177 +3 +178 +2 +179 +2 +271 +0 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +340 +50 +371 +-2 +372 +-2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 +25 + 0 +BLOCK_RECORD + 5 +17 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +1A + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +54 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +DOOR +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +5B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +WINDOW +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +64 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +BED +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +6B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +TABLE +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +77 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +SOFA +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +7F +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +WC +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +84 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +SINK +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +8A +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +BATH +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +8F +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +AXIS +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +94 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +NORTH +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +9A +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +LEVEL +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +163 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D1 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +168 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_CLOSEDFILLED +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +176 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D2 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +185 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D3 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +194 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D4 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1A3 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D5 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1B2 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D6 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1C1 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D7 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1D1 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D8 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1E1 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D9 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1F4 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D10 +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +206 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space0 +340 +209 + 70 +0 +280 +1 +281 +0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +18 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +19 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +55 +330 +54 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +DOOR + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +DOOR + 1 + + 0 +LINE + 5 +57 +330 +54 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +900.0 + 31 +0.0 + 0 +ARC + 5 +58 +330 +54 +100 +AcDbEntity + 8 +A-DOOR + 6 +DASHED +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +900.0 +100 +AcDbArc + 50 +0.0 + 51 +90.0 + 0 +LWPOLYLINE + 5 +59 +330 +54 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +900.0 + 20 +0.0 + 10 +900.0 + 20 +40.0 + 10 +0.0 + 20 +40.0 + 0 +ATTDEF + 5 +5A +330 +54 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +350.0 + 20 +-330.0 + 30 +0.0 + 40 +110.0 + 1 +D-000 +100 +AcDbAttributeDefinition + 3 + + 2 +TAG + 70 +0 + 71 +1 + 72 +0 + 0 +ENDBLK + 5 +56 +330 +54 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +5C +330 +5B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +WINDOW + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +WINDOW + 1 + + 0 +LINE + 5 +5E +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +1.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +5F +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.35 + 30 +0.0 + 11 +1.0 + 21 +0.35 + 31 +0.0 + 0 +LINE + 5 +60 +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.65 + 30 +0.0 + 11 +1.0 + 21 +0.65 + 31 +0.0 + 0 +LINE + 5 +61 +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +1.0 + 30 +0.0 + 11 +1.0 + 21 +1.0 + 31 +0.0 + 0 +LINE + 5 +62 +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +1.0 + 31 +0.0 + 0 +LINE + 5 +63 +330 +5B +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +1.0 + 20 +0.0 + 30 +0.0 + 11 +1.0 + 21 +1.0 + 31 +0.0 + 0 +ENDBLK + 5 +5D +330 +5B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +65 +330 +64 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +BED + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +BED + 1 + + 0 +LWPOLYLINE + 5 +67 +330 +64 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1600.0 + 20 +0.0 + 10 +1600.0 + 20 +2000.0 + 10 +0.0 + 20 +2000.0 + 0 +LWPOLYLINE + 5 +68 +330 +64 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +80.0 + 20 +1300.0 + 10 +760.0 + 20 +1300.0 + 10 +760.0 + 20 +1920.0 + 10 +80.0 + 20 +1920.0 + 0 +LWPOLYLINE + 5 +69 +330 +64 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +1300.0 + 10 +1520.0 + 20 +1300.0 + 10 +1520.0 + 20 +1920.0 + 10 +840.0 + 20 +1920.0 + 0 +LINE + 5 +6A +330 +64 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbLine + 10 +0.0 + 20 +1200.0 + 30 +0.0 + 11 +1600.0 + 21 +1200.0 + 31 +0.0 + 0 +ENDBLK + 5 +66 +330 +64 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +6C +330 +6B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +TABLE + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +TABLE + 1 + + 0 +LWPOLYLINE + 5 +6E +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1800.0 + 20 +0.0 + 10 +1800.0 + 20 +900.0 + 10 +0.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +6F +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +-450.0 + 10 +550.0 + 20 +-450.0 + 10 +550.0 + 20 +-50.0 + 10 +150.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +70 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +950.0 + 10 +550.0 + 20 +950.0 + 10 +550.0 + 20 +1350.0 + 10 +150.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +71 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +600.0 + 20 +-450.0 + 10 +1000.0 + 20 +-450.0 + 10 +1000.0 + 20 +-50.0 + 10 +600.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +72 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +600.0 + 20 +950.0 + 10 +1000.0 + 20 +950.0 + 10 +1000.0 + 20 +1350.0 + 10 +600.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +73 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1050.0 + 20 +-450.0 + 10 +1450.0 + 20 +-450.0 + 10 +1450.0 + 20 +-50.0 + 10 +1050.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +74 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1050.0 + 20 +950.0 + 10 +1450.0 + 20 +950.0 + 10 +1450.0 + 20 +1350.0 + 10 +1050.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +75 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1500.0 + 20 +-450.0 + 10 +1900.0 + 20 +-450.0 + 10 +1900.0 + 20 +-50.0 + 10 +1500.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +76 +330 +6B +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1500.0 + 20 +950.0 + 10 +1900.0 + 20 +950.0 + 10 +1900.0 + 20 +1350.0 + 10 +1500.0 + 20 +1350.0 + 0 +ENDBLK + 5 +6D +330 +6B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +78 +330 +77 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +SOFA + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +SOFA + 1 + + 0 +LWPOLYLINE + 5 +7A +330 +77 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +2200.0 + 20 +0.0 + 10 +2200.0 + 20 +950.0 + 10 +0.0 + 20 +950.0 + 0 +LWPOLYLINE + 5 +7B +330 +77 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +2200.0 + 20 +0.0 + 10 +2200.0 + 20 +250.0 + 10 +0.0 + 20 +250.0 + 0 +LWPOLYLINE + 5 +7C +330 +77 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +120.0 + 20 +300.0 + 10 +720.0 + 20 +300.0 + 10 +720.0 + 20 +900.0 + 10 +120.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +7D +330 +77 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +770.0 + 20 +300.0 + 10 +1370.0 + 20 +300.0 + 10 +1370.0 + 20 +900.0 + 10 +770.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +7E +330 +77 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1420.0 + 20 +300.0 + 10 +2020.0 + 20 +300.0 + 10 +2020.0 + 20 +900.0 + 10 +1420.0 + 20 +900.0 + 0 +ENDBLK + 5 +79 +330 +77 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +80 +330 +7F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +WC + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +WC + 1 + + 0 +LWPOLYLINE + 5 +82 +330 +7F +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +400.0 + 20 +0.0 + 10 +400.0 + 20 +200.0 + 10 +0.0 + 20 +200.0 + 0 +ELLIPSE + 5 +83 +330 +7F +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbEllipse + 10 +200.0 + 20 +-250.0 + 30 +0.0 + 11 +0.0 + 21 +230.0 + 31 +0.0 + 40 +0.8 + 41 +0.0 + 42 +6.283185307179586 + 0 +ENDBLK + 5 +81 +330 +7F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +85 +330 +84 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +SINK + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +SINK + 1 + + 0 +LWPOLYLINE + 5 +87 +330 +84 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +600.0 + 20 +0.0 + 10 +600.0 + 20 +450.0 + 10 +0.0 + 20 +450.0 + 0 +CIRCLE + 5 +88 +330 +84 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbCircle + 10 +300.0 + 20 +225.0 + 30 +0.0 + 40 +160.0 + 0 +CIRCLE + 5 +89 +330 +84 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbCircle + 10 +300.0 + 20 +225.0 + 30 +0.0 + 40 +25.0 + 0 +ENDBLK + 5 +86 +330 +84 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8B +330 +8A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +BATH + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +BATH + 1 + + 0 +LWPOLYLINE + 5 +8D +330 +8A +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1700.0 + 20 +0.0 + 10 +1700.0 + 20 +750.0 + 10 +0.0 + 20 +750.0 + 0 +LWPOLYLINE + 5 +8E +330 +8A +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +5 + 70 +1 + 10 +100.0 + 20 +100.0 + 10 +1500.0 + 20 +100.0 + 10 +1600.0 + 20 +375.0 + 10 +1500.0 + 20 +650.0 + 10 +100.0 + 20 +650.0 + 0 +ENDBLK + 5 +8C +330 +8A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +90 +330 +8F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +AXIS + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +AXIS + 1 + + 0 +CIRCLE + 5 +92 +330 +8F +100 +AcDbEntity + 8 +A-GRID +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +300.0 + 0 +ATTDEF + 5 +93 +330 +8F +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +300.0 + 1 +A + 72 +4 + 11 +0.0 + 21 +0.0 + 31 +0.0 +100 +AcDbAttributeDefinition + 3 + + 2 +ID + 70 +0 + 71 +1 + 72 +0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +91 +330 +8F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +95 +330 +94 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +NORTH + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +NORTH + 1 + + 0 +CIRCLE + 5 +97 +330 +94 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +500.0 + 0 +SOLID + 5 +98 +330 +94 +100 +AcDbEntity + 8 +A-ANNO + 62 +7 +100 +AcDbTrace + 10 +0.0 + 20 +650.0 + 30 +0.0 + 11 +-170.0 + 21 +-400.0 + 31 +0.0 + 12 +0.0 + 22 +-200.0 + 32 +0.0 + 13 +170.0 + 23 +-400.0 + 33 +0.0 + 0 +TEXT + 5 +99 +330 +94 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +0.0 + 20 +800.0 + 30 +0.0 + 40 +300.0 + 1 +N + 72 +1 + 11 +0.0 + 21 +800.0 + 31 +0.0 +100 +AcDbText + 73 +1 + 0 +ENDBLK + 5 +96 +330 +94 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +9B +330 +9A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +LEVEL + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +LEVEL + 1 + + 0 +LWPOLYLINE + 5 +9D +330 +9A +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbPolyline + 90 +3 + 70 +1 + 10 +-250.0 + 20 +250.0 + 10 +0.0 + 20 +0.0 + 10 +250.0 + 20 +250.0 + 0 +LINE + 5 +9E +330 +9A +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbLine + 10 +-250.0 + 20 +250.0 + 30 +0.0 + 11 +900.0 + 21 +250.0 + 31 +0.0 + 0 +ATTDEF + 5 +9F +330 +9A +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +320.0 + 20 +290.0 + 30 +0.0 + 40 +120.0 + 1 ++0.00 +100 +AcDbAttributeDefinition + 3 + + 2 +H + 70 +0 + 71 +1 + 72 +0 + 0 +ENDBLK + 5 +9C +330 +9A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +164 +330 +163 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D1 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D1 + 1 + + 0 +LINE + 5 +166 +330 +163 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +-176.0 + 30 +0.0 + 11 +0.0 + 21 +-3232.0 + 31 +0.0 + 0 +LINE + 5 +167 +330 +163 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +10000.0 + 20 +-176.0 + 30 +0.0 + 11 +10000.0 + 21 +-3232.0 + 31 +0.0 + 0 +INSERT + 5 +16C +330 +163 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +-3100.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +180.0 + 0 +INSERT + 5 +16E +330 +163 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +10000.0 + 20 +-3100.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 0 +LINE + 5 +170 +330 +163 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +176.0 + 20 +-3100.0 + 30 +0.0 + 11 +9824.0 + 21 +-3100.0 + 31 +0.0 + 0 +MTEXT + 5 +171 +330 +163 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +5000.0 + 20 +-2924.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +10000 + 7 +ARCH-TEXT + 0 +POINT + 5 +172 +330 +163 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-3100.0 + 30 +0.0 + 0 +POINT + 5 +173 +330 +163 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +174 +330 +163 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +10000.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +165 +330 +163 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +169 +330 +168 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_CLOSEDFILLED + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_CLOSEDFILLED + 1 + + 0 +SOLID + 5 +16B +330 +168 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 +0 +100 +AcDbTrace + 10 +-1.0 + 20 +0.16439898372402537 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 12 +-1.0 + 22 +-0.16439898372402537 + 32 +0.0 + 13 +-1.0 + 23 +-0.16439898372402537 + 33 +0.0 + 0 +ENDBLK + 5 +16A +330 +168 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +177 +330 +176 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D2 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D2 + 1 + + 0 +LINE + 5 +179 +330 +176 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +0.0 + 20 +-176.0 + 30 +0.0 + 11 +0.0 + 21 +-2732.0 + 31 +0.0 + 0 +LINE + 5 +17A +330 +176 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +3500.0 + 20 +-176.0 + 30 +0.0 + 11 +3500.0 + 21 +-2732.0 + 31 +0.0 + 0 +INSERT + 5 +17B +330 +176 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +0.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +180.0 + 0 +INSERT + 5 +17D +330 +176 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +3500.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 0 +LINE + 5 +17F +330 +176 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +176.0 + 20 +-2600.0 + 30 +0.0 + 11 +3324.0 + 21 +-2600.0 + 31 +0.0 + 0 +MTEXT + 5 +180 +330 +176 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +1750.0 + 20 +-2424.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +3500 + 7 +ARCH-TEXT + 0 +POINT + 5 +181 +330 +176 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +-2600.0 + 30 +0.0 + 0 +POINT + 5 +182 +330 +176 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +183 +330 +176 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +3500.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +178 +330 +176 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +186 +330 +185 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D3 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D3 + 1 + + 0 +LINE + 5 +188 +330 +185 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +3500.0 + 20 +-176.0 + 30 +0.0 + 11 +3500.0 + 21 +-2732.0 + 31 +0.0 + 0 +LINE + 5 +189 +330 +185 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +6200.0 + 20 +-176.0 + 30 +0.0 + 11 +6200.0 + 21 +-2732.0 + 31 +0.0 + 0 +INSERT + 5 +18A +330 +185 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +3500.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +180.0 + 0 +INSERT + 5 +18C +330 +185 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +6200.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 0 +LINE + 5 +18E +330 +185 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +3676.0 + 20 +-2600.0 + 30 +0.0 + 11 +6024.0 + 21 +-2600.0 + 31 +0.0 + 0 +MTEXT + 5 +18F +330 +185 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +4850.0 + 20 +-2424.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +2700 + 7 +ARCH-TEXT + 0 +POINT + 5 +190 +330 +185 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +3500.0 + 20 +-2600.0 + 30 +0.0 + 0 +POINT + 5 +191 +330 +185 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +3500.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +192 +330 +185 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +6200.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +187 +330 +185 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +195 +330 +194 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D4 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D4 + 1 + + 0 +LINE + 5 +197 +330 +194 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +6200.0 + 20 +-176.0 + 30 +0.0 + 11 +6200.0 + 21 +-2732.0 + 31 +0.0 + 0 +LINE + 5 +198 +330 +194 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +10000.0 + 20 +-176.0 + 30 +0.0 + 11 +10000.0 + 21 +-2732.0 + 31 +0.0 + 0 +INSERT + 5 +199 +330 +194 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +6200.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +180.0 + 0 +INSERT + 5 +19B +330 +194 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +10000.0 + 20 +-2600.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 0 +LINE + 5 +19D +330 +194 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +6376.0 + 20 +-2600.0 + 30 +0.0 + 11 +9824.0 + 21 +-2600.0 + 31 +0.0 + 0 +MTEXT + 5 +19E +330 +194 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +8100.0 + 20 +-2424.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +3800 + 7 +ARCH-TEXT + 0 +POINT + 5 +19F +330 +194 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +6200.0 + 20 +-2600.0 + 30 +0.0 + 0 +POINT + 5 +1A0 +330 +194 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +6200.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +1A1 +330 +194 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +10000.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +196 +330 +194 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1A4 +330 +1A3 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D5 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D5 + 1 + + 0 +LINE + 5 +1A6 +330 +1A3 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +0.0 + 30 +0.0 + 11 +-3232.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +1A7 +330 +1A3 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +8000.0 + 30 +0.0 + 11 +-3232.0 + 21 +8000.0 + 31 +0.0 + 0 +INSERT + 5 +1A8 +330 +1A3 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-3100.0 + 20 +0.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +270.0 + 0 +INSERT + 5 +1AA +330 +1A3 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-3100.0 + 20 +8000.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +90.0 + 0 +LINE + 5 +1AC +330 +1A3 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-3100.0 + 20 +176.0 + 30 +0.0 + 11 +-3100.0 + 21 +7824.0 + 31 +0.0 + 0 +MTEXT + 5 +1AD +330 +1A3 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +-3276.0 + 20 +4000.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +8000 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +1AE +330 +1A3 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-3100.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +1AF +330 +1A3 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +1B0 +330 +1A3 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +8000.0 + 30 +0.0 + 0 +ENDBLK + 5 +1A5 +330 +1A3 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1B3 +330 +1B2 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D6 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D6 + 1 + + 0 +LINE + 5 +1B5 +330 +1B2 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +0.0 + 30 +0.0 + 11 +-2732.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +1B6 +330 +1B2 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +4200.0 + 30 +0.0 + 11 +-2732.0 + 21 +4200.0 + 31 +0.0 + 0 +INSERT + 5 +1B7 +330 +1B2 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-2600.0 + 20 +0.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +270.0 + 0 +INSERT + 5 +1B9 +330 +1B2 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-2600.0 + 20 +4200.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +90.0 + 0 +LINE + 5 +1BB +330 +1B2 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-2600.0 + 20 +176.0 + 30 +0.0 + 11 +-2600.0 + 21 +4024.0 + 31 +0.0 + 0 +MTEXT + 5 +1BC +330 +1B2 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +-2776.0 + 20 +2100.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +4200 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +1BD +330 +1B2 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-2600.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +1BE +330 +1B2 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +POINT + 5 +1BF +330 +1B2 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +4200.0 + 30 +0.0 + 0 +ENDBLK + 5 +1B4 +330 +1B2 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C2 +330 +1C1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D7 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D7 + 1 + + 0 +LINE + 5 +1C4 +330 +1C1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +4200.0 + 30 +0.0 + 11 +-2732.0 + 21 +4200.0 + 31 +0.0 + 0 +LINE + 5 +1C5 +330 +1C1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-176.0 + 20 +8000.0 + 30 +0.0 + 11 +-2732.0 + 21 +8000.0 + 31 +0.0 + 0 +INSERT + 5 +1C6 +330 +1C1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-2600.0 + 20 +4200.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +270.0 + 0 +INSERT + 5 +1C8 +330 +1C1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +-2600.0 + 20 +8000.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +90.0 + 0 +LINE + 5 +1CA +330 +1C1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +-2600.0 + 20 +4376.0 + 30 +0.0 + 11 +-2600.0 + 21 +7824.0 + 31 +0.0 + 0 +MTEXT + 5 +1CB +330 +1C1 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +-2776.0 + 20 +6100.0 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +3800 + 7 +ARCH-TEXT + 50 +90.0 + 0 +POINT + 5 +1CC +330 +1C1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +-2600.0 + 20 +4200.0 + 30 +0.0 + 0 +POINT + 5 +1CD +330 +1C1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +4200.0 + 30 +0.0 + 0 +POINT + 5 +1CE +330 +1C1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +0.0 + 20 +8000.0 + 30 +0.0 + 0 +ENDBLK + 5 +1C3 +330 +1C1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1D2 +330 +1D1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D8 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D8 + 1 + + 0 +LINE + 5 +1D4 +330 +1D1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +11624.450793488832 + 20 +375.54920651116765 + 30 +0.0 + 11 +12088.312841947207 + 21 +-88.31284194720743 + 31 +0.0 + 0 +LINE + 5 +1D5 +330 +1D1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +14624.450793488832 + 20 +3375.5492065111675 + 30 +0.0 + 11 +15088.312841947207 + 21 +2911.6871580527927 + 31 +0.0 + 0 +INSERT + 5 +1D6 +330 +1D1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +11994.974746830583 + 20 +5.025253169416828 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +225.0 + 0 +INSERT + 5 +1D8 +330 +1D1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +14994.974746830583 + 20 +3005.025253169417 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +45.0 + 0 +LINE + 5 +1DA +330 +1D1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +12119.425540319415 + 20 +129.47604665824917 + 30 +0.0 + 11 +14870.523953341752 + 21 +2880.5744596805844 + 31 +0.0 + 0 +MTEXT + 5 +1DB +330 +1D1 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +13370.523953341752 + 20 +1629.4760466582493 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +4243 + 7 +ARCH-TEXT + 50 +45.0 + 0 +POINT + 5 +1DC +330 +1D1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +11994.974746830583 + 20 +5.025253169416828 + 30 +0.0 + 0 +POINT + 5 +1DD +330 +1D1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 0 +POINT + 5 +1DE +330 +1D1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +14500.0 + 20 +3500.0 + 30 +0.0 + 0 +ENDBLK + 5 +1D3 +330 +1D1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1E2 +330 +1E1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D9 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D9 + 1 + + 0 +LINE + 5 +1E4 +330 +1E1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +11676.0 + 20 +500.0 + 30 +0.0 + 11 +12456.621125123533 + 21 +500.0 + 31 +0.0 + 0 +LINE + 5 +1E5 +330 +1E1 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +11624.450793488832 + 20 +624.4507934888323 + 30 +0.0 + 11 +12176.433284601155 + 21 +1176.4332846011544 + 31 +0.0 + 0 +INSERT + 5 +1E6 +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +12324.621125123533 + 20 +500.0 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +443.88564221369427 + 0 +INSERT + 5 +1E8 +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +12083.09518948453 + 20 +1083.0951894845302 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +321.11435778630573 + 0 +MTEXT + 5 +1EA +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +12546.405475591537 + 20 +933.4353397314832 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +45° + 7 +ARCH-TEXT + 50 +-67.5 + 0 +ARC + 5 +1EB +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbCircle + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 40 +824.6211251235321 +100 +AcDbArc + 50 +0.0 + 51 +45.0 + 0 +ARC + 5 +1EC +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbCircle + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 40 +824.6211251235321 +100 +AcDbArc + 50 +-24.45743114522284 + 51 +-12.22871557261142 + 0 +ARC + 5 +1ED +330 +1E1 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbCircle + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 40 +824.6211251235321 +100 +AcDbArc + 50 +57.22871557261142 + 51 +69.45743114522284 + 0 +POINT + 5 +1EE +330 +1E1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +14500.0 + 20 +500.0 + 30 +0.0 + 0 +POINT + 5 +1EF +330 +1E1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 0 +POINT + 5 +1F0 +330 +1E1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +14500.0 + 20 +3500.0 + 30 +0.0 + 0 +POINT + 5 +1F1 +330 +1E1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 0 +POINT + 5 +1F2 +330 +1E1 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +12300.0 + 20 +700.0 + 30 +0.0 + 0 +ENDBLK + 5 +1E3 +330 +1E1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1F5 +330 +1F4 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D10 + 70 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D10 + 1 + + 0 +INSERT + 5 +1F7 +330 +1F4 +100 +AcDbEntity + 8 +A-DIMS + 62 +3 +100 +AcDbBlockReference + 2 +_CLOSEDFILLED + 10 +6911.396103067893 + 20 +2336.396103067893 + 30 +0.0 + 41 +176.0 + 42 +176.0 + 50 +225.0 + 0 +LINE + 5 +1F9 +330 +1F4 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +6275.0 + 20 +1700.0 + 30 +0.0 + 11 +6911.396103067893 + 21 +2336.396103067893 + 31 +0.0 + 0 +LINE + 5 +1FA +330 +1F4 +100 +AcDbEntity + 8 +0 + 62 +3 +100 +AcDbLine + 10 +7035.846896556725 + 20 +2460.8468965567254 + 30 +0.0 + 11 +7704.7699115591995 + 21 +3129.7699115591995 + 31 +0.0 + 0 +MTEXT + 5 +1FB +330 +1F4 +100 +AcDbEntity + 8 +A-DIMS + 62 +2 +100 +AcDbMText + 10 +7269.192134348285 + 20 +2943.093721325951 + 30 +0.0 + 40 +220.0 + 71 +5 + 1 +R900 + 7 +ARCH-TEXT + 50 +45.0 + 0 +POINT + 5 +1FC +330 +1F4 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +6275.0 + 20 +1700.0 + 30 +0.0 + 0 +POINT + 5 +1FD +330 +1F4 +100 +AcDbEntity + 8 +Defpoints +100 +AcDbPoint + 10 +6911.396103067893 + 20 +2336.396103067893 + 30 +0.0 + 0 +ENDBLK + 5 +1F6 +330 +1F4 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +207 +330 +206 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space0 + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space0 + 1 + + 0 +VIEWPORT + 5 +20A +330 +206 +100 +AcDbEntity + 67 +1 + 8 +VIEWPORTS +100 +AcDbViewport + 10 +200.0 + 20 +138.5 + 30 +0.0 + 40 +462.00000000000006 + 41 +326.70000000000005 + 68 +1 + 69 +1 + 12 +200.0 + 22 +138.5 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 45 +326.70000000000005 + 50 +0.0 + 51 +0.0 + 72 +100 + 90 +557088 + 1 + +281 +0 + 71 +0 + 74 +0 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 +282 +0 + 0 +LWPOLYLINE + 5 +20B +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +10.0 + 20 +10.0 + 10 +410.0 + 20 +10.0 + 10 +410.0 + 20 +287.0 + 10 +10.0 + 20 +287.0 + 0 +LWPOLYLINE + 5 +20C +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +5.0 + 20 +5.0 + 10 +415.0 + 20 +5.0 + 10 +415.0 + 20 +292.0 + 10 +5.0 + 20 +292.0 + 0 +LWPOLYLINE + 5 +20D +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +260.0 + 20 +10.0 + 10 +410.0 + 20 +10.0 + 10 +410.0 + 20 +60.0 + 10 +260.0 + 20 +60.0 + 0 +LINE + 5 +20E +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbLine + 10 +260.0 + 20 +35.0 + 30 +0.0 + 11 +410.0 + 21 +35.0 + 31 +0.0 + 0 +LINE + 5 +20F +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbLine + 10 +335.0 + 20 +10.0 + 30 +0.0 + 11 +335.0 + 21 +35.0 + 31 +0.0 + 0 +TEXT + 5 +210 +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbText + 10 +265.0 + 20 +45.0 + 30 +0.0 + 40 +7.0 + 1 +HOUSE, GROUND FLOOR + 7 +ARCH-TITLE + 11 +265.0 + 21 +45.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +211 +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbText + 10 +265.0 + 20 +18.0 + 30 +0.0 + 40 +4.0 + 1 +Scale 1:50 + 7 +ARCH-TEXT + 11 +265.0 + 21 +18.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +212 +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-SHEET +100 +AcDbText + 10 +340.0 + 20 +18.0 + 30 +0.0 + 40 +4.0 + 1 +Sheet A-101 + 7 +ARCH-TEXT + 11 +340.0 + 21 +18.0 + 31 +0.0 +100 +AcDbText + 0 +VIEWPORT + 5 +213 +330 +206 +100 +AcDbEntity + 67 +1 + 8 +A-VPORT +100 +AcDbViewport + 10 +135.0 + 20 +160.0 + 30 +0.0 + 40 +250.0 + 41 +200.0 + 68 +1 + 69 +3 + 12 +5000.0 + 22 +3400.0 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 45 +10000.0 + 50 +0.0 + 51 +0.0 + 72 +100 + 90 +0 + 1 + +281 +0 + 71 +0 + 74 +0 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 +282 +0 + 0 +ENDBLK + 5 +208 +330 +206 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +HATCH + 5 +A0 +330 +17 +100 +AcDbEntity + 8 +A-SLAB + 62 +254 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +0.0 + 10 +10000.0 + 20 +0.0 + 10 +10000.0 + 20 +8000.0 + 10 +0.0 + 20 +8000.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +A1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +150.0 + 10 +1400.0 + 20 +150.0 + 10 +1400.0 + 20 +-150.0 + 10 +0.0 + 20 +-150.0 + 0 +HATCH + 5 +A2 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +150.0 + 10 +1400.0 + 20 +150.0 + 10 +1400.0 + 20 +-150.0 + 10 +0.0 + 20 +-150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +A3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +2900.0 + 20 +150.0 + 10 +3600.0 + 20 +150.0 + 10 +3600.0 + 20 +-150.0 + 10 +2900.0 + 20 +-150.0 + 0 +HATCH + 5 +A4 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +2900.0 + 20 +150.0 + 10 +3600.0 + 20 +150.0 + 10 +3600.0 + 20 +-150.0 + 10 +2900.0 + 20 +-150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +A5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +4500.0 + 20 +150.0 + 10 +6200.0 + 20 +150.0 + 10 +6200.0 + 20 +-150.0 + 10 +4500.0 + 20 +-150.0 + 0 +HATCH + 5 +A6 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +4500.0 + 20 +150.0 + 10 +6200.0 + 20 +150.0 + 10 +6200.0 + 20 +-150.0 + 10 +4500.0 + 20 +-150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +A7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +7100.0 + 20 +150.0 + 10 +8200.0 + 20 +150.0 + 10 +8200.0 + 20 +-150.0 + 10 +7100.0 + 20 +-150.0 + 0 +HATCH + 5 +A8 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +7100.0 + 20 +150.0 + 10 +8200.0 + 20 +150.0 + 10 +8200.0 + 20 +-150.0 + 10 +7100.0 + 20 +-150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +A9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +9400.0 + 20 +150.0 + 10 +10000.0 + 20 +150.0 + 10 +10000.0 + 20 +-150.0 + 10 +9400.0 + 20 +-150.0 + 0 +HATCH + 5 +AA +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +9400.0 + 20 +150.0 + 10 +10000.0 + 20 +150.0 + 10 +10000.0 + 20 +-150.0 + 10 +9400.0 + 20 +-150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +AB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +1400.0 + 20 +150.0 + 30 +0.0 + 11 +1400.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +AC +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +2900.0 + 20 +150.0 + 30 +0.0 + 11 +2900.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +AD +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +3600.0 + 20 +150.0 + 30 +0.0 + 11 +3600.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +AE +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +4500.0 + 20 +150.0 + 30 +0.0 + 11 +4500.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +AF +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6200.0 + 20 +150.0 + 30 +0.0 + 11 +6200.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +B0 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +7100.0 + 20 +150.0 + 30 +0.0 + 11 +7100.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +B1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +8200.0 + 20 +150.0 + 30 +0.0 + 11 +8200.0 + 21 +-150.0 + 31 +0.0 + 0 +LINE + 5 +B2 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +9400.0 + 20 +150.0 + 30 +0.0 + 11 +9400.0 + 21 +-150.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +B3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +9850.0 + 20 +0.0 + 10 +9850.0 + 20 +1500.0 + 10 +10150.0 + 20 +1500.0 + 10 +10150.0 + 20 +0.0 + 0 +HATCH + 5 +B4 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +9850.0 + 20 +0.0 + 10 +9850.0 + 20 +1500.0 + 10 +10150.0 + 20 +1500.0 + 10 +10150.0 + 20 +0.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +B5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +9850.0 + 20 +2800.0 + 10 +9850.0 + 20 +4800.0 + 10 +10150.0 + 20 +4800.0 + 10 +10150.0 + 20 +2800.0 + 0 +HATCH + 5 +B6 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +9850.0 + 20 +2800.0 + 10 +9850.0 + 20 +4800.0 + 10 +10150.0 + 20 +4800.0 + 10 +10150.0 + 20 +2800.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +B7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +9850.0 + 20 +6100.0 + 10 +9850.0 + 20 +8000.0 + 10 +10150.0 + 20 +8000.0 + 10 +10150.0 + 20 +6100.0 + 0 +HATCH + 5 +B8 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +9850.0 + 20 +6100.0 + 10 +9850.0 + 20 +8000.0 + 10 +10150.0 + 20 +8000.0 + 10 +10150.0 + 20 +6100.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +B9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +9850.0 + 20 +1500.0 + 30 +0.0 + 11 +10150.0 + 21 +1500.0 + 31 +0.0 + 0 +LINE + 5 +BA +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +9850.0 + 20 +2800.0 + 30 +0.0 + 11 +10150.0 + 21 +2800.0 + 31 +0.0 + 0 +LINE + 5 +BB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +9850.0 + 20 +4800.0 + 30 +0.0 + 11 +10150.0 + 21 +4800.0 + 31 +0.0 + 0 +LINE + 5 +BC +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +9850.0 + 20 +6100.0 + 30 +0.0 + 11 +10150.0 + 21 +6100.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +BD +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +10000.0 + 20 +7850.0 + 10 +8800.0 + 20 +7850.0 + 10 +8800.0 + 20 +8150.0 + 10 +10000.0 + 20 +8150.0 + 0 +HATCH + 5 +BE +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +10000.0 + 20 +7850.0 + 10 +8800.0 + 20 +7850.0 + 10 +8800.0 + 20 +8150.0 + 10 +10000.0 + 20 +8150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +BF +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +7400.0 + 20 +7850.0 + 10 +6400.0 + 20 +7850.0 + 10 +6400.0 + 20 +8150.0 + 10 +7400.0 + 20 +8150.0 + 0 +HATCH + 5 +C0 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +7400.0 + 20 +7850.0 + 10 +6400.0 + 20 +7850.0 + 10 +6400.0 + 20 +8150.0 + 10 +7400.0 + 20 +8150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +C1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +4800.0 + 20 +7850.0 + 10 +3400.0 + 20 +7850.0 + 10 +3400.0 + 20 +8150.0 + 10 +4800.0 + 20 +8150.0 + 0 +HATCH + 5 +C2 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +4800.0 + 20 +7850.0 + 10 +3400.0 + 20 +7850.0 + 10 +3400.0 + 20 +8150.0 + 10 +4800.0 + 20 +8150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +C3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +2200.0 + 20 +7850.0 + 10 +0.0 + 20 +7850.0 + 10 +0.0 + 20 +8150.0 + 10 +2200.0 + 20 +8150.0 + 0 +HATCH + 5 +C4 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +2200.0 + 20 +7850.0 + 10 +0.0 + 20 +7850.0 + 10 +0.0 + 20 +8150.0 + 10 +2200.0 + 20 +8150.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +C5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +8800.0 + 20 +7850.0 + 30 +0.0 + 11 +8800.0 + 21 +8150.0 + 31 +0.0 + 0 +LINE + 5 +C6 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +7400.0 + 20 +7850.0 + 30 +0.0 + 11 +7400.0 + 21 +8150.0 + 31 +0.0 + 0 +LINE + 5 +C7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6400.0 + 20 +7850.0 + 30 +0.0 + 11 +6400.0 + 21 +8150.0 + 31 +0.0 + 0 +LINE + 5 +C8 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +4800.0 + 20 +7850.0 + 30 +0.0 + 11 +4800.0 + 21 +8150.0 + 31 +0.0 + 0 +LINE + 5 +C9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +3400.0 + 20 +7850.0 + 30 +0.0 + 11 +3400.0 + 21 +8150.0 + 31 +0.0 + 0 +LINE + 5 +CA +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +2200.0 + 20 +7850.0 + 30 +0.0 + 11 +2200.0 + 21 +8150.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +CB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +8000.0 + 10 +150.0 + 20 +6400.0 + 10 +-150.0 + 20 +6400.0 + 10 +-150.0 + 20 +8000.0 + 0 +HATCH + 5 +CC +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +150.0 + 20 +8000.0 + 10 +150.0 + 20 +6400.0 + 10 +-150.0 + 20 +6400.0 + 10 +-150.0 + 20 +8000.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +CD +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +5000.0 + 10 +150.0 + 20 +3000.0 + 10 +-150.0 + 20 +3000.0 + 10 +-150.0 + 20 +5000.0 + 0 +HATCH + 5 +CE +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +150.0 + 20 +5000.0 + 10 +150.0 + 20 +3000.0 + 10 +-150.0 + 20 +3000.0 + 10 +-150.0 + 20 +5000.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +CF +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +1600.0 + 10 +150.0 + 20 +0.0 + 10 +-150.0 + 20 +0.0 + 10 +-150.0 + 20 +1600.0 + 0 +HATCH + 5 +D0 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +150.0 + 20 +1600.0 + 10 +150.0 + 20 +0.0 + 10 +-150.0 + 20 +0.0 + 10 +-150.0 + 20 +1600.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +D1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +150.0 + 20 +6400.0 + 30 +0.0 + 11 +-150.0 + 21 +6400.0 + 31 +0.0 + 0 +LINE + 5 +D2 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +150.0 + 20 +5000.0 + 30 +0.0 + 11 +-150.0 + 21 +5000.0 + 31 +0.0 + 0 +LINE + 5 +D3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +150.0 + 20 +3000.0 + 30 +0.0 + 11 +-150.0 + 21 +3000.0 + 31 +0.0 + 0 +LINE + 5 +D4 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +150.0 + 20 +1600.0 + 30 +0.0 + 11 +-150.0 + 21 +1600.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +D5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +4275.0 + 10 +600.0 + 20 +4275.0 + 10 +600.0 + 20 +4125.0 + 10 +0.0 + 20 +4125.0 + 0 +HATCH + 5 +D6 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +4275.0 + 10 +600.0 + 20 +4275.0 + 10 +600.0 + 20 +4125.0 + 10 +0.0 + 20 +4125.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +D7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1500.0 + 20 +4275.0 + 10 +2700.0 + 20 +4275.0 + 10 +2700.0 + 20 +4125.0 + 10 +1500.0 + 20 +4125.0 + 0 +HATCH + 5 +D8 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +1500.0 + 20 +4275.0 + 10 +2700.0 + 20 +4275.0 + 10 +2700.0 + 20 +4125.0 + 10 +1500.0 + 20 +4125.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +D9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3600.0 + 20 +4275.0 + 10 +4800.0 + 20 +4275.0 + 10 +4800.0 + 20 +4125.0 + 10 +3600.0 + 20 +4125.0 + 0 +HATCH + 5 +DA +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +3600.0 + 20 +4275.0 + 10 +4800.0 + 20 +4275.0 + 10 +4800.0 + 20 +4125.0 + 10 +3600.0 + 20 +4125.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +DB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +5700.0 + 20 +4275.0 + 10 +6200.0 + 20 +4275.0 + 10 +6200.0 + 20 +4125.0 + 10 +5700.0 + 20 +4125.0 + 0 +HATCH + 5 +DC +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +5700.0 + 20 +4275.0 + 10 +6200.0 + 20 +4275.0 + 10 +6200.0 + 20 +4125.0 + 10 +5700.0 + 20 +4125.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +DD +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +600.0 + 20 +4275.0 + 30 +0.0 + 11 +600.0 + 21 +4125.0 + 31 +0.0 + 0 +LINE + 5 +DE +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +1500.0 + 20 +4275.0 + 30 +0.0 + 11 +1500.0 + 21 +4125.0 + 31 +0.0 + 0 +LINE + 5 +DF +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +2700.0 + 20 +4275.0 + 30 +0.0 + 11 +2700.0 + 21 +4125.0 + 31 +0.0 + 0 +LINE + 5 +E0 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +3600.0 + 20 +4275.0 + 30 +0.0 + 11 +3600.0 + 21 +4125.0 + 31 +0.0 + 0 +LINE + 5 +E1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +4800.0 + 20 +4275.0 + 30 +0.0 + 11 +4800.0 + 21 +4125.0 + 31 +0.0 + 0 +LINE + 5 +E2 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +5700.0 + 20 +4275.0 + 30 +0.0 + 11 +5700.0 + 21 +4125.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +E3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6125.0 + 20 +0.0 + 10 +6125.0 + 20 +1700.0 + 10 +6275.0 + 20 +1700.0 + 10 +6275.0 + 20 +0.0 + 0 +HATCH + 5 +E4 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6125.0 + 20 +0.0 + 10 +6125.0 + 20 +1700.0 + 10 +6275.0 + 20 +1700.0 + 10 +6275.0 + 20 +0.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +E5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6125.0 + 20 +2600.0 + 10 +6125.0 + 20 +4200.0 + 10 +6275.0 + 20 +4200.0 + 10 +6275.0 + 20 +2600.0 + 0 +HATCH + 5 +E6 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6125.0 + 20 +2600.0 + 10 +6125.0 + 20 +4200.0 + 10 +6275.0 + 20 +4200.0 + 10 +6275.0 + 20 +2600.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +E7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6125.0 + 20 +1700.0 + 30 +0.0 + 11 +6275.0 + 21 +1700.0 + 31 +0.0 + 0 +LINE + 5 +E8 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6125.0 + 20 +2600.0 + 30 +0.0 + 11 +6275.0 + 21 +2600.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +E9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6125.0 + 20 +4200.0 + 10 +6125.0 + 20 +6300.0 + 10 +6275.0 + 20 +6300.0 + 10 +6275.0 + 20 +4200.0 + 0 +HATCH + 5 +EA +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6125.0 + 20 +4200.0 + 10 +6125.0 + 20 +6300.0 + 10 +6275.0 + 20 +6300.0 + 10 +6275.0 + 20 +4200.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +EB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6125.0 + 20 +7200.0 + 10 +6125.0 + 20 +8000.0 + 10 +6275.0 + 20 +8000.0 + 10 +6275.0 + 20 +7200.0 + 0 +HATCH + 5 +EC +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6125.0 + 20 +7200.0 + 10 +6125.0 + 20 +8000.0 + 10 +6275.0 + 20 +8000.0 + 10 +6275.0 + 20 +7200.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +ED +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6125.0 + 20 +6300.0 + 30 +0.0 + 11 +6275.0 + 21 +6300.0 + 31 +0.0 + 0 +LINE + 5 +EE +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +6125.0 + 20 +7200.0 + 30 +0.0 + 11 +6275.0 + 21 +7200.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +EF +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3425.0 + 20 +0.0 + 10 +3425.0 + 20 +2400.0 + 10 +3575.0 + 20 +2400.0 + 10 +3575.0 + 20 +0.0 + 0 +HATCH + 5 +F0 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +3425.0 + 20 +0.0 + 10 +3425.0 + 20 +2400.0 + 10 +3575.0 + 20 +2400.0 + 10 +3575.0 + 20 +0.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +F1 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +3425.0 + 20 +3300.0 + 10 +3425.0 + 20 +4200.0 + 10 +3575.0 + 20 +4200.0 + 10 +3575.0 + 20 +3300.0 + 0 +HATCH + 5 +F2 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +3425.0 + 20 +3300.0 + 10 +3425.0 + 20 +4200.0 + 10 +3575.0 + 20 +4200.0 + 10 +3575.0 + 20 +3300.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +F3 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +3425.0 + 20 +2400.0 + 30 +0.0 + 11 +3575.0 + 21 +2400.0 + 31 +0.0 + 0 +LINE + 5 +F4 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +3425.0 + 20 +3300.0 + 30 +0.0 + 11 +3575.0 + 21 +3300.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +F5 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6200.0 + 20 +4275.0 + 10 +10000.0 + 20 +4275.0 + 10 +10000.0 + 20 +4125.0 + 10 +6200.0 + 20 +4125.0 + 0 +HATCH + 5 +F6 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +6200.0 + 20 +4275.0 + 10 +10000.0 + 20 +4275.0 + 10 +10000.0 + 20 +4125.0 + 10 +6200.0 + 20 +4125.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +F7 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +8125.0 + 20 +4200.0 + 10 +8125.0 + 20 +5800.0 + 10 +8275.0 + 20 +5800.0 + 10 +8275.0 + 20 +4200.0 + 0 +HATCH + 5 +F8 +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +8125.0 + 20 +4200.0 + 10 +8125.0 + 20 +5800.0 + 10 +8275.0 + 20 +5800.0 + 10 +8275.0 + 20 +4200.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +F9 +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +8125.0 + 20 +6700.0 + 10 +8125.0 + 20 +8000.0 + 10 +8275.0 + 20 +8000.0 + 10 +8275.0 + 20 +6700.0 + 0 +HATCH + 5 +FA +330 +17 +100 +AcDbEntity + 8 +A-WALL-PAT + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +8125.0 + 20 +6700.0 + 10 +8125.0 + 20 +8000.0 + 10 +8275.0 + 20 +8000.0 + 10 +8275.0 + 20 +6700.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +40.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-89.802561212 + 46 +89.802561212 + 79 +0 + 98 +0 + 0 +LINE + 5 +FB +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +8125.0 + 20 +5800.0 + 30 +0.0 + 11 +8275.0 + 21 +5800.0 + 31 +0.0 + 0 +LINE + 5 +FC +330 +17 +100 +AcDbEntity + 8 +A-WALL +100 +AcDbLine + 10 +8125.0 + 20 +6700.0 + 30 +0.0 + 11 +8275.0 + 21 +6700.0 + 31 +0.0 + 0 +INSERT + 5 +FD +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +1700.0 + 20 +150.0 + 30 +0.0 + 0 +ATTRIB + 5 +FF +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +2050.0 + 20 +-180.0 + 30 +0.0 + 40 +110.0 + 1 +D-101 + 11 +2050.0 + 21 +-180.0 + 31 +0.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 71 +1 + 72 +0 + 11 +2050.0 + 21 +-180.0 + 31 +0.0 + 0 +SEQEND + 5 +FE +330 +FD +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +100 +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +6275.0 + 20 +1700.0 + 30 +0.0 + 50 +90.0 + 0 +ATTRIB + 5 +102 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +6605.0 + 20 +2050.0 + 30 +0.0 + 40 +110.0 + 1 +D-102 + 50 +90.0 + 11 +6605.0 + 21 +2050.0 + 31 +0.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 71 +1 + 72 +0 + 11 +6605.0 + 21 +2050.0 + 31 +0.0 + 0 +SEQEND + 5 +101 +330 +100 +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +103 +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +3575.0 + 20 +2400.0 + 30 +0.0 + 50 +90.0 + 0 +ATTRIB + 5 +105 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +3905.0 + 20 +2750.0 + 30 +0.0 + 40 +110.0 + 1 +D-103 + 50 +90.0 + 11 +3905.0 + 21 +2750.0 + 31 +0.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 71 +1 + 72 +0 + 11 +3905.0 + 21 +2750.0 + 31 +0.0 + 0 +SEQEND + 5 +104 +330 +103 +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +106 +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +700.0 + 20 +4275.0 + 30 +0.0 + 42 +-1.0 + 0 +ATTRIB + 5 +108 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +-1050.0 + 20 +4605.0 + 30 +0.0 + 40 +110.0 + 1 +D-104 + 50 +180.0 + 11 +-1050.0 + 21 +4605.0 + 31 +0.0 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 71 +1 + 72 +0 + 11 +-1050.0 + 21 +4605.0 + 31 +0.0 + 0 +SEQEND + 5 +107 +330 +106 +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +109 +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +2800.0 + 20 +4275.0 + 30 +0.0 + 0 +ATTRIB + 5 +10B +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +3150.0 + 20 +3945.0 + 30 +0.0 + 40 +110.0 + 1 +D-105 + 11 +3150.0 + 21 +3945.0 + 31 +0.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 71 +1 + 72 +0 + 11 +3150.0 + 21 +3945.0 + 31 +0.0 + 0 +SEQEND + 5 +10A +330 +109 +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +10C +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +4900.0 + 20 +4275.0 + 30 +0.0 + 42 +-1.0 + 0 +ATTRIB + 5 +10E +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +-5250.0 + 20 +4605.0 + 30 +0.0 + 40 +110.0 + 1 +D-106 + 50 +180.0 + 11 +-5250.0 + 21 +4605.0 + 31 +0.0 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 71 +1 + 72 +0 + 11 +-5250.0 + 21 +4605.0 + 31 +0.0 + 0 +SEQEND + 5 +10D +330 +10C +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +10F +330 +17 +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbBlockReference + 66 +1 + 2 +DOOR + 10 +8275.0 + 20 +5800.0 + 30 +0.0 + 50 +90.0 + 0 +ATTRIB + 5 +111 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +8605.0 + 20 +6150.0 + 30 +0.0 + 40 +110.0 + 1 +D-107 + 50 +90.0 + 11 +8605.0 + 21 +6150.0 + 31 +0.0 +100 +AcDbAttribute + 2 +TAG + 70 +0 + 71 +1 + 72 +0 + 11 +8605.0 + 21 +6150.0 + 31 +0.0 + 0 +SEQEND + 5 +110 +330 +10F +100 +AcDbEntity + 8 +A-DOOR + 0 +INSERT + 5 +112 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +3600.0 + 20 +-150.0 + 30 +0.0 + 41 +900.0 + 42 +300.0 + 0 +INSERT + 5 +114 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +6200.0 + 20 +-150.0 + 30 +0.0 + 41 +900.0 + 42 +300.0 + 0 +INSERT + 5 +116 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +8200.0 + 20 +-150.0 + 30 +0.0 + 41 +1200.0 + 42 +300.0 + 0 +INSERT + 5 +118 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +10150.0 + 20 +4800.0 + 30 +0.0 + 41 +1300.0 + 42 +300.0 + 50 +90.0 + 0 +INSERT + 5 +11A +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +1200.0 + 20 +7850.0 + 30 +0.0 + 41 +1400.0 + 42 +300.0 + 0 +INSERT + 5 +11C +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +3600.0 + 20 +7850.0 + 30 +0.0 + 41 +1600.0 + 42 +300.0 + 0 +INSERT + 5 +11E +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +6600.0 + 20 +7850.0 + 30 +0.0 + 41 +1200.0 + 42 +300.0 + 0 +INSERT + 5 +120 +330 +17 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbBlockReference + 2 +WINDOW + 10 +150.0 + 20 +5000.0 + 30 +0.0 + 41 +1400.0 + 42 +300.0 + 50 +90.0 + 0 +INSERT + 5 +122 +330 +17 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbBlockReference + 2 +SOFA + 10 +1200.0 + 20 +6900.0 + 30 +0.0 + 0 +INSERT + 5 +124 +330 +17 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbBlockReference + 2 +TABLE + 10 +3900.0 + 20 +5300.0 + 30 +0.0 + 0 +INSERT + 5 +126 +330 +17 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbBlockReference + 2 +BED + 10 +4300.0 + 20 +400.0 + 30 +0.0 + 0 +INSERT + 5 +128 +330 +17 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbBlockReference + 2 +BED + 10 +500.0 + 20 +600.0 + 30 +0.0 + 41 +0.8 + 42 +0.9 + 0 +INSERT + 5 +12A +330 +17 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbBlockReference + 2 +BATH + 10 +6800.0 + 20 +300.0 + 30 +0.0 + 0 +INSERT + 5 +12C +330 +17 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbBlockReference + 2 +WC + 10 +8300.0 + 20 +3200.0 + 30 +0.0 + 50 +90.0 + 0 +INSERT + 5 +12E +330 +17 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbBlockReference + 2 +SINK + 10 +6500.0 + 20 +3350.0 + 30 +0.0 + 0 +LINE + 5 +130 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +4400.0 + 30 +0.0 + 11 +7400.0 + 21 +4400.0 + 31 +0.0 + 0 +LINE + 5 +131 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +4680.0 + 30 +0.0 + 11 +7400.0 + 21 +4680.0 + 31 +0.0 + 0 +LINE + 5 +132 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +4960.0 + 30 +0.0 + 11 +7400.0 + 21 +4960.0 + 31 +0.0 + 0 +LINE + 5 +133 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +5240.0 + 30 +0.0 + 11 +7400.0 + 21 +5240.0 + 31 +0.0 + 0 +LINE + 5 +134 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +5520.0 + 30 +0.0 + 11 +7400.0 + 21 +5520.0 + 31 +0.0 + 0 +LINE + 5 +135 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +5800.0 + 30 +0.0 + 11 +7400.0 + 21 +5800.0 + 31 +0.0 + 0 +LINE + 5 +136 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +6080.0 + 30 +0.0 + 11 +7400.0 + 21 +6080.0 + 31 +0.0 + 0 +LINE + 5 +137 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +6360.0 + 30 +0.0 + 11 +7400.0 + 21 +6360.0 + 31 +0.0 + 0 +LINE + 5 +138 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +6640.0 + 30 +0.0 + 11 +7400.0 + 21 +6640.0 + 31 +0.0 + 0 +LINE + 5 +139 +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +6920.0 + 30 +0.0 + 11 +7400.0 + 21 +6920.0 + 31 +0.0 + 0 +LINE + 5 +13A +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +7200.0 + 30 +0.0 + 11 +7400.0 + 21 +7200.0 + 31 +0.0 + 0 +LINE + 5 +13B +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLine + 10 +6400.0 + 20 +7480.0 + 30 +0.0 + 11 +7400.0 + 21 +7480.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +13C +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +6400.0 + 20 +4400.0 + 10 +7400.0 + 20 +4400.0 + 10 +7400.0 + 20 +7760.0 + 10 +6400.0 + 20 +7760.0 + 0 +LWPOLYLINE + 5 +13D +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +6900.0 + 20 +4500.0 + 10 +6900.0 + 20 +7700.0 + 0 +LEADER + 5 +13E +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbLeader + 3 +Standard + 73 +3 + 76 +3 + 10 +6900.0 + 20 +7700.0 + 30 +0.0 + 10 +6820.0 + 20 +7400.0 + 30 +0.0 + 10 +6980.0 + 20 +7400.0 + 30 +0.0 + 0 +TEXT + 5 +13F +330 +17 +100 +AcDbEntity + 8 +A-STAIR +100 +AcDbText + 10 +6950.0 + 20 +4600.0 + 30 +0.0 + 40 +150.0 + 1 +UP + 7 +ARCH-TEXT + 11 +6950.0 + 21 +4600.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +140 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +0.0 + 20 +-1700.0 + 30 +0.0 + 11 +0.0 + 21 +9200.0 + 31 +0.0 + 0 +INSERT + 5 +141 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +0.0 + 20 +-2000.0 + 30 +0.0 + 0 +ATTRIB + 5 +143 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +0.0 + 20 +-2000.0 + 30 +0.0 + 40 +300.0 + 1 +1 + 72 +4 + 11 +0.0 + 21 +-2000.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 71 +1 + 72 +0 + 11 +0.0 + 21 +-2000.0 + 31 +0.0 + 0 +SEQEND + 5 +142 +330 +141 +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +144 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +3500.0 + 20 +-1700.0 + 30 +0.0 + 11 +3500.0 + 21 +9200.0 + 31 +0.0 + 0 +INSERT + 5 +145 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +3500.0 + 20 +-2000.0 + 30 +0.0 + 0 +ATTRIB + 5 +147 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +3500.0 + 20 +-2000.0 + 30 +0.0 + 40 +300.0 + 1 +2 + 72 +4 + 11 +3500.0 + 21 +-2000.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 71 +1 + 72 +0 + 11 +3500.0 + 21 +-2000.0 + 31 +0.0 + 0 +SEQEND + 5 +146 +330 +145 +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +148 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +6200.0 + 20 +-1700.0 + 30 +0.0 + 11 +6200.0 + 21 +9200.0 + 31 +0.0 + 0 +INSERT + 5 +149 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +6200.0 + 20 +-2000.0 + 30 +0.0 + 0 +ATTRIB + 5 +14B +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +6200.0 + 20 +-2000.0 + 30 +0.0 + 40 +300.0 + 1 +3 + 72 +4 + 11 +6200.0 + 21 +-2000.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 71 +1 + 72 +0 + 11 +6200.0 + 21 +-2000.0 + 31 +0.0 + 0 +SEQEND + 5 +14A +330 +149 +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +14C +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +10000.0 + 20 +-1700.0 + 30 +0.0 + 11 +10000.0 + 21 +9200.0 + 31 +0.0 + 0 +INSERT + 5 +14D +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +10000.0 + 20 +-2000.0 + 30 +0.0 + 0 +ATTRIB + 5 +14F +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +10000.0 + 20 +-2000.0 + 30 +0.0 + 40 +300.0 + 1 +4 + 72 +4 + 11 +10000.0 + 21 +-2000.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 71 +1 + 72 +0 + 11 +10000.0 + 21 +-2000.0 + 31 +0.0 + 0 +SEQEND + 5 +14E +330 +14D +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +150 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +-1700.0 + 20 +0.0 + 30 +0.0 + 11 +11200.0 + 21 +0.0 + 31 +0.0 + 0 +INSERT + 5 +151 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +-2000.0 + 20 +0.0 + 30 +0.0 + 0 +ATTRIB + 5 +153 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +-2000.0 + 20 +0.0 + 30 +0.0 + 40 +300.0 + 1 +A + 72 +4 + 11 +-2000.0 + 21 +0.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 71 +1 + 72 +0 + 11 +-2000.0 + 21 +0.0 + 31 +0.0 + 0 +SEQEND + 5 +152 +330 +151 +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +154 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +-1700.0 + 20 +4200.0 + 30 +0.0 + 11 +11200.0 + 21 +4200.0 + 31 +0.0 + 0 +INSERT + 5 +155 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +-2000.0 + 20 +4200.0 + 30 +0.0 + 0 +ATTRIB + 5 +157 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +-2000.0 + 20 +4200.0 + 30 +0.0 + 40 +300.0 + 1 +B + 72 +4 + 11 +-2000.0 + 21 +4200.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 71 +1 + 72 +0 + 11 +-2000.0 + 21 +4200.0 + 31 +0.0 + 0 +SEQEND + 5 +156 +330 +155 +100 +AcDbEntity + 8 +A-GRID + 0 +LINE + 5 +158 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +-1700.0 + 20 +8000.0 + 30 +0.0 + 11 +11200.0 + 21 +8000.0 + 31 +0.0 + 0 +INSERT + 5 +159 +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbBlockReference + 66 +1 + 2 +AXIS + 10 +-2000.0 + 20 +8000.0 + 30 +0.0 + 0 +ATTRIB + 5 +15B +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +-2000.0 + 20 +8000.0 + 30 +0.0 + 40 +300.0 + 1 +C + 72 +4 + 11 +-2000.0 + 21 +8000.0 + 31 +0.0 +100 +AcDbAttribute + 2 +ID + 70 +0 + 71 +1 + 72 +0 + 11 +-2000.0 + 21 +8000.0 + 31 +0.0 + 0 +SEQEND + 5 +15A +330 +159 +100 +AcDbEntity + 8 +A-GRID + 0 +MTEXT + 5 +15C +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +1750.0 + 20 +2100.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;BEDROOM 1\P\fArial|b0;14.7 m² + 7 +ARCH-TEXT + 0 +MTEXT + 5 +15D +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +4850.0 + 20 +2100.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;BEDROOM 2\P\fArial|b0;11.3 m² + 7 +ARCH-TEXT + 0 +MTEXT + 5 +15E +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +7500.0 + 20 +2100.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;BATH\P\fArial|b0;16.0 m² + 7 +ARCH-TEXT + 0 +MTEXT + 5 +15F +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +3100.0 + 20 +6100.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;LIVING ROOM\P\fArial|b0;23.6 m² + 7 +ARCH-TEXT + 0 +MTEXT + 5 +160 +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +7150.0 + 20 +6100.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;KITCHEN\P\fArial|b0;14.4 m² + 7 +ARCH-TEXT + 0 +MTEXT + 5 +161 +330 +17 +100 +AcDbEntity + 8 +A-AREA +100 +AcDbMText + 10 +1500.0 + 20 +4650.0 + 30 +0.0 + 40 +260.0 + 41 +2600.0 + 71 +5 + 1 +\fArial|b1;HALL + 7 +ARCH-TEXT + 0 +DIMENSION + 5 +162 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D1 + 3 +PLAN50 + 10 +0.0 + 20 +-3100.0 + 30 +0.0 + 11 +5000.0 + 21 +-2924.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +10000.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +175 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D2 + 3 +PLAN50 + 10 +0.0 + 20 +-2600.0 + 30 +0.0 + 11 +1750.0 + 21 +-2424.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +3500.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +184 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D3 + 3 +PLAN50 + 10 +3500.0 + 20 +-2600.0 + 30 +0.0 + 11 +4850.0 + 21 +-2424.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +3500.0 + 23 +0.0 + 33 +0.0 + 14 +6200.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +193 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D4 + 3 +PLAN50 + 10 +6200.0 + 20 +-2600.0 + 30 +0.0 + 11 +8100.0 + 21 +-2424.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +6200.0 + 23 +0.0 + 33 +0.0 + 14 +10000.0 + 24 +0.0 + 34 +0.0 + 50 +0.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1A2 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D5 + 3 +PLAN50 + 10 +-3100.0 + 20 +0.0 + 30 +0.0 + 11 +-3276.0 + 21 +4000.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +0.0 + 24 +8000.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1B1 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D6 + 3 +PLAN50 + 10 +-2600.0 + 20 +0.0 + 30 +0.0 + 11 +-2776.0 + 21 +2100.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +0.0 + 33 +0.0 + 14 +0.0 + 24 +4200.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1C0 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D7 + 3 +PLAN50 + 10 +-2600.0 + 20 +4200.0 + 30 +0.0 + 11 +-2776.0 + 21 +6100.0 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +0.0 + 23 +4200.0 + 33 +0.0 + 14 +0.0 + 24 +8000.0 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension + 0 +LWPOLYLINE + 5 +1CF +330 +17 +100 +AcDbEntity + 8 +A-WALL + 6 +DASHED +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +11500.0 + 20 +500.0 + 10 +14500.0 + 20 +3500.0 + 0 +DIMENSION + 5 +1D0 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D8 + 3 +PLAN50 + 10 +11994.974746830583 + 20 +5.025253169416828 + 30 +0.0 + 11 +13370.523953341752 + 21 +1629.4760466582493 + 31 +0.0 + 70 +32 + 71 +5 + 1 +<> +100 +AcDbAlignedDimension + 13 +11500.0 + 23 +500.0 + 33 +0.0 + 14 +14500.0 + 24 +3500.0 + 34 +0.0 + 50 +45.0 +100 +AcDbRotatedDimension + 0 +LINE + 5 +1DF +330 +17 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbLine + 10 +11500.0 + 20 +500.0 + 30 +0.0 + 11 +14500.0 + 21 +500.0 + 31 +0.0 + 0 +DIMENSION + 5 +1E0 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D9 + 3 +PLAN50 + 10 +14500.0 + 20 +500.0 + 30 +0.0 + 11 +12546.405475591537 + 21 +933.4353397314832 + 31 +0.0 + 70 +34 + 71 +5 + 1 +<> +100 +AcDb2LineAngularDimension + 13 +11500.0 + 23 +500.0 + 33 +0.0 + 14 +14500.0 + 24 +3500.0 + 34 +0.0 + 15 +11500.0 + 25 +500.0 + 35 +0.0 + 16 +12300.0 + 26 +700.0 + 36 +0.0 + 0 +DIMENSION + 5 +1F3 +330 +17 +100 +AcDbEntity + 8 +A-DIMS +100 +AcDbDimension +280 +0 + 2 +*D10 + 3 +PLAN50 + 10 +6275.0 + 20 +1700.0 + 30 +0.0 + 11 +7269.192134348285 + 21 +2943.093721325951 + 31 +0.0 + 70 +36 + 71 +5 + 1 +<> +100 +AcDbRadialDimension + 15 +6911.396103067893 + 25 +2336.396103067893 + 35 +0.0 + 0 +INSERT + 5 +1FE +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 2 +NORTH + 10 +12200.0 + 20 +8700.0 + 30 +0.0 + 0 +INSERT + 5 +200 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbBlockReference + 66 +1 + 2 +LEVEL + 10 +5000.0 + 20 +3400.0 + 30 +0.0 + 0 +ATTRIB + 5 +202 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +5320.0 + 20 +3690.0 + 30 +0.0 + 40 +120.0 + 1 +±0.00 + 11 +5320.0 + 21 +3690.0 + 31 +0.0 +100 +AcDbAttribute + 2 +H + 70 +0 + 71 +1 + 72 +0 + 11 +5320.0 + 21 +3690.0 + 31 +0.0 + 0 +SEQEND + 5 +201 +330 +200 +100 +AcDbEntity + 8 +A-ANNO + 0 +TEXT + 5 +203 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +0.0 + 20 +-4700.0 + 30 +0.0 + 40 +330.0 + 1 +GROUND FLOOR PLAN 1:50 + 7 +ARCH-TITLE + 11 +0.0 + 21 +-4700.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +204 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +370 +70 +100 +AcDbLine + 10 +0.0 + 20 +-4900.0 + 30 +0.0 + 11 +4500.0 + 21 +-4900.0 + 31 +0.0 + 0 +TEXT + 5 +205 +330 +17 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +0.0 + 20 +-5200.0 + 30 +0.0 + 40 +130.0 + 1 +Drawn for the exav demo. Dimensions in millimetres. + 7 +ARCH-NOTE + 11 +0.0 + 21 +-5200.0 + 31 +0.0 +100 +AcDbText + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +A +330 +0 +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ACAD_COLOR +350 +B + 3 +ACAD_GROUP +350 +C + 3 +ACAD_LAYOUT +350 +D + 3 +ACAD_MATERIAL +350 +E + 3 +ACAD_MLEADERSTYLE +350 +F + 3 +ACAD_MLINESTYLE +350 +10 + 3 +ACAD_PLOTSETTINGS +350 +11 + 3 +ACAD_PLOTSTYLENAME +350 +12 + 3 +ACAD_SCALELIST +350 +14 + 3 +ACAD_TABLESTYLE +350 +15 + 3 +ACAD_VISUALSTYLE +350 +16 + 3 +EZDXF_META +350 +2D + 0 +DICTIONARY + 5 +B +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +C +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +D +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Model +350 +1A + 3 +Layout1 +350 +1E + 3 +A3 Plan +350 +209 + 0 +DICTIONARY + 5 +E +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ByBlock +350 +1F + 3 +ByLayer +350 +20 + 3 +Global +350 +21 + 0 +DICTIONARY + 5 +F +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +2C + 0 +DICTIONARY + 5 +10 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +22 + 0 +DICTIONARY + 5 +11 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +ACDBDICTIONARYWDFLT + 5 +12 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Normal +350 +13 +100 +AcDbDictionaryWithDefault +340 +13 + 0 +ACDBPLACEHOLDER + 5 +13 +330 +12 + 0 +DICTIONARY + 5 +14 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +15 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +16 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +LAYOUT + 5 +1A +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +1024 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 +1 + 71 +0 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +17 + 0 +LAYOUT + 5 +1E +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +0 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 +1 + 71 +1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +1B + 0 +MATERIAL + 5 +1F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByBlock + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +20 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByLayer + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +21 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +Global + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MLINESTYLE + 5 +22 +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMlineStyle + 2 +Standard + 70 +0 + 3 + + 62 +256 + 51 +90.0 + 52 +90.0 + 71 +2 + 49 +0.5 + 62 +256 + 6 +BYLAYER + 49 +-0.5 + 62 +256 + 6 +BYLAYER + 0 +MLEADERSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +F +102 +} +330 +F +100 +AcDbMLeaderStyle +179 +2 +170 +2 +171 +1 +172 +0 + 90 +2 + 40 +0.0 + 41 +0.0 +173 +1 + 91 +-1056964608 + 92 +-2 +290 +1 + 42 +2.0 +291 +1 + 43 +8.0 + 3 +Standard + 44 +4.0 +300 + +342 +29 +174 +1 +175 +1 +176 +0 +178 +1 + 93 +-1056964608 + 45 +4.0 +292 +0 +297 +0 + 46 +4.0 + 94 +-1056964608 + 47 +1.0 + 49 +1.0 +140 +1.0 +294 +1 +141 +0.0 +177 +0 +142 +1.0 +295 +0 +296 +0 +143 +3.75 +271 +0 +272 +9 +273 +9 + 0 +DICTIONARY + 5 +2D +330 +A +100 +AcDbDictionary +281 +1 + 3 +CREATED_BY_EZDXF +350 +2E + 3 +WRITTEN_BY_EZDXF +350 +217 + 0 +DICTIONARYVAR + 5 +2E +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +LAYOUT + 5 +209 +330 +D +100 +AcDbPlotSettings + 1 + + 2 +DWG to PDF.pc3 + 4 +ezdxf_(420.00_x_297.00_MM) + 6 + + 40 +10.0 + 41 +10.0 + 42 +10.0 + 43 +10.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +672 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +A3 Plan + 70 +1 + 71 +3 + 10 +-10.0 + 20 +-10.0 + 11 +410.0 + 21 +287.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +206 +331 +20A + 0 +DICTIONARYVAR + 5 +217 +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +ENDSEC + 0 +EOF diff --git a/crates/exav-viewer/demo/examples/files/cad/legacy-r12.dxf b/crates/exav-viewer/demo/examples/files/cad/legacy-r12.dxf new file mode 100644 index 0000000..c7210ca --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/cad/legacy-r12.dxf @@ -0,0 +1,2602 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1009 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$EXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 +0 + 9 +$REGENMODE + 70 +1 + 9 +$FILLMODE + 70 +1 + 9 +$DRAGMODE + 70 +2 + 9 +$QTEXTMODE + 70 +0 + 9 +$MIRRTEXT + 70 +1 + 9 +$OSMODE + 70 +20583 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 +1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 +256 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 +0 + 9 +$DIMLIM + 70 +0 + 9 +$DIMTIH + 70 +0 + 9 +$DIMTOH + 70 +0 + 9 +$DIMSE1 + 70 +0 + 9 +$DIMSE2 + 70 +0 + 9 +$DIMTAD + 70 +1 + 9 +$DIMZIN + 70 +8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 +1 + 9 +$DIMSHO + 70 +1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 +0 + 9 +$DIMALTD + 70 +3 + 9 +$DIMALTF + 40 +0.03937007874 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 +1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 +0 + 9 +$DIMSOXD + 70 +0 + 9 +$DIMSAH + 70 +0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 +0 + 9 +$DIMCLRE + 70 +0 + 9 +$DIMCLRT + 70 +0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$COORDS + 70 +1 + 9 +$ATTDIA + 70 +0 + 9 +$ATTREQ + 70 +1 + 9 +$HANDLING + 70 +1 + 9 +$LUNITS + 70 +2 + 9 +$LUPREC + 70 +4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 +0 + 9 +$AUPREC + 70 +2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 +0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$SKPOLY + 70 +0 + 9 +$TDCREATE + 40 +2451545.0 + 9 +$TDUPDATE + 40 +2451545.0 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 +1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 +0 + 9 +$PDMODE + 70 +0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 +0 + 9 +$SPLINETYPE + 70 +6 + 9 +$SPLINESEGS + 70 +8 + 9 +$HANDSEED + 5 +A1 + 9 +$SURFTAB1 + 70 +6 + 9 +$SURFTAB2 + 70 +6 + 9 +$SURFTYPE + 70 +6 + 9 +$SURFU + 70 +6 + 9 +$SURFV + 70 +6 + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$USERI1 + 70 +0 + 9 +$USERI2 + 70 +0 + 9 +$USERI3 + 70 +0 + 9 +$USERI4 + 70 +0 + 9 +$USERI5 + 70 +0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 +1 + 9 +$SHADEDGE + 70 +3 + 9 +$SHADEDIF + 70 +70 + 9 +$TILEMODE + 70 +1 + 9 +$MAXACTVP + 70 +64 + 9 +$PLIMCHECK + 70 +0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 +0 + 9 +$VISRETAIN + 70 +1 + 9 +$PLINEGEN + 70 +0 + 9 +$PSLTSCALE + 70 +1 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 70 +1 + 0 +VPORT + 5 +9E + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +10.0 + 22 +-7.427997320830542 + 13 +0.0 + 23 +0.0 + 14 +0.5 + 24 +0.5 + 15 +0.5 + 25 +0.5 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +120.59879437374414 + 41 +1.34 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +1000 + 73 +1 + 74 +3 + 75 +0 + 76 +0 + 77 +0 + 78 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 70 +3 + 0 +LTYPE + 5 +24 + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +25 + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +26 + 2 +Continuous + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 70 +6 + 0 +LAYER + 5 +27 + 2 +0 + 70 +0 + 62 +7 + 6 +Continuous + 0 +LAYER + 5 +28 + 2 +Defpoints + 70 +0 + 62 +7 + 6 +Continuous + 0 +LAYER + 5 +2D + 2 +GEAR + 70 +0 + 62 +7 + 6 +Continuous + 0 +LAYER + 5 +2E + 2 +AXES + 70 +0 + 62 +1 + 6 +Continuous + 0 +LAYER + 5 +2F + 2 +TEXT + 70 +0 + 62 +2 + 6 +Continuous + 0 +LAYER + 5 +30 + 2 +DIMS + 70 +0 + 62 +3 + 6 +Continuous + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 70 +1 + 0 +STYLE + 5 +29 + 2 +Standard + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 70 +3 + 0 +APPID + 5 +2A + 2 +ACAD + 70 +0 + 0 +APPID + 5 +9F + 2 +HATCHBACKGROUNDCOLOR + 70 +0 + 0 +APPID + 5 +A0 + 2 +EZDXF + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 70 +1 + 0 +DIMSTYLE +105 +2B + 2 +Standard + 70 +0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +0 +177 +0 +178 +0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +18 + 8 +0 + 2 +$Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +$Model_Space + 1 + +1001 +EZDXF +1000 +CREATED_BY_EZDXF +1000 +0.0 @ 2000-01-01T00:00:00.000000+00:00 +1000 +WRITTEN_BY_EZDXF +1000 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +ENDBLK + 5 +19 + 8 +0 + 0 +BLOCK + 5 +1C + 8 +0 + 2 +$Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +$Paper_Space + 1 + + 0 +ENDBLK + 5 +1D + 8 +0 + 0 +BLOCK + 5 +94 + 8 +0 + 2 +TAG + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +TAG + 1 + + 0 +CIRCLE + 5 +96 + 8 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +5.0 + 0 +TEXT + 5 +97 + 8 +0 + 10 +-1.5 + 20 +-2.0 + 30 +0.0 + 40 +5.0 + 1 +1 + 11 +-1.5 + 21 +-2.0 + 31 +0.0 + 0 +ENDBLK + 5 +95 + 8 +0 + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +POLYLINE + 5 +31 + 8 +GEAR + 66 +1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 +1 + 0 +VERTEX + 5 +33 + 8 +GEAR + 10 +33.0 + 20 +0.0 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +34 + 8 +GEAR + 10 +39.921069137130864 + 20 +2.511620781172535 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +35 + 8 +GEAR + 10 +39.404373046190955 + 20 +6.877164011176382 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +36 + 8 +GEAR + 10 +32.088207373123325 + 20 +7.703697007244878 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +37 + 8 +GEAR + 10 +31.384865037740067 + 20 +10.197560814373263 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +38 + 8 +GEAR + 10 +37.19105943553006 + 20 +14.724982107387117 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +39 + 8 +GEAR + 10 +35.350625203547736 + 20 +18.717192570422934 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +3A + 8 +GEAR + 10 +28.137125423685042 + 20 +17.24245263562631 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +3B + 8 +GEAR + 10 +26.697560814373265 + 20 +19.396913325651614 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +3C + 8 +GEAR + 10 +30.82052971103157 + 20 +25.496959589947586 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +3D + 8 +GEAR + 10 +27.83651186369257 + 20 +28.725051910527554 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +3E + 8 +GEAR + 10 +21.43178559489606 + 20 +25.093396864801022 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +3F + 8 +GEAR + 10 +19.396913325651614 + 20 +26.697560814373265 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +40 + 8 +GEAR + 10 +21.433071799159862 + 20 +33.773117020080605 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +41 + 8 +GEAR + 10 +17.59756679423661 + 20 +35.92110303042462 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +42 + 8 +GEAR + 10 +12.628553268047964 + 20 +30.48802457287246 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +43 + 8 +GEAR + 10 +10.197560814373265 + 20 +31.384865037740067 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +44 + 8 +GEAR + 10 +9.947595486594189 + 20 +38.74332644514524 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +45 + 8 +GEAR + 10 +5.636049277503313 + 20 +39.6009463086623 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +46 + 8 +GEAR + 10 +2.589150159018885 + 20 +32.89827201319322 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +47 + 8 +GEAR + 10 +2.0206672185931327e-15 + 20 +33.0 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +48 + 8 +GEAR + 10 +-2.511620781172536 + 20 +39.921069137130864 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +49 + 8 +GEAR + 10 +-6.877164011176376 + 20 +39.40437304619096 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +4A + 8 +GEAR + 10 +-7.703697007244876 + 20 +32.08820737312333 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +4B + 8 +GEAR + 10 +-10.197560814373261 + 20 +31.38486503774007 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +4C + 8 +GEAR + 10 +-14.724982107387119 + 20 +37.19105943553005 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +4D + 8 +GEAR + 10 +-18.71719257042293 + 20 +35.350625203547736 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +4E + 8 +GEAR + 10 +-17.24245263562631 + 20 +28.137125423685045 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +4F + 8 +GEAR + 10 +-19.39691332565161 + 20 +26.697560814373265 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +50 + 8 +GEAR + 10 +-25.49695958994759 + 20 +30.82052971103157 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +51 + 8 +GEAR + 10 +-28.725051910527547 + 20 +27.83651186369258 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +52 + 8 +GEAR + 10 +-25.093396864801022 + 20 +21.431785594896063 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +53 + 8 +GEAR + 10 +-26.69756081437326 + 20 +19.396913325651617 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +54 + 8 +GEAR + 10 +-33.773117020080605 + 20 +21.433071799159865 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +55 + 8 +GEAR + 10 +-35.92110303042462 + 20 +17.597566794236613 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +56 + 8 +GEAR + 10 +-30.48802457287246 + 20 +12.628553268047966 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +57 + 8 +GEAR + 10 +-31.384865037740067 + 20 +10.197560814373269 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +58 + 8 +GEAR + 10 +-38.74332644514524 + 20 +9.947595486594192 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +59 + 8 +GEAR + 10 +-39.6009463086623 + 20 +5.636049277503314 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +5A + 8 +GEAR + 10 +-32.89827201319322 + 20 +2.5891501590188875 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +5B + 8 +GEAR + 10 +-33.0 + 20 +4.0413344371862654e-15 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +5C + 8 +GEAR + 10 +-39.921069137130864 + 20 +-2.511620781172534 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +5D + 8 +GEAR + 10 +-39.40437304619096 + 20 +-6.877164011176373 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +5E + 8 +GEAR + 10 +-32.08820737312333 + 20 +-7.703697007244874 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +5F + 8 +GEAR + 10 +-31.384865037740074 + 20 +-10.197560814373247 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +60 + 8 +GEAR + 10 +-37.191059435530065 + 20 +-14.724982107387099 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +61 + 8 +GEAR + 10 +-35.35062520354775 + 20 +-18.71719257042291 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +62 + 8 +GEAR + 10 +-28.137125423685053 + 20 +-17.242452635626297 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +63 + 8 +GEAR + 10 +-26.69756081437327 + 20 +-19.39691332565161 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +64 + 8 +GEAR + 10 +-30.82052971103157 + 20 +-25.496959589947586 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +65 + 8 +GEAR + 10 +-27.836511863692582 + 20 +-28.725051910527547 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +66 + 8 +GEAR + 10 +-21.431785594896077 + 20 +-25.093396864801008 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +67 + 8 +GEAR + 10 +-19.396913325651617 + 20 +-26.69756081437326 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +68 + 8 +GEAR + 10 +-21.433071799159883 + 20 +-33.77311702008059 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +69 + 8 +GEAR + 10 +-17.597566794236613 + 20 +-35.92110303042462 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +6A + 8 +GEAR + 10 +-12.62855326804798 + 20 +-30.488024572872455 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +6B + 8 +GEAR + 10 +-10.19756081437327 + 20 +-31.384865037740067 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +6C + 8 +GEAR + 10 +-9.947595486594212 + 20 +-38.743326445145236 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +6D + 8 +GEAR + 10 +-5.636049277503316 + 20 +-39.6009463086623 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +6E + 8 +GEAR + 10 +-2.589150159018904 + 20 +-32.89827201319322 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +6F + 8 +GEAR + 10 +-6.062001655779398e-15 + 20 +-33.0 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +70 + 8 +GEAR + 10 +2.511620781172513 + 20 +-39.921069137130864 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +71 + 8 +GEAR + 10 +6.8771640111763706 + 20 +-39.40437304619096 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +72 + 8 +GEAR + 10 +7.703697007244858 + 20 +-32.08820737312333 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +73 + 8 +GEAR + 10 +10.197560814373258 + 20 +-31.38486503774007 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +74 + 8 +GEAR + 10 +14.724982107387097 + 20 +-37.191059435530065 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +75 + 8 +GEAR + 10 +18.717192570422924 + 20 +-35.35062520354774 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +76 + 8 +GEAR + 10 +17.242452635626297 + 20 +-28.137125423685053 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +77 + 8 +GEAR + 10 +19.396913325651607 + 20 +-26.69756081437327 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +78 + 8 +GEAR + 10 +25.496959589947572 + 20 +-30.820529711031583 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +79 + 8 +GEAR + 10 +28.725051910527544 + 20 +-27.836511863692582 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +7A + 8 +GEAR + 10 +25.093396864801004 + 20 +-21.43178559489608 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +7B + 8 +GEAR + 10 +26.69756081437326 + 20 +-19.39691332565162 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +7C + 8 +GEAR + 10 +33.77311702008059 + 20 +-21.433071799159883 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +7D + 8 +GEAR + 10 +35.92110303042462 + 20 +-17.597566794236617 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +7E + 8 +GEAR + 10 +30.488024572872455 + 20 +-12.628553268047982 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +7F + 8 +GEAR + 10 +31.384865037740067 + 20 +-10.197560814373272 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +80 + 8 +GEAR + 10 +38.743326445145236 + 20 +-9.947595486594214 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +81 + 8 +GEAR + 10 +39.6009463086623 + 20 +-5.63604927750332 + 30 +0.0 + 70 +0 + 0 +VERTEX + 5 +82 + 8 +GEAR + 10 +32.89827201319322 + 20 +-2.5891501590189057 + 30 +0.0 + 70 +0 + 0 +SEQEND + 5 +32 + 8 +GEAR + 0 +CIRCLE + 5 +83 + 8 +GEAR + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +10.0 + 0 +CIRCLE + 5 +84 + 8 +GEAR + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +4.0 + 0 +CIRCLE + 5 +85 + 8 +GEAR + 10 +20.0 + 20 +0.0 + 30 +0.0 + 40 +4.0 + 0 +CIRCLE + 5 +86 + 8 +GEAR + 10 +10.000000000000002 + 20 +17.32050807568877 + 30 +0.0 + 40 +4.0 + 0 +CIRCLE + 5 +87 + 8 +GEAR + 10 +-9.999999999999996 + 20 +17.320508075688775 + 30 +0.0 + 40 +4.0 + 0 +CIRCLE + 5 +88 + 8 +GEAR + 10 +-20.0 + 20 +2.4492935982947065e-15 + 30 +0.0 + 40 +4.0 + 0 +CIRCLE + 5 +89 + 8 +GEAR + 10 +-10.000000000000009 + 20 +-17.320508075688767 + 30 +0.0 + 40 +4.0 + 0 +CIRCLE + 5 +8A + 8 +GEAR + 10 +10.000000000000002 + 20 +-17.32050807568877 + 30 +0.0 + 40 +4.0 + 0 +LINE + 5 +8B + 8 +AXES + 10 +-50.0 + 20 +0.0 + 30 +0.0 + 11 +50.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +8C + 8 +AXES + 10 +0.0 + 20 +-50.0 + 30 +0.0 + 11 +0.0 + 21 +50.0 + 31 +0.0 + 0 +ARC + 5 +8D + 8 +GEAR + 62 +4 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +30.0 + 50 +30.0 + 51 +150.0 + 0 +TEXT + 5 +8E + 8 +TEXT + 10 +-45.0 + 20 +-58.0 + 30 +0.0 + 40 +4.0 + 1 +GEAR, 20 TEETH (R12 FILE) + 11 +-45.0 + 21 +-58.0 + 31 +0.0 + 0 +TEXT + 5 +8F + 8 +TEXT + 10 +-45.0 + 20 +-64.0 + 30 +0.0 + 40 +3.0 + 1 +module 4, pitch diameter 80 + 11 +-45.0 + 21 +-64.0 + 31 +0.0 + 0 +POINT + 5 +90 + 8 +AXES + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +SOLID + 5 +91 + 8 +DIMS + 10 +55.0 + 20 +40.0 + 30 +0.0 + 11 +65.0 + 21 +40.0 + 31 +0.0 + 12 +55.0 + 22 +46.0 + 32 +0.0 + 13 +65.0 + 23 +46.0 + 33 +0.0 + 0 +3DFACE + 5 +92 + 8 +DIMS + 62 +5 + 10 +55.0 + 20 +-10.0 + 30 +0.0 + 11 +70.0 + 21 +-10.0 + 31 +0.0 + 12 +70.0 + 22 +5.0 + 32 +0.0 + 13 +55.0 + 23 +5.0 + 33 +0.0 + 0 +INSERT + 5 +98 + 8 +DIMS + 2 +TAG + 10 +60.0 + 20 +20.0 + 30 +0.0 + 0 +INSERT + 5 +9A + 8 +DIMS + 2 +TAG + 10 +60.0 + 20 +5.0 + 30 +0.0 + 41 +1.3 + 42 +1.3 + 0 +INSERT + 5 +9C + 8 +DIMS + 2 +TAG + 10 +60.0 + 20 +-10.0 + 30 +0.0 + 41 +1.6 + 42 +1.6 + 0 +ENDSEC + 0 +EOF diff --git a/crates/exav-viewer/demo/examples/files/cad/linetypes.dxf b/crates/exav-viewer/demo/examples/files/cad/linetypes.dxf new file mode 100644 index 0000000..72ce2da --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/cad/linetypes.dxf @@ -0,0 +1,7112 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1032 + 9 +$ACADMAINTVER + 90 +4 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$LASTSAVEDBY + 1 +ezdxf + 9 +$REQUIREDVERSIONS +160 +0 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$EXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 +0 + 9 +$REGENMODE + 70 +1 + 9 +$FILLMODE + 70 +1 + 9 +$QTEXTMODE + 70 +0 + 9 +$MIRRTEXT + 70 +1 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 +1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 +256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 +0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 +0 + 9 +$DIMLIM + 70 +0 + 9 +$DIMTIH + 70 +0 + 9 +$DIMTOH + 70 +0 + 9 +$DIMSE1 + 70 +0 + 9 +$DIMSE2 + 70 +0 + 9 +$DIMTAD + 70 +1 + 9 +$DIMZIN + 70 +8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 +1 + 9 +$DIMSHO + 70 +1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 +0 + 9 +$DIMALTD + 70 +3 + 9 +$DIMALTF + 40 +0.03937007874 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 +1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 +0 + 9 +$DIMSOXD + 70 +0 + 9 +$DIMSAH + 70 +0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 +0 + 9 +$DIMCLRE + 70 +0 + 9 +$DIMCLRT + 70 +0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 +0 + 9 +$DIMSD1 + 70 +0 + 9 +$DIMSD2 + 70 +0 + 9 +$DIMTOLJ + 70 +0 + 9 +$DIMTZIN + 70 +8 + 9 +$DIMALTZ + 70 +0 + 9 +$DIMALTTZ + 70 +0 + 9 +$DIMUPT + 70 +0 + 9 +$DIMDEC + 70 +2 + 9 +$DIMTDEC + 70 +2 + 9 +$DIMALTU + 70 +2 + 9 +$DIMALTTD + 70 +3 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 +0 + 9 +$DIMADEC + 70 +0 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 +0 + 9 +$DIMDSEP + 70 +44 + 9 +$DIMATFIT + 70 +3 + 9 +$DIMFRAC + 70 +0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 +2 + 9 +$DIMLWD + 70 +-2 + 9 +$DIMLWE + 70 +-2 + 9 +$DIMTMOVE + 70 +0 + 9 +$DIMFXL + 40 +1.0 + 9 +$DIMFXLON + 70 +0 + 9 +$DIMJOGANG + 40 +0.785398163397 + 9 +$DIMTFILL + 70 +0 + 9 +$DIMTFILLCLR + 70 +0 + 9 +$DIMARCSYM + 70 +0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$DIMTXTDIRECTION + 70 +0 + 9 +$LUNITS + 70 +2 + 9 +$LUPREC + 70 +4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 +0 + 9 +$AUPREC + 70 +2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 +0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 +0 + 9 +$TDCREATE + 40 +2451545.0 + 9 +$TDUCREATE + 40 +2451545.0 + 9 +$TDUPDATE + 40 +2451545.0 + 9 +$TDUUPDATE + 40 +2451545.0 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 +1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 +0 + 9 +$PDMODE + 70 +0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 +0 + 9 +$SPLINETYPE + 70 +6 + 9 +$SPLINESEGS + 70 +8 + 9 +$HANDSEED + 5 +B3 + 9 +$SURFTAB1 + 70 +6 + 9 +$SURFTAB2 + 70 +6 + 9 +$SURFTYPE + 70 +6 + 9 +$SURFU + 70 +6 + 9 +$SURFV + 70 +6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 +0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 +0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 +0 + 9 +$USERI2 + 70 +0 + 9 +$USERI3 + 70 +0 + 9 +$USERI4 + 70 +0 + 9 +$USERI5 + 70 +0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 +1 + 9 +$SHADEDGE + 70 +3 + 9 +$SHADEDIF + 70 +70 + 9 +$TILEMODE + 70 +1 + 9 +$MAXACTVP + 70 +64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 +0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 +0 + 9 +$VISRETAIN + 70 +1 + 9 +$PLINEGEN + 70 +0 + 9 +$PSLTSCALE + 70 +1 + 9 +$TREEDEPTH + 70 +3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 +0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 +1 + 9 +$MEASUREMENT + 70 +1 + 9 +$CELWEIGHT +370 +-1 + 9 +$ENDCAPS +280 +0 + 9 +$JOINSTYLE +280 +0 + 9 +$LWDISPLAY +290 +0 + 9 +$INSUNITS + 70 +4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 +1 + 9 +$CEPSNTYPE +380 +0 + 9 +$PSTYLEMODE +290 +1 + 9 +$FINGERPRINTGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$VERSIONGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$EXTNAMES +290 +1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 +0 + 9 +$SORTENTS +280 +127 + 9 +$INDEXCTL +280 +0 + 9 +$HIDETEXT +280 +1 + 9 +$XCLIPFRAME +280 +1 + 9 +$HALOGAP +280 +0 + 9 +$OBSCOLOR + 70 +257 + 9 +$OBSLTYPE +280 +0 + 9 +$INTERSECTIONDISPLAY +280 +0 + 9 +$INTERSECTIONCOLOR + 70 +257 + 9 +$DIMASSOC +280 +2 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 +0 + 9 +$LENSLENGTH + 40 +50.0 + 9 +$CAMERAHEIGHT + 40 +0.0 + 9 +$STEPSPERSEC + 40 +24.0 + 9 +$STEPSIZE + 40 +100.0 + 9 +$3DDWFPREC + 40 +2.0 + 9 +$PSOLWIDTH + 40 +0.005 + 9 +$PSOLHEIGHT + 40 +0.08 + 9 +$LOFTANG1 + 40 +1.570796326795 + 9 +$LOFTANG2 + 40 +1.570796326795 + 9 +$LOFTMAG1 + 40 +0.0 + 9 +$LOFTMAG2 + 40 +0.0 + 9 +$LOFTPARAM + 70 +7 + 9 +$LOFTNORMALS +280 +1 + 9 +$LATITUDE + 40 +37.795 + 9 +$LONGITUDE + 40 +-122.394 + 9 +$NORTHDIRECTION + 40 +0.0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 +1 + 9 +$TILEMODELIGHTSYNCH +280 +1 + 9 +$CMATERIAL +347 +20 + 9 +$SOLIDHIST +280 +0 + 9 +$SHOWHIST +280 +1 + 9 +$DWFFRAME +280 +2 + 9 +$DGNFRAME +280 +2 + 9 +$REALWORLDSCALE +290 +1 + 9 +$INTERFERECOLOR + 62 +256 + 9 +$CSHADOW +280 +0 + 9 +$SHADOWPLANELOCATION + 40 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +CELLSTYLEMAP + 2 +AcDbCellStyleMap + 3 +ObjectDBX Classes + 90 +1152 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MENTALRAYRENDERSETTINGS + 2 +AcDbMentalRayRenderSettings + 3 +SCENEOE + 90 +1024 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBDETAILVIEWSTYLE + 2 +AcDbDetailViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBSECTIONVIEWSTYLE + 2 +AcDbSectionViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +RASTERVARIABLES + 2 +AcDbRasterVariables + 3 +ISM + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 +1 + 0 +VPORT + 5 +AF +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +165.9919624916276 + 22 +-187.56625834024877 + 13 +0.0 + 23 +0.0 + 14 +0.5 + 24 +0.5 + 15 +0.5 + 25 +0.5 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +398.08914251452245 + 41 +1.34 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +1000 + 73 +1 + 74 +3 + 75 +0 + 76 +0 + 77 +0 + 78 +0 +281 +0 + 65 +1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 +25 + 0 +LTYPE + 5 +24 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +25 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +26 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +2F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 +0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +5.08 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +30 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 +0 + 3 +Center (2x) ________ __ ________ __ ________ + 72 +65 + 73 +4 + 40 +8.89 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 +0 + 3 +Center (.5x) ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +2.54 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +32 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 +0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 +65 + 73 +2 + 40 +1.524 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +33 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 +0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ____ + 72 +65 + 73 +2 + 40 +3.048 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +34 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 +0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 +65 + 73 +2 + 40 +0.762 + 49 +0.635 + 74 +0 + 49 +-0.127 + 74 +0 + 0 +LTYPE + 5 +35 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM + 70 +0 + 3 +Phantom ______ __ __ ______ __ __ ______ + 72 +65 + 73 +6 + 40 +6.35 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOMX2 + 70 +0 + 3 +Phantom (2x)____________ ____ ____ ____________ + 72 +65 + 73 +6 + 40 +10.795 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +37 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 +0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___ + 72 +65 + 73 +6 + 40 +3.175 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +38 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 +0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 +65 + 73 +4 + 40 +3.556 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +39 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 +0 + 3 +Dash dot (2x) ____ . ____ . ____ . ____ + 72 +65 + 73 +4 + 40 +6.096 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 +0 + 3 +Dash dot (.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +4 + 40 +1.778 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 +0 + 3 +Dot . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.508 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 +0 + 3 +Dot (2x) . . . . . . . . + 72 +65 + 73 +2 + 40 +1.016 + 49 +0.0 + 74 +0 + 49 +-1.016 + 74 +0 + 0 +LTYPE + 5 +3D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 +0 + 3 +Dot (.5) . . . . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.254 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 +0 + 3 +Divide __ . . __ . . __ . . __ . . __ . . __ + 72 +65 + 73 +6 + 40 +4.064 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 +0 + 3 +Divide (2x) ____ . . ____ . . ____ . . ____ + 72 +65 + 73 +6 + 40 +6.604 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +40 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 +0 + 3 +Divide(.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +6 + 40 +2.032 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +42 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +EXAV_DASH3 + 70 +0 + 3 +Dash and three dots + 72 +65 + 73 +6 + 40 +10.0 + 49 +6.0 + 74 +0 + 49 +-3.0 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-3.0 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-3.0 + 74 +0 + 0 +LTYPE + 5 +43 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +GAS_LINE + 70 +0 + 3 +Gas line ---- GAS ---- + 72 +65 + 73 +3 + 40 +0.0 + 49 +5.0 + 74 +0 + 49 +-2.0 + 74 +2 + 75 +0 +340 +41 + 46 +1.5 + 50 +0.0 + 44 +-1.0 + 45 +-0.75 + 9 +GAS + 49 +-4.0 + 74 +0 + 0 +LTYPE + 5 +44 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +HOT_WATER + 70 +0 + 3 +Hot water ---- HW ---- + 72 +65 + 73 +3 + 40 +0.0 + 49 +6.0 + 74 +0 + 49 +-1.5 + 74 +2 + 75 +0 +340 +41 + 46 +1.5 + 50 +0.0 + 44 +-1.0 + 45 +-0.75 + 9 +HW + 49 +-3.0 + 74 +0 + 0 +LTYPE + 5 +45 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +FENCE + 70 +0 + 3 +Fence ---- x ---- + 72 +65 + 73 +3 + 40 +0.0 + 49 +4.0 + 74 +0 + 49 +-2.0 + 74 +2 + 75 +0 +340 +41 + 46 +1.4 + 50 +0.0 + 44 +-0.5 + 45 +-0.7 + 9 +x + 49 +-2.0 + 74 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 +22 + 0 +LAYER + 5 +27 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 62 +7 + 6 +Continuous +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +28 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Defpoints + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +46 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-00 + 70 +0 + 62 +1 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +49 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-01 + 70 +0 + 62 +2 + 6 +DASHED +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +4C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-02 + 70 +0 + 62 +3 + 6 +DASHED2 +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +4F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-03 + 70 +0 + 62 +4 + 6 +DASHEDX2 +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +52 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-04 + 70 +0 + 62 +5 + 6 +DASHED +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +55 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-05 + 70 +0 + 62 +6 + 6 +CENTER +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +58 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-06 + 70 +0 + 62 +7 + 6 +CENTER2 +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +5B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-07 + 70 +0 + 62 +1 + 6 +CENTERX2 +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +5E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-08 + 70 +0 + 62 +2 + 6 +PHANTOM +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +61 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-09 + 70 +0 + 62 +3 + 6 +PHANTOM2 +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +64 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-10 + 70 +0 + 62 +4 + 6 +DASHDOT +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +67 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-11 + 70 +0 + 62 +5 + 6 +DASHDOT2 +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +6A +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-12 + 70 +0 + 62 +6 + 6 +DOT +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +6D +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-13 + 70 +0 + 62 +7 + 6 +DOT2 +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +70 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-14 + 70 +0 + 62 +1 + 6 +DIVIDE +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +73 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-15 + 70 +0 + 62 +2 + 6 +DIVIDE2 +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +76 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-16 + 70 +0 + 62 +3 + 6 +EXAV_DASH3 +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +79 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-17 + 70 +0 + 62 +4 + 6 +GAS_LINE +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +7C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-18 + 70 +0 + 62 +5 + 6 +HOT_WATER +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +7F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LT-19 + 70 +0 + 62 +6 + 6 +FENCE +370 +25 +390 +13 +347 +21 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 +2 + 0 +STYLE + 5 +29 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +41 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +LT-TEXT + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 +3 + 0 +APPID + 5 +2A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 +0 + 0 +APPID + 5 +B0 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +HATCHBACKGROUNDCOLOR + 70 +0 + 0 +APPID + 5 +B1 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +EZDXF + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +4 +330 +0 +100 +AcDbSymbolTable + 70 +1 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +2B +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 +0 + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +0 +177 +0 +178 +0 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +371 +-2 +372 +-2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 +2 + 0 +BLOCK_RECORD + 5 +17 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +1A + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 70 +0 +280 +1 +281 +0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +18 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +19 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +47 +330 +17 +100 +AcDbEntity + 8 +LT-00 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +220.0 + 21 +0.0 + 31 +0.0 + 0 +TEXT + 5 +48 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-1.0 + 30 +0.0 + 40 +3.0 + 1 +Continuous + 7 +LT-TEXT + 11 +230.0 + 21 +-1.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +4A +330 +17 +100 +AcDbEntity + 8 +LT-01 +100 +AcDbLine + 10 +0.0 + 20 +-8.0 + 30 +0.0 + 11 +220.0 + 21 +-8.0 + 31 +0.0 + 0 +TEXT + 5 +4B +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-9.0 + 30 +0.0 + 40 +3.0 + 1 +DASHED + 7 +LT-TEXT + 11 +230.0 + 21 +-9.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +4D +330 +17 +100 +AcDbEntity + 8 +LT-02 +100 +AcDbLine + 10 +0.0 + 20 +-16.0 + 30 +0.0 + 11 +220.0 + 21 +-16.0 + 31 +0.0 + 0 +TEXT + 5 +4E +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-17.0 + 30 +0.0 + 40 +3.0 + 1 +DASHED2 + 7 +LT-TEXT + 11 +230.0 + 21 +-17.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +50 +330 +17 +100 +AcDbEntity + 8 +LT-03 +100 +AcDbLine + 10 +0.0 + 20 +-24.0 + 30 +0.0 + 11 +220.0 + 21 +-24.0 + 31 +0.0 + 0 +TEXT + 5 +51 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-25.0 + 30 +0.0 + 40 +3.0 + 1 +DASHEDX2 + 7 +LT-TEXT + 11 +230.0 + 21 +-25.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +53 +330 +17 +100 +AcDbEntity + 8 +LT-04 +100 +AcDbLine + 10 +0.0 + 20 +-32.0 + 30 +0.0 + 11 +220.0 + 21 +-32.0 + 31 +0.0 + 0 +TEXT + 5 +54 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-33.0 + 30 +0.0 + 40 +3.0 + 1 +DASHED + 7 +LT-TEXT + 11 +230.0 + 21 +-33.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +56 +330 +17 +100 +AcDbEntity + 8 +LT-05 +100 +AcDbLine + 10 +0.0 + 20 +-40.0 + 30 +0.0 + 11 +220.0 + 21 +-40.0 + 31 +0.0 + 0 +TEXT + 5 +57 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-41.0 + 30 +0.0 + 40 +3.0 + 1 +CENTER + 7 +LT-TEXT + 11 +230.0 + 21 +-41.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +59 +330 +17 +100 +AcDbEntity + 8 +LT-06 +100 +AcDbLine + 10 +0.0 + 20 +-48.0 + 30 +0.0 + 11 +220.0 + 21 +-48.0 + 31 +0.0 + 0 +TEXT + 5 +5A +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-49.0 + 30 +0.0 + 40 +3.0 + 1 +CENTER2 + 7 +LT-TEXT + 11 +230.0 + 21 +-49.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +5C +330 +17 +100 +AcDbEntity + 8 +LT-07 +100 +AcDbLine + 10 +0.0 + 20 +-56.0 + 30 +0.0 + 11 +220.0 + 21 +-56.0 + 31 +0.0 + 0 +TEXT + 5 +5D +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-57.0 + 30 +0.0 + 40 +3.0 + 1 +CENTERX2 + 7 +LT-TEXT + 11 +230.0 + 21 +-57.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +5F +330 +17 +100 +AcDbEntity + 8 +LT-08 +100 +AcDbLine + 10 +0.0 + 20 +-64.0 + 30 +0.0 + 11 +220.0 + 21 +-64.0 + 31 +0.0 + 0 +TEXT + 5 +60 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-65.0 + 30 +0.0 + 40 +3.0 + 1 +PHANTOM + 7 +LT-TEXT + 11 +230.0 + 21 +-65.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +62 +330 +17 +100 +AcDbEntity + 8 +LT-09 +100 +AcDbLine + 10 +0.0 + 20 +-72.0 + 30 +0.0 + 11 +220.0 + 21 +-72.0 + 31 +0.0 + 0 +TEXT + 5 +63 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-73.0 + 30 +0.0 + 40 +3.0 + 1 +PHANTOM2 + 7 +LT-TEXT + 11 +230.0 + 21 +-73.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +65 +330 +17 +100 +AcDbEntity + 8 +LT-10 +100 +AcDbLine + 10 +0.0 + 20 +-80.0 + 30 +0.0 + 11 +220.0 + 21 +-80.0 + 31 +0.0 + 0 +TEXT + 5 +66 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-81.0 + 30 +0.0 + 40 +3.0 + 1 +DASHDOT + 7 +LT-TEXT + 11 +230.0 + 21 +-81.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +68 +330 +17 +100 +AcDbEntity + 8 +LT-11 +100 +AcDbLine + 10 +0.0 + 20 +-88.0 + 30 +0.0 + 11 +220.0 + 21 +-88.0 + 31 +0.0 + 0 +TEXT + 5 +69 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-89.0 + 30 +0.0 + 40 +3.0 + 1 +DASHDOT2 + 7 +LT-TEXT + 11 +230.0 + 21 +-89.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +6B +330 +17 +100 +AcDbEntity + 8 +LT-12 +100 +AcDbLine + 10 +0.0 + 20 +-96.0 + 30 +0.0 + 11 +220.0 + 21 +-96.0 + 31 +0.0 + 0 +TEXT + 5 +6C +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-97.0 + 30 +0.0 + 40 +3.0 + 1 +DOT + 7 +LT-TEXT + 11 +230.0 + 21 +-97.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +6E +330 +17 +100 +AcDbEntity + 8 +LT-13 +100 +AcDbLine + 10 +0.0 + 20 +-104.0 + 30 +0.0 + 11 +220.0 + 21 +-104.0 + 31 +0.0 + 0 +TEXT + 5 +6F +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-105.0 + 30 +0.0 + 40 +3.0 + 1 +DOT2 + 7 +LT-TEXT + 11 +230.0 + 21 +-105.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +71 +330 +17 +100 +AcDbEntity + 8 +LT-14 +100 +AcDbLine + 10 +0.0 + 20 +-112.0 + 30 +0.0 + 11 +220.0 + 21 +-112.0 + 31 +0.0 + 0 +TEXT + 5 +72 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-113.0 + 30 +0.0 + 40 +3.0 + 1 +DIVIDE + 7 +LT-TEXT + 11 +230.0 + 21 +-113.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +74 +330 +17 +100 +AcDbEntity + 8 +LT-15 +100 +AcDbLine + 10 +0.0 + 20 +-120.0 + 30 +0.0 + 11 +220.0 + 21 +-120.0 + 31 +0.0 + 0 +TEXT + 5 +75 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-121.0 + 30 +0.0 + 40 +3.0 + 1 +DIVIDE2 + 7 +LT-TEXT + 11 +230.0 + 21 +-121.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +77 +330 +17 +100 +AcDbEntity + 8 +LT-16 +100 +AcDbLine + 10 +0.0 + 20 +-128.0 + 30 +0.0 + 11 +220.0 + 21 +-128.0 + 31 +0.0 + 0 +TEXT + 5 +78 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-129.0 + 30 +0.0 + 40 +3.0 + 1 +EXAV_DASH3 + 7 +LT-TEXT + 11 +230.0 + 21 +-129.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +7A +330 +17 +100 +AcDbEntity + 8 +LT-17 +100 +AcDbLine + 10 +0.0 + 20 +-136.0 + 30 +0.0 + 11 +220.0 + 21 +-136.0 + 31 +0.0 + 0 +TEXT + 5 +7B +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-137.0 + 30 +0.0 + 40 +3.0 + 1 +GAS_LINE + 7 +LT-TEXT + 11 +230.0 + 21 +-137.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +7D +330 +17 +100 +AcDbEntity + 8 +LT-18 +100 +AcDbLine + 10 +0.0 + 20 +-144.0 + 30 +0.0 + 11 +220.0 + 21 +-144.0 + 31 +0.0 + 0 +TEXT + 5 +7E +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-145.0 + 30 +0.0 + 40 +3.0 + 1 +HOT_WATER + 7 +LT-TEXT + 11 +230.0 + 21 +-145.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +80 +330 +17 +100 +AcDbEntity + 8 +LT-19 +100 +AcDbLine + 10 +0.0 + 20 +-152.0 + 30 +0.0 + 11 +220.0 + 21 +-152.0 + 31 +0.0 + 0 +TEXT + 5 +81 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-153.0 + 30 +0.0 + 40 +3.0 + 1 +FENCE + 7 +LT-TEXT + 11 +230.0 + 21 +-153.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +82 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +0.0 + 20 +-160.0 + 30 +0.0 + 40 +4.0 + 1 +Line weights (mm) + 7 +LT-TEXT + 11 +0.0 + 21 +-160.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +83 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +0 +100 +AcDbLine + 10 +0.0 + 20 +-166.0 + 30 +0.0 + 11 +220.0 + 21 +-166.0 + 31 +0.0 + 0 +TEXT + 5 +84 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-167.0 + 30 +0.0 + 40 +3.0 + 1 +0.00 + 7 +LT-TEXT + 11 +230.0 + 21 +-167.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +85 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +5 +100 +AcDbLine + 10 +0.0 + 20 +-171.0 + 30 +0.0 + 11 +220.0 + 21 +-171.0 + 31 +0.0 + 0 +TEXT + 5 +86 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-172.0 + 30 +0.0 + 40 +3.0 + 1 +0.05 + 7 +LT-TEXT + 11 +230.0 + 21 +-172.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +87 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +9 +100 +AcDbLine + 10 +0.0 + 20 +-176.0 + 30 +0.0 + 11 +220.0 + 21 +-176.0 + 31 +0.0 + 0 +TEXT + 5 +88 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-177.0 + 30 +0.0 + 40 +3.0 + 1 +0.09 + 7 +LT-TEXT + 11 +230.0 + 21 +-177.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +89 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +13 +100 +AcDbLine + 10 +0.0 + 20 +-181.0 + 30 +0.0 + 11 +220.0 + 21 +-181.0 + 31 +0.0 + 0 +TEXT + 5 +8A +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-182.0 + 30 +0.0 + 40 +3.0 + 1 +0.13 + 7 +LT-TEXT + 11 +230.0 + 21 +-182.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +8B +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +18 +100 +AcDbLine + 10 +0.0 + 20 +-186.0 + 30 +0.0 + 11 +220.0 + 21 +-186.0 + 31 +0.0 + 0 +TEXT + 5 +8C +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-187.0 + 30 +0.0 + 40 +3.0 + 1 +0.18 + 7 +LT-TEXT + 11 +230.0 + 21 +-187.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +8D +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +25 +100 +AcDbLine + 10 +0.0 + 20 +-191.0 + 30 +0.0 + 11 +220.0 + 21 +-191.0 + 31 +0.0 + 0 +TEXT + 5 +8E +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-192.0 + 30 +0.0 + 40 +3.0 + 1 +0.25 + 7 +LT-TEXT + 11 +230.0 + 21 +-192.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +8F +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +35 +100 +AcDbLine + 10 +0.0 + 20 +-196.0 + 30 +0.0 + 11 +220.0 + 21 +-196.0 + 31 +0.0 + 0 +TEXT + 5 +90 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-197.0 + 30 +0.0 + 40 +3.0 + 1 +0.35 + 7 +LT-TEXT + 11 +230.0 + 21 +-197.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +91 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +50 +100 +AcDbLine + 10 +0.0 + 20 +-201.0 + 30 +0.0 + 11 +220.0 + 21 +-201.0 + 31 +0.0 + 0 +TEXT + 5 +92 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-202.0 + 30 +0.0 + 40 +3.0 + 1 +0.50 + 7 +LT-TEXT + 11 +230.0 + 21 +-202.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +93 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +70 +100 +AcDbLine + 10 +0.0 + 20 +-206.0 + 30 +0.0 + 11 +220.0 + 21 +-206.0 + 31 +0.0 + 0 +TEXT + 5 +94 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-207.0 + 30 +0.0 + 40 +3.0 + 1 +0.70 + 7 +LT-TEXT + 11 +230.0 + 21 +-207.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +95 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +100 +100 +AcDbLine + 10 +0.0 + 20 +-211.0 + 30 +0.0 + 11 +220.0 + 21 +-211.0 + 31 +0.0 + 0 +TEXT + 5 +96 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-212.0 + 30 +0.0 + 40 +3.0 + 1 +1.00 + 7 +LT-TEXT + 11 +230.0 + 21 +-212.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +97 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +140 +100 +AcDbLine + 10 +0.0 + 20 +-216.0 + 30 +0.0 + 11 +220.0 + 21 +-216.0 + 31 +0.0 + 0 +TEXT + 5 +98 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-217.0 + 30 +0.0 + 40 +3.0 + 1 +1.40 + 7 +LT-TEXT + 11 +230.0 + 21 +-217.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +99 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +370 +200 +100 +AcDbLine + 10 +0.0 + 20 +-221.0 + 30 +0.0 + 11 +220.0 + 21 +-221.0 + 31 +0.0 + 0 +TEXT + 5 +9A +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-222.0 + 30 +0.0 + 40 +3.0 + 1 +2.00 + 7 +LT-TEXT + 11 +230.0 + 21 +-222.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +9B +330 +17 +100 +AcDbEntity + 8 +0 + 6 +DASHED + 62 +4 + 48 +0.25 +100 +AcDbLine + 10 +0.0 + 20 +-236.0 + 30 +0.0 + 11 +220.0 + 21 +-236.0 + 31 +0.0 + 0 +TEXT + 5 +9C +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-237.0 + 30 +0.0 + 40 +3.0 + 1 +DASHED, ltscale 0.25 + 7 +LT-TEXT + 11 +230.0 + 21 +-237.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +9D +330 +17 +100 +AcDbEntity + 8 +0 + 6 +DASHED + 62 +4 + 48 +0.5 +100 +AcDbLine + 10 +0.0 + 20 +-242.0 + 30 +0.0 + 11 +220.0 + 21 +-242.0 + 31 +0.0 + 0 +TEXT + 5 +9E +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-243.0 + 30 +0.0 + 40 +3.0 + 1 +DASHED, ltscale 0.5 + 7 +LT-TEXT + 11 +230.0 + 21 +-243.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +9F +330 +17 +100 +AcDbEntity + 8 +0 + 6 +DASHED + 62 +4 +100 +AcDbLine + 10 +0.0 + 20 +-248.0 + 30 +0.0 + 11 +220.0 + 21 +-248.0 + 31 +0.0 + 0 +TEXT + 5 +A0 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-249.0 + 30 +0.0 + 40 +3.0 + 1 +DASHED, ltscale 1 + 7 +LT-TEXT + 11 +230.0 + 21 +-249.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +A1 +330 +17 +100 +AcDbEntity + 8 +0 + 6 +DASHED + 62 +4 + 48 +2.0 +100 +AcDbLine + 10 +0.0 + 20 +-254.0 + 30 +0.0 + 11 +220.0 + 21 +-254.0 + 31 +0.0 + 0 +TEXT + 5 +A2 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-255.0 + 30 +0.0 + 40 +3.0 + 1 +DASHED, ltscale 2 + 7 +LT-TEXT + 11 +230.0 + 21 +-255.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +A3 +330 +17 +100 +AcDbEntity + 8 +0 + 6 +DASHED + 62 +4 + 48 +4.0 +100 +AcDbLine + 10 +0.0 + 20 +-260.0 + 30 +0.0 + 11 +220.0 + 21 +-260.0 + 31 +0.0 + 0 +TEXT + 5 +A4 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-261.0 + 30 +0.0 + 40 +3.0 + 1 +DASHED, ltscale 4 + 7 +LT-TEXT + 11 +230.0 + 21 +-261.0 + 31 +0.0 +100 +AcDbText + 0 +LWPOLYLINE + 5 +A5 +330 +17 +100 +AcDbEntity + 8 +0 + 6 +PHANTOM + 62 +1 +100 +AcDbPolyline + 90 +6 + 70 +128 + 10 +0.0 + 20 +-274.0 + 10 +40.0 + 20 +-286.0 + 10 +80.0 + 20 +-274.0 + 10 +120.0 + 20 +-286.0 + 10 +160.0 + 20 +-274.0 + 10 +200.0 + 20 +-286.0 + 0 +TEXT + 5 +A6 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-275.0 + 30 +0.0 + 40 +3.0 + 1 +lwpolyline, linetype generation on + 7 +LT-TEXT + 11 +230.0 + 21 +-275.0 + 31 +0.0 +100 +AcDbText + 0 +LWPOLYLINE + 5 +A7 +330 +17 +100 +AcDbEntity + 8 +0 + 6 +PHANTOM + 62 +3 +100 +AcDbPolyline + 90 +6 + 70 +0 + 10 +0.0 + 20 +-299.0 + 10 +40.0 + 20 +-311.0 + 10 +80.0 + 20 +-299.0 + 10 +120.0 + 20 +-311.0 + 10 +160.0 + 20 +-299.0 + 10 +200.0 + 20 +-311.0 + 0 +TEXT + 5 +A8 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-300.0 + 30 +0.0 + 40 +3.0 + 1 +lwpolyline, linetype generation off + 7 +LT-TEXT + 11 +230.0 + 21 +-300.0 + 31 +0.0 +100 +AcDbText + 0 +LWPOLYLINE + 5 +A9 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +6 +100 +AcDbPolyline + 90 +5 + 70 +0 + 10 +0.0 + 20 +-330.0 + 40 +0.0 + 41 +6.0 + 10 +50.0 + 20 +-330.0 + 40 +6.0 + 41 +1.0 + 10 +100.0 + 20 +-345.0 + 40 +1.0 + 41 +6.0 + 10 +150.0 + 20 +-330.0 + 40 +6.0 + 41 +6.0 + 10 +200.0 + 20 +-338.0 + 0 +TEXT + 5 +AA +330 +17 +100 +AcDbEntity + 8 +0 + 62 +7 +100 +AcDbText + 10 +230.0 + 20 +-331.0 + 30 +0.0 + 40 +3.0 + 1 +lwpolyline with start and end widths per segment + 7 +LT-TEXT + 11 +230.0 + 21 +-331.0 + 31 +0.0 +100 +AcDbText + 0 +CIRCLE + 5 +AB +330 +17 +100 +AcDbEntity + 8 +0 + 6 +CENTER + 62 +1 +370 +35 +100 +AcDbCircle + 10 +30.0 + 20 +-360.0 + 30 +0.0 + 40 +15.0 + 0 +ARC + 5 +AC +330 +17 +100 +AcDbEntity + 8 +0 + 6 +DASHED + 62 +3 +100 +AcDbCircle + 10 +90.0 + 20 +-360.0 + 30 +0.0 + 40 +15.0 +100 +AcDbArc + 50 +30.0 + 51 +300.0 + 0 +ELLIPSE + 5 +AD +330 +17 +100 +AcDbEntity + 8 +0 + 6 +PHANTOM + 62 +5 +100 +AcDbEllipse + 10 +150.0 + 20 +-360.0 + 30 +0.0 + 11 +25.0 + 21 +0.0 + 31 +0.0 + 40 +0.5 + 41 +0.0 + 42 +6.283185307179586 + 0 +SPLINE + 5 +AE +330 +17 +100 +AcDbEntity + 8 +0 + 6 +DASHDOT + 62 +6 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +4 + 11 +190.0 + 21 +-370.0 + 31 +0.0 + 11 +200.0 + 21 +-348.0 + 31 +0.0 + 11 +215.0 + 21 +-374.0 + 31 +0.0 + 11 +225.0 + 21 +-350.0 + 31 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +A +330 +0 +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ACAD_COLOR +350 +B + 3 +ACAD_GROUP +350 +C + 3 +ACAD_LAYOUT +350 +D + 3 +ACAD_MATERIAL +350 +E + 3 +ACAD_MLEADERSTYLE +350 +F + 3 +ACAD_MLINESTYLE +350 +10 + 3 +ACAD_PLOTSETTINGS +350 +11 + 3 +ACAD_PLOTSTYLENAME +350 +12 + 3 +ACAD_SCALELIST +350 +14 + 3 +ACAD_TABLESTYLE +350 +15 + 3 +ACAD_VISUALSTYLE +350 +16 + 3 +EZDXF_META +350 +2D + 0 +DICTIONARY + 5 +B +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +C +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +D +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Model +350 +1A + 3 +Layout1 +350 +1E + 0 +DICTIONARY + 5 +E +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ByBlock +350 +1F + 3 +ByLayer +350 +20 + 3 +Global +350 +21 + 0 +DICTIONARY + 5 +F +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +2C + 0 +DICTIONARY + 5 +10 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +22 + 0 +DICTIONARY + 5 +11 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +ACDBDICTIONARYWDFLT + 5 +12 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Normal +350 +13 +100 +AcDbDictionaryWithDefault +340 +13 + 0 +ACDBPLACEHOLDER + 5 +13 +330 +12 + 0 +DICTIONARY + 5 +14 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +15 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +16 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +LAYOUT + 5 +1A +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +1024 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 +1 + 71 +0 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +17 + 0 +LAYOUT + 5 +1E +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +0 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 +1 + 71 +1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +1B + 0 +MATERIAL + 5 +1F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByBlock + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +20 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByLayer + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +21 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +Global + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MLINESTYLE + 5 +22 +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMlineStyle + 2 +Standard + 70 +0 + 3 + + 62 +256 + 51 +90.0 + 52 +90.0 + 71 +2 + 49 +0.5 + 62 +256 + 6 +BYLAYER + 49 +-0.5 + 62 +256 + 6 +BYLAYER + 0 +MLEADERSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +F +102 +} +330 +F +100 +AcDbMLeaderStyle +179 +2 +170 +2 +171 +1 +172 +0 + 90 +2 + 40 +0.0 + 41 +0.0 +173 +1 + 91 +-1056964608 + 92 +-2 +290 +1 + 42 +2.0 +291 +1 + 43 +8.0 + 3 +Standard + 44 +4.0 +300 + +342 +29 +174 +1 +175 +1 +176 +0 +178 +1 + 93 +-1056964608 + 45 +4.0 +292 +0 +297 +0 + 46 +4.0 + 94 +-1056964608 + 47 +1.0 + 49 +1.0 +140 +1.0 +294 +1 +141 +0.0 +177 +0 +142 +1.0 +295 +0 +296 +0 +143 +3.75 +271 +0 +272 +9 +273 +9 + 0 +DICTIONARY + 5 +2D +330 +A +100 +AcDbDictionary +281 +1 + 3 +CREATED_BY_EZDXF +350 +2E + 3 +WRITTEN_BY_EZDXF +350 +B2 + 0 +DICTIONARYVAR + 5 +2E +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +DICTIONARYVAR + 5 +B2 +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +ENDSEC + 0 +EOF diff --git a/crates/exav-viewer/demo/examples/files/cad/site-plan.dxf b/crates/exav-viewer/demo/examples/files/cad/site-plan.dxf new file mode 100644 index 0000000..92e0d42 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/cad/site-plan.dxf @@ -0,0 +1,14098 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1032 + 9 +$ACADMAINTVER + 90 +4 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$LASTSAVEDBY + 1 +ezdxf + 9 +$REQUIREDVERSIONS +160 +0 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$EXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 +0 + 9 +$REGENMODE + 70 +1 + 9 +$FILLMODE + 70 +1 + 9 +$QTEXTMODE + 70 +0 + 9 +$MIRRTEXT + 70 +1 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 +1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 +256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 +0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 +0 + 9 +$DIMLIM + 70 +0 + 9 +$DIMTIH + 70 +0 + 9 +$DIMTOH + 70 +0 + 9 +$DIMSE1 + 70 +0 + 9 +$DIMSE2 + 70 +0 + 9 +$DIMTAD + 70 +1 + 9 +$DIMZIN + 70 +8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 +1 + 9 +$DIMSHO + 70 +1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 +0 + 9 +$DIMALTD + 70 +3 + 9 +$DIMALTF + 40 +0.03937007874 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 +1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 +0 + 9 +$DIMSOXD + 70 +0 + 9 +$DIMSAH + 70 +0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 +0 + 9 +$DIMCLRE + 70 +0 + 9 +$DIMCLRT + 70 +0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 +0 + 9 +$DIMSD1 + 70 +0 + 9 +$DIMSD2 + 70 +0 + 9 +$DIMTOLJ + 70 +0 + 9 +$DIMTZIN + 70 +8 + 9 +$DIMALTZ + 70 +0 + 9 +$DIMALTTZ + 70 +0 + 9 +$DIMUPT + 70 +0 + 9 +$DIMDEC + 70 +2 + 9 +$DIMTDEC + 70 +2 + 9 +$DIMALTU + 70 +2 + 9 +$DIMALTTD + 70 +3 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 +0 + 9 +$DIMADEC + 70 +0 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 +0 + 9 +$DIMDSEP + 70 +44 + 9 +$DIMATFIT + 70 +3 + 9 +$DIMFRAC + 70 +0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 +2 + 9 +$DIMLWD + 70 +-2 + 9 +$DIMLWE + 70 +-2 + 9 +$DIMTMOVE + 70 +0 + 9 +$DIMFXL + 40 +1.0 + 9 +$DIMFXLON + 70 +0 + 9 +$DIMJOGANG + 40 +0.785398163397 + 9 +$DIMTFILL + 70 +0 + 9 +$DIMTFILLCLR + 70 +0 + 9 +$DIMARCSYM + 70 +0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$DIMTXTDIRECTION + 70 +0 + 9 +$LUNITS + 70 +2 + 9 +$LUPREC + 70 +4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 +0 + 9 +$AUPREC + 70 +2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 +0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 +0 + 9 +$TDCREATE + 40 +2451545.0 + 9 +$TDUCREATE + 40 +2451545.0 + 9 +$TDUPDATE + 40 +2451545.0 + 9 +$TDUUPDATE + 40 +2451545.0 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 +1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 +0 + 9 +$PDMODE + 70 +0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 +0 + 9 +$SPLINETYPE + 70 +6 + 9 +$SPLINESEGS + 70 +8 + 9 +$HANDSEED + 5 +158 + 9 +$SURFTAB1 + 70 +6 + 9 +$SURFTAB2 + 70 +6 + 9 +$SURFTYPE + 70 +6 + 9 +$SURFU + 70 +6 + 9 +$SURFV + 70 +6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 +0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 +0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 +0 + 9 +$USERI2 + 70 +0 + 9 +$USERI3 + 70 +0 + 9 +$USERI4 + 70 +0 + 9 +$USERI5 + 70 +0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 +1 + 9 +$SHADEDGE + 70 +3 + 9 +$SHADEDIF + 70 +70 + 9 +$TILEMODE + 70 +1 + 9 +$MAXACTVP + 70 +64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 +0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 +0 + 9 +$VISRETAIN + 70 +1 + 9 +$PLINEGEN + 70 +0 + 9 +$PSLTSCALE + 70 +1 + 9 +$TREEDEPTH + 70 +3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 +0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 +1 + 9 +$MEASUREMENT + 70 +1 + 9 +$CELWEIGHT +370 +-1 + 9 +$ENDCAPS +280 +0 + 9 +$JOINSTYLE +280 +0 + 9 +$LWDISPLAY +290 +0 + 9 +$INSUNITS + 70 +6 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 +1 + 9 +$CEPSNTYPE +380 +0 + 9 +$PSTYLEMODE +290 +1 + 9 +$FINGERPRINTGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$VERSIONGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$EXTNAMES +290 +1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 +0 + 9 +$SORTENTS +280 +127 + 9 +$INDEXCTL +280 +0 + 9 +$HIDETEXT +280 +1 + 9 +$XCLIPFRAME +280 +1 + 9 +$HALOGAP +280 +0 + 9 +$OBSCOLOR + 70 +257 + 9 +$OBSLTYPE +280 +0 + 9 +$INTERSECTIONDISPLAY +280 +0 + 9 +$INTERSECTIONCOLOR + 70 +257 + 9 +$DIMASSOC +280 +2 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 +0 + 9 +$LENSLENGTH + 40 +50.0 + 9 +$CAMERAHEIGHT + 40 +0.0 + 9 +$STEPSPERSEC + 40 +24.0 + 9 +$STEPSIZE + 40 +100.0 + 9 +$3DDWFPREC + 40 +2.0 + 9 +$PSOLWIDTH + 40 +0.005 + 9 +$PSOLHEIGHT + 40 +0.08 + 9 +$LOFTANG1 + 40 +1.570796326795 + 9 +$LOFTANG2 + 40 +1.570796326795 + 9 +$LOFTMAG1 + 40 +0.0 + 9 +$LOFTMAG2 + 40 +0.0 + 9 +$LOFTPARAM + 70 +7 + 9 +$LOFTNORMALS +280 +1 + 9 +$LATITUDE + 40 +37.795 + 9 +$LONGITUDE + 40 +-122.394 + 9 +$NORTHDIRECTION + 40 +0.0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 +1 + 9 +$TILEMODELIGHTSYNCH +280 +1 + 9 +$CMATERIAL +347 +20 + 9 +$SOLIDHIST +280 +0 + 9 +$SHOWHIST +280 +1 + 9 +$DWFFRAME +280 +2 + 9 +$DGNFRAME +280 +2 + 9 +$REALWORLDSCALE +290 +1 + 9 +$INTERFERECOLOR + 62 +256 + 9 +$CSHADOW +280 +0 + 9 +$SHADOWPLANELOCATION + 40 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +CELLSTYLEMAP + 2 +AcDbCellStyleMap + 3 +ObjectDBX Classes + 90 +1152 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MENTALRAYRENDERSETTINGS + 2 +AcDbMentalRayRenderSettings + 3 +SCENEOE + 90 +1024 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBDETAILVIEWSTYLE + 2 +AcDbDetailViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBSECTIONVIEWSTYLE + 2 +AcDbSectionViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +RASTERVARIABLES + 2 +AcDbRasterVariables + 3 +ISM + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 +1 + 0 +VPORT + 5 +154 +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +193.55039660541104 + 22 +20.714668452779648 + 13 +0.0 + 23 +0.0 + 14 +0.5 + 24 +0.5 + 15 +0.5 + 25 +0.5 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +384.29437374413936 + 41 +1.34 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +1000 + 73 +1 + 74 +3 + 75 +0 + 76 +0 + 77 +0 + 78 +0 +281 +0 + 65 +1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 +21 + 0 +LTYPE + 5 +24 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +25 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +26 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +2F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 +0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +5.08 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +30 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 +0 + 3 +Center (2x) ________ __ ________ __ ________ + 72 +65 + 73 +4 + 40 +8.89 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 +0 + 3 +Center (.5x) ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +2.54 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +32 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 +0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 +65 + 73 +2 + 40 +1.524 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +33 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 +0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ____ + 72 +65 + 73 +2 + 40 +3.048 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +34 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 +0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 +65 + 73 +2 + 40 +0.762 + 49 +0.635 + 74 +0 + 49 +-0.127 + 74 +0 + 0 +LTYPE + 5 +35 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM + 70 +0 + 3 +Phantom ______ __ __ ______ __ __ ______ + 72 +65 + 73 +6 + 40 +6.35 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOMX2 + 70 +0 + 3 +Phantom (2x)____________ ____ ____ ____________ + 72 +65 + 73 +6 + 40 +10.795 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +37 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 +0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___ + 72 +65 + 73 +6 + 40 +3.175 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +38 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 +0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 +65 + 73 +4 + 40 +3.556 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +39 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 +0 + 3 +Dash dot (2x) ____ . ____ . ____ . ____ + 72 +65 + 73 +4 + 40 +6.096 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 +0 + 3 +Dash dot (.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +4 + 40 +1.778 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 +0 + 3 +Dot . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.508 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 +0 + 3 +Dot (2x) . . . . . . . . + 72 +65 + 73 +2 + 40 +1.016 + 49 +0.0 + 74 +0 + 49 +-1.016 + 74 +0 + 0 +LTYPE + 5 +3D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 +0 + 3 +Dot (.5) . . . . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.254 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 +0 + 3 +Divide __ . . __ . . __ . . __ . . __ . . __ + 72 +65 + 73 +6 + 40 +4.064 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 +0 + 3 +Divide (2x) ____ . . ____ . . ____ . . ____ + 72 +65 + 73 +6 + 40 +6.604 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +40 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 +0 + 3 +Divide(.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +6 + 40 +2.032 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 +12 + 0 +LAYER + 5 +27 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 62 +7 + 6 +Continuous +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +28 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Defpoints + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +41 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +CONTOUR-MINOR + 70 +0 + 62 +8 + 6 +Continuous +370 +9 +390 +13 +347 +21 + 0 +LAYER + 5 +42 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +CONTOUR-MAJOR + 70 +0 + 62 +30 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +43 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +PARCEL + 70 +0 + 62 +1 + 6 +DASHDOT +370 +35 +390 +13 +347 +21 + 0 +LAYER + 5 +44 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +BUILDING + 70 +0 + 62 +7 + 6 +Continuous +370 +50 +390 +13 +347 +21 + 0 +LAYER + 5 +45 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +ROAD + 70 +0 + 62 +9 + 6 +Continuous +370 +18 +390 +13 +347 +21 + 0 +LAYER + 5 +46 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +WATER + 70 +0 + 62 +5 + 6 +Continuous +370 +18 +390 +13 +347 +21 + 0 +LAYER + 5 +47 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +TREES + 70 +0 + 62 +3 + 6 +Continuous +370 +9 +390 +13 +347 +21 + 0 +LAYER + 5 +48 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +SPOT + 70 +0 + 62 +2 + 6 +Continuous +370 +9 +390 +13 +347 +21 + 0 +LAYER + 5 +49 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +TEXT + 70 +0 + 62 +2 + 6 +Continuous +370 +13 +390 +13 +347 +21 + 0 +LAYER + 5 +4A +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LEGEND + 70 +0 + 62 +7 + 6 +Continuous +370 +13 +390 +13 +347 +21 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 +2 + 0 +STYLE + 5 +29 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +4B +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +SITE + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 +3 + 0 +APPID + 5 +2A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 +0 + 0 +APPID + 5 +155 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +HATCHBACKGROUNDCOLOR + 70 +0 + 0 +APPID + 5 +156 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +EZDXF + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +4 +330 +0 +100 +AcDbSymbolTable + 70 +1 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +2B +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 +0 + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +0 +177 +0 +178 +0 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +371 +-2 +372 +-2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 +13 + 0 +BLOCK_RECORD + 5 +17 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +1A + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +4C +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +DOOR +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +53 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +WINDOW +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +5C +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +BED +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +63 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +TABLE +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +6F +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +SOFA +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +77 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +WC +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +7C +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +SINK +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +82 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +BATH +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +87 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +AXIS +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +8C +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +NORTH +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +92 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +LEVEL +340 +0 + 70 +0 +280 +1 +281 +0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +18 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +19 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +4D +330 +4C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +DOOR + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +DOOR + 1 + + 0 +LINE + 5 +4F +330 +4C +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +900.0 + 31 +0.0 + 0 +ARC + 5 +50 +330 +4C +100 +AcDbEntity + 8 +A-DOOR + 6 +DASHED +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +900.0 +100 +AcDbArc + 50 +0.0 + 51 +90.0 + 0 +LWPOLYLINE + 5 +51 +330 +4C +100 +AcDbEntity + 8 +A-DOOR +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +900.0 + 20 +0.0 + 10 +900.0 + 20 +40.0 + 10 +0.0 + 20 +40.0 + 0 +ATTDEF + 5 +52 +330 +4C +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +350.0 + 20 +-330.0 + 30 +0.0 + 40 +110.0 + 1 +D-000 +100 +AcDbAttributeDefinition + 3 + + 2 +TAG + 70 +0 + 71 +1 + 72 +0 + 0 +ENDBLK + 5 +4E +330 +4C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +54 +330 +53 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +WINDOW + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +WINDOW + 1 + + 0 +LINE + 5 +56 +330 +53 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +1.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +57 +330 +53 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.35 + 30 +0.0 + 11 +1.0 + 21 +0.35 + 31 +0.0 + 0 +LINE + 5 +58 +330 +53 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.65 + 30 +0.0 + 11 +1.0 + 21 +0.65 + 31 +0.0 + 0 +LINE + 5 +59 +330 +53 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +1.0 + 30 +0.0 + 11 +1.0 + 21 +1.0 + 31 +0.0 + 0 +LINE + 5 +5A +330 +53 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +1.0 + 31 +0.0 + 0 +LINE + 5 +5B +330 +53 +100 +AcDbEntity + 8 +A-WIND +100 +AcDbLine + 10 +1.0 + 20 +0.0 + 30 +0.0 + 11 +1.0 + 21 +1.0 + 31 +0.0 + 0 +ENDBLK + 5 +55 +330 +53 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +5D +330 +5C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +BED + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +BED + 1 + + 0 +LWPOLYLINE + 5 +5F +330 +5C +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1600.0 + 20 +0.0 + 10 +1600.0 + 20 +2000.0 + 10 +0.0 + 20 +2000.0 + 0 +LWPOLYLINE + 5 +60 +330 +5C +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +80.0 + 20 +1300.0 + 10 +760.0 + 20 +1300.0 + 10 +760.0 + 20 +1920.0 + 10 +80.0 + 20 +1920.0 + 0 +LWPOLYLINE + 5 +61 +330 +5C +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +840.0 + 20 +1300.0 + 10 +1520.0 + 20 +1300.0 + 10 +1520.0 + 20 +1920.0 + 10 +840.0 + 20 +1920.0 + 0 +LINE + 5 +62 +330 +5C +100 +AcDbEntity + 8 +A-FURN +100 +AcDbLine + 10 +0.0 + 20 +1200.0 + 30 +0.0 + 11 +1600.0 + 21 +1200.0 + 31 +0.0 + 0 +ENDBLK + 5 +5E +330 +5C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +64 +330 +63 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +TABLE + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +TABLE + 1 + + 0 +LWPOLYLINE + 5 +66 +330 +63 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1800.0 + 20 +0.0 + 10 +1800.0 + 20 +900.0 + 10 +0.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +67 +330 +63 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +-450.0 + 10 +550.0 + 20 +-450.0 + 10 +550.0 + 20 +-50.0 + 10 +150.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +68 +330 +63 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +950.0 + 10 +550.0 + 20 +950.0 + 10 +550.0 + 20 +1350.0 + 10 +150.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +69 +330 +63 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +600.0 + 20 +-450.0 + 10 +1000.0 + 20 +-450.0 + 10 +1000.0 + 20 +-50.0 + 10 +600.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +6A +330 +63 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +600.0 + 20 +950.0 + 10 +1000.0 + 20 +950.0 + 10 +1000.0 + 20 +1350.0 + 10 +600.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +6B +330 +63 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1050.0 + 20 +-450.0 + 10 +1450.0 + 20 +-450.0 + 10 +1450.0 + 20 +-50.0 + 10 +1050.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +6C +330 +63 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1050.0 + 20 +950.0 + 10 +1450.0 + 20 +950.0 + 10 +1450.0 + 20 +1350.0 + 10 +1050.0 + 20 +1350.0 + 0 +LWPOLYLINE + 5 +6D +330 +63 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1500.0 + 20 +-450.0 + 10 +1900.0 + 20 +-450.0 + 10 +1900.0 + 20 +-50.0 + 10 +1500.0 + 20 +-50.0 + 0 +LWPOLYLINE + 5 +6E +330 +63 +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1500.0 + 20 +950.0 + 10 +1900.0 + 20 +950.0 + 10 +1900.0 + 20 +1350.0 + 10 +1500.0 + 20 +1350.0 + 0 +ENDBLK + 5 +65 +330 +63 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +70 +330 +6F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +SOFA + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +SOFA + 1 + + 0 +LWPOLYLINE + 5 +72 +330 +6F +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +2200.0 + 20 +0.0 + 10 +2200.0 + 20 +950.0 + 10 +0.0 + 20 +950.0 + 0 +LWPOLYLINE + 5 +73 +330 +6F +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +2200.0 + 20 +0.0 + 10 +2200.0 + 20 +250.0 + 10 +0.0 + 20 +250.0 + 0 +LWPOLYLINE + 5 +74 +330 +6F +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +120.0 + 20 +300.0 + 10 +720.0 + 20 +300.0 + 10 +720.0 + 20 +900.0 + 10 +120.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +75 +330 +6F +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +770.0 + 20 +300.0 + 10 +1370.0 + 20 +300.0 + 10 +1370.0 + 20 +900.0 + 10 +770.0 + 20 +900.0 + 0 +LWPOLYLINE + 5 +76 +330 +6F +100 +AcDbEntity + 8 +A-FURN +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +1420.0 + 20 +300.0 + 10 +2020.0 + 20 +300.0 + 10 +2020.0 + 20 +900.0 + 10 +1420.0 + 20 +900.0 + 0 +ENDBLK + 5 +71 +330 +6F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +78 +330 +77 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +WC + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +WC + 1 + + 0 +LWPOLYLINE + 5 +7A +330 +77 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +400.0 + 20 +0.0 + 10 +400.0 + 20 +200.0 + 10 +0.0 + 20 +200.0 + 0 +ELLIPSE + 5 +7B +330 +77 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbEllipse + 10 +200.0 + 20 +-250.0 + 30 +0.0 + 11 +0.0 + 21 +230.0 + 31 +0.0 + 40 +0.8 + 41 +0.0 + 42 +6.283185307179586 + 0 +ENDBLK + 5 +79 +330 +77 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +7D +330 +7C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +SINK + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +SINK + 1 + + 0 +LWPOLYLINE + 5 +7F +330 +7C +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +600.0 + 20 +0.0 + 10 +600.0 + 20 +450.0 + 10 +0.0 + 20 +450.0 + 0 +CIRCLE + 5 +80 +330 +7C +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbCircle + 10 +300.0 + 20 +225.0 + 30 +0.0 + 40 +160.0 + 0 +CIRCLE + 5 +81 +330 +7C +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbCircle + 10 +300.0 + 20 +225.0 + 30 +0.0 + 40 +25.0 + 0 +ENDBLK + 5 +7E +330 +7C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +83 +330 +82 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +BATH + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +BATH + 1 + + 0 +LWPOLYLINE + 5 +85 +330 +82 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +0.0 + 10 +1700.0 + 20 +0.0 + 10 +1700.0 + 20 +750.0 + 10 +0.0 + 20 +750.0 + 0 +LWPOLYLINE + 5 +86 +330 +82 +100 +AcDbEntity + 8 +A-FIXT +100 +AcDbPolyline + 90 +5 + 70 +1 + 10 +100.0 + 20 +100.0 + 10 +1500.0 + 20 +100.0 + 10 +1600.0 + 20 +375.0 + 10 +1500.0 + 20 +650.0 + 10 +100.0 + 20 +650.0 + 0 +ENDBLK + 5 +84 +330 +82 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +88 +330 +87 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +AXIS + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +AXIS + 1 + + 0 +CIRCLE + 5 +8A +330 +87 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +300.0 + 0 +ATTDEF + 5 +8B +330 +87 +100 +AcDbEntity + 8 +A-GRID +100 +AcDbText + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +300.0 + 1 +A + 72 +4 + 11 +0.0 + 21 +0.0 + 31 +0.0 +100 +AcDbAttributeDefinition + 3 + + 2 +ID + 70 +0 + 71 +1 + 72 +0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +89 +330 +87 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8D +330 +8C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +NORTH + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +NORTH + 1 + + 0 +CIRCLE + 5 +8F +330 +8C +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +500.0 + 0 +SOLID + 5 +90 +330 +8C +100 +AcDbEntity + 8 +A-ANNO + 62 +7 +100 +AcDbTrace + 10 +0.0 + 20 +650.0 + 30 +0.0 + 11 +-170.0 + 21 +-400.0 + 31 +0.0 + 12 +0.0 + 22 +-200.0 + 32 +0.0 + 13 +170.0 + 23 +-400.0 + 33 +0.0 + 0 +TEXT + 5 +91 +330 +8C +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +0.0 + 20 +800.0 + 30 +0.0 + 40 +300.0 + 1 +N + 72 +1 + 11 +0.0 + 21 +800.0 + 31 +0.0 +100 +AcDbText + 73 +1 + 0 +ENDBLK + 5 +8E +330 +8C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +93 +330 +92 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +LEVEL + 70 +2 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +LEVEL + 1 + + 0 +LWPOLYLINE + 5 +95 +330 +92 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbPolyline + 90 +3 + 70 +1 + 10 +-250.0 + 20 +250.0 + 10 +0.0 + 20 +0.0 + 10 +250.0 + 20 +250.0 + 0 +LINE + 5 +96 +330 +92 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbLine + 10 +-250.0 + 20 +250.0 + 30 +0.0 + 11 +900.0 + 21 +250.0 + 31 +0.0 + 0 +ATTDEF + 5 +97 +330 +92 +100 +AcDbEntity + 8 +A-ANNO +100 +AcDbText + 10 +320.0 + 20 +290.0 + 30 +0.0 + 40 +120.0 + 1 ++0.00 +100 +AcDbAttributeDefinition + 3 + + 2 +H + 70 +0 + 71 +1 + 72 +0 + 0 +ENDBLK + 5 +94 +330 +92 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +SPLINE + 5 +98 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +162.72 + 21 +110.0 + 31 +0.0 + 11 +162.75464820619362 + 21 +112.56319826494449 + 31 +0.0 + 11 +161.09938142686286 + 21 +114.8061731409782 + 31 +0.0 + 11 +158.84528137423857 + 21 +116.63396103067893 + 31 +0.0 + 11 +156.18 + 21 +118.02805549308175 + 31 +0.0 + 11 +153.02229025050545 + 21 +118.45950557757982 + 31 +0.0 + 11 +150.0 + 21 +117.92 + 31 +0.0 + 11 +147.33770974949454 + 21 +117.45185185953622 + 31 +0.0 + 11 +144.18 + 21 +117.56040177503814 + 31 +0.0 + 11 +140.43471862576143 + 21 +117.17396103067892 + 31 +0.0 + 11 +137.82061857313715 + 21 +115.2738268590218 + 31 +0.0 + 11 +137.6053517938064 + 21 +112.49085198298809 + 31 +0.0 + 11 +138.72 + 21 +110.0 + 31 +0.0 + 11 +139.57242837525598 + 21 +107.90445545309912 + 31 +0.0 + 11 +140.31477173603633 + 21 +105.8061731409782 + 31 +0.0 + 11 +141.87471862576143 + 21 +103.90603896932107 + 31 +0.0 + 11 +144.18 + 21 +102.43959822496186 + 31 +0.0 + 11 +146.81063316804494 + 21 +101.07284070437659 + 31 +0.0 + 11 +150.0 + 21 +99.92 + 31 +0.0 + 11 +153.54936683195504 + 21 +100.06518698633299 + 31 +0.0 + 11 +156.18 + 21 +101.97194450691825 + 31 +0.0 + 11 +157.40528137423857 + 21 +104.44603896932107 + 31 +0.0 + 11 +158.60522826396368 + 21 +106.2738268590218 + 31 +0.0 + 11 +160.787571624744 + 21 +107.8321091711427 + 31 +0.0 + 11 +162.72 + 21 +110.0 + 31 +0.0 + 0 +SPLINE + 5 +99 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +173.81378607118785 + 21 +108.0 + 31 +0.0 + 11 +173.58551100564256 + 21 +112.13690328730793 + 31 +0.0 + 11 +170.48583079664297 + 21 +115.57158683808454 + 31 +0.0 + 11 +166.61721940455368 + 21 +118.21291455341525 + 31 +0.0 + 11 +162.44810696440607 + 21 +120.2734509732725 + 31 +0.0 + 11 +157.68061818399474 + 21 +121.10122865512437 + 31 +0.0 + 11 +153.0 + 21 +120.61637460359522 + 31 +0.0 + 11 +148.64275899723438 + 21 +120.19608360235772 + 31 +0.0 + 11 +143.44810696440607 + 21 +120.408273034584 + 31 +0.0 + 11 +137.56899452425847 + 21 +119.57325410680613 + 31 +0.0 + 11 +133.80416920335705 + 21 +116.31203855832024 + 31 +0.0 + 11 +133.90489788431614 + 21 +111.83738789346549 + 31 +0.0 + 11 +135.81378607118785 + 21 +108.0 + 31 +0.0 + 11 +136.88032960665797 + 21 +104.76056050188609 + 31 +0.0 + 11 +137.57686545283428 + 21 +101.32158683808456 + 31 +0.0 + 11 +139.74716171946486 + 21 +98.06037128959865 + 31 +0.0 + 11 +143.44810696440607 + 21 +95.591726965416 + 31 +0.0 + 11 +147.84549447009897 + 21 +93.57234260588592 + 31 +0.0 + 11 +153.0 + 21 +92.11637460359522 + 31 +0.0 + 11 +158.47788271113018 + 21 +92.66719755311927 + 31 +0.0 + 11 +162.44810696440607 + 21 +95.7265490267275 + 31 +0.0 + 11 +164.4390522093473 + 21 +99.42071084298954 + 31 +0.0 + 11 +166.7131345471657 + 21 +102.06203855832024 + 31 +0.0 + 11 +170.61007928330073 + 21 +104.46104510804363 + 31 +0.0 + 11 +173.81378607118785 + 21 +108.0 + 31 +0.0 + 0 +SPLINE + 5 +9A +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +185.32168451699252 + 21 +106.0 + 31 +0.0 + 11 +184.46611427526742 + 21 +111.72060424878246 + 31 +0.0 + 11 +179.57671671897407 + 21 +116.20901780823043 + 31 +0.0 + 11 +174.01145761161308 + 21 +119.50859320870981 + 31 +0.0 + 11 +168.50915774150374 + 21 +122.24987257613353 + 31 +0.0 + 11 +162.32561819866925 + 21 +123.705646380037 + 31 +0.0 + 11 +156.0 + 21 +123.56871466111136 + 31 +0.0 + 11 +149.80956051465776 + 21 +123.32727601035833 + 31 +0.0 + 11 +142.50915774150374 + 21 +123.52511817145958 + 31 +0.0 + 11 +134.66685787139443 + 21 +121.9998565964542 + 31 +0.0 + 11 +130.08328328102593 + 21 +117.22226753065821 + 31 +0.0 + 11 +130.72039152839807 + 21 +111.08023800620553 + 31 +0.0 + 11 +133.32168451699252 + 21 +106.0 + 31 +0.0 + 11 +134.23797130823584 + 21 +101.62666148978415 + 31 +0.0 + 11 +134.54339572218328 + 21 +96.70901780823043 + 31 +0.0 + 11 +137.2419049899126 + 21 +91.93142874243446 + 31 +0.0 + 11 +142.50915774150374 + 21 +88.47488182854042 + 31 +0.0 + 11 +148.8670278533382 + 21 +86.03453915476334 + 31 +0.0 + 11 +156.0 + 21 +84.56871466111136 + 31 +0.0 + 11 +163.26815085998882 + 21 +85.65616878508466 + 31 +0.0 + 11 +168.50915774150374 + 21 +89.75012742386647 + 31 +0.0 + 11 +171.43641049309488 + 21 +94.42269213017883 + 31 +0.0 + 11 +175.11660427781672 + 21 +97.72226753065821 + 31 +0.0 + 11 +180.9485344954296 + 21 +100.98629524720721 + 31 +0.0 + 11 +185.32168451699252 + 21 +106.0 + 31 +0.0 + 0 +SPLINE + 5 +9B +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MAJOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +197.08197456212483 + 21 +104.0 + 31 +0.0 + 11 +195.17052761006573 + 21 +111.26889774719355 + 31 +0.0 + 11 +188.2256252190079 + 21 +116.65506694057198 + 31 +0.0 + 11 +181.02432423526957 + 21 +120.51824317645217 + 31 +0.0 + 11 +174.44401271893759 + 21 +124.06236102645488 + 31 +0.0 + 11 +167.01782816409502 + 21 +126.44220655606952 + 31 +0.0 + 11 +159.0 + 21 +126.90381839423613 + 31 +0.0 + 11 +150.83677034427416 + 21 +126.84919087176635 + 31 +0.0 + 11 +141.44401271893759 + 21 +126.80589646087483 + 31 +0.0 + 11 +131.8937012026056 + 21 +124.3297240980458 + 31 +0.0 + 11 +126.8043747809921 + 21 +117.94111466519188 + 31 +0.0 + 11 +128.0568484436899 + 21 +110.21839435309036 + 31 +0.0 + 11 +131.08197456212483 + 21 +104.0 + 31 +0.0 + 11 +131.41942307498724 + 21 +98.45735501461877 + 31 +0.0 + 11 +131.06794856923494 + 21 +91.905066940572 + 31 +0.0 + 11 +134.35527667695743 + 21 +85.51645750771809 + 31 +0.0 + 11 +141.44401271893756 + 21 +81.19410353912518 + 31 +0.0 + 11 +149.93577118732867 + 21 +78.62887815476064 + 31 +0.0 + 11 +159.0 + 21 +77.40381839423614 + 31 +0.0 + 11 +167.9188273210405 + 21 +79.03586247045747 + 31 +0.0 + 11 +174.44401271893759 + 21 +83.9376389735451 + 31 +0.0 + 11 +178.56274876091774 + 21 +89.3279384293117 + 31 +0.0 + 11 +183.96205143076503 + 21 +93.19111466519188 + 31 +0.0 + 11 +191.80795297876838 + 21 +97.40685162051555 + 31 +0.0 + 11 +197.08197456212483 + 21 +104.0 + 31 +0.0 + 0 +TEXT + 5 +9C +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +198.08197456212483 + 20 +104.0 + 30 +0.0 + 40 +3.0 + 1 +100 + 7 +SITE + 11 +198.08197456212483 + 21 +104.0 + 31 +0.0 +100 +AcDbText + 73 +2 + 0 +SPLINE + 5 +9D +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +208.8737876126427 + 21 +102.0 + 31 +0.0 + 11 +205.48066257146198 + 21 +110.73795631679504 + 31 +0.0 + 11 +196.34730905042596 + 21 +116.87282109465201 + 31 +0.0 + 11 +187.71703605188458 + 21 +121.28777703891343 + 31 +0.0 + 11 +180.36310619367865 + 21 +125.85437468417562 + 31 +0.0 + 11 +171.81568470126695 + 21 +129.47447551215362 + 31 +0.0 + 11 +162.0 + 21 +130.69551208388398 + 31 +0.0 + 11 +151.74679538136968 + 21 +130.69911043284617 + 31 +0.0 + 11 +140.36310619367868 + 21 +130.10714954289068 + 31 +0.0 + 11 +129.40917633547275 + 21 +126.44311774839545 + 31 +0.0 + 11 +124.05269094957404 + 21 +118.431666821464 + 31 +0.0 + 11 +125.83064495854407 + 21 +109.26866210558451 + 31 +0.0 + 11 +128.87378761264267 + 21 +102.0 + 31 +0.0 + 11 +128.2065964683365 + 21 +95.20881361064379 + 31 +0.0 + 11 +127.06527674767085 + 21 +86.87282109465202 + 31 +0.0 + 11 +131.14849355696077 + 21 +78.8613701677206 + 31 +0.0 + 11 +140.36310619367865 + 21 +73.89285045710932 + 31 +0.0 + 11 +151.1101610930653 + 21 +71.51892593480952 + 31 +0.0 + 11 +162.0 + 21 +70.69551208388398 + 31 +0.0 + 11 +172.45231898957132 + 21 +72.74356085550205 + 31 +0.0 + 11 +180.36310619367865 + 21 +78.14562531582438 + 31 +0.0 + 11 +185.97771883039653 + 21 +84.0167108772026 + 31 +0.0 + 11 +193.33472325232913 + 21 +88.431666821464 + 31 +0.0 + 11 +203.10471106166952 + 21 +93.73951939943323 + 31 +0.0 + 11 +208.8737876126427 + 21 +102.0 + 31 +0.0 + 0 +SPLINE + 5 +9E +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +220.44587172444687 + 21 +100.0 + 31 +0.0 + 11 +215.2185489394071 + 21 +110.09201472503271 + 31 +0.0 + 11 +203.9337015827805 + 21 +116.85878731702515 + 31 +0.0 + 11 +194.2105617622472 + 21 +121.90792132168542 + 31 +0.0 + 11 +186.39206413777657 + 21 +127.78910647405084 + 31 +0.0 + 11 +176.76687478692395 + 21 +132.93593091332605 + 31 +0.0 + 11 +165.0 + 21 +134.95078163694564 + 31 +0.0 + 11 +152.58391324349594 + 21 +134.75309995484218 + 31 +0.0 + 11 +139.39206413777657 + 21 +133.2656844927521 + 31 +0.0 + 11 +127.34356651330592 + 21 +128.24232511502058 + 31 +0.0 + 11 +121.83629841721952 + 21 +118.69043104602923 + 31 +0.0 + 11 +123.8765347546199 + 21 +108.26424947685172 + 31 +0.0 + 11 +126.44587172444687 + 21 +100.0 + 31 +0.0 + 11 +124.42152126823467 + 21 +91.845272045305 + 31 +0.0 + 11 +122.52731362704324 + 21 +81.60878731702516 + 31 +0.0 + 11 +127.74252433071173 + 21 +72.05689324803383 + 31 +0.0 + 11 +139.39206413777654 + 21 +66.73431550724791 + 31 +0.0 + 11 +152.437884547287 + 21 +64.83816015994672 + 31 +0.0 + 11 +165.0 + 21 +64.45078163694562 + 31 +0.0 + 11 +176.91290348313285 + 21 +66.65532920146288 + 31 +0.0 + 11 +186.39206413777657 + 21 +72.21089352594916 + 31 +0.0 + 11 +193.81160394484138 + 21 +78.39129704136896 + 31 +0.0 + 11 +203.24268637295674 + 21 +83.44043104602923 + 31 +0.0 + 11 +214.67356242579228 + 21 +90.01750679712397 + 31 +0.0 + 11 +220.44587172444687 + 21 +100.0 + 31 +0.0 + 0 +SPLINE + 5 +9F +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +231.55053264809072 + 21 +98.0 + 31 +0.0 + 11 +224.2745897545753 + 21 +109.30904815934838 + 31 +0.0 + 11 +211.0603489523935 + 21 +116.6456780442977 + 31 +0.0 + 11 +200.6723650732226 + 21 +122.50427380491696 + 31 +0.0 + 11 +192.65473367595465 + 21 +130.02743853037464 + 31 +0.0 + 11 +181.90076483781027 + 21 +136.90877047908117 + 31 +0.0 + 11 +168.0 + 21 +139.6042021802084 + 31 +0.0 + 11 +153.40941990157745 + 21 +138.83958967941223 + 31 +0.0 + 11 +138.65473367595467 + 21 +136.1206191761649 + 31 +0.0 + 11 +125.7771022786867 + 21 +129.66717329098498 + 31 +0.0 + 11 +120.07965104760649 + 21 +118.75011977549389 + 31 +0.0 + 11 +121.96575815412771 + 21 +107.25112844508537 + 31 +0.0 + 11 +123.5505326480907 + 21 +98.0 + 31 +0.0 + 11 +119.9546005153559 + 21 +88.3447055060442 + 31 +0.0 + 11 +117.52960534367412 + 21 +76.14567804429772 + 31 +0.0 + 11 +124.30483270507546 + 21 +65.22862452880662 + 31 +0.0 + 11 +138.65473367595462 + 21 +59.8793808238351 + 31 +0.0 + 11 +153.94830796673804 + 21 +58.668778549666634 + 31 +0.0 + 11 +168.0 + 21 +58.604202180208404 + 31 +0.0 + 11 +181.36187677264965 + 21 +60.599597749997685 + 31 +0.0 + 11 +192.65473367595465 + 21 +65.97256146962538 + 31 +0.0 + 11 +202.14463464683382 + 21 +72.39152401487462 + 31 +0.0 + 11 +213.61039465632584 + 21 +78.25011977549389 + 31 +0.0 + 11 +226.28574739334704 + 21 +86.28678579178114 + 31 +0.0 + 11 +231.55053264809072 + 21 +98.0 + 31 +0.0 + 0 +SPLINE + 5 +A0 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +241.97869256386974 + 21 +96.0 + 31 +0.0 + 11 +232.62816735388895 + 21 +108.38491325511347 + 31 +0.0 + 11 +217.88217571324788 + 21 +116.30057757617925 + 31 +0.0 + 11 +207.29643062760906 + 21 +123.22232297070678 + 31 +0.0 + 11 +199.25565371806513 + 21 +132.70517088057093 + 31 +0.0 + 11 +187.2228793400974 + 21 +141.40845745672718 + 31 +0.0 + 11 +171.0 + 21 +144.52160511425322 + 31 +0.0 + 11 +154.29431866282246 + 21 +142.75983864405134 + 31 +0.0 + 11 +138.25565371806513 + 21 +138.5361535657052 + 31 +0.0 + 11 +124.7248768085212 + 21 +130.7063423936091 + 31 +0.0 + 11 +118.62782428675212 + 21 +118.67781730956753 + 31 +0.0 + 11 +119.83332720706096 + 21 +106.28255149069165 + 31 +0.0 + 11 +119.97869256386977 + 21 +96.0 + 31 +0.0 + 11 +114.7852165466226 + 21 +84.70297062823282 + 31 +0.0 + 11 +112.22707645154637 + 21 +70.55057757617926 + 31 +0.0 + 11 +121.02940332285021 + 21 +58.5220524921377 + 31 +0.0 + 11 +138.25565371806508 + 21 +53.4638464342948 + 31 +0.0 + 11 +155.64695583758987 + 21 +53.02624435127743 + 31 +0.0 + 11 +171.0 + 21 +53.02160511425322 + 31 +0.0 + 11 +185.87024216532996 + 21 +54.377625538601585 + 31 +0.0 + 11 +199.25565371806513 + 21 +59.29482911942907 + 31 +0.0 + 11 +210.99190411328 + 21 +66.00607191504 + 31 +0.0 + 11 +224.2829235484536 + 21 +72.92781730956752 + 31 +0.0 + 11 +237.67627801432727 + 21 +82.60060886381095 + 31 +0.0 + 11 +241.97869256386974 + 21 +96.0 + 31 +0.0 + 0 +SPLINE + 5 +A1 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MAJOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +251.59177955329739 + 21 +94.0 + 31 +0.0 + 11 +240.35779355666563 + 21 +107.33538789626478 + 31 +0.0 + 11 +224.61873766490416 + 21 +115.91855636265359 + 31 +0.0 + 11 +214.27880498462827 + 21 +124.20910373847119 + 31 +0.0 + 11 +206.2641102233513 + 21 +135.91230862588517 + 31 +0.0 + 11 +192.71218111520287 + 21 +146.37610798177593 + 31 +0.0 + 11 +174.0 + 21 +149.51284953911244 + 31 +0.0 + 11 +155.31036754823066 + 21 +146.3129934135935 + 31 +0.0 + 11 +138.26411022335134 + 21 +140.42228256012757 + 31 +0.0 + 11 +124.12941546207435 + 21 +131.40293840344424 + 31 +0.0 + 11 +117.26126233509584 + 21 +118.56859409823397 + 31 +0.0 + 11 +117.21143733319828 + 21 +105.41233712942031 + 31 +0.0 + 11 +115.59177955329739 + 21 +94.0 + 31 +0.0 + 11 +108.99188118135231 + 21 +80.93584529580767 + 31 +0.0 + 11 +106.83928275022049 + 21 +64.91855636265362 + 31 +0.0 + 11 +118.11228274325775 + 21 +52.08421205744336 + 31 +0.0 + 11 +138.26411022335128 + 21 +47.57771743987244 + 31 +0.0 + 11 +157.51279098126005 + 21 +47.85167370029099 + 31 +0.0 + 11 +174.0 + 21 +47.51284953911243 + 31 +0.0 + 11 +190.50975768217344 + 21 +47.78855913210852 + 31 +0.0 + 11 +206.2641102233513 + 21 +52.08769137411484 + 31 +0.0 + 11 +220.2959377034448 + 21 +59.27804672241638 + 31 +0.0 + 11 +235.04071724977945 + 21 +67.56859409823397 + 31 +0.0 + 11 +248.57734970851152 + 21 +79.01279452896313 + 31 +0.0 + 11 +251.59177955329739 + 21 +94.0 + 31 +0.0 + 0 +TEXT + 5 +A2 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +252.59177955329739 + 20 +94.0 + 30 +0.0 + 40 +3.0 + 1 +110 + 7 +SITE + 11 +252.59177955329739 + 21 +94.0 + 31 +0.0 +100 +AcDbText + 73 +2 + 0 +SPLINE + 5 +A3 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +260.3464189221045 + 21 +92.0 + 31 +0.0 + 11 +247.63915514445503 + 21 +106.19577843123014 + 31 +0.0 + 11 +231.5303603072676 + 21 +115.61233865180617 + 31 +0.0 + 11 +221.79147448886206 + 21 +125.59360586664654 + 31 +0.0 + 11 +213.70179053894776 + 21 +139.67702445665617 + 31 +0.0 + 11 +198.32159503188961 + 21 +151.67995696806514 + 31 +0.0 + 11 +177.0 + 21 +154.35248695861517 + 31 +0.0 + 11 +156.520517929023 + 21 +149.32285070118658 + 31 +0.0 + 11 +138.70179053894776 + 21 +141.75083346909315 + 31 +0.0 + 11 +123.86210658903349 + 21 +131.85342005822488 + 31 +0.0 + 11 +115.71963969273239 + 21 +118.53517438957866 + 31 +0.0 + 11 +113.86515081673686 + 21 +104.68769888968708 + 31 +0.0 + 11 +110.34641892210448 + 21 +92.0 + 31 +0.0 + 11 +102.75028120109478 + 21 +77.07863585719655 + 31 +0.0 + 11 +101.6265497396018 + 21 +59.3623386518062 + 31 +0.0 + 11 +115.72545731087988 + 21 +46.04409298315996 + 31 +0.0 + 11 +138.7017905389477 + 21 +42.24916653090684 + 31 +0.0 + 11 +159.4987382665115 + 21 +43.01330151054496 + 31 +0.0 + 11 +177.0 + 21 +41.85248695861517 + 31 +0.0 + 11 +195.34337469440106 + 21 +40.656195243666396 + 31 +0.0 + 11 +213.70179053894776 + 21 +44.32297554334383 + 31 +0.0 + 11 +229.9281237670156 + 21 +52.303907174738285 + 31 +0.0 + 11 +245.62345026039816 + 21 +62.28517438957864 + 31 +0.0 + 11 +258.7540247600971 + 21 +75.57055631565343 + 31 +0.0 + 11 +260.3464189221045 + 21 +92.0 + 31 +0.0 + 0 +SPLINE + 5 +A4 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +268.3086208793091 + 21 +90.0 + 31 +0.0 + 11 +254.7307773468165 + 21 +105.01803857987214 + 31 +0.0 + 11 +238.88767397846223 + 21 +115.49911081756206 + 31 +0.0 + 11 +229.95768253436816 + 21 +127.46826190077613 + 31 +0.0 + 11 +221.53568956034547 + 21 +143.9564434844449 + 31 +0.0 + 11 +203.98184946367417 + 21 +157.1261104934253 + 31 +0.0 + 11 +180.0 + 21 +158.80614462491127 + 31 +0.0 + 11 +157.96988001827322 + 21 +151.66314530148202 + 31 +0.0 + 11 +139.53568956034547 + 21 +142.56468118104107 + 31 +0.0 + 11 +123.73369658632276 + 21 +132.19972756025794 + 31 +0.0 + 11 +113.73232602153777 + 21 +118.69474455752663 + 31 +0.0 + 11 +109.62611405054523 + 21 +104.14246943129727 + 31 +0.0 + 11 +104.3086208793091 + 21 +90.0 + 31 +0.0 + 11 +96.31894183540929 + 21 +73.18329603226208 + 31 +0.0 + 11 +96.85950775781428 + 21 +53.99911081756209 + 31 +0.0 + 11 +113.99217041977431 + 21 +40.4941278148308 + 31 +0.0 + 11 +139.53568956034542 + 21 +37.43531881895895 + 31 +0.0 + 11 +161.53552606686077 + 21 +38.317233859869916 + 31 +0.0 + 11 +180.0 + 21 +35.8061446249113 + 31 +0.0 + 11 +200.41620341508658 + 21 +32.85426866792661 + 31 +0.0 + 11 +221.53568956034547 + 21 +36.0435565155551 + 31 +0.0 + 11 +239.69920870091653 + 21 +45.22559347431258 + 31 +0.0 + 11 +255.76049224218568 + 21 +57.19474455752662 + 31 +0.0 + 11 +268.03794956195236 + 21 +72.30772688368715 + 31 +0.0 + 11 +268.3086208793091 + 21 +90.0 + 31 +0.0 + 0 +SPLINE + 5 +A5 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +275.6552759865501 + 21 +88.0 + 31 +0.0 + 11 +261.948464748782 + 21 +103.86563302983481 + 31 +0.0 + 11 +246.93791112697645 + 21 +115.68592765043665 + 31 +0.0 + 11 +238.83172356101434 + 21 +129.87379267076074 + 31 +0.0 + 11 +229.67736200672496 + 21 +148.63567191919958 + 31 +0.0 + 11 +209.60832482703114 + 21 +162.47771511908246 + 31 +0.0 + 11 +183.0 + 21 +162.65971295697 + 31 +0.0 + 11 +159.6783269602572 + 21 +153.27825152637212 + 31 +0.0 + 11 +140.677362006725 + 21 +142.97871948602298 + 31 +0.0 + 11 +123.51300045243556 + 21 +132.61524966067333 + 31 +0.0 + 11 +111.05208887302356 + 21 +119.15435939259334 + 31 +0.0 + 11 +104.4201594504798 + 21 +103.79155361245776 + 31 +0.0 + 11 +97.65527598655011 + 21 +88.00000000000001 + 31 +0.0 + 11 +90.01366766932783 + 21 +69.3132905086483 + 31 +0.0 + 11 +92.78538925334634 + 21 +48.93592765043668 + 31 +0.0 + 11 +112.96671650980882 + 21 +35.475037382356675 + 31 +0.0 + 11 +140.6773620067249 + 21 +33.021280513977025 + 31 +0.0 + 11 +163.53853479878248 + 21 +33.52661730949184 + 31 +0.0 + 11 +182.99999999999997 + 21 +29.15971295697001 + 31 +0.0 + 11 +205.74811698850584 + 21 +24.32715371678151 + 31 +0.0 + 11 +229.67736200672496 + 21 +27.364328080800412 + 31 +0.0 + 11 +249.37800750364102 + 21 +38.216494372269224 + 31 +0.0 + 11 +265.2046107466536 + 21 +52.40435939259331 + 31 +0.0 + 11 +276.35495652993393 + 21 +69.23921109127117 + 31 +0.0 + 11 +275.6552759865501 + 21 +88.0 + 31 +0.0 + 0 +SPLINE + 5 +A6 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +282.66216449324327 + 21 +86.0 + 31 +0.0 + 11 +269.63102300052367 + 21 +102.80664880638423 + 31 +0.0 + 11 +255.87182740148103 + 21 +116.2553887692621 + 31 +0.0 + 11 +248.38584026920222 + 21 +132.78938020190168 + 31 +0.0 + 11 +237.98891775337836 + 21 +153.53558523452818 + 31 +0.0 + 11 +215.11023842160583 + 21 +167.48066660740744 + 31 +0.0 + 11 +186.0 + 21 +165.74799271712703 + 31 +0.0 + 11 +161.63569887818144 + 21 +154.19660725815072 + 31 +0.0 + 11 +141.98891775337836 + 21 +143.17207291043098 + 31 +0.0 + 11 +122.95199523755448 + 21 +133.28600357183416 + 31 +0.0 + 11 +107.488172598519 + 21 +119.99661851361085 + 31 +0.0 + 11 +98.28520419293238 + 21 +103.62733152557347 + 31 +0.0 + 11 +90.66216449324332 + 21 +86.00000000000001 + 31 +0.0 + 11 +84.17326435302257 + 21 +65.53670631162123 + 31 +0.0 + 11 +89.59494987486876 + 21 +44.25538876926211 + 31 +0.0 + 11 +112.62133828138504 + 21 +30.966003711038837 + 31 +0.0 + 11 +141.9889177533783 + 21 +28.827927089569023 + 31 +0.0 + 11 +165.41698176192185 + 21 +28.387347621781622 + 31 +0.0 + 11 +185.99999999999997 + 21 +21.747992717127033 + 31 +0.0 + 11 +211.32895553786537 + 21 +15.103288272524864 + 31 +0.0 + 11 +237.98891775337836 + 21 +18.46441476547183 + 31 +0.0 + 11 +258.7164972253716 + 21 +31.46262708097128 + 31 +0.0 + 11 +273.7650501251312 + 21 +47.996618513610834 + 31 +0.0 + 11 +283.74296284043345 + 21 +66.3573890308104 + 31 +0.0 + 11 +282.66216449324327 + 21 +86.0 + 31 +0.0 + 0 +SPLINE + 5 +A7 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MAJOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +289.6792102724861 + 21 +84.0 + 31 +0.0 + 11 +278.10086537956244 + 21 +101.90587869252595 + 31 +0.0 + 11 +265.7951834933446 + 21 +117.25328989676191 + 31 +0.0 + 11 +258.5061316860145 + 21 +136.12959876451086 + 31 +0.0 + 11 +246.29539486375697 + 21 +158.42890120781095 + 31 +0.0 + 11 +220.40119987005744 + 21 +171.89315500025964 + 31 +0.0 + 11 +189.0 + 21 +167.9793924599353 + 31 +0.0 + 11 +163.80030512244247 + 21 +154.53490621370847 + 31 +0.0 + 11 +143.295394863757 + 21 +143.37202367688482 + 31 +0.0 + 11 +121.81465804149943 + 21 +134.38900646887544 + 31 +0.0 + 11 +102.93481650665538 + 21 +121.26731764330279 + 31 +0.0 + 11 +91.3768399004238 + 21 +103.61853518344175 + 31 +0.0 + 11 +83.67921027248609 + 21 +84.00000000000001 + 31 +0.0 + 11 +79.12014516401436 + 21 +61.91833622418649 + 31 +0.0 + 11 +87.39395031375024 + 21 +40.003289896761935 + 31 +0.0 + 11 +112.84213476158564 + 21 +26.881601071189287 + 31 +0.0 + 11 +143.29539486375688 + 21 +24.627976323115185 + 31 +0.0 + 11 +167.08447657893817 + 21 +22.65761483859861 + 31 +0.0 + 11 +188.99999999999997 + 21 +13.479392459935312 + 31 +0.0 + 11 +217.11702841356168 + 21 +5.299366052047418 + 31 +0.0 + 11 +246.29539486375697 + 21 +9.571098792189048 + 31 +0.0 + 11 +267.4786549659282 + 21 +25.14100877555383 + 31 +0.0 + 11 +281.33604968624974 + 21 +44.01731764330274 + 31 +0.0 + 11 +290.35756011597186 + 21 +63.63099271510221 + 31 +0.0 + 11 +289.6792102724861 + 21 +84.0 + 31 +0.0 + 0 +TEXT + 5 +A8 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +290.6792102724861 + 20 +84.0 + 30 +0.0 + 40 +3.0 + 1 +120 + 7 +SITE + 11 +290.6792102724861 + 21 +84.0 + 31 +0.0 +100 +AcDbText + 73 +2 + 0 +SPLINE + 5 +A9 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +297.09519980414063 + 21 +82.0 + 31 +0.0 + 11 +287.6238385648448 + 21 +101.21674774046065 + 31 +0.0 + 11 +276.7083605162395 + 21 +118.67979605999705 + 31 +0.0 + 11 +268.9984246076013 + 21 +139.74881845570098 + 31 +0.0 + 11 +254.4024000979297 + 21 +163.06309561289146 + 31 +0.0 + 11 +225.4099757694517 + 21 +175.51579528842916 + 31 +0.0 + 11 +192.0 + 21 +169.3535821312729 + 31 +0.0 + 11 +166.101073367697 + 21 +154.49208253994016 + 31 +0.0 + 11 +144.4024000979297 + 21 +143.83109601154092 + 31 +0.0 + 11 +119.90637558825807 + 21 +136.07021830880646 + 31 +0.0 + 11 +97.3916394837605 + 21 +122.96662180873003 + 31 +0.0 + 11 +83.96031210214717 + 21 +103.71186034205518 + 31 +0.0 + 11 +77.09519980414066 + 21 +82.00000000000001 + 31 +0.0 + 11 +75.12015678124975 + 21 +58.51160529854472 + 31 +0.0 + 11 +86.18277168366298 + 21 +36.17979605999709 + 31 +0.0 + 11 +113.43493274656076 + 21 +23.07619955992064 + 31 +0.0 + 11 +144.40240009792961 + 21 +20.168903988459085 + 31 +0.0 + 11 +168.46978584689717 + 21 +16.138033950732904 + 31 +0.0 + 11 +191.99999999999997 + 21 +4.35358213127293 + 31 +0.0 + 11 +223.0412632902515 + 21 +-4.885678797756128 + 31 +0.0 + 11 +254.4024000979297 + 21 +0.936904387108541 + 31 +0.0 + 11 +275.4698674492985 + 21 +19.397599413026093 + 31 +0.0 + 11 +287.917228316337 + 21 +40.466621808729975 + 31 +0.0 + 11 +296.4639938857421 + 21 +61.006717900139165 + 31 +0.0 + 11 +297.09519980414063 + 21 +82.0 + 31 +0.0 + 0 +SPLINE + 5 +AA +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +305.29547714798207 + 21 +80.0 + 31 +0.0 + 11 +298.37287227290756 + 21 +100.77400823360838 + 31 +0.0 + 11 +288.4969068196331 + 21 +120.48534824053439 + 31 +0.0 + 11 +279.60396831283094 + 21 +143.45297623462324 + 31 +0.0 + 11 +262.117261426009 + 21 +167.18788014104774 + 31 +0.0 + 11 +230.0902297418953 + 21 +178.21889018451336 + 31 +0.0 + 11 +195.0 + 21 +169.96967976800613 + 31 +0.0 + 11 +168.44329427676334 + 21 +154.33323128058083 + 31 +0.0 + 11 +145.117261426009 + 21 +144.79957822312127 + 31 +0.0 + 11 +117.100554539187 + 21 +138.42458409560976 + 31 +0.0 + 11 +90.97309318036686 + 21 +125.04497199145948 + 31 +0.0 + 11 +76.38908085641586 + 21 +103.83627499852744 + 31 +0.0 + 11 +71.29547714798206 + 21 +80.00000000000001 + 31 +0.0 + 11 +72.34622892126559 + 21 +55.35126581811599 + 31 +0.0 + 11 +85.84696233407446 + 21 +32.735348240534435 + 31 +0.0 + 11 +114.14098151517878 + 21 +19.355736136384152 + 31 +0.0 + 11 +145.11726142600892 + 21 +15.200421776878756 + 31 +0.0 + 11 +169.52657318790546 + 21 +8.69890767078185 + 31 +0.0 + 11 +194.99999999999997 + 21 +-5.530320231993883 + 31 +0.0 + 11 +229.0069508307531 + 21 +-15.186751233150659 + 31 +0.0 + 11 +262.117261426009 + 21 +-7.187880141047728 + 31 +0.0 + 11 +282.5635413368391 + 21 +14.327343997370647 + 31 +0.0 + 11 +293.6230376659255 + 21 +37.294971991459434 + 31 +0.0 + 11 +302.4157242080578 + 21 +58.413532583034964 + 31 +0.0 + 11 +305.29547714798207 + 21 +80.0 + 31 +0.0 + 0 +SPLINE + 5 +AB +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +314.61707062052267 + 21 +78.0 + 31 +0.0 + 11 +310.39982562073607 + 21 +100.58808187835643 + 31 +0.0 + 11 +300.9347020451329 + 21 +122.57203345103352 + 31 +0.0 + 11 +290.02369799366005 + 21 +147.01777349524502 + 31 +0.0 + 11 +269.27146468973865 + 21 +170.5843484793589 + 31 +0.0 + 11 +234.42806617887177 + 21 +179.96354535077322 + 31 +0.0 + 11 +198.0 + 21 +170.0235113448158 + 31 +0.0 + 11 +170.71750253251963 + 21 +154.36475002950453 + 31 +0.0 + 11 +145.27146468973868 + 21 +146.49637662454666 + 31 +0.0 + 11 +113.3592313858173 + 21 +141.48057646063705 + 31 +0.0 + 11 +83.90529795486715 + 21 +127.40445520415068 + 31 +0.0 + 11 +69.07167628839522 + 21 +103.90968016501718 + 31 +0.0 + 11 +66.6170706205227 + 21 +78.00000000000001 + 31 +0.0 + 11 +70.85022070104716 + 21 +52.44773948928757 + 31 +0.0 + 11 +86.16040190659201 + 21 +29.572033451033548 + 31 +0.0 + 11 +114.66121625939617 + 21 +15.49591219454721 + 31 +0.0 + 11 +145.2714646897386 + 21 +9.50362337545333 + 31 +0.0 + 11 +170.24094299344665 + 21 +0.3013416610065178 + 31 +0.0 + 11 +197.99999999999997 + 21 +-15.976488655184184 + 31 +0.0 + 11 +234.9046257179447 + 21 +-25.297453660262192 + 31 +0.0 + 11 +269.27146468973865 + 21 +-14.584348479358908 + 31 +0.0 + 11 +288.721713120081 + 21 +9.958715159939203 + 31 +0.0 + 11 +298.67959809340795 + 21 +34.40445520415064 + 31 +0.0 + 11 +308.6212812080841 + 21 +55.76933777594823 + 31 +0.0 + 11 +314.61707062052267 + 21 +78.0 + 31 +0.0 + 0 +SPLINE + 5 +AC +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +325.30619319380804 + 21 +76.0 + 31 +0.0 + 11 +323.6191801154361 + 21 +100.64178271637311 + 31 +0.0 + 11 +313.70008640020285 + 21 +124.80056891563837 + 31 +0.0 + 11 +299.94879679625774 + 21 +150.2115975971933 + 31 +0.0 + 11 +275.741903403096 + 21 +173.09258061142555 + 31 +0.0 + 11 +238.44639969149011 + 21 +180.81389965687947 + 31 +0.0 + 11 +201.0 + 21 +169.79364241341398 + 31 +0.0 + 11 +172.81066332134702 + 21 +154.9030275372984 + 31 +0.0 + 11 +144.741903403096 + 21 +149.08141123221665 + 31 +0.0 + 11 +108.74501000993425 + 21 +145.19124249254932 + 31 +0.0 + 11 +76.50991359979716 + 21 +129.90578867094766 + 31 +0.0 + 11 +62.429950065534825 + 21 +103.84729973131024 + 31 +0.0 + 11 +63.30619319380807 + 21 +76.00000000000001 + 31 +0.0 + 11 +70.5466136277002 + 21 +49.78384035372778 + 31 +0.0 + 11 +86.80143060867987 + 21 +26.550568915638408 + 31 +0.0 + 11 +114.6868201253822 + 21 +11.26511509403673 + 31 +0.0 + 11 +144.7419034030959 + 21 +2.918588767783362 + 31 +0.0 + 11 +170.6358098746297 + 21 +-8.990525208922435 + 31 +0.0 + 11 +200.99999999999997 + 21 +-26.706357586586023 + 31 +0.0 + 11 +240.62125313820738 + 21 +-34.90139732850352 + 31 +0.0 + 11 +275.741903403096 + 21 +-21.09258061142556 + 31 +0.0 + 11 +294.00698668080963 + 21 +6.2447599893927475 + 31 +0.0 + 11 +303.40856939132004 + 21 +31.655788670947608 + 31 +0.0 + 11 +315.50251655327065 + 21 +52.98935736866483 + 31 +0.0 + 11 +325.30619319380804 + 21 +76.0 + 31 +0.0 + 0 +SPLINE + 5 +AD +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MAJOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +337.4830200860729 + 21 +74.0 + 31 +0.0 + 11 +337.80607878372757 + 21 +100.88992306435622 + 31 +0.0 + 11 +326.40387787526345 + 21 +127.00243388085306 + 31 +0.0 + 11 +309.09448277351214 + 21 +152.8208620801341 + 31 +0.0 + 11 +281.4684899569636 + 21 +174.63452044332516 + 31 +0.0 + 11 +242.2054805241532 + 21 +180.93859583279217 + 31 +0.0 + 11 +204.0 + 21 +169.61711448079248 + 31 +0.0 + 11 +174.61853921606337 + 21 +156.239828334683 + 31 +0.0 + 11 +143.4684899569636 + 21 +152.63273814005362 + 31 +0.0 + 11 +103.42249714041503 + 21 +149.43312714468874 + 31 +0.0 + 11 +69.17612212473654 + 21 +132.38045163835443 + 31 +0.0 + 11 +56.852921562128785 + 21 +103.57095562702003 + 31 +0.0 + 11 +61.483020086072855 + 21 +74.00000000000001 + 31 +0.0 + 11 +71.21055072794468 + 21 +47.314380728134424 + 31 +0.0 + 11 +87.38086643075837 + 21 +23.502433880853104 + 31 +0.0 + 11 +113.93301116602497 + 21 +6.449758374518808 + 31 +0.0 + 11 +143.4684899569635 + 21 +-4.632738140053604 + 31 +0.0 + 11 +170.77142407585745 + 21 +-19.008050209044967 + 31 +0.0 + 11 +203.99999999999997 + 21 +-37.382885519207505 + 31 +0.0 + 11 +246.05259566435902 + 21 +-43.706817707154116 + 31 +0.0 + 11 +281.4684899569636 + 21 +-26.634520443325158 + 31 +0.0 + 11 +298.5839687479021 + 21 +3.0620234390733856 + 31 +0.0 + 11 +308.1991335692416 + 21 +28.88045163835438 + 31 +0.0 + 11 +323.44844961791154 + 21 +49.99541329079813 + 31 +0.0 + 11 +337.4830200860729 + 21 +74.0 + 31 +0.0 + 0 +TEXT + 5 +AE +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +338.4830200860729 + 20 +74.0 + 30 +0.0 + 40 +3.0 + 1 +130 + 7 +SITE + 11 +338.4830200860729 + 21 +74.0 + 31 +0.0 +100 +AcDbText + 73 +2 + 0 +SPLINE + 5 +AF +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +0 + 73 +0 + 74 +25 + 11 +351.11807155880115 + 21 +72.0 + 31 +0.0 + 11 +352.6097441378531 + 21 +101.2620100138801 + 31 +0.0 + 11 +338.6268386404416 + 21 +128.99609304122876 + 31 +0.0 + 11 +317.23344872074955 + 21 +154.67508654056215 + 31 +0.0 + 11 +286.46596422059946 + 21 +175.22931562689658 + 31 +0.0 + 11 +245.79929922142856 + 21 +180.60071699432928 + 31 +0.0 + 11 +207.0 + 21 +169.85699815784898 + 31 +0.0 + 11 +176.05793000529485 + 21 +158.6080329836941 + 31 +0.0 + 11 +141.4659642205995 + 21 +157.1312096962188 + 31 +0.0 + 11 +97.64847972044937 + 21 +154.01364020966298 + 31 +0.0 + 11 +62.323161359558384 + 21 +134.64690880092223 + 31 +0.0 + 11 +52.6510981942246 + 21 +103.01824769361616 + 31 +0.0 + 11 +61.11807155880112 + 21 +72.00000000000001 + 31 +0.0 + 11 +72.4912545140233 + 21 +44.96886770408183 + 31 +0.0 + 11 +87.47947154295434 + 21 +20.246093041228818 + 31 +0.0 + 11 +112.17248217665069 + 21 +0.8793616324880986 + 31 +0.0 + 11 +141.4659642205994 + 21 +-13.131209696218804 + 31 +0.0 + 11 +170.74177614169758 + 21 +-29.4881502235431 + 31 +0.0 + 11 +206.99999999999997 + 21 +-47.64300184215102 + 31 +0.0 + 11 +251.1154530850258 + 21 +-51.4808342341783 + 31 +0.0 + 11 +286.4659642205995 + 21 +-31.22931562689662 + 31 +0.0 + 11 +302.70944626454815 + 21 +0.2179153015888602 + 31 +0.0 + 11 +313.4705284570456 + 21 +25.896908800922198 + 31 +0.0 + 11 +332.76958781805433 + 21 +46.7251053838178 + 31 +0.0 + 11 +351.11807155880115 + 21 +72.0 + 31 +0.0 + 0 +LWPOLYLINE + 5 +B0 +330 +17 +100 +AcDbEntity + 8 +ROAD +100 +AcDbPolyline + 90 +5 + 70 +0 + 43 +9.0 + 10 +-40.0 + 20 +40.0 + 10 +60.0 + 20 +50.0 + 10 +140.0 + 20 +20.0 + 10 +260.0 + 20 +30.0 + 10 +360.0 + 20 +70.0 + 0 +LWPOLYLINE + 5 +B1 +330 +17 +100 +AcDbEntity + 8 +ROAD +100 +AcDbPolyline + 90 +3 + 70 +0 + 43 +6.0 + 10 +140.0 + 20 +20.0 + 10 +150.0 + 20 +-40.0 + 10 +130.0 + 20 +-90.0 + 0 +CIRCLE + 5 +B2 +330 +17 +100 +AcDbEntity + 8 +ROAD +100 +AcDbCircle + 10 +140.0 + 20 +20.0 + 30 +0.0 + 40 +12.0 + 0 +LWPOLYLINE + 5 +B3 +330 +17 +100 +AcDbEntity + 8 +PARCEL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +20.0 + 20 +60.0 + 10 +120.0 + 20 +66.0 + 10 +116.0 + 20 +150.0 + 10 +14.0 + 20 +140.0 + 0 +MTEXT + 5 +B4 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +67.5 + 20 +64.0 + 30 +0.0 + 40 +5.0 + 71 +5 + 1 +Parcel 101\P8322 m² + 7 +SITE + 0 +LWPOLYLINE + 5 +B5 +330 +17 +100 +AcDbEntity + 8 +PARCEL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +120.0 + 20 +66.0 + 10 +230.0 + 20 +62.0 + 10 +240.0 + 20 +160.0 + 10 +116.0 + 20 +150.0 + 0 +MTEXT + 5 +B6 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +176.5 + 20 +69.5 + 30 +0.0 + 40 +5.0 + 71 +5 + 1 +Parcel 102\P10638 m² + 7 +SITE + 0 +LWPOLYLINE + 5 +B7 +330 +17 +100 +AcDbEntity + 8 +PARCEL +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +230.0 + 20 +62.0 + 10 +330.0 + 20 +80.0 + 10 +320.0 + 20 +170.0 + 10 +240.0 + 20 +160.0 + 0 +MTEXT + 5 +B8 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +280.0 + 20 +78.0 + 30 +0.0 + 40 +5.0 + 71 +5 + 1 +Parcel 103\P8460 m² + 7 +SITE + 0 +LWPOLYLINE + 5 +B9 +330 +17 +100 +AcDbEntity + 8 +BUILDING +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +40.0 + 20 +90.0 + 10 +80.0 + 20 +90.0 + 10 +80.0 + 20 +116.0 + 10 +40.0 + 20 +116.0 + 0 +HATCH + 5 +BA +330 +17 +100 +AcDbEntity + 8 +BUILDING + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +40.0 + 20 +90.0 + 10 +80.0 + 20 +90.0 + 10 +80.0 + 20 +116.0 + 10 +40.0 + 20 +116.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +3.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-6.7351920909 + 46 +6.7351920909 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +BB +330 +17 +100 +AcDbEntity + 8 +BUILDING +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +150.0 + 20 +95.0 + 10 +184.0 + 20 +95.0 + 10 +184.0 + 20 +125.0 + 10 +150.0 + 20 +125.0 + 0 +HATCH + 5 +BC +330 +17 +100 +AcDbEntity + 8 +BUILDING + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +150.0 + 20 +95.0 + 10 +184.0 + 20 +95.0 + 10 +184.0 + 20 +125.0 + 10 +150.0 + 20 +125.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +3.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-6.7351920909 + 46 +6.7351920909 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +BD +330 +17 +100 +AcDbEntity + 8 +BUILDING +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +262.0 + 20 +110.0 + 10 +306.0 + 20 +110.0 + 10 +306.0 + 20 +138.0 + 10 +262.0 + 20 +138.0 + 0 +HATCH + 5 +BE +330 +17 +100 +AcDbEntity + 8 +BUILDING + 62 +8 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 +0 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +262.0 + 20 +110.0 + 10 +306.0 + 20 +110.0 + 10 +306.0 + 20 +138.0 + 10 +262.0 + 20 +138.0 + 97 +0 + 75 +1 + 76 +1 + 52 +0.0 + 41 +3.0 + 77 +0 + 78 +1 + 53 +45.0 + 43 +0.0 + 44 +0.0 + 45 +-6.7351920909 + 46 +6.7351920909 + 79 +0 + 98 +0 + 0 +LWPOLYLINE + 5 +BF +330 +17 +100 +AcDbEntity + 8 +WATER +100 +AcDbPolyline + 90 +5 + 70 +1 + 10 +280.0 + 20 +-10.0 + 10 +310.0 + 20 +-25.0 + 10 +340.0 + 20 +-5.0 + 10 +325.0 + 20 +20.0 + 10 +295.0 + 20 +18.0 + 0 +HATCH + 5 +C0 +330 +17 +100 +AcDbEntity + 8 +WATER + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +5 + 10 +280.0 + 20 +-10.0 + 10 +310.0 + 20 +-25.0 + 10 +340.0 + 20 +-5.0 + 10 +325.0 + 20 +20.0 + 10 +295.0 + 20 +18.0 + 97 +0 + 75 +0 + 76 +1 + 98 +0 +450 +1 +451 +0 +460 +1.5707963267948966 +461 +0.0 +452 +0 +462 +0.0 +453 +2 +463 +0 +421 +9226495 +463 +1 +421 +1989290 +470 +LINEAR + 0 +CIRCLE + 5 +C1 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +204.2446101602927 + 20 +1.2680483891094099 + 30 +0.0 + 40 +2.851829061461684 + 0 +CIRCLE + 5 +C2 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +312.03699879955013 + 20 +-105.6492157574578 + 30 +0.0 + 40 +2.291558512442779 + 0 +CIRCLE + 5 +C3 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +304.3241770302242 + 20 +-93.01910530202835 + 30 +0.0 + 40 +2.2974173812296783 + 0 +CIRCLE + 5 +C4 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +68.76621974313892 + 20 +-28.435871114610435 + 30 +0.0 + 40 +2.475700019477771 + 0 +CIRCLE + 5 +C5 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +-15.278891747995207 + 20 +-77.49052993042278 + 30 +0.0 + 40 +1.9751200222188876 + 0 +CIRCLE + 5 +C6 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +37.45751644889376 + 20 +9.572048714680676 + 30 +0.0 + 40 +1.7359046112781353 + 0 +CIRCLE + 5 +C7 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +202.28290736780198 + 20 +-90.99511511745955 + 30 +0.0 + 40 +1.5030172657443088 + 0 +CIRCLE + 5 +C8 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +293.70570810074156 + 20 +-78.58154262573231 + 30 +0.0 + 40 +1.8663179876820448 + 0 +CIRCLE + 5 +C9 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +84.14986038889354 + 20 +34.221698342512525 + 30 +0.0 + 40 +2.4166798970803782 + 0 +CIRCLE + 5 +CA +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +224.01897181021323 + 20 +-79.28307281993108 + 30 +0.0 + 40 +3.0996592018495983 + 0 +CIRCLE + 5 +CB +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +228.63109879848696 + 20 +34.98464684757931 + 30 +0.0 + 40 +3.0193608518800135 + 0 +CIRCLE + 5 +CC +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +87.56400322739239 + 20 +-55.82150979164238 + 30 +0.0 + 40 +1.7821252971205674 + 0 +CIRCLE + 5 +CD +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +32.4526874346457 + 20 +-100.22904299364856 + 30 +0.0 + 40 +2.012310471308086 + 0 +CIRCLE + 5 +CE +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +197.11959906675557 + 20 +-109.49253209384649 + 30 +0.0 + 40 +2.6524882242310754 + 0 +CIRCLE + 5 +CF +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +101.64287018603144 + 20 +-63.50631025953068 + 30 +0.0 + 40 +2.8914807269000207 + 0 +CIRCLE + 5 +D0 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +153.068267186814 + 20 +-62.631034123033395 + 30 +0.0 + 40 +2.3180712566026687 + 0 +CIRCLE + 5 +D1 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +233.68088829072732 + 20 +-101.44986056963151 + 30 +0.0 + 40 +3.1576692573452 + 0 +CIRCLE + 5 +D2 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +-11.768397229020543 + 20 +2.469253343690994 + 30 +0.0 + 40 +2.9362975119598205 + 0 +CIRCLE + 5 +D3 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +-13.495687263729156 + 20 +8.16074559706513 + 30 +0.0 + 40 +2.122513608931163 + 0 +CIRCLE + 5 +D4 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +188.26677846047485 + 20 +-108.63824197707073 + 30 +0.0 + 40 +1.5794361017882006 + 0 +CIRCLE + 5 +D5 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +45.13101566237722 + 20 +33.27698493867496 + 30 +0.0 + 40 +1.834086839872114 + 0 +CIRCLE + 5 +D6 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +252.0651084824744 + 20 +29.448297939628162 + 30 +0.0 + 40 +3.101474510027089 + 0 +CIRCLE + 5 +D7 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +103.97745269908431 + 20 +-56.78101924131317 + 30 +0.0 + 40 +2.391993095178304 + 0 +CIRCLE + 5 +D8 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +259.2170852916383 + 20 +-93.79206964027506 + 30 +0.0 + 40 +2.772276696023927 + 0 +CIRCLE + 5 +D9 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +267.0016039328798 + 20 +18.954147878137007 + 30 +0.0 + 40 +1.5622736859028068 + 0 +CIRCLE + 5 +DA +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +320.48806661518614 + 20 +-96.32302037423472 + 30 +0.0 + 40 +2.079258910357178 + 0 +CIRCLE + 5 +DB +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +199.89791371334474 + 20 +27.71307782999682 + 30 +0.0 + 40 +2.077931195263936 + 0 +CIRCLE + 5 +DC +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +92.48213296344649 + 20 +-62.48000215049342 + 30 +0.0 + 40 +1.8017122183584806 + 0 +CIRCLE + 5 +DD +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +8.150643599406454 + 20 +-87.66979330651272 + 30 +0.0 + 40 +2.6715967984930877 + 0 +CIRCLE + 5 +DE +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +338.8216532332134 + 20 +-85.77058033630756 + 30 +0.0 + 40 +1.5825386780323756 + 0 +CIRCLE + 5 +DF +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +126.11968764258575 + 20 +-74.39950942185689 + 30 +0.0 + 40 +2.509732375178605 + 0 +CIRCLE + 5 +E0 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +277.4663842475056 + 20 +-41.65023477640028 + 30 +0.0 + 40 +2.216987379249702 + 0 +CIRCLE + 5 +E1 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +0.05460316284163724 + 20 +27.410402266298632 + 30 +0.0 + 40 +1.5556260739477688 + 0 +CIRCLE + 5 +E2 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +157.68311143149958 + 20 +15.764392175219825 + 30 +0.0 + 40 +1.721972106160304 + 0 +CIRCLE + 5 +E3 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +243.39919241560352 + 20 +32.46978439328481 + 30 +0.0 + 40 +2.5716787988248706 + 0 +CIRCLE + 5 +E4 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +263.6834379209285 + 20 +-94.00540854541117 + 30 +0.0 + 40 +2.238743824020743 + 0 +CIRCLE + 5 +E5 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +33.72832403449282 + 20 +16.71008455080444 + 30 +0.0 + 40 +2.001181974560351 + 0 +CIRCLE + 5 +E6 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +143.13576885999143 + 20 +39.894992210420185 + 30 +0.0 + 40 +2.9488295405193634 + 0 +CIRCLE + 5 +E7 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +331.3627251087871 + 20 +-41.969001561256505 + 30 +0.0 + 40 +2.329870297543901 + 0 +CIRCLE + 5 +E8 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +242.6218071160675 + 20 +-38.14363247822725 + 30 +0.0 + 40 +1.9947384491498574 + 0 +CIRCLE + 5 +E9 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +125.3641894807649 + 20 +-88.02404562470278 + 30 +0.0 + 40 +2.1409012712351494 + 0 +CIRCLE + 5 +EA +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +335.81957214646536 + 20 +33.97238252244469 + 30 +0.0 + 40 +2.5658404506232264 + 0 +CIRCLE + 5 +EB +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +159.75608223980376 + 20 +-59.22818595902589 + 30 +0.0 + 40 +1.6515336076629565 + 0 +CIRCLE + 5 +EC +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +78.03164828914694 + 20 +7.302845658474254 + 30 +0.0 + 40 +2.9745575715214136 + 0 +CIRCLE + 5 +ED +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +110.07744388818116 + 20 +7.903386945074544 + 30 +0.0 + 40 +2.817326756601691 + 0 +CIRCLE + 5 +EE +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +230.054829802322 + 20 +-10.39723325410651 + 30 +0.0 + 40 +2.7913858519471324 + 0 +CIRCLE + 5 +EF +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +110.83543480450777 + 20 +-4.329563898994536 + 30 +0.0 + 40 +1.9774484948806108 + 0 +CIRCLE + 5 +F0 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +154.84668057671962 + 20 +5.462120973642854 + 30 +0.0 + 40 +2.674501025804691 + 0 +CIRCLE + 5 +F1 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +85.78673649190924 + 20 +31.83213301756237 + 30 +0.0 + 40 +2.6044766538121102 + 0 +CIRCLE + 5 +F2 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +189.03789748740132 + 20 +-108.26290144662875 + 30 +0.0 + 40 +2.4298845165619176 + 0 +CIRCLE + 5 +F3 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +70.24922368918189 + 20 +-9.253561414385103 + 30 +0.0 + 40 +2.2869962810799858 + 0 +CIRCLE + 5 +F4 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +267.14534080300797 + 20 +-57.81732379584502 + 30 +0.0 + 40 +2.5949072240851008 + 0 +CIRCLE + 5 +F5 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbCircle + 10 +245.61784697700637 + 20 +14.228300238179813 + 30 +0.0 + 40 +2.0950767574307805 + 0 +POINT + 5 +F6 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +278.1502637782402 + 20 +136.1769256399019 + 30 +0.0 + 0 +TEXT + 5 +F7 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +279.6502637782402 + 20 +136.6769256399019 + 30 +0.0 + 40 +1.8 + 1 +97.04 + 7 +SITE + 11 +279.6502637782402 + 21 +136.6769256399019 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +F8 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +227.15119576773597 + 20 +163.79176895850463 + 30 +0.0 + 0 +TEXT + 5 +F9 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +228.65119576773597 + 20 +164.29176895850463 + 30 +0.0 + 40 +1.8 + 1 +106.61 + 7 +SITE + 11 +228.65119576773597 + 21 +164.29176895850463 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +FA +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +315.65043740221824 + 20 +44.71625191631267 + 30 +0.0 + 0 +TEXT + 5 +FB +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +317.15043740221824 + 20 +45.21625191631267 + 30 +0.0 + 40 +1.8 + 1 +109.24 + 7 +SITE + 11 +317.15043740221824 + 21 +45.21625191631267 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +FC +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +174.68222665390067 + 20 +-46.79511940740176 + 30 +0.0 + 0 +TEXT + 5 +FD +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +176.18222665390067 + 20 +-46.29511940740176 + 30 +0.0 + 40 +1.8 + 1 +89.47 + 7 +SITE + 11 +176.18222665390067 + 21 +-46.29511940740176 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +FE +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +276.08469284675675 + 20 +153.71923969687705 + 30 +0.0 + 0 +TEXT + 5 +FF +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +277.58469284675675 + 20 +154.21923969687705 + 30 +0.0 + 40 +1.8 + 1 +98.95 + 7 +SITE + 11 +277.58469284675675 + 21 +154.21923969687705 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +100 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +157.48884784685973 + 20 +89.77065205944737 + 30 +0.0 + 0 +TEXT + 5 +101 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +158.98884784685973 + 20 +90.27065205944737 + 30 +0.0 + 40 +1.8 + 1 +99.23 + 7 +SITE + 11 +158.98884784685973 + 21 +90.27065205944737 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +102 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +237.49653705495027 + 20 +99.89189064744619 + 30 +0.0 + 0 +TEXT + 5 +103 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +238.99653705495027 + 20 +100.39189064744619 + 30 +0.0 + 40 +1.8 + 1 +101.39 + 7 +SITE + 11 +238.99653705495027 + 21 +100.39189064744619 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +104 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +56.702829029690825 + 20 +112.8966233388964 + 30 +0.0 + 0 +TEXT + 5 +105 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +58.202829029690825 + 20 +113.3966233388964 + 30 +0.0 + 40 +1.8 + 1 +89.38 + 7 +SITE + 11 +58.202829029690825 + 21 +113.3966233388964 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +106 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +191.67894907616233 + 20 +83.04461958611074 + 30 +0.0 + 0 +TEXT + 5 +107 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +193.17894907616233 + 20 +83.54461958611074 + 30 +0.0 + 40 +1.8 + 1 +108.85 + 7 +SITE + 11 +193.17894907616233 + 21 +83.54461958611074 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +108 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +138.8613700857744 + 20 +72.17164429898583 + 30 +0.0 + 0 +TEXT + 5 +109 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +140.3613700857744 + 20 +72.67164429898583 + 30 +0.0 + 40 +1.8 + 1 +93.96 + 7 +SITE + 11 +140.3613700857744 + 21 +72.67164429898583 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +10A +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +255.6525661509654 + 20 +75.58533378231209 + 30 +0.0 + 0 +TEXT + 5 +10B +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +257.1525661509654 + 20 +76.08533378231209 + 30 +0.0 + 40 +1.8 + 1 +103.97 + 7 +SITE + 11 +257.1525661509654 + 21 +76.08533378231209 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +10C +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +237.7367766103562 + 20 +-82.81827590722068 + 30 +0.0 + 0 +TEXT + 5 +10D +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +239.2367766103562 + 20 +-82.31827590722068 + 30 +0.0 + 40 +1.8 + 1 +111.09 + 7 +SITE + 11 +239.2367766103562 + 21 +-82.31827590722068 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +10E +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +52.80761237090758 + 20 +24.677788036008693 + 30 +0.0 + 0 +TEXT + 5 +10F +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +54.30761237090758 + 20 +25.177788036008693 + 30 +0.0 + 40 +1.8 + 1 +105.79 + 7 +SITE + 11 +54.30761237090758 + 21 +25.177788036008693 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +110 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +214.53863091502416 + 20 +-33.050077279364636 + 30 +0.0 + 0 +TEXT + 5 +111 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +216.03863091502416 + 20 +-32.550077279364636 + 30 +0.0 + 40 +1.8 + 1 +100.20 + 7 +SITE + 11 +216.03863091502416 + 21 +-32.550077279364636 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +112 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +226.36588655096244 + 20 +74.02494212091122 + 30 +0.0 + 0 +TEXT + 5 +113 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +227.86588655096244 + 20 +74.52494212091122 + 30 +0.0 + 40 +1.8 + 1 +111.23 + 7 +SITE + 11 +227.86588655096244 + 21 +74.52494212091122 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +114 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +13.814362775791947 + 20 +32.61223118556728 + 30 +0.0 + 0 +TEXT + 5 +115 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +15.314362775791947 + 20 +33.11223118556728 + 30 +0.0 + 40 +1.8 + 1 +104.03 + 7 +SITE + 11 +15.314362775791947 + 21 +33.11223118556728 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +116 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +74.66005656641728 + 20 +-75.92281720138668 + 30 +0.0 + 0 +TEXT + 5 +117 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +76.16005656641728 + 20 +-75.42281720138668 + 30 +0.0 + 40 +1.8 + 1 +94.51 + 7 +SITE + 11 +76.16005656641728 + 21 +-75.42281720138668 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +118 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +44.06387199888762 + 20 +-7.488781126775365 + 30 +0.0 + 0 +TEXT + 5 +119 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +45.56387199888762 + 20 +-6.988781126775365 + 30 +0.0 + 40 +1.8 + 1 +118.38 + 7 +SITE + 11 +45.56387199888762 + 21 +-6.988781126775365 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +11A +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +59.910580361473656 + 20 +-39.7263735341773 + 30 +0.0 + 0 +TEXT + 5 +11B +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +61.410580361473656 + 20 +-39.2263735341773 + 30 +0.0 + 40 +1.8 + 1 +113.50 + 7 +SITE + 11 +61.410580361473656 + 21 +-39.2263735341773 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +11C +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +11.766991668281122 + 20 +30.985842580243627 + 30 +0.0 + 0 +TEXT + 5 +11D +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +13.266991668281122 + 20 +31.485842580243627 + 30 +0.0 + 40 +1.8 + 1 +104.07 + 7 +SITE + 11 +13.266991668281122 + 21 +31.485842580243627 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +11E +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +125.4986206340262 + 20 +69.06642719145128 + 30 +0.0 + 0 +TEXT + 5 +11F +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +126.9986206340262 + 20 +69.56642719145128 + 30 +0.0 + 40 +1.8 + 1 +99.26 + 7 +SITE + 11 +126.9986206340262 + 21 +69.56642719145128 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +120 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +194.75425271273303 + 20 +-28.15993348744543 + 30 +0.0 + 0 +TEXT + 5 +121 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +196.25425271273303 + 20 +-27.65993348744543 + 30 +0.0 + 40 +1.8 + 1 +96.10 + 7 +SITE + 11 +196.25425271273303 + 21 +-27.65993348744543 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +122 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +298.0501666175098 + 20 +-89.82823989439535 + 30 +0.0 + 0 +TEXT + 5 +123 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +299.5501666175098 + 20 +-89.32823989439535 + 30 +0.0 + 40 +1.8 + 1 +97.12 + 7 +SITE + 11 +299.5501666175098 + 21 +-89.32823989439535 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +124 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +133.77399701025467 + 20 +-17.582701574845416 + 30 +0.0 + 0 +TEXT + 5 +125 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +135.27399701025467 + 20 +-17.082701574845416 + 30 +0.0 + 40 +1.8 + 1 +87.04 + 7 +SITE + 11 +135.27399701025467 + 21 +-17.082701574845416 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +126 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +135.31396385962077 + 20 +-60.08064598513852 + 30 +0.0 + 0 +TEXT + 5 +127 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +136.81396385962077 + 20 +-59.58064598513852 + 30 +0.0 + 40 +1.8 + 1 +93.24 + 7 +SITE + 11 +136.81396385962077 + 21 +-59.58064598513852 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +128 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +274.35211971841903 + 20 +7.208710541847154 + 30 +0.0 + 0 +TEXT + 5 +129 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +275.85211971841903 + 20 +7.708710541847154 + 30 +0.0 + 40 +1.8 + 1 +126.01 + 7 +SITE + 11 +275.85211971841903 + 21 +7.708710541847154 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +12A +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +11.90049649386008 + 20 +69.52666370838458 + 30 +0.0 + 0 +TEXT + 5 +12B +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +13.40049649386008 + 20 +70.02666370838458 + 30 +0.0 + 40 +1.8 + 1 +87.73 + 7 +SITE + 11 +13.40049649386008 + 21 +70.02666370838458 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +12C +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +31.291149090549617 + 20 +51.757424423757186 + 30 +0.0 + 0 +TEXT + 5 +12D +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +32.79114909054962 + 20 +52.257424423757186 + 30 +0.0 + 40 +1.8 + 1 +93.73 + 7 +SITE + 11 +32.79114909054962 + 21 +52.257424423757186 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +12E +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +111.99319313365189 + 20 +61.03302192859255 + 30 +0.0 + 0 +TEXT + 5 +12F +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +113.49319313365189 + 20 +61.53302192859255 + 30 +0.0 + 40 +1.8 + 1 +105.95 + 7 +SITE + 11 +113.49319313365189 + 21 +61.53302192859255 + 31 +0.0 +100 +AcDbText + 0 +POINT + 5 +130 +330 +17 +100 +AcDbEntity + 8 +SPOT + 62 +2 +100 +AcDbPoint + 10 +316.2391662302166 + 20 +122.81571994410109 + 30 +0.0 + 0 +TEXT + 5 +131 +330 +17 +100 +AcDbEntity + 8 +SPOT +100 +AcDbText + 10 +317.7391662302166 + 20 +123.31571994410109 + 30 +0.0 + 40 +1.8 + 1 +101.01 + 7 +SITE + 11 +317.7391662302166 + 21 +123.31571994410109 + 31 +0.0 +100 +AcDbText + 0 +INSERT + 5 +132 +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbBlockReference + 2 +NORTH + 10 +370.0 + 20 +180.0 + 30 +0.0 + 41 +0.02 + 42 +0.02 + 43 +0.02 + 0 +LWPOLYLINE + 5 +134 +330 +17 +100 +AcDbEntity + 8 +LEGEND + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +0.0 + 20 +-130.0 + 10 +20.0 + 20 +-130.0 + 10 +20.0 + 20 +-125.0 + 10 +0.0 + 20 +-125.0 + 0 +HATCH + 5 +135 +330 +17 +100 +AcDbEntity + 8 +LEGEND + 62 +252 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +0.0 + 20 +-130.0 + 10 +20.0 + 20 +-130.0 + 10 +20.0 + 20 +-125.0 + 10 +0.0 + 20 +-125.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +136 +330 +17 +100 +AcDbEntity + 8 +LEGEND + 62 +7 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +20.0 + 20 +-130.0 + 10 +40.0 + 20 +-130.0 + 10 +40.0 + 20 +-125.0 + 10 +20.0 + 20 +-125.0 + 0 +HATCH + 5 +137 +330 +17 +100 +AcDbEntity + 8 +LEGEND + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +20.0 + 20 +-130.0 + 10 +40.0 + 20 +-130.0 + 10 +40.0 + 20 +-125.0 + 10 +20.0 + 20 +-125.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +138 +330 +17 +100 +AcDbEntity + 8 +LEGEND + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +40.0 + 20 +-130.0 + 10 +60.0 + 20 +-130.0 + 10 +60.0 + 20 +-125.0 + 10 +40.0 + 20 +-125.0 + 0 +HATCH + 5 +139 +330 +17 +100 +AcDbEntity + 8 +LEGEND + 62 +252 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +40.0 + 20 +-130.0 + 10 +60.0 + 20 +-130.0 + 10 +60.0 + 20 +-125.0 + 10 +40.0 + 20 +-125.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +13A +330 +17 +100 +AcDbEntity + 8 +LEGEND + 62 +7 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +60.0 + 20 +-130.0 + 10 +80.0 + 20 +-130.0 + 10 +80.0 + 20 +-125.0 + 10 +60.0 + 20 +-125.0 + 0 +HATCH + 5 +13B +330 +17 +100 +AcDbEntity + 8 +LEGEND + 62 +7 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +60.0 + 20 +-130.0 + 10 +80.0 + 20 +-130.0 + 10 +80.0 + 20 +-125.0 + 10 +60.0 + 20 +-125.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +LWPOLYLINE + 5 +13C +330 +17 +100 +AcDbEntity + 8 +LEGEND + 62 +8 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +80.0 + 20 +-130.0 + 10 +100.0 + 20 +-130.0 + 10 +100.0 + 20 +-125.0 + 10 +80.0 + 20 +-125.0 + 0 +HATCH + 5 +13D +330 +17 +100 +AcDbEntity + 8 +LEGEND + 62 +252 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +SOLID + 70 +1 + 71 +0 + 91 +1 + 92 +3 + 72 +0 + 73 +1 + 93 +4 + 10 +80.0 + 20 +-130.0 + 10 +100.0 + 20 +-130.0 + 10 +100.0 + 20 +-125.0 + 10 +80.0 + 20 +-125.0 + 97 +0 + 75 +1 + 76 +1 + 98 +0 + 0 +TEXT + 5 +13E +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +0.0 + 20 +-138.0 + 30 +0.0 + 40 +3.0 + 1 +0 + 7 +SITE + 72 +1 + 11 +0.0 + 21 +-138.0 + 31 +0.0 +100 +AcDbText + 73 +3 + 0 +TEXT + 5 +13F +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +20.0 + 20 +-138.0 + 30 +0.0 + 40 +3.0 + 1 +20 + 7 +SITE + 72 +1 + 11 +20.0 + 21 +-138.0 + 31 +0.0 +100 +AcDbText + 73 +3 + 0 +TEXT + 5 +140 +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +40.0 + 20 +-138.0 + 30 +0.0 + 40 +3.0 + 1 +40 + 7 +SITE + 72 +1 + 11 +40.0 + 21 +-138.0 + 31 +0.0 +100 +AcDbText + 73 +3 + 0 +TEXT + 5 +141 +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +60.0 + 20 +-138.0 + 30 +0.0 + 40 +3.0 + 1 +60 + 7 +SITE + 72 +1 + 11 +60.0 + 21 +-138.0 + 31 +0.0 +100 +AcDbText + 73 +3 + 0 +TEXT + 5 +142 +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +80.0 + 20 +-138.0 + 30 +0.0 + 40 +3.0 + 1 +80 + 7 +SITE + 72 +1 + 11 +80.0 + 21 +-138.0 + 31 +0.0 +100 +AcDbText + 73 +3 + 0 +TEXT + 5 +143 +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +100.0 + 20 +-138.0 + 30 +0.0 + 40 +3.0 + 1 +100 + 7 +SITE + 72 +1 + 11 +100.0 + 21 +-138.0 + 31 +0.0 +100 +AcDbText + 73 +3 + 0 +TEXT + 5 +144 +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +108.0 + 20 +-138.0 + 30 +0.0 + 40 +3.0 + 1 +m + 7 +SITE + 11 +108.0 + 21 +-138.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +145 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MINOR +100 +AcDbLine + 10 +370.0 + 20 +170.0 + 30 +0.0 + 11 +390.0 + 21 +170.0 + 31 +0.0 + 0 +TEXT + 5 +146 +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +394.0 + 20 +169.0 + 30 +0.0 + 40 +3.0 + 1 +Contour, 2 m + 7 +SITE + 11 +394.0 + 21 +169.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +147 +330 +17 +100 +AcDbEntity + 8 +CONTOUR-MAJOR +100 +AcDbLine + 10 +370.0 + 20 +162.0 + 30 +0.0 + 11 +390.0 + 21 +162.0 + 31 +0.0 + 0 +TEXT + 5 +148 +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +394.0 + 20 +161.0 + 30 +0.0 + 40 +3.0 + 1 +Contour, 10 m + 7 +SITE + 11 +394.0 + 21 +161.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +149 +330 +17 +100 +AcDbEntity + 8 +PARCEL +100 +AcDbLine + 10 +370.0 + 20 +154.0 + 30 +0.0 + 11 +390.0 + 21 +154.0 + 31 +0.0 + 0 +TEXT + 5 +14A +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +394.0 + 20 +153.0 + 30 +0.0 + 40 +3.0 + 1 +Parcel boundary + 7 +SITE + 11 +394.0 + 21 +153.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +14B +330 +17 +100 +AcDbEntity + 8 +BUILDING +100 +AcDbLine + 10 +370.0 + 20 +146.0 + 30 +0.0 + 11 +390.0 + 21 +146.0 + 31 +0.0 + 0 +TEXT + 5 +14C +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +394.0 + 20 +145.0 + 30 +0.0 + 40 +3.0 + 1 +Building + 7 +SITE + 11 +394.0 + 21 +145.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +14D +330 +17 +100 +AcDbEntity + 8 +ROAD +100 +AcDbLine + 10 +370.0 + 20 +138.0 + 30 +0.0 + 11 +390.0 + 21 +138.0 + 31 +0.0 + 0 +TEXT + 5 +14E +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +394.0 + 20 +137.0 + 30 +0.0 + 40 +3.0 + 1 +Road + 7 +SITE + 11 +394.0 + 21 +137.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +14F +330 +17 +100 +AcDbEntity + 8 +WATER +100 +AcDbLine + 10 +370.0 + 20 +130.0 + 30 +0.0 + 11 +390.0 + 21 +130.0 + 31 +0.0 + 0 +TEXT + 5 +150 +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +394.0 + 20 +129.0 + 30 +0.0 + 40 +3.0 + 1 +Water + 7 +SITE + 11 +394.0 + 21 +129.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +151 +330 +17 +100 +AcDbEntity + 8 +TREES +100 +AcDbLine + 10 +370.0 + 20 +122.0 + 30 +0.0 + 11 +390.0 + 21 +122.0 + 31 +0.0 + 0 +TEXT + 5 +152 +330 +17 +100 +AcDbEntity + 8 +LEGEND +100 +AcDbText + 10 +394.0 + 20 +121.0 + 30 +0.0 + 40 +3.0 + 1 +Tree + 7 +SITE + 11 +394.0 + 21 +121.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +153 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-160.0 + 30 +0.0 + 40 +8.0 + 1 +SITE PLAN 1:1000 + 7 +SITE + 11 +0.0 + 21 +-160.0 + 31 +0.0 +100 +AcDbText + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +A +330 +0 +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ACAD_COLOR +350 +B + 3 +ACAD_GROUP +350 +C + 3 +ACAD_LAYOUT +350 +D + 3 +ACAD_MATERIAL +350 +E + 3 +ACAD_MLEADERSTYLE +350 +F + 3 +ACAD_MLINESTYLE +350 +10 + 3 +ACAD_PLOTSETTINGS +350 +11 + 3 +ACAD_PLOTSTYLENAME +350 +12 + 3 +ACAD_SCALELIST +350 +14 + 3 +ACAD_TABLESTYLE +350 +15 + 3 +ACAD_VISUALSTYLE +350 +16 + 3 +EZDXF_META +350 +2D + 0 +DICTIONARY + 5 +B +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +C +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +D +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Model +350 +1A + 3 +Layout1 +350 +1E + 0 +DICTIONARY + 5 +E +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ByBlock +350 +1F + 3 +ByLayer +350 +20 + 3 +Global +350 +21 + 0 +DICTIONARY + 5 +F +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +2C + 0 +DICTIONARY + 5 +10 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +22 + 0 +DICTIONARY + 5 +11 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +ACDBDICTIONARYWDFLT + 5 +12 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Normal +350 +13 +100 +AcDbDictionaryWithDefault +340 +13 + 0 +ACDBPLACEHOLDER + 5 +13 +330 +12 + 0 +DICTIONARY + 5 +14 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +15 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +16 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +LAYOUT + 5 +1A +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +1024 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 +1 + 71 +0 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +17 + 0 +LAYOUT + 5 +1E +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +0 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 +1 + 71 +1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +1B + 0 +MATERIAL + 5 +1F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByBlock + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +20 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByLayer + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +21 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +Global + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MLINESTYLE + 5 +22 +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMlineStyle + 2 +Standard + 70 +0 + 3 + + 62 +256 + 51 +90.0 + 52 +90.0 + 71 +2 + 49 +0.5 + 62 +256 + 6 +BYLAYER + 49 +-0.5 + 62 +256 + 6 +BYLAYER + 0 +MLEADERSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +F +102 +} +330 +F +100 +AcDbMLeaderStyle +179 +2 +170 +2 +171 +1 +172 +0 + 90 +2 + 40 +0.0 + 41 +0.0 +173 +1 + 91 +-1056964608 + 92 +-2 +290 +1 + 42 +2.0 +291 +1 + 43 +8.0 + 3 +Standard + 44 +4.0 +300 + +342 +29 +174 +1 +175 +1 +176 +0 +178 +1 + 93 +-1056964608 + 45 +4.0 +292 +0 +297 +0 + 46 +4.0 + 94 +-1056964608 + 47 +1.0 + 49 +1.0 +140 +1.0 +294 +1 +141 +0.0 +177 +0 +142 +1.0 +295 +0 +296 +0 +143 +3.75 +271 +0 +272 +9 +273 +9 + 0 +DICTIONARY + 5 +2D +330 +A +100 +AcDbDictionary +281 +1 + 3 +CREATED_BY_EZDXF +350 +2E + 3 +WRITTEN_BY_EZDXF +350 +157 + 0 +DICTIONARYVAR + 5 +2E +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +DICTIONARYVAR + 5 +157 +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +ENDSEC + 0 +EOF diff --git a/crates/exav-viewer/demo/examples/files/cad/text-styles.dxf b/crates/exav-viewer/demo/examples/files/cad/text-styles.dxf new file mode 100644 index 0000000..25fe2cb --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/cad/text-styles.dxf @@ -0,0 +1,5696 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1032 + 9 +$ACADMAINTVER + 90 +4 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$LASTSAVEDBY + 1 +ezdxf + 9 +$REQUIREDVERSIONS +160 +0 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$EXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 +0 + 9 +$REGENMODE + 70 +1 + 9 +$FILLMODE + 70 +1 + 9 +$QTEXTMODE + 70 +0 + 9 +$MIRRTEXT + 70 +1 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 +1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 +256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 +0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 +0 + 9 +$DIMLIM + 70 +0 + 9 +$DIMTIH + 70 +0 + 9 +$DIMTOH + 70 +0 + 9 +$DIMSE1 + 70 +0 + 9 +$DIMSE2 + 70 +0 + 9 +$DIMTAD + 70 +1 + 9 +$DIMZIN + 70 +8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 +1 + 9 +$DIMSHO + 70 +1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 +0 + 9 +$DIMALTD + 70 +3 + 9 +$DIMALTF + 40 +0.03937007874 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 +1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 +0 + 9 +$DIMSOXD + 70 +0 + 9 +$DIMSAH + 70 +0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 +0 + 9 +$DIMCLRE + 70 +0 + 9 +$DIMCLRT + 70 +0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 +0 + 9 +$DIMSD1 + 70 +0 + 9 +$DIMSD2 + 70 +0 + 9 +$DIMTOLJ + 70 +0 + 9 +$DIMTZIN + 70 +8 + 9 +$DIMALTZ + 70 +0 + 9 +$DIMALTTZ + 70 +0 + 9 +$DIMUPT + 70 +0 + 9 +$DIMDEC + 70 +2 + 9 +$DIMTDEC + 70 +2 + 9 +$DIMALTU + 70 +2 + 9 +$DIMALTTD + 70 +3 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 +0 + 9 +$DIMADEC + 70 +0 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 +0 + 9 +$DIMDSEP + 70 +44 + 9 +$DIMATFIT + 70 +3 + 9 +$DIMFRAC + 70 +0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 +2 + 9 +$DIMLWD + 70 +-2 + 9 +$DIMLWE + 70 +-2 + 9 +$DIMTMOVE + 70 +0 + 9 +$DIMFXL + 40 +1.0 + 9 +$DIMFXLON + 70 +0 + 9 +$DIMJOGANG + 40 +0.785398163397 + 9 +$DIMTFILL + 70 +0 + 9 +$DIMTFILLCLR + 70 +0 + 9 +$DIMARCSYM + 70 +0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$DIMTXTDIRECTION + 70 +0 + 9 +$LUNITS + 70 +2 + 9 +$LUPREC + 70 +4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 +0 + 9 +$AUPREC + 70 +2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 +0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 +0 + 9 +$TDCREATE + 40 +2451545.0 + 9 +$TDUCREATE + 40 +2451545.0 + 9 +$TDUPDATE + 40 +2451545.0 + 9 +$TDUUPDATE + 40 +2451545.0 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 +1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 +0 + 9 +$PDMODE + 70 +0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 +0 + 9 +$SPLINETYPE + 70 +6 + 9 +$SPLINESEGS + 70 +8 + 9 +$HANDSEED + 5 +87 + 9 +$SURFTAB1 + 70 +6 + 9 +$SURFTAB2 + 70 +6 + 9 +$SURFTYPE + 70 +6 + 9 +$SURFU + 70 +6 + 9 +$SURFV + 70 +6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 +0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 +0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 +0 + 9 +$USERI2 + 70 +0 + 9 +$USERI3 + 70 +0 + 9 +$USERI4 + 70 +0 + 9 +$USERI5 + 70 +0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 +1 + 9 +$SHADEDGE + 70 +3 + 9 +$SHADEDIF + 70 +70 + 9 +$TILEMODE + 70 +1 + 9 +$MAXACTVP + 70 +64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 +0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 +0 + 9 +$VISRETAIN + 70 +1 + 9 +$PLINEGEN + 70 +0 + 9 +$PSLTSCALE + 70 +1 + 9 +$TREEDEPTH + 70 +3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 +0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 +1 + 9 +$MEASUREMENT + 70 +1 + 9 +$CELWEIGHT +370 +-1 + 9 +$ENDCAPS +280 +0 + 9 +$JOINSTYLE +280 +0 + 9 +$LWDISPLAY +290 +0 + 9 +$INSUNITS + 70 +4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 +1 + 9 +$CEPSNTYPE +380 +0 + 9 +$PSTYLEMODE +290 +1 + 9 +$FINGERPRINTGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$VERSIONGUID + 2 +{00000000-0000-0000-0000-000000000000} + 9 +$EXTNAMES +290 +1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 +0 + 9 +$SORTENTS +280 +127 + 9 +$INDEXCTL +280 +0 + 9 +$HIDETEXT +280 +1 + 9 +$XCLIPFRAME +280 +1 + 9 +$HALOGAP +280 +0 + 9 +$OBSCOLOR + 70 +257 + 9 +$OBSLTYPE +280 +0 + 9 +$INTERSECTIONDISPLAY +280 +0 + 9 +$INTERSECTIONCOLOR + 70 +257 + 9 +$DIMASSOC +280 +2 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 +0 + 9 +$LENSLENGTH + 40 +50.0 + 9 +$CAMERAHEIGHT + 40 +0.0 + 9 +$STEPSPERSEC + 40 +24.0 + 9 +$STEPSIZE + 40 +100.0 + 9 +$3DDWFPREC + 40 +2.0 + 9 +$PSOLWIDTH + 40 +0.005 + 9 +$PSOLHEIGHT + 40 +0.08 + 9 +$LOFTANG1 + 40 +1.570796326795 + 9 +$LOFTANG2 + 40 +1.570796326795 + 9 +$LOFTMAG1 + 40 +0.0 + 9 +$LOFTMAG2 + 40 +0.0 + 9 +$LOFTPARAM + 70 +7 + 9 +$LOFTNORMALS +280 +1 + 9 +$LATITUDE + 40 +37.795 + 9 +$LONGITUDE + 40 +-122.394 + 9 +$NORTHDIRECTION + 40 +0.0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 +1 + 9 +$TILEMODELIGHTSYNCH +280 +1 + 9 +$CMATERIAL +347 +20 + 9 +$SOLIDHIST +280 +0 + 9 +$SHOWHIST +280 +1 + 9 +$DWFFRAME +280 +2 + 9 +$DGNFRAME +280 +2 + 9 +$REALWORLDSCALE +290 +1 + 9 +$INTERFERECOLOR + 62 +256 + 9 +$CSHADOW +280 +0 + 9 +$SHADOWPLANELOCATION + 40 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 +1153 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 +4095 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +CELLSTYLEMAP + 2 +AcDbCellStyleMap + 3 +ObjectDBX Classes + 90 +1152 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +MENTALRAYRENDERSETTINGS + 2 +AcDbMentalRayRenderSettings + 3 +SCENEOE + 90 +1024 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBDETAILVIEWSTYLE + 2 +AcDbDetailViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBSECTIONVIEWSTYLE + 2 +AcDbSectionViewStyle + 3 +ObjectDBX Classes + 90 +1025 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +RASTERVARIABLES + 2 +AcDbRasterVariables + 3 +ISM + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 +0 + 91 +0 +280 +0 +281 +0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 +1 + 0 +VPORT + 5 +83 +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +305.0 + 22 +-179.42799732083054 + 13 +0.0 + 23 +0.0 + 14 +0.5 + 24 +0.5 + 15 +0.5 + 25 +0.5 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +389.3987943737442 + 41 +1.34 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +1000 + 73 +1 + 74 +3 + 75 +0 + 76 +0 + 77 +0 + 78 +0 +281 +0 + 65 +1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 +21 + 0 +LTYPE + 5 +24 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +25 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +26 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +2F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 +0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +5.08 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +30 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 +0 + 3 +Center (2x) ________ __ ________ __ ________ + 72 +65 + 73 +4 + 40 +8.89 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 +0 + 3 +Center (.5x) ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +2.54 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +32 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 +0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 +65 + 73 +2 + 40 +1.524 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +33 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 +0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ____ + 72 +65 + 73 +2 + 40 +3.048 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +34 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 +0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 +65 + 73 +2 + 40 +0.762 + 49 +0.635 + 74 +0 + 49 +-0.127 + 74 +0 + 0 +LTYPE + 5 +35 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM + 70 +0 + 3 +Phantom ______ __ __ ______ __ __ ______ + 72 +65 + 73 +6 + 40 +6.35 + 49 +3.175 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +0.635 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOMX2 + 70 +0 + 3 +Phantom (2x)____________ ____ ____ ____________ + 72 +65 + 73 +6 + 40 +10.795 + 49 +6.35 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 49 +1.27 + 74 +0 + 49 +-0.635 + 74 +0 + 0 +LTYPE + 5 +37 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 +0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___ + 72 +65 + 73 +6 + 40 +3.175 + 49 +1.587 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 49 +0.318 + 74 +0 + 49 +-0.318 + 74 +0 + 0 +LTYPE + 5 +38 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 +0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 +65 + 73 +4 + 40 +3.556 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +39 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 +0 + 3 +Dash dot (2x) ____ . ____ . ____ . ____ + 72 +65 + 73 +4 + 40 +6.096 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 +0 + 3 +Dash dot (.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +4 + 40 +1.778 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 +0 + 3 +Dot . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.508 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 +0 + 3 +Dot (2x) . . . . . . . . + 72 +65 + 73 +2 + 40 +1.016 + 49 +0.0 + 74 +0 + 49 +-1.016 + 74 +0 + 0 +LTYPE + 5 +3D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 +0 + 3 +Dot (.5) . . . . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +0.254 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +LTYPE + 5 +3E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 +0 + 3 +Divide __ . . __ . . __ . . __ . . __ . . __ + 72 +65 + 73 +6 + 40 +4.064 + 49 +2.54 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +3F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 +0 + 3 +Divide (2x) ____ . . ____ . . ____ . . ____ + 72 +65 + 73 +6 + 40 +6.604 + 49 +5.08 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.508 + 74 +0 + 0 +LTYPE + 5 +40 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 +0 + 3 +Divide(.5x) _ . _ . _ . _ . _ . _ . _ . _ + 72 +65 + 73 +6 + 40 +2.032 + 49 +1.27 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-0.254 + 74 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 +4 + 0 +LAYER + 5 +27 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 62 +7 + 6 +Continuous +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +28 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Defpoints + 70 +0 + 62 +7 + 6 +Continuous +290 +0 +370 +-3 +390 +13 +347 +21 + 0 +LAYER + 5 +41 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +TEXT + 70 +0 + 62 +7 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +LAYER + 5 +42 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +NOTE + 70 +0 + 62 +8 + 6 +Continuous +370 +25 +390 +13 +347 +21 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 +11 + 0 +STYLE + 5 +29 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +43 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +S-ARIAL + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +STYLE + 5 +44 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +S-TIMES + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +times.ttf + 4 + + 0 +STYLE + 5 +45 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +S-COURIER + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +cour.ttf + 4 + + 0 +STYLE + 5 +46 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +S-NARROW + 70 +0 + 40 +0.0 + 41 +0.6 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +STYLE + 5 +47 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +S-WIDE + 70 +0 + 40 +0.0 + 41 +1.6 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +STYLE + 5 +48 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +S-SLANT + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +20.0 + 71 +0 + 42 +2.5 + 3 +times.ttf + 4 + + 0 +STYLE + 5 +49 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +S-ROMANS + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +romans.shx + 4 + + 0 +STYLE + 5 +4A +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +S-SIMPLEX + 70 +0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +simplex.shx + 4 + + 0 +STYLE + 5 +4B +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +S-BACKWARDS + 70 +2 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +STYLE + 5 +4C +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +S-UPSIDE + 70 +4 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +arial.ttf + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 +3 + 0 +APPID + 5 +2A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 +0 + 0 +APPID + 5 +84 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +HATCHBACKGROUNDCOLOR + 70 +0 + 0 +APPID + 5 +85 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +EZDXF + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +4 +330 +0 +100 +AcDbSymbolTable + 70 +1 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +2B +330 +4 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 +0 + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +2.5 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 +148 +0.0 + 69 +0 + 70 +0 + 71 +0 + 72 +0 + 73 +0 + 74 +0 + 75 +0 + 76 +0 + 77 +1 + 78 +8 + 79 +3 +170 +0 +171 +3 +172 +1 +173 +0 +174 +0 +175 +0 +176 +0 +177 +0 +178 +0 +179 +2 +271 +2 +272 +2 +273 +2 +274 +3 +275 +0 +276 +0 +277 +2 +278 +44 +279 +0 +280 +0 +281 +0 +282 +0 +283 +0 +284 +8 +285 +0 +286 +0 +288 +0 +289 +3 +290 +0 +371 +-2 +372 +-2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 +2 + 0 +BLOCK_RECORD + 5 +17 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +1A + 70 +0 +280 +1 +281 +0 + 0 +BLOCK_RECORD + 5 +1B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 70 +0 +280 +1 +281 +0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +18 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +19 +330 +17 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +TEXT + 5 +4D +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +6.0 + 1 +S-ARIAL (arial.ttf): Sphinx of black quartz, judge my vow 0123456789 + 7 +S-ARIAL + 11 +0.0 + 21 +0.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +4E +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-12.0 + 30 +0.0 + 40 +6.0 + 1 +S-TIMES (times.ttf): Sphinx of black quartz, judge my vow 0123456789 + 7 +S-TIMES + 11 +0.0 + 21 +-12.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +4F +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-24.0 + 30 +0.0 + 40 +6.0 + 1 +S-COURIER (cour.ttf): Sphinx of black quartz, judge my vow 0123456789 + 7 +S-COURIER + 11 +0.0 + 21 +-24.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +50 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-36.0 + 30 +0.0 + 40 +6.0 + 1 +S-NARROW (arial.ttf): Sphinx of black quartz, judge my vow 0123456789 + 7 +S-NARROW + 11 +0.0 + 21 +-36.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +51 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-48.0 + 30 +0.0 + 40 +6.0 + 1 +S-WIDE (arial.ttf): Sphinx of black quartz, judge my vow 0123456789 + 7 +S-WIDE + 11 +0.0 + 21 +-48.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +52 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-60.0 + 30 +0.0 + 40 +6.0 + 1 +S-SLANT (times.ttf): Sphinx of black quartz, judge my vow 0123456789 + 7 +S-SLANT + 11 +0.0 + 21 +-60.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +53 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-72.0 + 30 +0.0 + 40 +6.0 + 1 +S-ROMANS (romans.shx): Sphinx of black quartz, judge my vow 0123456789 + 7 +S-ROMANS + 11 +0.0 + 21 +-72.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +54 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-84.0 + 30 +0.0 + 40 +6.0 + 1 +S-SIMPLEX (simplex.shx): Sphinx of black quartz, judge my vow 0123456789 + 7 +S-SIMPLEX + 11 +0.0 + 21 +-84.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +55 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-96.0 + 30 +0.0 + 40 +6.0 + 1 +S-BACKWARDS (arial.ttf): Sphinx of black quartz, judge my vow 0123456789 + 7 +S-BACKWARDS + 11 +0.0 + 21 +-96.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +56 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-108.0 + 30 +0.0 + 40 +6.0 + 1 +S-UPSIDE (arial.ttf): Sphinx of black quartz, judge my vow 0123456789 + 7 +S-UPSIDE + 11 +0.0 + 21 +-108.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +57 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbLine + 10 +15.0 + 20 +-126.0 + 30 +0.0 + 11 +25.0 + 21 +-126.0 + 31 +0.0 + 0 +LINE + 5 +58 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbLine + 10 +20.0 + 20 +-131.0 + 30 +0.0 + 11 +20.0 + 21 +-121.0 + 31 +0.0 + 0 +TEXT + 5 +59 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +20.0 + 20 +-126.0 + 30 +0.0 + 40 +6.0 + 1 +TOP_LEFT + 7 +S-ARIAL + 11 +20.0 + 21 +-126.0 + 31 +0.0 +100 +AcDbText + 73 +3 + 0 +LINE + 5 +5A +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbLine + 10 +145.0 + 20 +-126.0 + 30 +0.0 + 11 +155.0 + 21 +-126.0 + 31 +0.0 + 0 +LINE + 5 +5B +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbLine + 10 +150.0 + 20 +-131.0 + 30 +0.0 + 11 +150.0 + 21 +-121.0 + 31 +0.0 + 0 +TEXT + 5 +5C +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +150.0 + 20 +-126.0 + 30 +0.0 + 40 +6.0 + 1 +MIDDLE_CENTER + 7 +S-ARIAL + 72 +1 + 11 +150.0 + 21 +-126.0 + 31 +0.0 +100 +AcDbText + 73 +2 + 0 +LINE + 5 +5D +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbLine + 10 +275.0 + 20 +-126.0 + 30 +0.0 + 11 +285.0 + 21 +-126.0 + 31 +0.0 + 0 +LINE + 5 +5E +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbLine + 10 +280.0 + 20 +-131.0 + 30 +0.0 + 11 +280.0 + 21 +-121.0 + 31 +0.0 + 0 +TEXT + 5 +5F +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +280.0 + 20 +-126.0 + 30 +0.0 + 40 +6.0 + 1 +BOTTOM_RIGHT + 7 +S-ARIAL + 72 +2 + 11 +280.0 + 21 +-126.0 + 31 +0.0 +100 +AcDbText + 73 +1 + 0 +LINE + 5 +60 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbLine + 10 +405.0 + 20 +-126.0 + 30 +0.0 + 11 +415.0 + 21 +-126.0 + 31 +0.0 + 0 +LINE + 5 +61 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbLine + 10 +410.0 + 20 +-131.0 + 30 +0.0 + 11 +410.0 + 21 +-121.0 + 31 +0.0 + 0 +TEXT + 5 +62 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +410.0 + 20 +-126.0 + 30 +0.0 + 40 +6.0 + 1 +ALIGNED + 7 +S-ARIAL + 72 +3 + 11 +480.0 + 21 +-126.0 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +63 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbLine + 10 +535.0 + 20 +-126.0 + 30 +0.0 + 11 +545.0 + 21 +-126.0 + 31 +0.0 + 0 +LINE + 5 +64 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbLine + 10 +540.0 + 20 +-131.0 + 30 +0.0 + 11 +540.0 + 21 +-121.0 + 31 +0.0 + 0 +TEXT + 5 +65 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +540.0 + 20 +-126.0 + 30 +0.0 + 40 +6.0 + 1 +FIT + 7 +S-ARIAL + 72 +5 + 11 +610.0 + 21 +-126.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +66 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +20.0 + 20 +-150.0 + 30 +0.0 + 40 +6.0 + 1 +rotated 0 degrees + 7 +S-TIMES + 11 +20.0 + 21 +-150.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +67 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +65.0 + 20 +-150.0 + 30 +0.0 + 40 +6.0 + 1 +rotated 30 degrees + 50 +30.0 + 7 +S-TIMES + 11 +65.0 + 21 +-150.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +68 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +110.0 + 20 +-150.0 + 30 +0.0 + 40 +6.0 + 1 +rotated 60 degrees + 50 +60.0 + 7 +S-TIMES + 11 +110.0 + 21 +-150.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +69 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +155.0 + 20 +-150.0 + 30 +0.0 + 40 +6.0 + 1 +rotated 90 degrees + 50 +90.0 + 7 +S-TIMES + 11 +155.0 + 21 +-150.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +6A +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-220.0 + 30 +0.0 + 40 +5.0 + 1 +Special: %%d degree 45%%d, %%p plus/minus 0.5, %%c diameter 25, %%%% percent, %%u under%%u, %%o over%%o + 7 +S-ARIAL + 11 +0.0 + 21 +-220.0 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +6B +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +0.0 + 20 +-230.0 + 30 +0.0 + 40 +5.0 + 1 +Unicode: éèê üöä ß ñ ΔΩπ ЖÑ� € ½ ²³ + 7 +S-ARIAL + 11 +0.0 + 21 +-230.0 + 31 +0.0 +100 +AcDbText + 0 +MTEXT + 5 +6C +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +0.0 + 20 +-250.0 + 30 +0.0 + 40 +4.0 + 41 +120.0 + 71 +1 + 3 +{\C1;Red}, {\C3;green}, {\C5;blue} and {\c16744192;orange by RGB}.\P{\fTimes New Roman|b1;Bold serif}, {\fArial|i1;italic sans}, {\fCourier New|b1|i1;bold italic mono}.\PUnderline \Lis on\l, overline \Ois on\o, \Kstrike-through\k.\PHeight \H2x;double + 1 +s\H1x; and returns; width \W2;wide\W1; and back; slant \Q20;oblique\Q0;.\PStacked: \S1/2; \S1#2; \S1^2; \S\U+00B1 0.1^ -0.1; and x\S2^;, H\S2^ ;.\PTab\Pstops: A\tB\tC + 7 +S-ARIAL + 0 +MTEXT + 5 +6D +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +130.0 + 20 +-250.0 + 30 +0.0 + 40 +4.2 + 41 +90.0 + 71 +1 + 1 +{\L\C2;Paragraph 1}\PA justified-looking paragraph with a long text that wraps inside the box of the entity, set at width 90, to see how line breaks are made by the viewer. + 7 +S-ARIAL + 0 +MTEXT + 5 +6E +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +230.0 + 20 +-250.0 + 30 +0.0 + 40 +4.2 + 41 +70.0 + 71 +1 + 1 +Background box, with a border in the text colour: the viewer fills the box behind the text. + 7 +S-ARIAL + 45 +1.5 + 90 +1 + 63 +0 +421 +16771980 + 0 +MTEXT + 5 +6F +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +0.0 + 20 +-320.0 + 30 +0.0 + 40 +3.5 + 41 +40.0 + 46 +40.0 + 71 +1 + 1 +Column one text, a short paragraph that sits at the left.\NColumn two: more text, in the middle.\NColumn three at the right. + 7 +S-ARIAL +101 +Embedded Object + 70 +1 + 10 +1.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +-320.0 + 31 +0.0 + 40 +40.0 + 41 +40.0 + 42 +132.0 + 43 +40.0 + 71 +1 + 72 +3 + 44 +40.0 + 45 +6.0 + 73 +0 + 74 +0 + 0 +TEXT + 5 +70 +330 +17 +100 +AcDbEntity + 8 +NOTE +100 +AcDbText + 10 +0.0 + 20 +-364.0 + 30 +0.0 + 40 +3.0 + 1 +MTEXT in three static columns + 7 +S-ARIAL + 11 +0.0 + 21 +-364.0 + 31 +0.0 +100 +AcDbText + 0 +MTEXT + 5 +71 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +150.0 + 20 +-320.0 + 30 +0.0 + 40 +4.0 + 41 +30.0 + 71 +1 + 1 +AP 1 + 7 +S-ARIAL + 0 +CIRCLE + 5 +72 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbCircle + 10 +150.0 + 20 +-320.0 + 30 +0.0 + 40 +0.8 + 0 +MTEXT + 5 +73 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +190.0 + 20 +-320.0 + 30 +0.0 + 40 +4.0 + 41 +30.0 + 71 +2 + 1 +AP 2 + 7 +S-ARIAL + 0 +CIRCLE + 5 +74 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbCircle + 10 +190.0 + 20 +-320.0 + 30 +0.0 + 40 +0.8 + 0 +MTEXT + 5 +75 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +230.0 + 20 +-320.0 + 30 +0.0 + 40 +4.0 + 41 +30.0 + 71 +3 + 1 +AP 3 + 7 +S-ARIAL + 0 +CIRCLE + 5 +76 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbCircle + 10 +230.0 + 20 +-320.0 + 30 +0.0 + 40 +0.8 + 0 +MTEXT + 5 +77 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +150.0 + 20 +-334.0 + 30 +0.0 + 40 +4.0 + 41 +30.0 + 71 +4 + 1 +AP 4 + 7 +S-ARIAL + 0 +CIRCLE + 5 +78 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbCircle + 10 +150.0 + 20 +-334.0 + 30 +0.0 + 40 +0.8 + 0 +MTEXT + 5 +79 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +190.0 + 20 +-334.0 + 30 +0.0 + 40 +4.0 + 41 +30.0 + 71 +5 + 1 +AP 5 + 7 +S-ARIAL + 0 +CIRCLE + 5 +7A +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbCircle + 10 +190.0 + 20 +-334.0 + 30 +0.0 + 40 +0.8 + 0 +MTEXT + 5 +7B +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +230.0 + 20 +-334.0 + 30 +0.0 + 40 +4.0 + 41 +30.0 + 71 +6 + 1 +AP 6 + 7 +S-ARIAL + 0 +CIRCLE + 5 +7C +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbCircle + 10 +230.0 + 20 +-334.0 + 30 +0.0 + 40 +0.8 + 0 +MTEXT + 5 +7D +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +150.0 + 20 +-348.0 + 30 +0.0 + 40 +4.0 + 41 +30.0 + 71 +7 + 1 +AP 7 + 7 +S-ARIAL + 0 +CIRCLE + 5 +7E +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbCircle + 10 +150.0 + 20 +-348.0 + 30 +0.0 + 40 +0.8 + 0 +MTEXT + 5 +7F +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +190.0 + 20 +-348.0 + 30 +0.0 + 40 +4.0 + 41 +30.0 + 71 +8 + 1 +AP 8 + 7 +S-ARIAL + 0 +CIRCLE + 5 +80 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbCircle + 10 +190.0 + 20 +-348.0 + 30 +0.0 + 40 +0.8 + 0 +MTEXT + 5 +81 +330 +17 +100 +AcDbEntity + 8 +TEXT +100 +AcDbMText + 10 +230.0 + 20 +-348.0 + 30 +0.0 + 40 +4.0 + 41 +30.0 + 71 +9 + 1 +AP 9 + 7 +S-ARIAL + 0 +CIRCLE + 5 +82 +330 +17 +100 +AcDbEntity + 8 +0 + 62 +1 +100 +AcDbCircle + 10 +230.0 + 20 +-348.0 + 30 +0.0 + 40 +0.8 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +A +330 +0 +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ACAD_COLOR +350 +B + 3 +ACAD_GROUP +350 +C + 3 +ACAD_LAYOUT +350 +D + 3 +ACAD_MATERIAL +350 +E + 3 +ACAD_MLEADERSTYLE +350 +F + 3 +ACAD_MLINESTYLE +350 +10 + 3 +ACAD_PLOTSETTINGS +350 +11 + 3 +ACAD_PLOTSTYLENAME +350 +12 + 3 +ACAD_SCALELIST +350 +14 + 3 +ACAD_TABLESTYLE +350 +15 + 3 +ACAD_VISUALSTYLE +350 +16 + 3 +EZDXF_META +350 +2D + 0 +DICTIONARY + 5 +B +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +C +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +D +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Model +350 +1A + 3 +Layout1 +350 +1E + 0 +DICTIONARY + 5 +E +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ByBlock +350 +1F + 3 +ByLayer +350 +20 + 3 +Global +350 +21 + 0 +DICTIONARY + 5 +F +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +2C + 0 +DICTIONARY + 5 +10 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +22 + 0 +DICTIONARY + 5 +11 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +ACDBDICTIONARYWDFLT + 5 +12 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Normal +350 +13 +100 +AcDbDictionaryWithDefault +340 +13 + 0 +ACDBPLACEHOLDER + 5 +13 +330 +12 + 0 +DICTIONARY + 5 +14 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +15 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +16 +330 +A +100 +AcDbDictionary +280 +0 +281 +1 + 0 +LAYOUT + 5 +1A +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +1024 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 +1 + 71 +0 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +17 + 0 +LAYOUT + 5 +1E +330 +D +100 +AcDbPlotSettings + 1 + + 4 +A3 + 6 + + 40 +7.5 + 41 +20.0 + 42 +7.5 + 43 +20.0 + 44 +420.0 + 45 +297.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +0 + 72 +1 + 73 +0 + 74 +5 + 7 + + 75 +16 + 76 +0 + 77 +2 + 78 +300 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 +1 + 71 +1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1e+20 + 24 +1e+20 + 34 +1e+20 + 15 +-1e+20 + 25 +-1e+20 + 35 +-1e+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +1 +330 +1B + 0 +MATERIAL + 5 +1F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByBlock + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +20 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +ByLayer + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MATERIAL + 5 +21 +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbMaterial + 1 +Global + 2 + + 70 +0 + 40 +1.0 + 71 +1 + 41 +1.0 + 91 +-1023410177 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 44 +0.5 + 73 +0 + 45 +1.0 + 46 +1.0 + 77 +1 + 4 + + 78 +1 + 79 +1 +170 +1 + 48 +1.0 +171 +1 + 6 + +172 +1 +173 +1 +174 +1 +140 +1.0 +141 +1.0 +175 +1 + 7 + +176 +1 +177 +1 +178 +1 +143 +1.0 +179 +1 + 8 + +270 +1 +271 +1 +272 +1 +145 +1.0 +146 +1.0 +273 +1 + 9 + +274 +1 +275 +1 +276 +1 + 42 +1.0 + 72 +1 + 3 + + 73 +1 + 74 +1 + 75 +1 + 94 +63 + 0 +MLINESTYLE + 5 +22 +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMlineStyle + 2 +Standard + 70 +0 + 3 + + 62 +256 + 51 +90.0 + 52 +90.0 + 71 +2 + 49 +0.5 + 62 +256 + 6 +BYLAYER + 49 +-0.5 + 62 +256 + 6 +BYLAYER + 0 +MLEADERSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +F +102 +} +330 +F +100 +AcDbMLeaderStyle +179 +2 +170 +2 +171 +1 +172 +0 + 90 +2 + 40 +0.0 + 41 +0.0 +173 +1 + 91 +-1056964608 + 92 +-2 +290 +1 + 42 +2.0 +291 +1 + 43 +8.0 + 3 +Standard + 44 +4.0 +300 + +342 +29 +174 +1 +175 +1 +176 +0 +178 +1 + 93 +-1056964608 + 45 +4.0 +292 +0 +297 +0 + 46 +4.0 + 94 +-1056964608 + 47 +1.0 + 49 +1.0 +140 +1.0 +294 +1 +141 +0.0 +177 +0 +142 +1.0 +295 +0 +296 +0 +143 +3.75 +271 +0 +272 +9 +273 +9 + 0 +DICTIONARY + 5 +2D +330 +A +100 +AcDbDictionary +281 +1 + 3 +CREATED_BY_EZDXF +350 +2E + 3 +WRITTEN_BY_EZDXF +350 +86 + 0 +DICTIONARYVAR + 5 +2E +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +DICTIONARYVAR + 5 +86 +330 +2D +100 +DictionaryVariables +280 +0 + 1 +0.0 @ 2000-01-01T00:00:00.000000+00:00 + 0 +ENDSEC + 0 +EOF diff --git a/crates/exav-viewer/demo/examples/files/converted/deck.fodp b/crates/exav-viewer/demo/examples/files/converted/deck.fodp new file mode 100644 index 0000000..27e4ca5 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/converted/deck.fodp @@ -0,0 +1,54 @@ + + +exav projectHarbour reviewA deck made for the exav demo (CC0-1.0)2000-01-01T00:00:00 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + + + +Harbour reviewThe east quay, first half of the yearexavWelcome. These notes are speaker notes: the viewer does not show them.AgendaWhere we areberths letby lengthby seasonvisitorsWhat the figures sayWhat we do nextorder the new chainpaint the numbersFour items.Berths let, month by month +Berths let by month +This yearLast yearJan2018Feb2623Mar3228Apr3833May4438Jun5043Up 40% on last yearThe chart is a native chart, with its data inside the slide.FeesLengthBerthsFeeup to 6 m1218.006 to 8 m1824.508 to 10 m1431.00over 10 m1648.00Season fee includes waterPower is meteredVisitors pay by the nightA picture and shapesiVBORw0KGgoAAAANSUhEUgAAAyAAAAHCCAIAAACYATqfAAAVJ0lEQVR42u3caZhU1YGA4VvdBSiKICCggIIIooi44RYCgnHQgOIKURCXwQ13RGcykpmJSybJmBijwhiBBh1HcYNAFKPiMuIICAjtFhZZVBZtQMEVETo/emybbmh7OdV1q+p9n/4hWF1dfe+pc7/n3EMl9u18TQQAQDh5DgEAgMACABBYAAACCwCAGktGCQcBACAkK1gAAAILAEBgAQAILAAAas4mdwCAwKxgAQAElowsYQEABGUFCwAgsKT1KwCAwIHlDiEAQFhuEQIACCwAAIEFACCwAACoOZvcAQBCB5a+AgAIyy1CAACBBQAgsAAAckoyStiFBQAQkhUsAACBBQAQbz6mAQAgMCtYAACB+SR3AIDArGABAAgsAACBBQCQU/wrQgCA0IFlkzsAQFhuEQIACCwAAIEFAJBTkgmbsAAAwgaWvgIACMstQgAAgQUAILAAAHKKT3IHAAgdWDa5AwCE5RYhAIDAAgAQWAAAOcUmdwCA0IFlkzsAQFhuEQIACCwAgHizBwsAIDArWAAAgdnkDgAQPLAUFgBA2MCSVwAAYdmDBQAgsAAA4s0mdwCA0IGlrwAAwnKLEABAYAEACCwAgJySTNiEBQAQlBUsAACBBQAgsAAAcorPwQIACB1YPskdACAstwgBAAQWAEC82YMFABCYFSwAgMCSkY9yBwAIygoWAEBg9mABAARmBQsAQGABAMRb0h53AICwrGABAAgsAACBBQCQU3xMAwBA6MCKFBYAQFBuEQIABOYWIQBAYFawAAAEFgBAvNnkDgAQOrD0FQBAWG4RAgAILACAeHOLEAAgdGDZ5A4AEJZbhAAAgblFCAAQmBUsAACBBQAQb8mEe4QAAEFZwQIAEFgAAPGWjHwQFgBA2MCSVwAAgQPLAhYAQFj2YAEABOYWIQBAYFawAAAEFgBAvPkkdwCAwKxgAQAILACAePOvCAEAArOCBQAQmE9yBwAIHVj6CgAgLLcIAQAEFgBAvLlFCAAQOrBscgcACMstQgCAwNwiBAAIzAoWAEBgVrAAAEIHlk3uAABhuUUIABCYW4QAAIFZwQIAEFgAAPGWTLhHCAAQlBUsAACBBQAQb/4VIQBAYFawAAAC80nuAAChA0tfAQCE5RYhAEBgVrAAAAKzggUAEJhN7gAAoQNLXwEAhOUWIQCAwAIAiDe3CAEAQgeWTe4AAIEDS18BAIRlDxYAgMACAIg3twgBAEIHlk3uAACBA0tfAQCEZQ8WAIDAAgCIN7cIAQBCB5ZN7gAAYblFCAAQmFuEAACBWcECAAjMChYAQOjAsskdACAstwgBAAJzixAAIDArWAAAgVnBAgAIHVg2uQMAhOUWIQBAYG4RAgAEZgULACAwK1gAAKEDyyZ3AIDAgaWvAADCsgcLAEBgAQDEm1uEAAChA8smdwCAwIGlrwAAwrIHCwBAYAEAxJtbhAAAoQPLJncAgMCBpa8AAMKyBwsAIDArWAAAgVnBAgAIzCZ3AIDQgaWvAADCcosQACAwK1gAAIFZwQIACCyZsIQFABCUFSwAAIEFABBvNrkDAARmBQsAIDCb3AEAArOCBQAQWDIRFTsKAAABWcECAAjMvyIEAAgdWJHCAgAIyi1CAIDA3CIEAAjMChYAQGBWsAAAQgeWTe4AAIEDS18BAIRlDxYAQGBWsAAAArOCBQAQmE3uAAChA0tfAQCE5RYhAEBgVrAAAAKzggUAEFgyYQkLACBsYDkEANS9ggeGVf6Ai4aOdZTI4MCygAVA3Rj/Q1G1swK7WGyRcYHlEAAQq7Sq5NuVFhkTWFawAEiRcbXrqp2V1j/KLOIfWD7JHYCU1NXEYal65pLMukBmEePA0lcAhDU2ZWlVMeCGySxiyedgAZB5dZWuHwdVZAULgDDuT1PrjJ047BLrWMSMFSwAMriu4vDToaJklCh2FACoVd9MuCQOhXfJhfc7F8QlsNwiBKA2/hSDuirtvEs1FvHgFiGQMWa8ucBBUFeZ9XrIWVawgNh5fuchVa6xftL1MIeLio11mXUs0i1x6TkjHAVScYF05aPGFVVjRl0duy/Gy0Uai/RKJixhEdRzhQvKXj5POtQFz5BYUGc/q1y0GX4p9V8Fsb4Z5+pGmkfgZQOtYJHyS6nrnJCKA+MwpwIriqLLL7q/ikPX2CA4e7AI49lKL66ll95/MItl9YnOrAQ0GmtjTEEG7CVPVHkwlx0bBgZhht/lVrCo84uu+UtIxZBhmX2BFUXRFTtaxKr68DYqqDErWNTKX2t0GS6Z3fqaubLonGZfUxqflRhdkDEfhZCo3dguOyoMCao39q4YZAWLml6JFwa4EvftZs7KqhOarQzU7QJrfCZ91lSHI680GEhDYA2PZWA9s3DByUZwjD0T+krsdGfZCc16uTxi782cugqeVkYCmR1YLt45ezF2pqSV3hJYGdFVhgE/HFhXxiywpsd7uj8lt98/dXZ2TjFP5fx7LUPlwtC9J8aBla60MokR98DKlBk/B985aTk1ZihppbTUVWZ1lamM7wPrqp/FJbCeXpBhk/5PD8uV90x6T03uHGdvsayUZQP47nExCqyYd5UJTWDFIrAyeurP4jdMfM6LWUlaKS2BldFpZU7LucC6OgaB9VRWzP79su7dEsPz0s+UlJNvriyT0cP4j2kNrCzoKjObwHIByOn3ScxPislIWpkuciqwsrWrzG9ZHljXpDWw/pKl14D+mfwOyaCT0t9MlEtvqyyWKSP5rjqvq5xKK1NcbSa9GB6rxDXnXp+2I/LGwix/bxzeLcPGaGaekYw7zs4gGTqY7xp7qa4yPGI718Xt+CSuTVNgTcuZK8GpmfCWyILTcWpuTz3TpJVJI/X+kPrAklZmvNrMcrE6LOkJrNy8GMT2/ZBNp8Okg0kjEwNLV5n6Qk1u8TkUievqPLCm5vb14LQ4vQ2y9VyclhuZNVVamTfq1p2hA0tXmQBTNK3F4SAIrNx9A2T9icjizPImMnVkemBJKzNhqmeztP/iievPq9PA+vN8F4bvDTgiPac/185Cuo6zc0eWjerf31/bwNJVJsO6nMfS+/vWaWC5NsRhBOTsWcj0zPL2IQ4Du5LGEk8GTwynrzTO/IkRdRVYU1weKnV66geBU1A3x9lZI8vGtkFo/GT0sEnXtF9HgeX9mfah4BRkXH45ZdTBMDbMCDUZxnkspWVuT9yQ+sCa7A1cfWeEGw2OfwxPilMGZMHUl0GT1Rl13liJGwanNrAmz3OpqMWAOLKbg58jJ8spA4j/LF2NwBqZysB60tUihDNrNCYc/Mw6ic4XQGwvqfEKLBeMdI0JRx4A0ttYeYkoSsWXa3wqgvXJeQsdeQCo5fU0RfGz3deNKVjBesI1PvXOqhDgDjsA1PgyGlZeIhGF/XKZrxtPzFv4xLyFDjsA1OwyGjyBtvu6ach1AV/u43MLnTMAICOcfdShKXrmkHuw1BUAkEEen1uYoj1YeaFe4mPqCgDINI/NLUxFw4RZwVJXAEBGZ1boFaxaP8ej6goAyHCPzi0MWFi1XcF69HV1BQBkRWO9XhiLPViT1BUAkEVCtU3NV7DUFQCQlY2VthWsR9QVAJClat85yUSi2t/z8Bx1BQBkf2Ode3QNP4m02itY6goAyBE1zp7q7cFSVwBArjVWavdg/Y+6AgByTw0SqKorWOoKAMjlxqruJ7kXV+kLACCHPTSnsKrVlCiu0grWQ7PfdFgBgFxvrNlvBtuD9d/qCgCgOl2UrPxjsB5UVwAAFRrr/GO6VvKYPHUFAFBdlWdSXiIR7fBLXQEAVN5YO+uoHW9yf2CWugIA+AEPzHqzqpvcJ6orAICq2WE4lV/BUlcAANVtrMpWsCaoKwCA6isXUcnEd5/TUPCaugIAqFVjXXRc16h0BUtdAQDUXklT5SXUFQBA0MZKtDl2iAMBABBQnkMAACCwAAAEFgCAwAIAQGABAAgsAACBBQCAwAIAEFgAAAILAACBBQAgsAAABBYAgMACAEBgAQAILAAAgQUAgMACABBYAAACCwAAgQUAILAAAAQWAAACCwBAYAEACCwAAIEFAIDAAgAQWAAAAgsAAIEFACCwAAAEFgAAAgsAQGABAAgsAAAEFgCAwAIAEFgAAAILAACBBQAgsAAABBYAAAILAEBgAQAILAAABBYAgMACABBYAAAILAAAgQUAILAAAAQWAAACCwBAYAEACCwAAAQWAIDAAgAQWAAACCwAAIEFACCwAAAEFgAAAgsAQGABAAgsAAAEFgCAwAIAEFgAAAgsAACBBQAgsAAAEFgAAAILAEBgAQAILAAABBYAgMACABBYAAAILAAAgQUAILAAABBYAAACCwBAYAEAILAAAAQWAIDAAgAQWAAACCwAAIEFACCwAAAQWAAAAgsAQGABACCwAAAEFgCAwAIAQGABAAgsAACBBQAgsAAAEFgAAAILAEBgAQAgsAAABBYAgMACAEBgAQAILAAAgQUAILAAABBYAAACCwBAYAEAILAAAAQWAIDAAgBAYAEACCwAAIEFAIDAAgAQWAAAAgsAQGABACCwAAAEFgCAwAIAQGABAAgsAACBBQCAwAIAEFgAAAILAACBBQAgsAAAsjCwOrdv+cefn/VywdVvTf7nZ++7YvigHsnk/z/Domk3jx51Tsl/T7rjwmFnHVfJ84wedc6iaTcH/2V+8OcCAMQrsHoddcCTd16czM/75ZhnLr/l0RdfX3LVeT1vvapfxUfWr5dfP5lf979MtX5uiiIPACBZ9YfeeGGflWs+uer2x7cVF0dRNPONZV9v/vbygT+aNH3+gkWryj7yzOvGFRen4ZdJ188FAKhhYO27954LF6/eViZhJr9Q2Ll9y5bNGpV75N+m3jxj9uLhtz1W8sddd6k3fFCPfj27NG+y24cfffrw9PnlHl/ygP49u7Ro2mjt+k1PPL/wvkdf3bqtfCstmnbzjNmLH/rL3GuG9Oq0315btmyd+cbyOybMWF20acc/t0G9Kwb16N+rS/Mmu636eOPUF98cP2X25m++LXmq0ueMoujAU28vff7Sb4+iaPSoc048plPZ/ztz/rLrzz+h4M+zRz8ys+qvHAAQWDu29P2iIzq3Oa5bu9cWrij5mxWrNlx2y6TKv2uX+skHfzWk034txkyaWbh49UH7t7x2cK8vvtpc+oB6yfyCWwe3adF49KSZy1etP+zA1pcP6tGq2R7/eu/TFZ+tbcsmv7/pjIIps//w4Esd2ja/bsgJRxzcZsA1Yzd+9lW5R9avl19w63md9295z8OvvL10zeGd21x57o87t2957W+ejKJo0MgJIy/s0/2QfQeNnFD1I3BA2+bdOu1zzyOvvDRnSXVfOQAgsHbg9vufG/fLcyfcNvj1t95/ed7Sl+e+t3jFxz/4XRcMOLprx32u/c2Tz8x8N4qiVxcsf2vp2om3D/7+Aad1P7Tj3gOuHbtkZVEURa8tXLFl67aRF/QZP2XWilUbyj1bp3YtLhz1UEnhvbZwxbpPv7jrn8687Jzjfzt+RsWfe/hBbYbf9tiM2YtLHhwlomsH9+o2pfXCRasWLFq16Yuvoygqd3Ozcm333vPsEQVvL11Tg1cOAOSOamxyn/fOB30vH1MwZXar5nuMvKDPtLsveex3F3XtuE/l33VKj4PXrtv011ffLf2bWYUrln24vvSP/XsdUrhkzbIP1+fn55V8vThnSSIRHdu1XcVnW7FqQ+n6WRRFz776t6INn594dKeKj+zfs8vqjzeW1FWJR6bP/+34Gd9+u7XGB2vJyqLSuqruKwcAckeyWo/+aP1nvx73/K/HPd9x370G9O469LTuD/7HkLOuH//eB+t29i3tWjctXLS63N7zD9Z+sn+bZiX/3b5Ns13qJ9+Z8vNy39i0ccOKz/b+2k/K/nFbcfHy1RsOO7B1xUe2b91s/rsflv2bDRu/HDd5VrV+30QiUfaPq4s2bvcjqvPKAQCB9QOWvF90x8QXFq346I6Rp//s5MNvv/+5nf6A/LztKyWKoqhB/e9/bl4iMe+dD341tvwzrF33WcVnK674rwSLi7du3VbxkXl5ifz8an+MarlX2qhhg+16bvvd69V65QBA7qhqggw6+fAn77y4S4dWZf/yhTlLoijaq2mjSr5xddGmdq2blmusfVvtWfrfa4o2Ntyl/ltL1pR+ff7l5t7dO+62a/2Kz9amZZPteigR7bdP0+Wr11d85JqiTW1bbffgJo127d29Y8V/81hq67bihtv/0P3bNqvkV6vWKwcABFZ5i1cWdTlg72sG9yq7HlXSW5VvdX9xzuIWTRv1KbNNqnf3jvu0aFz6x5fnLu3cvuUBbZuX/s2FA465YuCPPtn0ZcVn69C2+dFd9yv94yk9Dm7ZrNH0V96t+MiZbyzbu/kevY46oPRvLjn7+DG/GJj8blmrZDGs9JPooyj6eMNnnfZrUe+7jyrtccT+zRrvVsmvVq1XDgDkjvw92hxalcetXbep+Z67n9qrS/cu+27e8m3TJg37Ht951GV9167bNOqep77ZsnX4oB5bt257dcHyjZ9/ffV5PZevWv/U/74TRdE77609tdchp/Q46POvvtl91wb9eh58wwV9Plj7SbMmu93z8CtRFL277KP+vbqceVK3L77a3Hj3Xc/v331wv6PufPCl/1uwvNxruPq8nmvXbTq9T9dtW4sb7lKvX88uPx920ttL1/zb6OkldwnL/txFKz4e0LvrT3988NebtzTctf7AvocPO+vYB6bOefq7Gjv+sPZdOrTasmVrfn7eqo82RlHUZI+GPY/scGD7Fp9u+urIg9uOurTvqo83Nv/udZZ98hJVf+UAQE6pxh6sfx89/ZV57w09rfu/DDtp990afPjRpw89NW/85FlffPVNFEWTXyg87YSuY34xsN/w+8p+14aNX55708QbLzpxxNATkvl5i1cWjfjPyeef2r1TuxYlD1j36ReDRk4YMbT3iKG9G9RPvvf+uht/N2Xay2/v8DW8/d7aWYUrh/Q7cp8WjYs2fD5x6pzRj8ws+ezQikU4cGTBiKG9rz6vZ716+StXb7hlzDOTnnmj9AETp8457MDWV53b8+tvthw56I4oiu5+6OXibcVn/OTQe0eds+zD9bf/6dkBfboe+N3rrKharxwAyB2JNscOyZTXWvGT1gEAYijPIQAAEFgAAAILACCXZNIeLACAjGAFCwBAYAEACCwAAIEFAIDAAgAQWAAAAgsAgCr5O4kk04EqXgwyAAAAAElFTkSuQmCCA lake at duskStartMoorPay?StarShapes with gradients, arrows and text. + + + diff --git a/crates/exav-viewer/demo/examples/files/converted/deck.odp b/crates/exav-viewer/demo/examples/files/converted/deck.odp new file mode 100644 index 0000000..2fdb16b Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/converted/deck.odp differ diff --git a/crates/exav-viewer/demo/examples/files/converted/deck.ppt b/crates/exav-viewer/demo/examples/files/converted/deck.ppt new file mode 100644 index 0000000..f3f914c Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/converted/deck.ppt differ diff --git a/crates/exav-viewer/demo/examples/files/converted/diagram.fodg b/crates/exav-viewer/demo/examples/files/converted/diagram.fodg new file mode 100644 index 0000000..5dad6ee --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/converted/diagram.fodg @@ -0,0 +1,28 @@ + + +exav projectFlowchartA drawing made for the exav demo (CC0-1.0)2000-01-01T00:00:00 + + + + + + + + + + + + + + + + + + + + + + + +Boat calls the officeIs a berth free?Give berth numberOffer the waiting listBoat moorsPay at the officeBoat waits at anchoryesnostart or endstepdecisionFlowchart for the exav demo (CC0-1.0). Connectors follow their shapes.Harbour office1Berth register2Billing3Layer 1Layer 2Layer 3Layer 4On a hidden layer + diff --git a/crates/exav-viewer/demo/examples/files/converted/diagram.odg b/crates/exav-viewer/demo/examples/files/converted/diagram.odg new file mode 100644 index 0000000..aefe219 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/converted/diagram.odg differ diff --git a/crates/exav-viewer/demo/examples/files/converted/handbook.doc b/crates/exav-viewer/demo/examples/files/converted/handbook.doc new file mode 100644 index 0000000..b5ead74 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/converted/handbook.doc differ diff --git a/crates/exav-viewer/demo/examples/files/converted/handbook.fodt b/crates/exav-viewer/demo/examples/files/converted/handbook.fodt new file mode 100644 index 0000000..f54b1c3 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/converted/handbook.fodt @@ -0,0 +1,99 @@ + + +exav projectHarbour handbookA document made for the exav demo (CC0-1.0)demoen-US2000-01-01T00:00:00 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// + + + + + + + + + + + + + + + + + + +Harbour handbookexav demoPage 1 of 1 +Harbour handbook (landscape section)Page 1 + + + +exav2000-01-01T00:00:00 +exav2000-01-01T00:00:00some deleted words + +Harbour handbookThe east quay: rules, figures and notesexav project, written for the demo (CC0-1.0)1 January 2000ContentsContents1. Introduction2. Text and styles3. Lists4. Tables5. Pictures and shapes6. Links, fields and notes7. Wide table (landscape)IntroductionThe east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell.Every berth has a number, a length in metres and a holder. The register is kept on paper and in a table; the two are compared each spring, and the differences are explained in the notes of the harbour master. 1The register of 2000 lists sixty berths.“A harbour is a promise that the sea will wait.â€� Visitors are asked to call the harbour office on channel 9 before they come in, to give the length of their boat and its draught, and to say how many nights they plan to stay.Text and stylesCharacter formattingBold, italic, underlined, struck through, red, highlighted, small capitals, large and monospaced text; H2O and 103; a mixed style.Paragraph formattingThe east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell. Every berth has a number, a length in metres and a holder. The register is kept on paper and in a table; the two are compared each spring, and the differences are explained in the notes of the harbour master.A centred lineA line aligned to the rightAn indented paragraph with a left border: Visitors are asked to call the harbour office on channel 9 before they come in, to give the length of their boat and its draught, and to say how many nights they plan to stay.moor --boat Aurora --length 6.5berth 14 free until 06:00A section in two columnsThe east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell. Every berth has a number, a length in metres and a holder. The register is kept on paper and in a table; the two are compared each spring, and the differences are explained in the notes of the harbour master. Visitors are asked to call the harbour office on channel 9 before they come in, to give the length of their boat and its draught, and to say how many nights they plan to stay. The east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell.ListsWater at every berthcold, from the quayhot, in the shower blockElectricity16 A at berths 1 to 40with a meterwithout a meter32 A at the east pontoonWi-Fi on the quayNumbered, with other numbering styles at each level:Call the office on channel 9Give the length and the draughtlength over all, in metresdraught, in metresTake the berth you are giventie up bow firsttie up stern firstPay at the officeTablesTable 1: berths by length, with merged cells and a repeated header rowLengthBerthsLet byFee (EUR)up to 6 m12week18.006 to 8 m18season24.508 to 10 m14season31.0010 to 12 m9year42.00over 12 m7year58.50Total60Merged across two columnsMerged down two rowsabcdePictures and shapesiVBORw0KGgoAAAANSUhEUgAAAoAAAAFoCAIAAABIUN0GAAAUj0lEQVR42u3dd5wU5f0H8FnuDjiUoiCggIooYKGJBUHBGoxCCETBgiUKGhsgQQ3RmPxiTHsZEyNiB2yxRelojIgKiUIUKaJBpBg9pB16KAoi3O+PhfPou8fu7O7N+/26P7hjbnbmu/M8H77z7C6xA1sOCACAcFVRAgAQwAAggAGA9MgPYooAADpgABDAAIAABoBKwhowAOiAASAqHbAWGADCD2DxCwCZ6IAlMACEzhowAAhgABDAAECaWAMGgEwEsPwFgPC5BQ0AAhgAoiE/iLkJDQA6YACIQges/wUAHTAARKMD9j5gANABA4AABgDSw4uwACATAWwNGADC5xY0AAhgAIiG/Jh70AAQfgDLXwAIn1vQACCAASAavA8YADIRwNaAASB8bkEDgAAGgGiwBgwAmQhga8AAED63oAEgEx2wBhgAdMAAEI0OOIjpgQFABwwAUeiA9b8AoAMGgGh0wN4HDAAZCGD5CwDhcwsaAAQwAERDvrcBA4AOGAAEMAAggAGg0rAGDAA6YAAQwABAmvgkLADIRAD7/4ABQAcMAJFgDRgABDAARIP3AQOADhgABDAAkCZeBQ0AmQjgQAIDQOjcggaATHTAGmAA0AEDQDQ6YGvAAJCBAJa/ABA+t6ABQAcMABEJYGvAABA+t6ABIBMdsAYYAHTAABCRDlgLDAA6YACIRAcceBk0AIQfwOIXADLRAUtgANABA0AUeBEWAAhgAIgG7wMGAB0wAESlA1YDANABA0AkOmDvAwaADASw/AWA8LkFDQA6YACISABbAwYAHTAARII1YAAQwAAQDT4LGgB0wAAQlQ5YDQBABwwA0eiAtcAAoAMGgGh0wGoAADpgAIhGB6wFBgAdMAAIYAAgLbwICwAyEcD+P2AA0AEDQCRYAwYAHTAARCSArQEDgA4YACLBGjAA6IABICIBbA0YAHTAABAJ1oABQAcMABEJYGvAAKADBoBIsAYMADpgAIhIAFsDBgAdMABEgjVgANABA0BEAtgaMADogAEgEqwBA4AOGAAiEsDWgAFABwwAkWANGAB0wAAQkQC2BgwAOmAAiARrwACgAwaAiASwNWAA0AEDQCRYAwYAHTAARCSArQEDgA4YAAQwAJAeXoQFABnpgLXAAKADBoBodMBqAAA6YACIRgesBQYAHTAARKMDDkpVAQB0wAAQhQ7YGjAAZCCA1QAAQucWNADogAEgIgHs/wMGAB0wAESCNWAA0AEDQFQCWAIDQOjcggaAjHTAagAAOmAAiEYHrAUGgPADWAkAEjHy0X673ebHFz+kUCTcAasBwM6NSCB3tw/pyyQxAhigAh5OJnd3FtuXi2F2EcA+Cxpg2/R9pF9q9hOP4UvEMDpggF16KEXRu02c95PBbMfbkADSmL5le07fztEBA+SwB9MfkA890q+/VpjvAjhWqgpATpg8d9ZprdqmY88PjOofWsxfcemDnkoCt6CBXIneyXNnxf+Qu+mbkYcja8WuOHewKgBZ6+WdJO7pKWqF789QHF6pD9YBKwGQtdH78s773ZdT0Qrfrxklc3wWNJB1/jknoXCNZ/AZrdvm4jneP6r/T36sCdYBkzUTCkR8mMS/whlc943McPub8QMg0x2wGqTfS3NmxaeJ7+XmP9UhnDGyh//ATWp83Zsd4WcGjrLYVb29CCuN/rGjaaWrGIZdjpEKS3xwDc+a7vNqN6Ij2wH7B1gaZ5bZs3Y243RtI4MxQGalfp9zZgVBsNvxNXxENt37NQlHNoA99enw4u5mlvjUc6YYxgBJT7Tn0OAyCUdW7Jo+bkGn2AvJTC7fl8EYHWmzs/E1bER2vfrp2svchc7wZZmRqdiroDM8v4Q8H1XWeZacuCTCvyp2+IjZlr7GbzZclhk5Ze8DTplJs2btybV+Vtu2lawOu76gK835kr6hkcIsyfLrLePz8PbPUSWblxI85ZDPN3bteW5BZ8sUUwmu9VRNteLZuEi5sovq7oezsQO+7vIHs/mpqXwdQjacqRdhpcDEFM0yk2bNOjtnr/KJKZ1qdz1IzhbP5cqendWYmE3RW/6iytqLJ5bdz0iWVy+FFQhzHo4N0AHvgQnpmWW65dRVPiHLptpuEYjnRGqekTpMyL7c3d7Ct+/JwqMamOoOOH3PRc4NsQqUIpxzjA04/3o5WsEn9Z3ZaUyRdm0iXoGI1DD8mqepLFl+MWR/DA/s90DOPQXZP8T2pCYhnF1soABO3viwLvTuWXx9j8+dCbd77idxCNWucJXG51r0ZmcGD0o+gLOk8lk4vlJVmXSfWsYCePw7s3N0Wgz5oq/EF7eZIidKvYui5e6VkIUxnEgAZ3PBs2RwpbxEaT2v2KBMBPC4cjX6QU7NieMyMQCyp0TjKsWEmxOXXOUotQxO3PU7CuBcvAwyNb7SV6v0nVHs+gvCDuCxM3dcph5HZ/W0uLPDDk1m65Px0698JY1OncVwIgb3f6AyXQBhDq4Qipam0wk1gBMpU3bGcJaMikwVp9KnQsavOrkb2Qxu1v4agysnBk46TiQ2OKwAHpNkpX6YNUk8Jpsmx5DLMiZiwRD+VTdG9EYshit94oYwsjI1alI+P8R+GkoAj65ovXpmNIZHZ+vkGEJZRkc7GNJd4dFyNzIZHM3ETdOwyvjASe3MEPvphWkP4NFvp6BkPduHncQpOew0XgdpK0iWn3hO11ltoxDDEjcdwyp7xk4K54TYkHQG8POpLlmvUGL4+dyZJVNekOclRHpKrbCVOIMlblrHVBaOnVRNvGkM4LRWLX1JnHMTZapKISHSUW1VrZQxLHFDGFNZPnZSMvHGbkhPAD8XSu1+lOoYfi43p8s9rMNzQiLVNVdSqPCYypXhs+cBFLuxb+oD+O9vhV2+c45pk3PHnA1FqARnnW1lV1KI7PCvQAAPSmn0zsloLVrn4mFnqgKV5qwBci53giCI3ZS6AH42ayb0c5OpyLOVK4cSOfdnRS9AJhJnqwD+WYoC+Jnsm9N7764oz1TeHNrZuT8jegFCj5udBPBFKQjgZ/6T1dN672Nb59wxp/ysK/35AmRb0OwmgIfuWQA/nTvTep8t1Xk6SlEUP+unpS9AWCmTaAD/fA8C+CnTOgBscV4yGVxF+gJASiSVjFVisaACX9IXAHaYwQkmadId8JMz5jw5Q/oCwE6DMrEOOAgS/xK9AJBIBu82UpMI4L9JXwBIzN92l8FVglhpIl9PSF8ASMYTM+bsIljzY7v7/cenz1VEAKhIBk+f2/f4Vjv8q93cgpa+ALAnHp8+dye3oHfuMekLAHtsh3m60/cBS18ASGEGb5OzO1gDfuRN0QsAKfbom3Mv6fDdenAV6QsA4Sgfslu9CEv6AkC6M3jLB3FsuRk9SvoCQPqNenNuLBbkB0Ew8g3RCwDhGfnG3FjjDn0VAgBCVkUJAEAAA4AABgAEMAAIYABAAAOAAAYABDAACGAAQAADgAAGAAEMAAhgABDAAIAABgABDAAIYAAQwACAAAYAAQwAAhgAEMAAIIABAAEMAAIYABDAACCAAQABDAACGAAEMAAggAFAAAMAAhgABDAAIIABQAADAAIYAAQwAAhgAEAAA4AABgAEMAAIYABAAAOAAAYABDAACGAAEMAAgAAGAAEMAAhgABDAAIAABgABDAAIYAAQwAAggAEAAQwAAhgAEMAAIIABAAEMAAIYABDAACCAAUAAAwACGAAEMAAggAFAAAMAAhgABDAAIIABQAADgAAGAAQwAAhgAEAAA4AABgAEMAAIYABAAAOAAAYAAQwACGAAEMAAgAAGAAEMAAhgABDAAIAABgABDAAIYAAQwAAggAEAAQwAAhgAEMAAIIABAAEMAAIYABDAACCAAUAAAwBplFercWtVSIn5428+olnDia+/l9rdPn3HpXVqFs58/xMVBtABE56qBXlV8/MS3Hj4LefOH3+zogFkv3wlyHK9Bj1cWqoMABEO4MLqBVf3ObFb5yPr71tzWfGa516eff8z/9q4qfTOG3qe2allz0EPz1+yIr7lX3/W66T2zbpf++Anyz8PguDA/fcZfPEpxxzRZO+9qn20dPWosTNGT54TBMHouy6vW3uvLj/+a/mAueumXh3bNu140V82fLsxrY8eBMH88TdPnv7B/CUr+pzZrrBawSszFvzi7kkd2za94dJTG+5X64MlK341/IV5C5eV3/iJCW8N6Nul+UH7bdiwcdo7i+8YNXnpyjVJlWubzXa72/+Ou3ny9A+u/s2zm3dbreCqPid263JkvTp7Fa0oGTdl7ogx09d/8218V2X7DIKgRffby/Zf9uvxLvm045uX/9tpMxddf9HJI8dOH/7UtMSPHIAwArggP2/kbRc2rl97+NPTFhcVt23R6Cd9TmxYt9at90z69X0vHt/6oP+75qzzbxxVWhp0bt+sa6fDb71nUjz/9qlV4/HfXbTmy3W/vv8fa79a37f7sb8f1H3lZ19Om7lo7CvvDu13etuWjd/ZssBZrWp+l2MOHffqu9ukbzoePb7now7dv7BawU1/Ht+h9cH9enWoXjX/sIPq3/nolOpV82+5out9t/Y++bJhGzduim/cpEGdO2/sOXLM9L889mqzJvUG9T356CMa9xjwUMkXXyderu1rm/huqxbkjbztgpaHNBj25NR5H37armXja84/qWXTBgP/8HwQBH2GjBpy6anHHnVgnyGjEr8CDm1Sr03zA4Y9NfXVGQuSPXIA0h7Al/zg2NaH7d9j4EMLPloZBMEbs5ds2LhpyCWnjhjz5pKi1b8a/sKwn5/Tu2u7sa/MvfUnZ059e+HTL74T/8WzTjqiQd2a19z+97kLlgZB8P7i5W88fv0ZJ7SYNnPRhNfn3XjZaWd2alkWwCcd3aywesHYKXNDePT4Bvvtu3fPgQ8Xl6yd+vbC049vfnqHFrfcPfHFae8HQXBok/36n3PCUYfuP3t+UXzj5gfXv/SWJ96YvSR+DKs+X3vXTb2uPLfjH0dMTuqAt9k4id32OK7d4Y2v/s2zk6d/EN84iAUDL+zSZkyj2fOLZs0vWrN2XRAEs7YccCKa7L/POYNHzvvw0wocOQAVluiLsLp1OWrOgk8XfVKcl1cl/jVlxoJYLOjQ6uAgCP75xvwJr88bcsmpQ/ufUXvv6j//68SyX5zynwV9howqm98/W/NVvDENgmDVZ1/++51FXTsdHott3rhrx5ZFK0pmvv9xCI8et+CjlcUla+N//njZZ5tTLQiCIIj30PuW23hJ0eqyvw2C4KV//Xfl6i9PO655suXaRhK77Xzk0hUl8fSNe+qFmX8cMfnbrW8YJGXBRyvL6pPskQOQ9g64aeO61avmvzdm6DY/37f25ny67b5/TBx+5XlnHn3DnWNXrP6ibIOlK0oa1K15+8BuRzVrWG+fvatXyw+CID9vc/CPffXdO37ao3XzRrPnFxXk551y3GGPTfjP9q85StOjB0Gw6vO1ZX+O3/cu3vKT+LdVqsTKNvjfss/KP/qm0tLFS1e3bdGoAuUqL4ndNqq7zfuRVpd89fDoN5N6ymOxWPlvl64sqfCRA5D2AK4Si7393se/feif2/x82arNaVejsGphtYIgCBrWrVV+gx+d3ub2Ad1ee+vDPz/+WrzFnDDsirK/ffmN+V+t++bMTofPnl90QpuDa+5VbdyUd0N79CAI1q3fUPbneO5/veUnpaWl28RV6fb/NCgtLVshTuqAt95HwrutEsvLS/qdY7Gtv61Zo9pWeb/1q6uSOnIA0h7An64sqVG96rsLvrtXeXCjfbt3OWrcq++u+iyIxYLfDuj2yfLPp85cdN0FnSdP/2Dhx6vim117/kkLP1l11W3PbCotDYJgr8Kq5Xf79foNL/17ftdOLf8w4uWunVq+u+DTxUXFoT16sho3qLN1KxkcdMC+i5cmfcB7sNs1TRputXGdmoXtWjZ+b9Gy5cU7DsiNm0prbH3WhzSpW+EnGoBUSbSdeu2tD1s2bXBok3plP7m0x/FX9e4UX1W94KxjOrQ++Jf3TLr7ideWF3/xu4Hd8rbcua1Tq3D152s3bWnyTmjTdJu2cuyUuY3q127botFpxzff/uVX6X70pDRrUu+4VgeVffv9E49oULfmC1PfT/aAK7zbae8s2r9erS7HHFr2k/7ndLz3F73LbqrHm+n8/O+e1hWrv2h+UP2CLR/lceLRh9StvVeFn2gAUiXRj6J8f9Hybl2O7HVGm7Vfr6+9d+FF3Y698Oxj/vzYq/+etfjA/fcZNvSc5yfPefKFmd9u3LSoqPiKczp+te6b+Gplq8MOOPHoQ9Z/820sFuvcvtmV53bcu7BayRfrnn95dnzPRctLzv1e23aHN27ScJ+hd034utw94XQ/+nUXdF5cVFz24ZFndz7ykMZ1hz05Nf7t4Yc0OL1Di0lT31v0SXF842Wr1vzw1FabNpbWqF5wducjh/Y7Y96Hn/5y+Avx28VX9zlx48ZN/5q1uOTLdbs44G1Obbe7LX+Q85es6HFKq7NOOmLd+g01Cqv27tqu3486PDpuxqQtad2xbdMjmzXcsGFjXl6VouUlQRDUqVWjc/tmLZrW/3zN1+2PaHLLFV2LVpTUq7NX/DS3qcCuS220AKRQoregV32+ts+QUYMvPmXwxadUq5q/8H+rbvjTmPGvzasSi/1+UPev1n9zxyOvbO7SZi6aNPW9ARd2mTx9weKi4lvunvjFV+sv79mh8LyCRUXFfxo1ZWj/M/apVVi2502lpeNfm9evV4fX315Y9oLk0B49KfMWLntzzkd9z25/QP3aK1d/+ci4GcOfmhb/EIwgCEa/MucHJ7e69xe9z776/p0dcAV2W96yVWt6Dxk5+OJTrrugc0FB3kdLV//63hfL3nMVBMEj42a0bdHo2vM7r/tmQ/s+dwRBcPcTr5VuKu15eut7bjl30SfFtz/wUo9TW7U4uH6yT7ShApBascYd+qpCIrb/SKls3i0AWc5/xgAAAhgABDAAkCbWgAFABwwAAhgAEMAAIIABAAEMAAIYABDAAJB9/h/jQKerSTk5XAAAAABJRU5ErkJggg==A lake at duskA made-up picture of a lake and a hill at dusk.The east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell. Every berth has a number, a length in metres and a holder. The register is kept on paper and in a table; the two are compared each spring, and the differences are explained in the notes of the harbour master. Visitors are asked to call the harbour office on channel 9 before they come in, to give the length of their boat and its draught, and to say how many nights they plan to stay. The east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell. Figure 1: a picture that text flows aroundiVBORw0KGgoAAAANSUhEUgAAAeAAAAEOCAIAAADe+FMwAAARDUlEQVR42u3de1zUZb7A8We4KZhCgKACKqBEEiAqZsVC0rZaqFQaqKBYaamZlmvbafOcfW3mXm3dzpq+SgXMOqmlkVrqmrcVV/HGxdS4iKByURCDvKQIc/741exwG2ZgLs8Mn/eLPwQG/P2emfnw9WFmVPUPni8AAPKxYwkAgEADAAzgIFQsAgAwQQMACDQAWDu2OABA2kBTaACQM9DkGQBknaApNABIiV8SAgCBBgAYgi0OAJA10PQZAOTEFgcAyDpBCxUzNAAwQQMA9J+gmZ8BQNJA8ygOAJATWxwAIOsEzQANAJIGmi0OAJATWxwAIOsEzQANAJIGmieqAICc2OIAAFknaOZnAJA00DyKAwDkxBYHAMg6QTNAA4CkgWaLAwDkxBYHAMg6QTNAA4CkgeaJKgAgJ7Y4AEDWCZr5GQAkDTSP4gAAJmgAgAHYgwYAaSdoRmgAYIIGABBoALB6bHEAABM0AMCwCZo1AAA5A81rcQAAEzQAwADsQQOAtBM0IzQAMEEDAAyZoFkDAJAz0LzcKADIiS0OAJB1gmaABgBJA80WBwAwQQMADMAeNABIO0EzQgOApIFmDQBASmxxAIC0EzQjNAAwQQMADJmgeSA0AMgZaPoMANJO0AAAGbEHDQDSTtCM0ADABA0AMGSCZg0AQM5A8ygOAGCCBgAQaACwgUCzxQEATNAAAAPwMDsAkHaCZoQGAEkDzRoAgJTY4gAAaSdoRmgAYIIGABgyQbMGACBpoCk0AEiJLQ4AkHaCZg0AQM5A81ocAMAEDQAg0ABgA4FmiwMAmKABAAQaAGwg0GxxAAATNACAQAOADQSaLQ4AYIIGABiAF0sCAGknaEZoAJA00KwBAEiJLQ4AkHaCZoQGAEkDzRoAAIEGABgQaJ6oAgBM0AAAAg0ANhBotjgAgAkaAECgAcAGAs0WBwAwQQMACDQA2EKgKTQASIlXswMAaSdo1gAAJA00hQYAKbHFAQDSTtCsAQBIGmgKDQBM0AAAAwIthJpVAAApJ2hGaACQNNCsAQAQaACAAYHm5UYBgAkaAECgAcAWAk2hAUBKvBYHAEg7QbMGACBpoCk0ADBBAzCn1I9m6r7A89PXsEpSB5olALpgmptdjFLLOkEzQgM2ZO26mR34KqXUL6SQadkCzRoANmFNh9LcLO4zaTSBBmBcqztdZ03lZ9FoiQKt4vWgAev2Yfos47b+xRmrWVUZ8EQVgDqb43uiI4FWCcGbGd72nMphEXgz+pvpSvph+iyW1+JvPIrDHHbn5QghvjmVI4R4PGwoCwKr8EH6rNnPsddhSfyS0OT+mZfTMta/ItMmW+2us7ar0ky+EUEfLEs1J2Ehq2Aiu5qmuaUxZNpkq90V1nZlmjl2iucyRFtwguZHpKl6kZujf1PGhFNqIy/1rrwc217Vlanm+j0eibDgBD03kQna+HbqUeeWxpJpEyy1ra7q+6nme6DFy88zRFtoguano9Ht6FCdNa15gkwbdZ135uawpMzQVhto1t54vs7J6fw3Ubrz5FCaYrR1tr0l/cdasz5OmUowQVu9r4xR52YNirNoU77KyYmTLGqdWeSv5TsdJmi0s/KvTGYPWro6N2O2rOg4CxnSZqxFtoFM/+9acz/Tb/4Lq812LfNzVGuC5rU4Om17dq4ZwjQuItyCR266YzD/Clv2XKx1lGsaCpPe5jU/ibmOrG+LY1t2rhBivBzX3DYTp7nVu0Rnzr2TB2yUY5Bkhbdn546n0foH2mpv89a97K9Oec2KDndr0xvHBItebVvNeEttSc9zN/VBmu4qMNvyTrD0nX9rdq6hx7B8zYtmPsjA4S/LUIAJXazUqtemyh7oL0+2f0eNHxYu4VGZQcsTt9SBGfcqMPNZmP/209Y56nkkf1ttvkBLkmYZrjILBHqh3IHOMOSO+pS5rrMMOeosoc5fBRZcWzPcfvQ/O90H867pAy1nly14ryfQxrmLmvQKI82muxYkWVtT3H46c2qtHo9JA20tae4KpVb9OkmuQH9xwmj30qeHh0t7bF2HPteCbAtrrFuOcc+r2VEt+9DIjbbSLpvhjm/JQC+SINBbTHn/fMZI19YW6myaK0Lahe3YLccMp6Mc2F+NF2ibSbOJ7vuWDPTrlg70ZrPcPyd27qraTJ1NcEXIv6r632wsci7nTrxPl81w97dkoH+TbIFAf37cMvfMSSPCreVQIQ8dNxtJbh6GlrrrpLnzBbBwoN9IftXMf+Vnx/MsftrPjgizlkOFDLRvMDLfKnSXust2ufMpsFig/8ssgd4k5W06Qed1s4k6w2o1KzVpNlYWzB7oaSYP9KZjUpcuITLM6o4ZgGUTYaZAv2myQG+0tsYlRoZZ42EDsEgrzBHo35og0BtoHICuZLJpkm3M/1Hl06N0GUBXpJlKp4w0ZqmN83Kj/0eaAeDnOXWqkTLdqUB/QpcBoO2ZNalzpe7g/6jycdYprgMA0HOKTX4wtCOBpssAYGqaeBpUan23ONaTZgAwUqmn6Zfpdh7F8dERugwARqYZeaePCu3IBL2ONAOAiWmG4JTWSt080Ol0GQDMTjMTz9Aq9X+2ONIOk2YAsDBlSn7uoVAhhMp3VDIrAgASsmMJAIBAAwAINAAQaAAAgQYAAg0AINAAAAINAAQaAECgAYBAAwAINACAQAMAgQYAEGgAINAAAAINAAQaAECgAQAEGgAINACAQAMAgQYAEGgAAIEGAAINACDQAECgAQAEGgAINACAQAMACDQAEGgAAIEGAAINACDQAAACDQAEGgBAoAGAQAMACDQAEGgAAIEGABBoACDQAAACDQAEGgBAoAEABBoACDQAgEADAIEGABBoAACBBgACDQAg0ABAoAEABBoACDQAgEADAAg0ABBoAACBBgACDQAg0AAAAg0ABBoAQKABgEADAAg0ABBoAACBBgDowcGgSwf7e8+dHBUe1M/DrUf5ldqMvac+3Pzvu3cbJTyxlYuffezBoPvGLzX0Czcum7H7cP6azYe5cQCwmgk6ZsSgLcufd7C3+/2qnbPf3rTvWOG8qdFL5sXZ2Io4Odo7Odjr/2Mgf9tb3IwAWHiCfn1GbGnFtXlLP29Uq4UQmdnFP96+OzvhkY07Tubkl9nMijzz6lq1mhsGAKsKdP++9+YWlDdq1euLvXnB/t7eHj2Vd527O85NjBoXHeLl3rPyat3mb3I/2HSoofGnyzt3c5yTGDUuJsTTrUfZldqt+06lZmTdvnNX+Wx3J4eZEx+Kiw7x9Xa7U3/3bPHldVuP7j6cr3w2f9tbe7IKPt+d+3JiVKCf57W6mxl7T63YcLChoVH7r46LDvF063Hp8vef7jjZ1lko3+qT7cfnJ8cEDehdX9+QmX1+Wfqe8qo65QLfbX1rT1bB3Hc+a/ewNbOz8gdlO0X5/povF003W5TPZp4sfm3ao2lfZq3ckNnuugEg0O0rulA1LNj3ofCBh3NLlI+UlNW89PZG5c+ODvZpS5J8vVxXbsw8X3Z16H0+sxOj+nj0+p/3v1b2DdKWTA0O8F7x6cHTRRURwb4vT/lFsL/3gj9vEUI4ONilLpkaHuSTlpF1MPtcj+5OCWMjVvx20l/T9qzZckT5/v16uy6Z9+R7Hx+4WHltwujQuZOjhBDvfXJAifv6PyQHDfBatTEzr6D8/gDvBUkxN27dbutE/Lzd/vabp9Mysv6+fn+gn+eryY8OG+IbP39N7Q+3Wm536DjsxEXpi2bERj7QP3FRuv7LOMjPMzyo34oNB/cfLWx33QAQaL0sXb177e+npL+TdOzbCwdOFB04fq6g5IrmsykTIsMG941fsKawtEoIcTi3pL6hcVFKbGrGkZKympT4kRH3+85957M9WQXKZ4VKLEiKCc/wyc0vmz4+cvgQvyUf7Pp4+3Hlu+07Vpj69tSFKbG7D+eXVlwTQtwf4D1nyaa9RwuFEFl5paPCBj4VG6oEOiV+ZOjgfgv+vGVn5lkhxKGc898WVa5bmtTWiQQN9Jqx+BPlx8zh3JLq72+898YzLz378F9S9zS7pO7Dzskvq7vxoxDCoB0ev773TlqYdrqoQp914wYKdGUG/JLwxJmLY2avSsvI6uPZa1FK7LZ/zPrs3edCB/dTPjsu5oG8woriS1ft7e2Ut31HC1UqMSp0oBBiXHRI+ZVaJXOKDTtO/iV1z927DUKICY+G1tTe1N6XUKvFqo2Z9naqcTEPKB+pqb2571ih8udGtbroQpW3Zy/l3SeihlRW1+06dFbz5UfySoovXW3rRErKajT/CBBC/PPQd1U11x8bGdTykroPu2MKS6s0dW533QAwQevr8tUf/rT2mz+t/WZw/97xo0OnT4hc/8fkia+lnrtY7e/r0d3J4UzGm82+xN3VRQjh7+Nx8uwl7Y/X1N5c+8VP2xcBvh55BeWaDWVFfmmVECLAz+OnDZaL1dq/u6u/22Bvp1L+PNDHPS+/vNlv9i5WXgvw9Wj1LC5UXtN+t1GtPl9eM/Q+n5aX1H3YelKpVNrvllfVNvkrdK4bAAJt+Bh4oWrZur35JZeXLXpq8tiIpat326lUJ85c/MOa3c0uWVn9gxDCzk5lb2/Yk2LUarUySiuu32xzT9nB3q5pA4UQopuTg+7v3OxDzX48/PTvC8MPWwjR7Fh6unRr8vOg6W//dK8bALY42pc4NmLL8udDAvtof1DZEe7t3lMIUVFV69Ld6dvCCs3b9Zu3R0cO7uHsJISoqKrz6+Om/bVuPZ1HRw5WHgFSfOlqoJ+ng0OTgwn29xZCnP95p0Ld9mPfyqvqBvq4N2t0/z73tnV5X2+3phOuGNDP/Xx5K1siug+7VQ2NahdnJ+2PaP4R0Crd6waAQLevoLQqZFDf+Ukx2sOq0mvlV4UHjhcF+3sP8vPUfHZG/INzEh65VndTCJGZXdzXs1fMiEGaz86a9PCq/05wsLcTQmzdf8rd1WXy2GHa0ZyT8EhDo3r7gW/bPbZ9Rwu83HvGam0ij44c3M/Lta3LB/p5jgwdoHn3iagh3h49dxw82/KSug9b82ND+0fLlZofggZ4Of78VJeoYQEerj10HLzudQPQldn38g3T53KV1XWe994zPiYkMqT/7fq77m4uYx4OXvzSmMrqusUrvrpT33C2+PK4mJBnHg+/ceu26z3O08ZFJsWNWL5+/79zzgsh8kuuxI8OffIXQ368Xe/i7JQwJmLmxFEfbT369cGzQohTRRWjwgZOenyoc3fHRrU6qL/XGy/8Mnp44Lvpe/cdKxJCvDI1+nzZ1a/+dUZzPHHRIQG+His+PSiEOHOucnzMA09E3X/91p17nLvFRQ/5dUrsxcprHm49lAtoe2VqdGV13VOxoY0NapfujnHRIW/OfPx0UcXvVu5Qdjm0/y7dhy2EeHiof0hgn/r6Bnt7u7LLtUIIt14u0cMD7/P3+r7u1vAhfotfHFN2pdbz5yNpeSK61w1AV6byHZWs/6UfezBo+oTIQF/Pe3p0u3T5+12Hvkv94siNW3eUz/b17LVw+ujoEYHdnBzOXahO/zJr24HTmq/16+O2cProqIgAR0f70vKaDTtObtyZrXnai3M3x5kTH4qLHuLr7abkPv3LrGZPVGnr2R9CCB8v19efe+yRCH8He7uC0qq/r98/bXxkq6/FoXyrI3mlyXHD+3m5VtVc3/6v0ys3ZN66Xd/q36X7sAcP6L389af9fTx+vFM/PHGZEMLeTjVvSvTTvwxz6+lcfOnqB5sOxceGNnuiivaJtLtuAAh0V9FqIgFAQrzcKAAQaAAAgQYAG9Dl9qABgAkaAECgAYBAAwAINAAQaAAAgQYAEGgAsHr/D8Hg2xT5E4m1AAAAAElFTkSuQmCCThe second pictureA shape with text in itA line of text beside a shape.Links, fields and notesAn external link: exav.org. An internal link: back to the introduction. A reference to a bookmark: Tables.Fields: this document is titled “Harbour handbookâ€�, and this line is on page 1. A fixed date: 01/01/2000.A comment is attached to this wordexav2000-01-01T00:00:00A comment: the viewer shows or ignores it.. A change that was tracked: this text was inserted, and some text was deleted before this one.Citations [1] [2]. 2A second footnote, with emphasis.Wide table (landscape)MonthBerth 1Berth 2Berth 3Berth 4Berth 5Berth 6Berth 7Berth 8Berth 9Berth 10TotalJan162738495146Feb849516273853Mar627384951651Apr495162738449May273849516247Jun951627384954Jul738495162752Aug516273849550Sep384951627348Oct162738495146Nov849516273853Dec627384951651Nights let at each berth, by month. + + diff --git a/crates/exav-viewer/demo/examples/files/converted/handbook.odt b/crates/exav-viewer/demo/examples/files/converted/handbook.odt new file mode 100644 index 0000000..ebd0b15 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/converted/handbook.odt differ diff --git a/crates/exav-viewer/demo/examples/files/converted/handbook.rtf b/crates/exav-viewer/demo/examples/files/converted/handbook.rtf new file mode 100644 index 0000000..39371ee --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/converted/handbook.rtf @@ -0,0 +1,620 @@ +{\rtf1\ansi\deff3\adeflang1025 +{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\fmodern\fprq1\fcharset0 Liberation Mono{\*\falt Courier New};}{\f5\fswiss\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f6\fswiss\fprq0\fcharset128 FreeSans;}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red192\green57\blue43;\red6\green69\blue173;\red106\green27\blue154;\red11\green79\blue108;\red20\green108\blue148;\red232\green241\blue245;\red255\green235\blue59;\red219\green233\blue244;\red240\green240\blue240;\pagebb} +{\stylesheet{\s0\snext0\rtlch\af8\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\widctlpar\hyphpar0\ltrpar\cf0\f3\fs22\lang1033\kerning1\dbch\af7\langfe2052 Normal;} +{\s1\sbasedon33\snext34\loch\ilvl0\outlinelevel0\cf20\fs34 heading 1;} +{\s2\sbasedon33\snext34\loch\ilvl1\outlinelevel1\cf21\fs26 heading 2;} +{\*\cs15\snext15\loch\b Strong;} +{\*\cs16\snext16\loch\i Emphasis;} +{\*\cs17\snext17\loch\ul\ulc0 Underline;} +{\*\cs18\snext18\loch\strike Strike;} +{\*\cs19\snext19\loch\cf17 Red;} +{\*\cs20\snext20\loch\chcbpat23 Highlight;} +{\*\cs21\snext21\loch\scaps SmallCaps;} +{\*\cs22\snext22\loch\fs30 Big;} +{\*\cs23\snext23\hich\af4\loch\f4\fs20 Mono;} +{\*\cs24\snext24\loch\sub Sub;} +{\*\cs25\snext25\loch\super Super;} +{\*\cs26\snext26\loch\cf18\ul\ulc0 Hyperlink;} +{\*\cs27\snext27\loch\cf19\ul\ulc0 FollowedHyperlink;} +{\*\cs28\snext28 Index Link;} +{\*\cs29\snext29 Footnote Characters;} +{\*\cs30\snext30\loch\super footnote reference;} +{\*\cs31\snext31\loch\super endnote reference;} +{\*\cs32\snext32 Endnote Characters;} +{\s33\sbasedon0\snext34\hich\af5\loch\sb255\sa113\keepn\f5\b Heading;} +{\s34\sbasedon0\snext34\loch\sl300\slmult1\sb0\sa125 Body Text;} +{\s35\sbasedon34\snext35\rtlch\af6 \ltrch List;} +{\s36\sbasedon0\snext36\loch\sb57\sa113\cf0\fs18\i caption;} +{\s37\sbasedon0\snext37\rtlch\af6 \ltrch\loch\noline Index;} +{\s38\sbasedon0\snext39\hich\af5\loch\ql\sb1701\sa170\cf20\f5\fs60\b Title;} +{\s39\sbasedon0\snext39\hich\af5\loch\sb0\sa340\cf0\f5\fs32 Subtitle;} +{\s40\sbasedon0\snext40\loch\sb0\sa57\cf0\fs20 Author;} +{\s41\sbasedon1\snext41 Heading 1 Landscape;} +{\s42\sbasedon33\snext42\rtlch\afs32\ab \ltrch\loch\fi0\li0\lin0\noline\fs32\b index heading;} +{\s43\sbasedon0\snext43\hich\af5\loch\sb850\sa170\f5\fs30\b TOC Heading;} +{\s44\sbasedon0\snext44\loch\sb0\sa57 toc 1;} +{\s45\sbasedon0\snext45\loch\li567\lin567\ri567\rin567\sb113\sa170\brdrt\brdrnone\brdrl\brdrs\brdrw45\brdrcf21\brsp85\brdrb\brdrnone\brdrr\brdrnone\cf0\i Block Quotation;} +{\s46\sbasedon34\snext46\loch\qj Justified;} +{\s47\sbasedon34\snext47\loch\qc Centered;} +{\s48\sbasedon34\snext48\loch\qr Right;} +{\s49\sbasedon34\snext49\loch\li850\lin850\brdrt\brdrnone\brdrl\brdrs\brdrw20\brdrcf0\brsp113\brdrb\brdrnone\brdrr\brdrnone Indented;} +{\s50\sbasedon0\snext50\hich\af4\loch\li283\lin283\sb0\sa0\brdrt\brdrnone\brdrl\brdrnone\brdrb\brdrnone\brdrr\brdrnone\cbpat25\f4\fs19 Code;} +{\s51\sbasedon0\snext51\loch\fi-283\li283\lin283\fs18 footnote text;} +{\s52\sbasedon0\snext52\loch\tqc\tx4819\tqr\tx9638\noline Header and Footer;} +{\s53\sbasedon0\snext53\loch\cf0\fs18 header;} +{\s54\sbasedon0\snext54\loch\qc\cf0\fs18 footer;} +{\s55\sbasedon0\snext55\loch\sb0\sa45 List Contents;} +{\s56\sbasedon0\snext56 Table Contents;} +{\s57\sbasedon56\snext57\loch\qc\cf8\b Table Heading;} +{\s58\sbasedon56\snext58\loch\qr Table Right;} +}{\*\listtable{\list\listtemplateid1 +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'03\'00. ;}{\levelnumbers\'01;}\fi-510\li510} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'04\'00.\'01 ;}{\levelnumbers\'01\'03;}\fi-680\li680} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}\listid1} +{\list\listtemplateid2 +{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f9\fi-283\li510} +{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9702 ?;}{\levelnumbers;}\f9\fi-283\li964} +{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9642 ?;}{\levelnumbers;}\f9\fi-283\li1417} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'03.;}{\levelnumbers\'01;}\fi-360\li1800} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'04.;}{\levelnumbers\'01;}\fi-360\li2160} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'05.;}{\levelnumbers\'01;}\fi-360\li2520} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'06.;}{\levelnumbers\'01;}\fi-360\li2880} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'07.;}{\levelnumbers\'01;}\fi-360\li3240} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'08.;}{\levelnumbers\'01;}\fi-360\li3600}\listid2} +{\list\listtemplateid3 +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'00.;}{\levelnumbers\'01;}\fi-340\li510} +{\listlevel\levelnfc4\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'01);}{\levelnumbers\'01;}\fi-340\li1020} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'02.;}{\levelnumbers\'01;}\fi-360\li1440} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'03.;}{\levelnumbers\'01;}\fi-360\li1800} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'04.;}{\levelnumbers\'01;}\fi-360\li2160} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'05.;}{\levelnumbers\'01;}\fi-360\li2520} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'06.;}{\levelnumbers\'01;}\fi-360\li2880} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'07.;}{\levelnumbers\'01;}\fi-360\li3240} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'08.;}{\levelnumbers\'01;}\fi-360\li3600}\listid3} +}{\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}}{\*\revtbl {Unknown;}{exav;}} +{\*\generator LibreOffice/25.2.3.2$Linux_AARCH64 LibreOffice_project/520$Build-2}{\info{\title Harbour handbook}{\subject A document made for the exav demo (CC0-1.0)}{\keywords demo}{\author exav project}{\creatim\yr2000\mo1\dy1\hr0\min0}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab709 +\hyphauto1\viewscale100\formprot\formshade\nobrkwrptbl\paperh16838\paperw11906\margl1247\margr1247\margt850\margb680\sectd\sbknone\sftnnar\saftnnrlc\sectunlocked1\pgwsxn11906\pghsxn16838\marglsxn1247\margrsxn1247\margtsxn1284\headery850\margbsxn1114\footery680{\header\pard\plain \s53\loch\cf0\fs18\ql\ltrpar{\loch +Harbour handbook\tab \tab exav demo} +\par }{\footer\pard\plain \s54\loch\qc\cf0\fs18\qc\ltrpar{\loch +Page }{\loch +{\field{\*\fldinst PAGE }{\fldrslt 5}}}{\loch + of }{\loch +{\field{\*\fldinst NUMPAGES }{\fldrslt 5}}} +\par }\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\fet\aftnrstcont\aftnstart1\aftnnrlc +{\*\ftnsep\chftnsep}\pgndec\pard\plain \s38\hich\af5\loch\ql\sb1701\sa170\cf20\f5\fs60\b\ql\sb1701\sa170\ltrpar{\loch +Harbour handbook} +\par \pard\plain \s39\hich\af5\loch\sb0\sa340\cf0\f5\fs32\ql\sb0\sa340\ltrpar{\loch +The east quay: rules, figures and notes} +\par \pard\plain \s40\loch\sb0\sa57\cf0\fs20\ql\sb0\sa57\ltrpar{\loch +exav project, written for the demo (CC0-1.0)} +\par \pard\plain \s40\loch\sb0\sa57\cf0\fs20\ql\sb0\sa57\ltrpar{\loch +1 January 2000} +\par \pard\plain \s43\hich\af5\loch\sb850\sa170\f5\fs30\b\ql\sb850\sa170\ltrpar{\loch\fs30\b\loch +Contents} +\par \pard\plain \s44\loch\sb0\sa57\ql\sb0\sa57\ltrpar +{\field{\*\fldinst { TOC \\f \\o "1-2" \\h}}{\fldrslt {{{\field{\*\fldinst HYPERLINK "#intro" }{\fldrslt {\loch +1. Introduction}}}} +\par \pard\plain \s44\loch\sb0\sa57\ql\sb0\sa57\ltrpar{{\field{\*\fldinst HYPERLINK "#text" }{\fldrslt {\loch +2. Text and styles}}}} +\par \pard\plain \s44\loch\sb0\sa57\ql\sb0\sa57\ltrpar{{\field{\*\fldinst HYPERLINK "#lists" }{\fldrslt {\loch +3. Lists}}}} +\par \pard\plain \s44\loch\sb0\sa57\ql\sb0\sa57\ltrpar{{\field{\*\fldinst HYPERLINK "#tables" }{\fldrslt {\loch +4. Tables}}}} +\par \pard\plain \s44\loch\sb0\sa57\ql\sb0\sa57\ltrpar{{\field{\*\fldinst HYPERLINK "#pictures" }{\fldrslt {\loch +5. Pictures and shapes}}}} +\par \pard\plain \s44\loch\sb0\sa57\ql\sb0\sa57\ltrpar{{\field{\*\fldinst HYPERLINK "#links" }{\fldrslt {\loch +6. Links, fields and notes}}}} +\par \pard\plain \s44\loch\sb0\sa57\ql\sb0\sa57\ltrpar{{\field{\*\fldinst HYPERLINK "#wide" }{\fldrslt {\loch +7. Wide table (landscape)}}}}}}} +\par \pard\plain \s1\loch\ilvl0\outlinelevel0\cf20\fs34{\listtext\pard\plain 1. \tab}\ls1 \fi-510\li510\lin510\ql\fi0\li0\lin0\ltrpar{\loch +{\*\bkmkstart intro}{\*\bkmkend intro}Introduction} +\par \pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +The east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell.} +\par \ql\fi-283\li283\lin283\ltrpar\pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +Every berth has a number, a length in metres and a holder. The register is kept on paper and in a table; the two are compared each spring, and the differences are explained in the notes of the harbour master. }{{\super \loch \chftn{\*\footnote \chftn\pard\plain \s51\loch\fi-283\li283\lin283\fs18{\loch +\tab The register of 2000 lists sixty berths.} +}} +} +\par \pard\plain \s45\loch\li567\lin567\ri567\rin567\sb113\sa170\brdrt\brdrnone\brdrl\brdrs\brdrw45\brdrcf21\brsp85\brdrb\brdrnone\brdrr\brdrnone\cf0\i\ql\li567\lin567\ri567\rin567\sb113\sa170\brdrt\brdrnone\brdrl\brdrs\brdrw45\brdrcf21\brsp85\brdrb\brdrnone\brdrr\brdrnone\ltrpar{ +\u8220\'93}{\loch +A harbour is a promise that the sea will wait.\u8221\'94 } +\par \pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +Visitors are asked to call the harbour office on channel 9 before they come in, to give the length of their boat and its draught, and to say how many nights they plan to stay.} +\par \pard\plain \s1\loch\ilvl0\outlinelevel0\cf20\fs34{\listtext\pard\plain 2. \tab}\ls1 \fi-510\li510\lin510\ql\fi0\li0\lin0\ltrpar{\loch +{\*\bkmkstart text}{\*\bkmkend text}Text and styles} +\par \pard\plain \s2\loch\ilvl1\outlinelevel1\cf21\fs26{\listtext\pard\plain 2.1 \tab}\ls1 \fi-680\li680\lin680\ql\fi0\li0\lin0\ltrpar{\loch +Character formatting} +\par \pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch\cs15\loch\b\loch +Bold}{\loch +, }{\loch\cs16\loch\i\loch +italic}{\loch +, }{\loch\cs17\loch\ul\ulc0\loch +underlined}{\loch +, }{\loch\cs18\loch\strike\loch +struck through}{\loch +, }{\loch\cs19\loch\cf17\loch +red}{\loch +, }{\loch\cs20\loch\chcbpat23\loch +highlighted}{\loch +, }{\loch\cs21\loch\scaps\loch +small capitals}{\loch +, }{\loch\cs22\loch\fs30\loch +large}{\loch + and }{\loch\cs23\hich\af4\loch\f4\fs20\loch +monospaced}{\loch + text; H}{\loch\cs24\loch\sub\loch +2}{\loch +O and 10}{\loch\cs25\loch\super\loch +3}{\loch +; a }{\loch\cs16\loch\i\loch +mixed}{\loch + style.} +\par \pard\plain \s2\loch\ilvl1\outlinelevel1\cf21\fs26{\listtext\pard\plain 2.2 \tab}\ls1 \fi-680\li680\lin680\ql\fi0\li0\lin0\ltrpar{\loch +Paragraph formatting} +\par \pard\plain \s46\loch\qj\qj\ltrpar{\loch +The east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell. Every berth has a number, a length in metres and a holder. The register is kept on paper and in a table; the two are compared each spring, and the differences are explained in the notes of the harbour master.} +\par \pard\plain \s47\loch\qc\qc\ltrpar{\loch +A centred line} +\par \pard\plain \s48\loch\qr\qr\ltrpar{\loch +A line aligned to the right} +\par \pard\plain \s49\loch\li850\lin850\brdrt\brdrnone\brdrl\brdrs\brdrw20\brdrcf0\brsp113\brdrb\brdrnone\brdrr\brdrnone\ql\li850\lin850\brdrt\brdrnone\brdrl\brdrs\brdrw20\brdrcf0\brsp113\brdrb\brdrnone\brdrr\brdrnone\ltrpar{\loch +An indented paragraph with a left border: Visitors are asked to call the harbour office on channel 9 before they come in, to give the length of their boat and its draught, and to say how many nights they plan to stay.} +\par \pard\plain \s50\hich\af4\loch\li283\lin283\sb0\sa0\brdrt\brdrnone\brdrl\brdrnone\brdrb\brdrnone\brdrr\brdrnone\cbpat25\f4\fs19\ql\li283\lin283\sb0\sa0\brdrt\brdrnone\brdrl\brdrnone\brdrb\brdrnone\brdrr\brdrnone\ltrpar\cbpat25{\loch +moor --boat Aurora --length 6.5} +\par \pard\plain \s50\hich\af4\loch\li283\lin283\sb0\sa0\brdrt\brdrnone\brdrl\brdrnone\brdrb\brdrnone\brdrr\brdrnone\cbpat25\f4\fs19\ql\li283\lin283\sb0\sa0\brdrt\brdrnone\brdrl\brdrnone\brdrb\brdrnone\brdrr\brdrnone\ltrpar\cbpat25{\loch +berth 14 free until 06:00} +\par \pard\plain \s2\loch\ilvl1\outlinelevel1\cf21\fs26{\listtext\pard\plain 2.3 \tab}\ls1 \fi-680\li680\lin680\ql\fi0\li0\lin0\ltrpar{\loch +A section in two columns} +\par \sect\sectd\sftnnar\saftnnrlc\sectunlocked1\pgwsxn11906\pghsxn16838\marglsxn1247\margrsxn1247\margtsxn1284\headery850\margbsxn1114\footery680\cols2\linebetcol\colsx454\ltrsect\sbknone\pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +The east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell. Every berth has a number, a length in metres and a holder. The register is kept on paper and in a table; the two are compared each spring, and the differences are explained in the notes of the harbour master. Visitors are asked to call the harbour office on channel 9 before they come in, to give the length of their boat and its draught, and to say how many nights they plan to stay. The east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell.} +\par \sect\sectd\sftnnar\saftnnrlc\sectunlocked1\pgwsxn11906\pghsxn16838\marglsxn1247\margrsxn1247\margtsxn1284\headery850\margbsxn1114\footery680\pgndec\sbknone\pard\plain \s1\loch\ilvl0\outlinelevel0\cf20\fs34{\listtext\pard\plain 3. \tab}\ls1 \fi-510\li510\lin510\ql\fi0\li0\lin0\ltrpar{\loch +{\*\bkmkstart lists}{\*\bkmkend lists}Lists} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls2 \fi-283\li510\lin510\ql\ltrpar{\loch +Water at every berth} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain \u9702\'3f\tab}\ilvl1\ls2 \fi-283\li964\lin964\ql\ltrpar{\loch +cold, from the quay} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain \u9702\'3f\tab}\ilvl1\ls2 \fi-283\li964\lin964\ql\ltrpar{\loch +hot, in the shower block} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls2 \fi-283\li510\lin510\ql\ltrpar{\loch +Electricity} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain \u9702\'3f\tab}\ilvl1\ls2 \fi-283\li964\lin964\ql\ltrpar{\loch +16 A at berths 1 to 40} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain \u9642\'3f\tab}\ilvl2\ls2 \fi-283\li1417\lin1417\ql\ltrpar{\loch +with a meter} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain \u9642\'3f\tab}\ilvl2\ls2 \fi-283\li1417\lin1417\ql\ltrpar{\loch +without a meter} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain \u9702\'3f\tab}\ilvl1\ls2 \fi-283\li964\lin964\ql\ltrpar{\loch +32 A at the east pontoon} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls2 \fi-283\li510\lin510\ql\ltrpar{\loch +Wi-Fi on the quay} +\par \pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +Numbered, with other numbering styles at each level:} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain 1.\tab}\ilvl0\ls3 \fi-340\li510\lin510\ql\ltrpar{\loch +Call the office on channel 9} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain 2.\tab}\ilvl0\ls3 \fi-340\li510\lin510\ql\ltrpar{\loch +Give the length and the draught} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain a)\tab}\ilvl1\ls3 \fi-340\li1020\lin1020\ql\ltrpar{\loch +length over all, in metres} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain b)\tab}\ilvl1\ls3 \fi-340\li1020\lin1020\ql\ltrpar{\loch +draught, in metres} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain 3.\tab}\ilvl0\ls3 \fi-340\li510\lin510\ql\ltrpar{\loch +Take the berth you are given} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain a)\tab}\ilvl1\ls3 \fi-340\li1020\lin1020\ql\ltrpar{\loch +tie up bow first} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain b)\tab}\ilvl1\ls3 \fi-340\li1020\lin1020\ql\ltrpar{\loch +tie up stern first} +\par \pard\plain \s55\loch\sb0\sa45{\listtext\pard\plain 4.\tab}\ilvl0\ls3 \fi-340\li510\lin510\ql\ltrpar{\loch +Pay at the office} +\par \pard\plain \s1\loch\ilvl0\outlinelevel0\cf20\fs34{\listtext\pard\plain 4. \tab}\ls1 \fi-510\li510\lin510\ql\fi0\li0\lin0\ltrpar{\loch +{\*\bkmkstart tables}{\*\bkmkend tables}Tables} +\par \pard\plain \s36\loch\sb57\sa113\cf0\fs18\i\ql\sb57\sa113\ltrpar{\loch +Table }{\loch +{\field{\*\fldinst SEQ Table \\* ARABIC }{\fldrslt 1}}}{\loch +: berths by length, with merged cells and a repeated header row} +\par \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx2551\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx4252\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx6236\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx7937\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Length}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Berths}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Let by}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Fee (EUR)}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2551\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4252\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6236\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx7937\pard\plain \s56\intbl\ql\ltrpar{\loch +up to 6 m}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +12}\cell\pard\plain \s56\intbl\ql\ltrpar{\loch +week}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +18.00}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2551\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4252\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6236\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx7937\pard\plain \s56\intbl\ql\ltrpar{\loch +6 to 8 m}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +18}\cell\pard\plain \s56\intbl\ql\ltrpar{\loch +season}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +24.50}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2551\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4252\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6236\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx7937\pard\plain \s56\intbl\ql\ltrpar{\loch +8 to 10 m}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +14}\cell\pard\plain \s56\intbl\ql\ltrpar{\loch +season}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +31.00}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2551\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4252\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6236\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx7937\pard\plain \s56\intbl\ql\ltrpar{\loch +10 to 12 m}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s56\intbl\ql\ltrpar{\loch +year}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +42.00}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2551\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4252\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6236\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx7937\pard\plain \s56\intbl\ql\ltrpar{\loch +over 12 m}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s56\intbl\ql\ltrpar{\loch +year}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +58.50}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx2551\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx4252\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx7937\pard\plain \s56\intbl\ql\ltrpar{\loch\cs15\loch\b\loch +Total}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +60}\cell\pard\plain \s56\intbl\ql\ltrpar\loch +\cell\row\pard \pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar\loch + +\par \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx5410\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clvmgf\cellx7937\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Merged across two columns}\cell\pard\plain \s56\intbl\ql\ltrpar{\loch +Merged down two rows}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3246\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5410\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clvmrg\cellx7937\pard\plain \s56\intbl\ql\ltrpar{\loch +a}\cell\pard\plain \s56\intbl\ql\ltrpar{\loch +b}\cell\pard\plain \s0\rtlch\af8\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\widctlpar\hyphpar0\ltrpar\cf0\f3\fs22\lang1033\kerning1\dbch\af7\langfe2052\intbl\ql\ltrpar\loch +\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3246\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5410\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx7937\pard\plain \s56\intbl\ql\ltrpar{\loch +c}\cell\pard\plain \s56\intbl\ql\ltrpar{\loch +d}\cell\pard\plain \s56\intbl\ql\ltrpar{\loch +e}\cell\row\pard \pard\plain \s1\loch\ilvl0\outlinelevel0\cf20\fs34{\listtext\pard\plain 5. \tab}\ls1 \fi-510\li510\lin510\ql\fi0\li0\lin0\ltrpar{\loch +{\*\bkmkstart pictures}{\*\bkmkend pictures}Pictures and shapes} +\par \pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +{\shp{\*\shpinst\shpwr2\shpwrk0\shpbypara\shpbyignore\shptop0\shpbottom2551\shpbxcolumn\shpbxignore\shpleft4877\shpright9412{\sp{\sn shapeType}{\sv 75}}{\sp{\sn wzDescription}{\sv A made-up picture of a lake and a hill at dusk.}}{\sp{\sn wzName}{\sv A lake at dusk}}{\sp{\sn pib}{\sv {\pict\picscalex47\picscaley47\piccropl0\piccropr0\piccropt0\piccropb0\picw640\pich360\picwgoal9600\pichgoal5400\pngblip +89504e470d0a1a0a0000000d49484452000002800000016808020000004850dd060000148f4944415478daeddd779c14e5fd07f059ee0e3894a220a0808a2860 +a1890541c11a8c420844c182250a1a1b20410dd198fc624c7b19132362076cb145e9688c880a89421429a241a4183da41d7a280a22dcef8f85f3e8bbc7eeecee +cdfbfdba3fb8636e76e6bbf33c1fbef3ec2eb1035b0e080080705551020010c00020800180f4c80f628a00003a600010c000800006804ac21a3000e88001202a +1db0161800c20f60f10b0099e88025300084ce1a300008600010c000409a580306804c04b0fc0580f0b9050d00021800a2213f88b9090d003a6000884207acff +05001d300044a303f63e6000d0010380000600d2c38bb0002013016c0d1800c2e71634000860008886fc987bd000107e00cb5f00089f5bd000208001201abc0f +18003211c0d68001207c6e41038000068068b0060c009908606bc000103eb7a00120131db006180074c000108d0e3888e9810140070c0051e880f5bf00a00306 +806874c0de070c00190860f90b00e1730b1a000430004443beb70103800e1800043000208001a0d2b0060c003a600010c000409af8242c00c84400fbff800140 +070c0091600d18000430004483f70103800e180004300090265e050d009908e040020340e8dc8206804c74c01a6000d0010340343a606bc00090810096bf0010 +3eb7a00140070c001109606bc000103eb7a00120131db006180074c00010910e580b0c003a60008844071c78193400841fc0e2170032d1014b6000d001034014 +781116000860008806ef0306001d300044a503560300d0010340243a60ef0306800c04b0fc0580f0b9050d003a60008848005b0306001d3000448235600010c0 +00100d3e0b1a0074c00010950e580d0040070c00d1e880b5c000a00306806874c06a00003a6000884607ac0506001d3000086000202dbc080b003211c0fe3f60 +00d001034024580306001d3000442480ad0103800e180022c11a3000e880012022016c0d180074c0001009d6800140070c001109606bc000a003068048b0060c +003a60008848005b0306001d30004482356000d00103404402d81a3000e880012012ac0103800e18002212c0d6800140070c0091600d180074c000109100b606 +0c003a600088046bc000a00306808804b0356000d001034024580306001d3000442480ad0103800e1800043000901e5e84050019e980b5c000a00306806874c0 +6a00003a6000884607ac0506001d300044a3030e4a55010074c00010850ed81a3000642080d5000042e7163400e88001202201ecff0306001d30004482356000 +d0010340540258020340e8dc8206808c74c06a00003a6000884607ac050680f0035809001231f2d17ebbdde6c7173fa45024dc01ab01c0ce8d482077b70fe9cb +24310218a0021e4e26777716db978b617611c03e0b1a60dbf47da45f6af6138fe14bc4303a60805d7a2845d1bb4d9cf793c16cc7db9000d298be657b4edfced1 +0103e4b007d31f900f3dd2afbf5698ef023856aa0a404e983c77d669addaa663cf0f8cea1f5acc5f71e9839e4a02b7a0815c89dec97367c5ff90bbe99b918723 +6bc5ae3877b02a0059ebe59d24eee9296a85efcf501c5ea90fd6012b0190b5d1fbf2cefbdd9753d10adfaf1925737c16349075fe3927a1708d67f019addbe6e2 +39de3faaff4f7eac09d6019335130a447c98c4bfc2195cf78dcc70fb9bf10320d31db01aa4df4b7366c5a789efe5e63fd5219c31b287ffc04d6a7cdd9b1de167 +068eb2d855bdbd082b8dfeb1a369a5ab18865d8e910a4b7c700dcf9aeef36a37a223db01fb07581a6796d9b37636e3746d2383314066a57e9f73660541b0dbf1 +357c4436ddfb35094736803df5e9f0e2ee6696f8d473a618c600494fb4e7d0e032094756ec9a3e6e41a7d80bc94c2edf97c1181d69b3b3f1356c4476bdfae9da +cbdc85cef0659991a9d8aba0333cbf843c1f55d679969cb824c2bf2a76f888d996bec66f365c96193965ef034e9949b366edc9b57e56dbb695ac0ebbbea02bcd +f992bea191c22cc9f2eb2de3f3f0f6cf51259b97123ce590cf3776ed796e4167cb145309aef5544db5e2d9b848b9b28beaee87b3b103beeef207b3f9a9a97c1d +42369ca91761a5c0c414cd329366cd3a3b67aff289299d6a773d48ce16cfe5ca9e9dd598984dd15bfea2cada8b2796ddcf4896572f851508731e8e0dd001ef81 +09e99965bae5d4553e21cba6da6e1188e7446a9e913a4cc8bedcdddec2b7efc9c2a31a98ea0e387dcf45ce0db10a94229c738c0d38ff7a395ac127f59dd9694c +91766d225e8188d430fc9aa7a92c597e31647f0c0fecf740ce3d05d93fc4f6a426219c5d6ca0004edef8b02ef4ee597c7d8fcf9d09b77bee277108d5ae7095c6 +e75af46667060f4a3e80b3a4f25938be525599749f5ac60278fc3bb373745a0cf9a2afc417b79922274abd8ba2e5ee959085319c48006773c1b36470a5bc4469 +3dafd8a04c04f0b87235fa414ecd89e3323100b2a744e32ac5849b13975ce528b50c4edcf53b0ae05cbc0c3235bed257abf49d51ecfa0bc20ee0b133775ca61e +4767f5b4b8b3c30e4d66eb93f1d3af7c258d4e9dc5702206f77fa0325d00610eae108a96a6d309358013295376c670968c8a4c15a7d2a742c6af3ab91bd90c6e +d6fe1a832b27064e3a4e243638ac001e9364a57e9835493c269b26c790cb322662c110fe553746f4462c862b7de28630b232356a523e3fc47e1a4a008fae68bd +7a6634864767ebe418425946473b18d25de1d1723732191ccdc44dd3b0caf8c049edcc10fbe985690fe0d16fa7a0643ddb879dc42939ec345e07692b48969f78 +4ed7596da310c312371dc32a7bc64e0ae784d8907406f0f3a92e59af5062f8f9dc9925535e90e725447a4aadb0953883256e5ac754168e9d544dbc690ce0b456 +2d7d499c731365aa4a2121d2516d55ad94312c71431853593e765232f1c66e484f003f174aed7e94ea187e2e37a7cb3dacc3734222d5355752a8f098ca95e1b3 +e70114bbb16fea03f8ef6f855dbe738e699373c79c0d45a804679d6d65575288ecf0af40000f4a69f4cec9682d5ae7e26167aa0295e6ac01722e77822088dd94 +ba007e366b26f47393a9c8b3952b871239f767452f40261267ab00fe598a02f899ec9bd37befae28cf54de1cdad9b93f237a01428f9b9d04f0452908e067fe93 +d5d37aef635be7dc31a7fcac2bfdf902645bd0ec268087ee59003f9d3bd37a9f2dd5793a4a51143feba7a52f405829936800ff7c0f02f829d33a006c715e3219 +5c45fa02404a24958c5562b1a0025fd217007698c1092669d21df09333e63c3943fa02c04e8332b10e380812ff12bd00904806ef36529308e0bf495f0048ccdf +7697c155825869225f4f485f0048c61333e6ec2258f363bbfbfdc7a7cf554400a848064f9fdbf7f8563bfcabdddc8296be00b0271e9f3e7727b7a077ee31e90b +007b6c8779bad3f7014b5f004861066f93b33b58037ee44dd10b0029f6e89b732fe9f0dd7a7015e90b00e1281fb25bbd084bfa0240ba3378cb07716cb9193d4a +fa0240fa8d7a736e2c16e4074130f20dd10b00e119f9c6dc58e30e7d150200425645090040000380000600043000086000400003800006000430000860004000 +0380000600010c0008600010c00080000600010c0008600010c00080000600010c0002180010c00020800100010c0002180010c00020800100010c0002180004 +30002080014000030002180004300020800140000300021800043000086000400003800006000430000860004000038000060004300008600010c00080000600 +010c0008600010c00080000600010c0008600010c00020800100010c0002180010c00020800100010c0002180010c00020800140000300021800043000208001 +40000300021800043000208001400003800006000430000860004000038000060004300008600040000380000600010c0008600010c00080000600010c000860 +0010c00080000600010c0008600010c00020800100010c0002180010c00020800100010c0002180010c00020800140000300699457ab716b554889f9e36f3ea2 +59c389afbf97dadd3e7dc7a5756a16ce7cff131506d001139eaa057955f3f312dc78f82de7ce1f7fb3a20164bf7c25c872bd063d5c5aaa0c00110ee0c2ea0557 +f739b15be723ebef5b7359f19ae75e9e7dff33ffdab8a9f4ce1b7a9ed9a965cf410fcf5fb222bee55f7fd6eba4f6cdba5ffbe027cb3f0f82e0c0fdf7197cf129 +c71cd164efbdaa7db474f5a8b133464f9e1304c1e8bb2eaf5b7baf2e3ffe6bf980b9eba65e1ddb36ed78d15f367cbb31ad8f1e04c1fcf1374f9efec1fc252bfa +9cd9aeb05ac12b3316fce2ee491ddb36bde1d2531bee57eb83252b7e35fc85790b9795dff889096f0de8dba5f941fb6dd8b071da3b8bef183579e9ca3549956b +9bcd76bbdbff8ebb79f2f40faefecdb39b775bade0aa3e2776eb7264bd3a7b15ad28193765ee8831d3d77ff36d7c5765fb0c82a045f7dbcbf65ff6ebf12ef9b4 +e39b97ffdb6933175d7fd1c923c74e1ffed4b4c48f1c803002b8203f6fe46d1736ae5f7bf8d3d3161715b76dd1e8277d4e6c58b7d6adf74cfaf57d2f1edffaa0 +ffbbe6acf36f1c555a1a746edfac6ba7c36fbd67523cfff6a955e3f1df5db4e6cb75bfbeff1f6bbf5adfb7fbb1bf1fd47de5675f4e9bb968ec2bef0eed777adb +968ddfd9b2c059ad6a7e97630e1df7eabbdba46f3a1e3dbee7a30eddbfb05ac14d7f1edfa1f5c1fd7a75a85e35ffb083eadff9e894ea55f36fb9a2eb7db7f63e +f9b2611b376e8a6fdca4419d3b6fec3972ccf4bf3cf66ab326f506f53df9e8231af718f050c9175f275eaeed6b9bf86eab16e48dbced8296873418f6e4d4791f +7edaae65e36bce3fa965d30603fff07c10047d868c1a72e9a9c71e75609f21a312bf020e6d52af4df303863d35f5d5190b923d7200d21ec097fce0d8d687eddf +63e0430b3e5a1904c11bb3976cd8b869c825a78e18f3e692a2d5bf1afec2b09f9fd3bb6bbbb1afccbdf527674e7d7be1d32fbe13ffc5b34e3aa241dd9ad7dcfe +f7b90b960641f0fee2e56f3c7efd1927b4983673d184d7e7dd78d96967766a5916c0271dddacb07ac1d829734378f4f806fbedbb77cf810f1797ac9dfaf6c2d3 +8f6f7e7a8716b7dc3df1c569ef0741706893fdfa9f73c25187ee3f7b7e517ce3e607d7bff49627de98bd247e0cab3e5f7bd74dbdae3cb7e31f474c4eea80b7d9 +3889ddf638aedde18daffecdb393a77f10df388805032fecd2664ca3d9f38b66cd2f5ab3765d1004b3b61c70229aecbfcf398347cefbf0d30a1c39001596e88b +b0ba75396ace824f177d529c975725fe3565c682582ce8d0eae02008fef9c6fc09afcf1b72c9a943fb9f517befea3fffebc4b25f9cf29f057d868c2a9bdf3f5b +f355bc310d8260d5675ffefb9d455d3b1d1e8b6ddeb86bc796452b4a66beff71088f1eb7e0a395c5256be37ffe78d9679b532d08822088f7d0fb96db7849d1ea +b2bf0d82e0a57ffd77e5ea2f4f3bae79b2e5da4612bbed7ce4d21525f1f48d7bea85997f1c31f9dbad6f182465c1472bcbea93ec910390f60eb869e3bad5abe6 +bf3766e8363fdfb7f6e67cbaedbe7f4c1c7ee579671e7dc39d6357acfea26c83a52b4a1ad4ad79fbc06e47356b586f9fbdab57cb0f82203f6f73f08f7df5dd3b +7edaa375f346b3e71715e4e79d72dc618f4df8cff6af394ad3a30741b0eaf3b5657f8edff72edef293f8b755aac4ca36f8dfb2cfca3ffaa6d2d2c54b57b76dd1 +a802e52a2f89dd36aabbcdfb9156977cf5f0e837937aca63b158f96f97ae2ca9f0910390f600ae128bbdfddec7bf7de89fdbfc7cd9aacd6957a3b06a61b58220 +081ad6ad557e831f9ddee6f601dd5e7bebc33f3ffe5abcc59c30ec8ab2bf7df98df95fadfbe6cc4e87cf9e5f74429b836bee556ddc9477437bf42008d6addf50 +f6e778ee7fbde527a5a5a5dbc455e9f6ff34282d2d5b214eea80b7de47c2bbad12cbcb4bfa9d63b1adbfad59a3da5679bff5abab923a7200d21ec09fae2ca951 +bdeabb0bbebb577970a37dbb77396adcabefaefa2c88c582df0ee8f6c9f2cfa7ce5c74dd059d274fff60e1c7abe29b5d7bfe490b3f5975d56dcf6c2a2d0d8260 +afc2aae577fbf5fa0d2ffd7b7ed74e2dff30e2e5ae9d5abebbe0d3c545c5a13d7ab21a37a8b3752b191c74c0be8b97267dc07bb0db354d1a6eb5719d9a85ed5a +367e6fd1b2e5c53b0ec88d9b4a6b6c7dd68734a95be1271a805449b49d7aedad0f5b366d7068937a653fb9b4c7f157f5ee145f55bde0ac633ab43ef897f74cba +fb89d796177ff1bb81ddf2b6dcb9ad53ab70f5e76b376d69f24e68d3749bb672ec94b98dead76edba2d169c737dffee557e97ef4a4346b52efb85607957dfbfd +138f6850b7e60b53df4ff6802bbcdb69ef2cdabf5ead2ec71c5af693fee774bcf717bdcb6eaac79be9fcfcef9ed615abbf687e50fd822d1fe571e2d187d4adbd +57859f68005225d18fa27c7fd1f26e5d8eec75469bb55fafafbd77e145dd8ebdf0ec63fefcd8abff9eb5f8c0fdf71936f49ce727cf79f28599df6edcb4a8a8f8 +8a733a7eb5ee9bf86a65abc30e38f1e843d67ff36d2c16ebdcbed995e776dcbbb05ac917eb9e7f79767ccf45cb4bcefd5edb7687376ed2709fa1774df8badc3d +e1743ffa7517745e5c545cf6e19167773ef290c675873d3935feede1873438bd438b4953df5bf449717ce365abd6fcf0d4569b3696d6a85e7076e72387f63b63 +de879ffe72f80bf1dbc557f73971e3c64dff9ab5b8e4cb75bb38e06d4e6db7bb2d7f90f397ace8714aabb34e3a62ddfa0d350aabf6eedaaedf8f3a3c3a6ec6a4 +2d69ddb16dd3239b35dcb061635e5e95a2e5254110d4a955a373fb662d9ad6ff7ccdd7ed8f6872cb155d8b5694d4abb357fc34b7a9c0ae4b6db400a450a2b7a0 +577dbeb6cf9051832f3e65f0c5a754ab9abff07fab6ef8d398f1afcdab128bfd7e50f7afd67f73c723af6ceed2662e9a34f5bd011776993c7dc1e2a2e25bee9e +f8c557eb2fefd9a1f0bc824545c57f1a356568ff33f6a95558b6e74da5a5e35f9bd7af5787d7df5e58f682e4d01e3d29f3162e7b73ce477dcf6e7f40fdda2b57 +7ff9c8b819c39f9a16ff108c200846bf32e70727b7baf717bdcfbefafe9d1d7005765bdeb2556b7a0f1939f8e253aebba0734141de474b57fffade17cbde7315 +04c123e366b46dd1e8daf33baffb6643fb3e77044170f713af956e2aed797aeb7b6e3977d127c5b73ff0528f535bb538b87eb24fb4a102905ab1c61dfaaa4222 +b6ff48a96cde2d0059ce7fc600000218000430009026d6800140070c0002180010c00020800100010c0002180010c000907dfe1fe340a7ab4939395c00000000 +49454e44ae426082}}}}} +The east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell. Every berth has a number, a length in metres and a holder. The register is kept on paper and in a table; the two are compared each spring, and the differences are explained in the notes of the harbour master. Visitors are asked to call the harbour office on channel 9 before they come in, to give the length of their boat and its draught, and to say how many nights they plan to stay. The east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell. } +\par \pard\plain \s36\loch\sb57\sa113\cf0\fs18\i\ql\sb57\sa113\ltrpar{\loch +Figure }{\loch +{\field{\*\fldinst SEQ Figure \\* ARABIC }{\fldrslt 1}}}{\loch +: a picture that text flows around} +\par \pard\plain \s47\loch\qc\qc\ltrpar{ +{\pict{\*\picprop{\sp{\sn wzDescription}{\sv }}{\sp{\sn wzName}{\sv The second picture}}}\picscalex47\picscaley47\piccropl0\piccropr0\piccropt0\piccropb0\picw480\pich270\picwgoal7200\pichgoal4050\pngblip +89504e470d0a1a0a0000000d49484452000001e00000010e0802000000def853300000110d4944415478daeddd7b5cd465bec0f167b829984280a0022aa04412 +202a66c542d2b65aa8541aa8a05869a999966bdb69f39c7d6de65e6dddce9abe4a05cc3aa9a5915aea9ab71557f1c6c5d4b888a072511083bca40873fef8d5ec +701b66602ecf0c9ff78b3f0406fcfd9e99f9f0f5616654f50f9e2f0000f2b1630900804003000ce020542c020030410300083400583bb6380040da4053680090 +33d0e41900649da029340048895f12020081060018822d0e009035d0f41900e4c4160700c83a410b1533340030410300f49fa0999f0140d240f3280e0090135b +1c0020eb04cd000d0092069a2d0e0090135b1c0020eb04cd000d0092069a27aa00809cd8e20000592768e667009034d03c8a0300e4c4160700c83a4133400380 +a481668b0300e4c4160700c83a4133400380a481e6892a002027b6380040d6099af91900240d348fe200002668008001d8830600692768466800608206001068 +00b07a6c710000133400c0b0099a3500003903cd6b710000133400c000ec410380b41334233400304103000c99a05903009033d0bcdc2800c8892d0e00907582 +668006004903cd160700304103000cc01e3400483b4133420380a481660d00404a6c710080b41334233400304103000c99a079203400c81968fa0c00d24ed000 +0019b1070d00d24ed08cd000c0040d00306482660d0040ce40f3280e0060820600106800b08140b3c501004cd0000003f0303b00907682668406004903cd1a00 +8094d8e2000069276846680060820600183241b306002069a029340048892d0e00907682660d0040ce40f35a1c00c0040d0020d000600381668b030098a00100 +041a006c20d06c710000133400804003800d049a2d0e00608206001880174b02006927684668009034d0ac010048892d0e00907682668406004903cd1a000081 +06001810689ea802004cd00000020d00361068b6380080091a0040a001c00602cd16070030410300083400d842a0293400488957b30300692768d60000240d34 +85060029b1c50100d24ed0ac0100481a680a0d004cd0000003022d849a5500002927684668009034d0ac0100106800800181e6e5460180091a0040a001c01602 +4da101404abc160700483b41b306002069a029340030410330a7d48f66eabec0f3d3d7b04a52079a2500ba609a9b5d8c52cb3a413342033664edba991df82aa5 +d42fa49069d902cd1a0036614d87d2dc2cee3369348106605cab3b5d674de567d1688902ade2f5a001ebf661fa2ce3b6fec519ab595519f04415803a9be37ba2 +23815609c19b19def69cca61117833fa9be94afa61fa2c96d7e26f3c8ac31c76e7e50821be39952384783c6c280b02abf041faacd9cfb1d76149fc92d0e4fe99 +97d332d6bf22d3265bedaeb3b6abd24cbe11411f2c4b35276121ab6022bb9aa6b9a53164da64abdd15d676659a39768ae732445b7082e647a4a97a919ba37f53 +c684536a232ff5aebc1cdb5ed595a9e6fa3d1e89b0e0043d379109daf876ea51e796c69269132cb5adaeeafba9e67ba0c5cbcf33445b6882e6a7a3d1ede8509d +35ad79824c1b759d77e6e6b0a4ccd0561b68d6de78becec9e9fc3751baf3e4509a62b475b6bd25fdc75ab33e4e994a30415bbdaf8c51e7660d8ab36853becac9 +89932c6a9d59e4afe53b1d2668b4b3f2af4c660f5aba3a3763b6ace8380b19d266ac45b6814cffef5a733fd36ffe0babcd762df373546b82e6b5383a6d7b76ae +19c2342e22dc82476eba6330ff0a5bf65cac75946b1a0a93dee6353f89b98eac6f8b635b76ae1062bc1cd7dc3613a7b9d5bb4467cebd93076c9463906485b767 +e78ea7d1fa07da6a6ff3d6bdecaf4e79cd8a0e776bd31bc7048b5e6d5bcd784b6d49cf7337f5419aee2a30dbf24eb0f49d7f6b76aea1c7b07ccd8b663ec8c0e1 +2fcb5080095dacd4aad7a6ca1ee82f4fb67f478d1f162ee1519941cb13b7d48119f72a30f35998fff6d3d639ea79247f5b6dbe404b926619ae320b047aa1dc81 +ce30e48efa94b9aeb30c39ea2ca1ce5f05165c5b33dc7ef43f3bdd07f3aee9032d67972d78af27d0c6b98b9af40a23cda6bb1624595b53dc7e3a736aad1e8f49 +036d2d69ee0aa556fd3a49ae407f71c268f7d2a787874b7b6c5d873ed7826c0b6bac5b8e71cfabd9512dfbd0c88db6d22e9be18e6fc9402f9220d05b4c79ff7c +c648d7d616ea6c9a2b42da85edd82dc70ca7a31cd85f8d17689b49b389eefb960cf4eb960ef466b3dc3f2776eeaada4c9d4d7045c8bfaafadf6c2c722ee74ebc +4f97cd70f7b764a07f936c81407f7edc32f7cc4923c2ade550210f1d371b496e1e8696baeba4b9f305b070a0df487ed5cc7fe567c7f32c7edacf8e08b3964385 +0cb46f3032df2a7497bacb76b9f329b058a0ffcb2c81de24e56d3a41e775b3893ac36a352b3569365616cc1ee869260ff4a66352972e2132ccea8e1980651361 +a640bf69b2406fb4b6c625468659e36103b0482bcc11e8df9a20d01b681c80ae64b269926dccff51e5d3a374194057a4994aa78c3466a98df372a3ff479a01e0 +e73975aa9132dda9407f429701a0ed9935a973a5eee0ffa8f271d629ae0300d0738a4d7e30b42381a6cb00606a9a781a546a7db738d69366003052a9a7e997e9 +761ec5f1d111ba0c0046a61979a78f0aedc804bd8e340380896986e094d64add3cd0e9741900cc4e3313cfd02af57fb638d20e936600b030654a7eeea1502184 +ca7754322b020012b26309008040030008340010680000810600020d0020d00000020d00041a0040a001804003000834008040030081060010680020d0000002 +0d00041a0040a00100041a000834008040030081060010680000810600020d0020d00040a00100041a000834008040030008340010680000810600020d0020d0 +0000020d00041a0040a001804003000834001068000081060010680020d00000020d00041a0040a00100041a000834008040030081060010680000810600020d +0020d00040a00100041a000834008040030008340010680000810600020d0020d00000020d00041a0040a0018040030008340010680000810600e8c1c1a04b07 +fb7bcf9d1c151ed4cfc3ad47f995da8cbda73edcfcefbb771b253cb1958b9f7decc1a0fbc62f35f40b372e9bb1fb70fe9acd87b97100b09a093a66c4a02dcb9f +77b0b7fbfdaa9db3dfdeb4ef58e1bca9d14be6c5d9d88a3839da3b39d8ebff63207fdb5bdc8c005878827e7d466c69c5b5794b3f6f54ab851099d9c53fdebe3b +3be1918d3b4ee6e497d9cc8a3cf3ea5ab59a1b0600ab0a74ffbef7e61694376ad5eb8bbd79c1fedede1e3d95779dbb3bce4d8c1a171de2e5deb3f26adde66f72 +3fd874a8a1f1a7cb3b77739c9318352e26c4d3ad47d995daadfb4ea56664ddbe7357f96c77278799131f8a8b0ef1f576bb537ff76cf1e5755b8fee3e9caf7c36 +7fdb5b7bb20a3edf9dfb726254a09fe7b5ba9b197b4fadd870b0a1a151fbaf8e8b0ef174eb71e9f2f79fee38d9d65928dfea93edc7e727c7040de85d5fdf9099 +7d7e59fa9ef2aa3ae502df6d7d6b4f56c1dc773e6bf7b035b3b3f207653b45f9fe9a2f174d375b94cf669e2c7e6ddaa3695f66addc90d9eeba0120d0ed2bba50 +352cd8f7a1f08187734b948f9494d5bcf4f646e5cf8e0ef6694b927cbd5c576ecc3c5f7675e87d3eb313a3fa78f4fa9ff7bf56f60dd2964c0d0ef05ef1e9c1d3 +451511c1be2f4ff945b0bff7823f6f11423838d8a52e991a1ee49396917530fb5c8fee4e09632356fc76d25fd3f6acd97244f9fefd7abb2e99f7e47b1f1fb858 +796dc2e8d0b993a38410ef7d724089fbfa3f24070df05ab53133afa0fcfe00ef054931376edd6eeb44fcbcddfef69ba7d332b2febe7e7fa09fe7abc98f0e1be2 +1b3f7f4ded0fb75a6e77e838ecc445e98b66c4463ed03f7151bafecb38c8cf333ca8df8a0d07f71f2d6c77dd001068bd2c5dbd7bedefa7a4bf9374ecdb0b074e +141d387eaea0e48ae6b3291322c306f78d5fb0a6b0b44a087138b7a4bea171514a6c6ac69192b29a94f89111f7fbce7de7b33d5905ca67854a2c488a09cff0c9 +cd2f9b3e3e72f810bf251fecfa78fb71e5bbed3b5698faf6d48529b1bb0fe797565c1342dc1fe03d67c9a6bd470b85105979a5a3c2063e151baa043a257e64e8 +e07e0bfebc6567e65921c4a19cf3df1655ae5b9ad4d689040df49ab1f813e5c7cce1dc92eaef6fbcf7c6332f3dfbf05f52f734bba4eec3cec92fabbbf1a310c2 +a01d1ebfbef74e5a9876baa8429f75e3060a746506fc92f0c4998b6366af4acbc8eae3d96b514aecb67fccfaecdde74207f7533e3b2ee681bcc28ae24b57eded +ed94b77d470b552a312a74a010625c7448f9955a25738a0d3b4efe2575cfddbb0d4288098f86d6d4ded4de9750abc5aa8d99f676aa71310f281fa9a9bdb9ef58 +a1f2e746b5bae84295b7672fe5dd27a2865456d7ed3a7456f3e547f24a8a2f5d6deb444aca6a34ff081042fcf3d0775535d71f1b19d4f292ba0fbb630a4bab34 +756e77dd003041ebebf2d51ffeb4f69b3fadfd6670ffdef1a343a74f885cffc7e489afa59ebb58edefebd1ddc9e14cc69bcdbec4ddd54508e1efe371f2ec25ed +8fd7d4de5cfbc54fdb1701be1e7905e59a0d65457e69951022c0cfe3a70d968bd5dabfbbabbfdb606fa752fe3cd0c73d2fbfbcd96ff62e565e0bf0f568f52c2e +545ed37eb751ad3e5f5e33f43e9f9697d47dd87a52a954daef9657d536f92b74ae1b00026df81878a16ad9babdf92597972d7a6af2d888a5ab77dba95427ce5c +fcc39addcd2e5959fd8310c2ce4e656f6fd89362d46ab5324a2baedf6c734fd9c1deae69038510a29b9383eeefdcec43cd7e3cfcf4ef0bc30f5b08d1ec587aba +746bf2f3a0e96fff74af1b00b638da97383662cbf2e74302fb687f50d911eeedde5308515155ebd2dde9dbc20acddbf59bb747470eeee1ec2484a8a8aaf3ebe3 +a6fdb56e3d9d47470e561e01527ce96aa09fa78343938309f6f716429cff79a742ddf663dfcaabea06fab8376b74ff3ef7b675795f6fb7a613ae18d0cffd7c79 +2b5b22ba0fbb550d8d6a176727ed8f68fe11d02addeb068040b7afa0b42a6450dff94931dac3aad26be55785078e1705fb7b0ff2f3d47c7646fc8373121eb956 +77530891995ddcd7b357cc88419acfce9af4f0aaff4e70b0b713426cdd7fcaddd565f2d861dad19c93f04843a37afb816fdb3db67d470bbcdc7bc66a6d228f8e +1cdccfcbb5adcb07fa798e0c1da079f789a821de1e3d771c3cdbf292ba0f5bf36343fb47cb959a1f82067839fefc5497a861011eae3d741cbcee7503d095d9f7 +f20dd3e77295d5759ef7de333e262432a4ffedfabbee6e2e631e0e5efcd298caeabac52bbeba53df70b6f8f2b89890671e0fbf71ebb6eb3dced3c64526c58d58 +be7effbf73ce0b21f24baec48f0e7df217437ebc5defe2ec94302662e6c4511f6d3dfaf5c1b34288534515a3c2064e7a7ca87377c746b53aa8bfd71b2ffc327a +78e0bbe97bf71d2b1242bc3235fa7cd9d5affe7546733c71d12101be1e2b3e3d28843873ae727ccc034f44dd7ffdd69d7b9cbbc5450ff9754aecc5ca6b1e6e3d +940b687b656a746575dd53b1a18d0d6a97ee8e71d1216fce7cfc7451c5ef56ee507639b4ff2edd872d847878a87f48609ffafa067b7bbbb2cbb54208b75e2ed1 +c303eff3f7fabeeed6f0217e8b5f1c5376a5d6f3e723697922bad70d4057a6f21d95acffa51f7b3068fa84c8405fcf7b7a74bb74f9fb5d87be4bfde2c88d5b77 +94cff6f5ecb570fae8e81181dd9c1cce5da84eff326bdb81d39aaff5ebe3b670fae8a888004747fbd2f29a0d3b4e6edc99ad79da8b7337c799131f8a8b1ee2eb +eda6e43efdcbac664f5469ebd91f42081f2fd7d79f7bec91087f077bbb82d2aabfafdf3f6d7c64abafc5a17cab2379a5c971c3fb79b956d55cdffeafd32b3764 +deba5ddfeadfa5fbb0070fe8bdfcf5a7fd7d3c7ebc533f3c719910c2de4e356f4af4d3bf0c73ebe95c7ce9ea079b0ec5c786367ba28af689b4bb6e00087457d1 +6a22014042bcdc2800106800008106001bd0e5f6a00180091a0040a0018040030008340010680000810600106800b07aff0fc1e0db14f91389b5000000004945 +4e44ae426082} +} +\par \pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +{\field{\*\fldinst SHAPE }{\fldrslt{\shp{\*\shpinst\shpleft1838\shptop113\shpright3830\shpbottom394\shpwr3\shpbxignore\shpbyignore\shpz2{\sp{\sn shapeType}{\sv 2}}{\sp{\sn posrelh}{\sv 3}}{\sp{\sn pVerticies}{\sv 8;4;(3600,0);(0,3600);(0,18000);(3600,21600)}}{\sp{\sn pSegmentInfo}{\sv 2;10;16384;42753;1;43009;1;42753;1;43009;24577;32768}}{\sp{\sn lineJoinStyle}{\sv 2}}{\sp{\sn lineColor}{\sv 10773812}}{\sp{\sn lineBackColor}{\sv 6003403}}{\sp{\sn geoTop}{\sv 0}}{\sp{\sn geoRight}{\sv 21600}}{\sp{\sn geoLeft}{\sv 0}}{\sp{\sn geoBottom}{\sv 21600}}{\sp{\sn fshadowObscured}{\sv 1}}{\sp{\sn fillColor}{\sv 13606770}}{\sp{\sn fillBackColor}{\sv 3170445}}{\sp{\sn fNoFillHitTest}{\sv 1}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn anchorText}{\sv 0}}{\sp{\sn adjustValue}{\sv 3600}}{\sp{\sn wzDescription}{\sv }}{\sp{\sn wzName}{\sv Callout}}{\sp{\sn gtextUNICODE}{\sv A shape with text in it}}{\sp{\sn gtextFont}{\sv Liberation Serif}}{\sp{\sn gtextSize}{\sv 720896}}{\sp{\sn rotation}{\sv 0}}}}}}A line of text beside a shape.} +\par \pard\plain \s1\loch\ilvl0\outlinelevel0\cf20\fs34{\listtext\pard\plain 6. \tab}\ls1 \fi-510\li510\lin510\ql\fi0\li0\lin0\ltrpar{\loch +{\*\bkmkstart links}{\*\bkmkend links}Links, fields and notes} +\par \pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +An external link: }{{\field{\*\fldinst HYPERLINK "https://exav.org/" }{\fldrslt {\loch\loch\cf18\ul\ulc0\loch +exav.org}{}}}\loch +. An internal link: }{{\field{\*\fldinst HYPERLINK "#intro" }{\fldrslt {\loch\loch\cf18\ul\ulc0\loch +back to the introduction}{}}}\loch +. A reference to a bookmark: }{\loch +{\field{\*\fldinst REF tables \\h }{\fldrslt }}}{\loch +.} +\par \pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +Fields: this document is titled \u8220\'93}{\loch +{\field{\*\fldinst TITLE }{\fldrslt Harbour handbook}}}{\loch +\u8221\'94, and this line is on page }{\loch +{\field{\*\fldinst PAGE }{\fldrslt 4}}}{\loch +. A fixed date: }{\loch +{\field\fldlock{\*\fldinst DATE \\@"dd/MM/yyyy" }{\fldrslt 01/01/2000}}}{\loch +.} +\par \pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +A comment is attached to this word}{ +{\*\atnid }{\*\atnauthor exav}\chatn{\*\annotation{\*\atndate -968816640}\loch\ltrpar\loch{\rtlch\af10\alang1023 \ltrch\lang1023\langfe1023\loch\lang1023\kerning0\fs24\dbch\langfe1023\af10\loch +A comment: the viewer shows or ignores it.}}}{\loch +. A change that was tracked: }{\revised\revauth1\revdttm-968816640 \loch +this text was inserted}{\loch +, }{\deleted\revauthdel1\revdttmdel-968816640 \loch +some deleted words }{\loch +and some text was deleted before this one.} +\par \ql\fi-283\li283\lin283\ltrpar\pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +Citations [1] [2]. }{{\super \loch \chftn{\*\footnote \chftn\pard\plain \s51\loch\fi-283\li283\lin283\fs18{\loch +\tab A second footnote, with }{\loch\cs16\loch\i\loch +emphasis}{\loch +.} +}} +} +\par \pard\plain \s41\ql\ltrpar{\loch +{\*\bkmkstart wide}{\*\bkmkend wide}Wide table (landscape)} +\par \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx12727\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat20\cellx13890\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Month}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Berth 1}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Berth 2}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Berth 3}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Berth 4}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Berth 5}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Berth 6}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Berth 7}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Berth 8}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Berth 9}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Berth 10}\cell\pard\plain \s57\loch\qc\cf8\b\intbl\qc\ltrpar{\loch +Total}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +Jan}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +46}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +Feb}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +53}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +Mar}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +51}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +Apr}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +49}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +May}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +47}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +Jun}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +54}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +Jul}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +52}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +Aug}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +50}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +Sep}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +48}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +Oct}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +46}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +Nov}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +53}\cell\row\pard \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx1157\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx2314\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx3471\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx4628\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx5785\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx6942\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx8099\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx9256\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx10413\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx11570\clbrdrt\brdrs\brdrw10\brdrcf0\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\cellx12727\clbrdrt\brdrs\brdrw30\brdrcf1\clpadfl3\clpadl57\clbrdrl\brdrs\brdrw10\brdrcf0\clpadft3\clpadt57\clbrdrb\brdrs\brdrw10\brdrcf0\clpadfb3\clpadb57\clbrdrr\brdrs\brdrw10\brdrcf0\clpadfr3\clpadr57\clcbpat22\cellx13890\pard\plain \s56\intbl\ql\ltrpar{\loch +Dec}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +2}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +7}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +3}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +8}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +4}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +9}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +5}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +1}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +6}\cell\pard\plain \s58\loch\qr\intbl\qr\ltrpar{\loch +51}\cell\row\pard \pard\plain \s34\loch\sl300\slmult1\sb0\sa125\sl300\slmult1\ql\sb0\sa125\ltrpar{\loch +Nights let at each berth, by month.} +\par } \ No newline at end of file diff --git a/crates/exav-viewer/demo/examples/files/converted/workbook.fods b/crates/exav-viewer/demo/examples/files/converted/workbook.fods new file mode 100644 index 0000000..51e83c5 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/converted/workbook.fods @@ -0,0 +1,62 @@ + + +exav projectHarbour workbookA workbook made for the exav demo (CC0-1.0)2000-01-01T00:00:00 + +view1 + +02 +33 + +02 +11 + + + + +€ +€ +% +// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Choose one of the five categories. +Harbour budget, first halfAmounts in euros; the totals are formulas.CategoryJanFebMarAprMayJunTotalShareBerths let112001180012100154002180024900972000.572775486152033Visitors31003300480082001560019200542000.319387153800825Shop120011001500260041005200157000.09251620506776664Fuel9008001100190033004400124000.07307012374779022Repairs-2100-900-3300-1500-800-1200-9800-0.05774896876841485Net1430016100162002660044000525001697001Averages and checksAverage a month28283.333333333332Best monthJunMonths in credit6Largest item24900Rounded share of fuel0.073StatussurplusLookup: categoryShopits total15700Linkexav.org/viewerNote on a cellexavThis cell has a comment.hover me +DateRegionProductUnitsUnit priceAmount01/01/2000WestMooring3215.74503.6802/01/2000EastPower448.47193.8803/01/2000NorthFuel347.46253.6404/01/2000SouthShop2327.12623.7606/01/2000WestWater2511.26281.507/01/2000EastMooring1944.61847.5908/01/2000NorthPower224.6949.3809/01/2000SouthFuel531.97159.8511/01/2000WestShop1736.03612.5112/01/2000EastWater1744.79761.4313/01/2000NorthMooring3018.48554.414/01/2000SouthPower3839.621505.5616/01/2000WestFuel2618.98493.4817/01/2000EastShop282.0958.5218/01/2000NorthWater319.3157.9319/01/2000SouthMooring3820.21767.9821/01/2000WestPower235.9471.8822/01/2000EastFuel3529.341026.923/01/2000NorthShop83.7630.0824/01/2000SouthWater3143.01333.026/01/2000WestMooring217.27152.6727/01/2000EastPower1540.31604.6528/01/2000NorthFuel2114.02294.4201/02/2000SouthShop3738.551426.3503/02/2000WestWater1045.02450.204/02/2000EastMooring1243.89526.6805/02/2000NorthPower2650.131303.3806/02/2000SouthFuel940.14361.2608/02/2000WestShop149.5649.5609/02/2000EastWater2726.86725.2210/02/2000NorthMooring3852.952012.111/02/2000SouthPower307.93237.913/02/2000WestFuel2424.85596.414/02/2000EastShop3429.821013.8815/02/2000NorthWater1642.51680.1616/02/2000SouthMooring618.93113.5818/02/2000WestPower2517.97449.2519/02/2000EastFuel3434.581175.7220/02/2000NorthShop1637.55600.821/02/2000SouthWater1613.41214.5623/02/2000WestMooring3245.321450.2424/02/2000EastPower845.63365.0425/02/2000NorthFuel1355.42720.4626/02/2000SouthShop2313.93320.3928/02/2000WestWater1011.8118.001/03/2000EastMooring3457.931969.6202/03/2000NorthPower3837.21413.603/03/2000SouthFuel2558.291457.2505/03/2000WestShop2447.821147.6806/03/2000EastWater315.14159.3407/03/2000NorthMooring216.92145.3208/03/2000SouthPower1513.22198.310/03/2000WestFuel2851.81450.411/03/2000EastShop99.3584.1512/03/2000NorthWater330.5991.7713/03/2000SouthMooring1251.27615.2415/03/2000WestPower2343.07990.6116/03/2000EastFuel3814.39546.8217/03/2000NorthShop3042.951288.518/03/2000SouthWater225.01110.2220/03/2000WestMooring1223.36280.3221/03/2000EastPower2736.2977.422/03/2000NorthFuel440.81163.2423/03/2000SouthShop2732.34873.1825/03/2000WestWater1213.49161.8826/03/2000EastMooring2230.72675.8427/03/2000NorthPower2529.88747.028/03/2000SouthFuel533.1165.502/04/2000WestShop2924.83720.0703/04/2000EastWater313.1497.3404/04/2000NorthMooring2513.9347.505/04/2000SouthPower2144.99944.7907/04/2000WestFuel2724.07649.8908/04/2000EastShop1654.75876.009/04/2000NorthWater422.2388.9210/04/2000SouthMooring1622.19355.0412/04/2000WestPower207.41148.213/04/2000EastFuel1933.71640.4914/04/2000NorthShop334.65103.9515/04/2000SouthWater3645.151625.417/04/2000WestMooring150.8450.8418/04/2000EastPower3745.151670.5519/04/2000NorthFuel649.57297.4220/04/2000SouthShop3216.72535.0422/04/2000WestWater2221.88481.3623/04/2000EastMooring1917.18326.4224/04/2000NorthPower2020.44408.825/04/2000SouthFuel2337.88871.2427/04/2000WestShop78.0656.4228/04/2000EastWater2327.66636.1801/05/2000NorthMooring3742.991590.6302/05/2000SouthPower167.11113.7604/05/2000WestFuel531.73158.6505/05/2000EastShop725.47178.2906/05/2000NorthWater3521.31745.8507/05/2000SouthMooring2613.44349.4409/05/2000WestPower3416.15549.110/05/2000EastFuel3710.53389.6111/05/2000NorthShop621.7130.212/05/2000SouthWater1115.06165.6614/05/2000WestMooring2556.341408.515/05/2000EastPower219.31195.5116/05/2000NorthFuel3140.751263.2517/05/2000SouthShop1753.31906.2719/05/2000WestWater3710.33382.2120/05/2000EastMooring3933.161293.2421/05/2000NorthPower45.0820.3222/05/2000SouthFuel3536.121264.224/05/2000WestShop246.5393.0625/05/2000EastWater756.38394.6626/05/2000NorthMooring122.5230.2427/05/2000SouthPower215.73120.3301/06/2000WestFuel551.14255.702/06/2000EastShop1715.73267.4103/06/2000NorthWater525.51127.5504/06/2000SouthMooring2717.38469.2606/06/2000WestPower3919.88775.3207/06/2000EastFuel2823.57659.9608/06/2000NorthShop1830.72552.9609/06/2000SouthWater3047.471424.1Total247970070.1 + +Spending by category + +Net income by month + +Share of the total + + + + + diff --git a/crates/exav-viewer/demo/examples/files/converted/workbook.ods b/crates/exav-viewer/demo/examples/files/converted/workbook.ods new file mode 100644 index 0000000..7633e61 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/converted/workbook.ods differ diff --git a/crates/exav-viewer/demo/examples/files/converted/workbook.xls b/crates/exav-viewer/demo/examples/files/converted/workbook.xls new file mode 100644 index 0000000..d6792cf Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/converted/workbook.xls differ diff --git a/crates/exav-viewer/demo/examples/files/ifc/house.ifc b/crates/exav-viewer/demo/examples/files/ifc/house.ifc new file mode 100644 index 0000000..4d68171 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/ifc/house.ifc @@ -0,0 +1,1438 @@ +ISO-10303-21; +HEADER; +FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1'); +FILE_NAME('house.ifc','2000-01-01T00:00:00',('exav'),('exav'),'exav make-ifc.py','exav make-ifc.py',''); +FILE_SCHEMA(('IFC4')); +ENDSEC; +DATA; +#1=IFCCARTESIANPOINT((0.0,0.0,0.0)); +#2=IFCAXIS2PLACEMENT3D(#1,$,$); +#3=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#2,$); +#4=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#3,$,.MODEL_VIEW.,$); +#5=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.); +#6=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.); +#7=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.); +#8=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.); +#9=IFCUNITASSIGNMENT((#5,#6,#7,#8)); +#10=IFCPROJECT('0iiDjLHJDU6JvG2gAu0Vub',$,'Example house',$,$,$,$,(#3),#9); +#11=IFCAXIS2PLACEMENT3D(#1,$,$); +#12=IFCLOCALPLACEMENT($,#11); +#13=IFCSITE('2KMASZqYy2AlEWEkUMXo6G',$,'Site',$,$,#12,$,$,.ELEMENT.,$,$,$,$,$); +#14=IFCAXIS2PLACEMENT3D(#1,$,$); +#15=IFCLOCALPLACEMENT(#12,#14); +#16=IFCBUILDING('2FwUvlYrJqXdTAReyC5SSO',$,'House',$,$,#15,$,$,.ELEMENT.,$,$,$); +#17=IFCAXIS2PLACEMENT3D(#1,$,$); +#18=IFCLOCALPLACEMENT(#15,#17); +#19=IFCBUILDINGSTOREY('09NtmAGcpl5Gr$RW07XYjX',$,'Ground floor',$,$,#18,$,$,.ELEMENT.,0.0); +#20=IFCCARTESIANPOINT((0.0,0.0,3.0)); +#21=IFCAXIS2PLACEMENT3D(#20,$,$); +#22=IFCLOCALPLACEMENT(#15,#21); +#23=IFCBUILDINGSTOREY('1galn8M2KF8wHmG39RqQr2',$,'First floor',$,$,#22,$,$,.ELEMENT.,3.0); +#24=IFCRELAGGREGATES('2sYclOCbti5hhc7FQxED0l',$,$,$,#10,(#13)); +#25=IFCRELAGGREGATES('2_Pl7nDxC1Hp2Ec1PpnkOB',$,$,$,#13,(#16)); +#26=IFCRELAGGREGATES('3rIlw0cwcrgHJsm1Z0AedM',$,$,$,#16,(#19,#23)); +#27=IFCMATERIAL('Brick, rendered'); +#28=IFCDIRECTION((0.0,0.0,1.0)); +#29=IFCDIRECTION((1.0,0.0,0.0)); +#30=IFCAXIS2PLACEMENT3D(#1,#28,#29); +#31=IFCLOCALPLACEMENT(#18,#30); +#32=IFCCARTESIANPOINT((5.0,0.0)); +#33=IFCAXIS2PLACEMENT2D(#32,$); +#34=IFCRECTANGLEPROFILEDEF(.AREA.,$,#33,10.0,0.3); +#35=IFCAXIS2PLACEMENT3D(#1,$,$); +#36=IFCDIRECTION((0.0,0.0,1.0)); +#37=IFCEXTRUDEDAREASOLID(#34,#35,#36,2.8); +#38=IFCCOLOURRGB($,0.93,0.9,0.82); +#39=IFCSURFACESTYLERENDERING(#38,0.0,$,$,$,$,$,$,.FLAT.); +#40=IFCSURFACESTYLE('Render',.BOTH.,(#39)); +#41=IFCSTYLEDITEM(#37,(#40),$); +#42=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#37)); +#43=IFCPRODUCTDEFINITIONSHAPE($,$,(#42)); +#44=IFCWALL('1jv90fDbLSS0zj$PR7F36D',$,'G-South',$,$,#31,#43,$,.STANDARD.); +#45=IFCCARTESIANPOINT((1.6,0.0,0.9)); +#46=IFCAXIS2PLACEMENT3D(#45,$,$); +#47=IFCLOCALPLACEMENT(#31,#46); +#48=IFCCARTESIANPOINT((0.0,0.0)); +#49=IFCAXIS2PLACEMENT2D(#48,$); +#50=IFCRECTANGLEPROFILEDEF(.AREA.,$,#49,1.2,0.5); +#51=IFCAXIS2PLACEMENT3D(#1,$,$); +#52=IFCDIRECTION((0.0,0.0,1.0)); +#53=IFCEXTRUDEDAREASOLID(#50,#51,#52,1.3); +#54=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#53)); +#55=IFCPRODUCTDEFINITIONSHAPE($,$,(#54)); +#56=IFCOPENINGELEMENT('2tx3XkEeRvnV9Jw3rqVVqa',$,'Opening G-South 1',$,$,#47,#55,$,.OPENING.); +#57=IFCRELVOIDSELEMENT('3EXGoG4S8oR6WagG$aChFm',$,$,$,#44,#56); +#58=IFCAXIS2PLACEMENT3D(#45,$,$); +#59=IFCLOCALPLACEMENT(#31,#58); +#60=IFCAXIS2PLACEMENT2D(#48,$); +#61=IFCRECTANGLEPROFILEDEF(.AREA.,$,#60,1.2,0.1); +#62=IFCAXIS2PLACEMENT3D(#1,$,$); +#63=IFCDIRECTION((0.0,0.0,1.0)); +#64=IFCEXTRUDEDAREASOLID(#61,#62,#63,1.3); +#65=IFCCOLOURRGB($,0.95,0.95,0.95); +#66=IFCSURFACESTYLERENDERING(#65,0.0,$,$,$,$,$,$,.FLAT.); +#67=IFCSURFACESTYLE('Frame',.BOTH.,(#66)); +#68=IFCSTYLEDITEM(#64,(#67),$); +#69=IFCAXIS2PLACEMENT2D(#48,$); +#70=IFCRECTANGLEPROFILEDEF(.AREA.,$,#69,1.08,0.04); +#71=IFCCARTESIANPOINT((0.0,0.0,0.06)); +#72=IFCAXIS2PLACEMENT3D(#71,$,$); +#73=IFCDIRECTION((0.0,0.0,1.0)); +#74=IFCEXTRUDEDAREASOLID(#70,#72,#73,1.1800000000000002); +#75=IFCCOLOURRGB($,0.55,0.78,0.92); +#76=IFCSURFACESTYLERENDERING(#75,0.55,$,$,$,$,$,$,.FLAT.); +#77=IFCSURFACESTYLE('Glass',.BOTH.,(#76)); +#78=IFCSTYLEDITEM(#74,(#77),$); +#79=IFCAXIS2PLACEMENT2D(#48,$); +#80=IFCRECTANGLEPROFILEDEF(.AREA.,$,#79,0.05,0.12); +#81=IFCAXIS2PLACEMENT3D(#1,$,$); +#82=IFCDIRECTION((0.0,0.0,1.0)); +#83=IFCEXTRUDEDAREASOLID(#80,#81,#82,1.3); +#84=IFCSTYLEDITEM(#83,(#67),$); +#85=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#64,#74,#83)); +#86=IFCPRODUCTDEFINITIONSHAPE($,$,(#85)); +#87=IFCWINDOW('0k7vnn7mWSodkjPeo9hnOL',$,'Window G-South 1',$,$,#59,#86,$,1.3,1.2,.WINDOW.,.NOTDEFINED.,$); +#88=IFCRELFILLSELEMENT('2RMS4yJ$3Ov9e_FWsCNrjn',$,$,$,#56,#87); +#89=IFCCARTESIANPOINT((4.2,0.0,0.9)); +#90=IFCAXIS2PLACEMENT3D(#89,$,$); +#91=IFCLOCALPLACEMENT(#31,#90); +#92=IFCAXIS2PLACEMENT2D(#48,$); +#93=IFCRECTANGLEPROFILEDEF(.AREA.,$,#92,1.2,0.5); +#94=IFCAXIS2PLACEMENT3D(#1,$,$); +#95=IFCDIRECTION((0.0,0.0,1.0)); +#96=IFCEXTRUDEDAREASOLID(#93,#94,#95,1.3); +#97=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#96)); +#98=IFCPRODUCTDEFINITIONSHAPE($,$,(#97)); +#99=IFCOPENINGELEMENT('0$chDW1fT87UzE$p4vq45Y',$,'Opening G-South 2',$,$,#91,#98,$,.OPENING.); +#100=IFCRELVOIDSELEMENT('0dTBEaLKSStc9jhDzzvHPK',$,$,$,#44,#99); +#101=IFCAXIS2PLACEMENT3D(#89,$,$); +#102=IFCLOCALPLACEMENT(#31,#101); +#103=IFCAXIS2PLACEMENT2D(#48,$); +#104=IFCRECTANGLEPROFILEDEF(.AREA.,$,#103,1.2,0.1); +#105=IFCAXIS2PLACEMENT3D(#1,$,$); +#106=IFCDIRECTION((0.0,0.0,1.0)); +#107=IFCEXTRUDEDAREASOLID(#104,#105,#106,1.3); +#108=IFCSTYLEDITEM(#107,(#67),$); +#109=IFCAXIS2PLACEMENT2D(#48,$); +#110=IFCRECTANGLEPROFILEDEF(.AREA.,$,#109,1.08,0.04); +#111=IFCAXIS2PLACEMENT3D(#71,$,$); +#112=IFCDIRECTION((0.0,0.0,1.0)); +#113=IFCEXTRUDEDAREASOLID(#110,#111,#112,1.1800000000000002); +#114=IFCSTYLEDITEM(#113,(#77),$); +#115=IFCAXIS2PLACEMENT2D(#48,$); +#116=IFCRECTANGLEPROFILEDEF(.AREA.,$,#115,0.05,0.12); +#117=IFCAXIS2PLACEMENT3D(#1,$,$); +#118=IFCDIRECTION((0.0,0.0,1.0)); +#119=IFCEXTRUDEDAREASOLID(#116,#117,#118,1.3); +#120=IFCSTYLEDITEM(#119,(#67),$); +#121=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#107,#113,#119)); +#122=IFCPRODUCTDEFINITIONSHAPE($,$,(#121)); +#123=IFCWINDOW('1HZ74_qNMwPbIgyj4du78g',$,'Window G-South 2',$,$,#102,#122,$,1.3,1.2,.WINDOW.,.NOTDEFINED.,$); +#124=IFCRELFILLSELEMENT('2hslLgUM3$Y49_YKHOr29Z',$,$,$,#99,#123); +#125=IFCCARTESIANPOINT((7.25,0.0,0.0)); +#126=IFCAXIS2PLACEMENT3D(#125,$,$); +#127=IFCLOCALPLACEMENT(#31,#126); +#128=IFCAXIS2PLACEMENT2D(#48,$); +#129=IFCRECTANGLEPROFILEDEF(.AREA.,$,#128,1.1,0.5); +#130=IFCAXIS2PLACEMENT3D(#1,$,$); +#131=IFCDIRECTION((0.0,0.0,1.0)); +#132=IFCEXTRUDEDAREASOLID(#129,#130,#131,2.1); +#133=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#132)); +#134=IFCPRODUCTDEFINITIONSHAPE($,$,(#133)); +#135=IFCOPENINGELEMENT('0HgAoBlkU8r1t7BofrmrGR',$,'Opening G-South 3',$,$,#127,#134,$,.OPENING.); +#136=IFCRELVOIDSELEMENT('3vD_FU1pSEsJLe2aFg2Brc',$,$,$,#44,#135); +#137=IFCAXIS2PLACEMENT3D(#125,$,$); +#138=IFCLOCALPLACEMENT(#31,#137); +#139=IFCAXIS2PLACEMENT2D(#48,$); +#140=IFCRECTANGLEPROFILEDEF(.AREA.,$,#139,1.0,0.06); +#141=IFCAXIS2PLACEMENT3D(#1,$,$); +#142=IFCDIRECTION((0.0,0.0,1.0)); +#143=IFCEXTRUDEDAREASOLID(#140,#141,#142,2.0500000000000003); +#144=IFCCOLOURRGB($,0.45,0.28,0.14); +#145=IFCSURFACESTYLERENDERING(#144,0.0,$,$,$,$,$,$,.FLAT.); +#146=IFCSURFACESTYLE('Door',.BOTH.,(#145)); +#147=IFCSTYLEDITEM(#143,(#146),$); +#148=IFCAXIS2PLACEMENT2D(#48,$); +#149=IFCRECTANGLEPROFILEDEF(.AREA.,$,#148,0.08,0.14); +#150=IFCCARTESIANPOINT((0.35000000000000003,0.0,1.0)); +#151=IFCAXIS2PLACEMENT3D(#150,$,$); +#152=IFCDIRECTION((0.0,0.0,1.0)); +#153=IFCEXTRUDEDAREASOLID(#149,#151,#152,0.08); +#154=IFCSTYLEDITEM(#153,(#67),$); +#155=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#143,#153)); +#156=IFCPRODUCTDEFINITIONSHAPE($,$,(#155)); +#157=IFCDOOR('127wtWXZdGDL8xBstF2f1M',$,'Door G-South 3',$,$,#138,#156,$,2.1,1.1,.DOOR.,.NOTDEFINED.,$); +#158=IFCRELFILLSELEMENT('0wKT_koxWhGVhAJtZ_mWqI',$,$,$,#135,#157); +#159=IFCCARTESIANPOINT((10.0,0.0,0.0)); +#160=IFCDIRECTION((0.0,0.0,1.0)); +#161=IFCDIRECTION((0.0,1.0,0.0)); +#162=IFCAXIS2PLACEMENT3D(#159,#160,#161); +#163=IFCLOCALPLACEMENT(#18,#162); +#164=IFCCARTESIANPOINT((4.0,0.0)); +#165=IFCAXIS2PLACEMENT2D(#164,$); +#166=IFCRECTANGLEPROFILEDEF(.AREA.,$,#165,8.0,0.3); +#167=IFCAXIS2PLACEMENT3D(#1,$,$); +#168=IFCDIRECTION((0.0,0.0,1.0)); +#169=IFCEXTRUDEDAREASOLID(#166,#167,#168,2.8); +#170=IFCSTYLEDITEM(#169,(#40),$); +#171=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#169)); +#172=IFCPRODUCTDEFINITIONSHAPE($,$,(#171)); +#173=IFCWALL('0qk0kq6a8AV2GIUo7T4G1J',$,'G-East',$,$,#163,#172,$,.STANDARD.); +#174=IFCCARTESIANPOINT((2.05,0.0,0.9)); +#175=IFCAXIS2PLACEMENT3D(#174,$,$); +#176=IFCLOCALPLACEMENT(#163,#175); +#177=IFCAXIS2PLACEMENT2D(#48,$); +#178=IFCRECTANGLEPROFILEDEF(.AREA.,$,#177,1.3,0.5); +#179=IFCAXIS2PLACEMENT3D(#1,$,$); +#180=IFCDIRECTION((0.0,0.0,1.0)); +#181=IFCEXTRUDEDAREASOLID(#178,#179,#180,1.3); +#182=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#181)); +#183=IFCPRODUCTDEFINITIONSHAPE($,$,(#182)); +#184=IFCOPENINGELEMENT('139w4z2NUPM6f02o5RLGf4',$,'Opening G-East 1',$,$,#176,#183,$,.OPENING.); +#185=IFCRELVOIDSELEMENT('0zHoDqcPl8c9r_1YaR3wI5',$,$,$,#173,#184); +#186=IFCAXIS2PLACEMENT3D(#174,$,$); +#187=IFCLOCALPLACEMENT(#163,#186); +#188=IFCAXIS2PLACEMENT2D(#48,$); +#189=IFCRECTANGLEPROFILEDEF(.AREA.,$,#188,1.3,0.1); +#190=IFCAXIS2PLACEMENT3D(#1,$,$); +#191=IFCDIRECTION((0.0,0.0,1.0)); +#192=IFCEXTRUDEDAREASOLID(#189,#190,#191,1.3); +#193=IFCSTYLEDITEM(#192,(#67),$); +#194=IFCAXIS2PLACEMENT2D(#48,$); +#195=IFCRECTANGLEPROFILEDEF(.AREA.,$,#194,1.1800000000000002,0.04); +#196=IFCAXIS2PLACEMENT3D(#71,$,$); +#197=IFCDIRECTION((0.0,0.0,1.0)); +#198=IFCEXTRUDEDAREASOLID(#195,#196,#197,1.1800000000000002); +#199=IFCSTYLEDITEM(#198,(#77),$); +#200=IFCAXIS2PLACEMENT2D(#48,$); +#201=IFCRECTANGLEPROFILEDEF(.AREA.,$,#200,0.05,0.12); +#202=IFCAXIS2PLACEMENT3D(#1,$,$); +#203=IFCDIRECTION((0.0,0.0,1.0)); +#204=IFCEXTRUDEDAREASOLID(#201,#202,#203,1.3); +#205=IFCSTYLEDITEM(#204,(#67),$); +#206=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#192,#198,#204)); +#207=IFCPRODUCTDEFINITIONSHAPE($,$,(#206)); +#208=IFCWINDOW('2bzrq0o36QD$kmJ_0Ouqn1',$,'Window G-East 1',$,$,#187,#207,$,1.3,1.3,.WINDOW.,.NOTDEFINED.,$); +#209=IFCRELFILLSELEMENT('20dGdEg6fNRR1GxAUiq7ZD',$,$,$,#184,#208); +#210=IFCCARTESIANPOINT((5.65,0.0,0.9)); +#211=IFCAXIS2PLACEMENT3D(#210,$,$); +#212=IFCLOCALPLACEMENT(#163,#211); +#213=IFCAXIS2PLACEMENT2D(#48,$); +#214=IFCRECTANGLEPROFILEDEF(.AREA.,$,#213,1.3,0.5); +#215=IFCAXIS2PLACEMENT3D(#1,$,$); +#216=IFCDIRECTION((0.0,0.0,1.0)); +#217=IFCEXTRUDEDAREASOLID(#214,#215,#216,1.3); +#218=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#217)); +#219=IFCPRODUCTDEFINITIONSHAPE($,$,(#218)); +#220=IFCOPENINGELEMENT('3sJK8Ff8kYCctpDoeIXd0e',$,'Opening G-East 2',$,$,#212,#219,$,.OPENING.); +#221=IFCRELVOIDSELEMENT('0V5SO6JX_r3Ehgn1GMrcv5',$,$,$,#173,#220); +#222=IFCAXIS2PLACEMENT3D(#210,$,$); +#223=IFCLOCALPLACEMENT(#163,#222); +#224=IFCAXIS2PLACEMENT2D(#48,$); +#225=IFCRECTANGLEPROFILEDEF(.AREA.,$,#224,1.3,0.1); +#226=IFCAXIS2PLACEMENT3D(#1,$,$); +#227=IFCDIRECTION((0.0,0.0,1.0)); +#228=IFCEXTRUDEDAREASOLID(#225,#226,#227,1.3); +#229=IFCSTYLEDITEM(#228,(#67),$); +#230=IFCAXIS2PLACEMENT2D(#48,$); +#231=IFCRECTANGLEPROFILEDEF(.AREA.,$,#230,1.1800000000000002,0.04); +#232=IFCAXIS2PLACEMENT3D(#71,$,$); +#233=IFCDIRECTION((0.0,0.0,1.0)); +#234=IFCEXTRUDEDAREASOLID(#231,#232,#233,1.1800000000000002); +#235=IFCSTYLEDITEM(#234,(#77),$); +#236=IFCAXIS2PLACEMENT2D(#48,$); +#237=IFCRECTANGLEPROFILEDEF(.AREA.,$,#236,0.05,0.12); +#238=IFCAXIS2PLACEMENT3D(#1,$,$); +#239=IFCDIRECTION((0.0,0.0,1.0)); +#240=IFCEXTRUDEDAREASOLID(#237,#238,#239,1.3); +#241=IFCSTYLEDITEM(#240,(#67),$); +#242=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#228,#234,#240)); +#243=IFCPRODUCTDEFINITIONSHAPE($,$,(#242)); +#244=IFCWINDOW('0Sa7fPbj7b6xbsiUCJrYmA',$,'Window G-East 2',$,$,#223,#243,$,1.3,1.3,.WINDOW.,.NOTDEFINED.,$); +#245=IFCRELFILLSELEMENT('0tVCZn0Q8PPDVhRp9m8tNN',$,$,$,#220,#244); +#246=IFCCARTESIANPOINT((10.0,8.0,0.0)); +#247=IFCDIRECTION((0.0,0.0,1.0)); +#248=IFCDIRECTION((-1.0,0.0,0.0)); +#249=IFCAXIS2PLACEMENT3D(#246,#247,#248); +#250=IFCLOCALPLACEMENT(#18,#249); +#251=IFCAXIS2PLACEMENT2D(#32,$); +#252=IFCRECTANGLEPROFILEDEF(.AREA.,$,#251,10.0,0.3); +#253=IFCAXIS2PLACEMENT3D(#1,$,$); +#254=IFCDIRECTION((0.0,0.0,1.0)); +#255=IFCEXTRUDEDAREASOLID(#252,#253,#254,2.8); +#256=IFCSTYLEDITEM(#255,(#40),$); +#257=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#255)); +#258=IFCPRODUCTDEFINITIONSHAPE($,$,(#257)); +#259=IFCWALL('26TpQmJG3YDhZhOG2PXDnr',$,'G-North',$,$,#250,#258,$,.STANDARD.); +#260=IFCCARTESIANPOINT((1.9,0.0,0.9)); +#261=IFCAXIS2PLACEMENT3D(#260,$,$); +#262=IFCLOCALPLACEMENT(#250,#261); +#263=IFCAXIS2PLACEMENT2D(#48,$); +#264=IFCRECTANGLEPROFILEDEF(.AREA.,$,#263,1.4,0.5); +#265=IFCAXIS2PLACEMENT3D(#1,$,$); +#266=IFCDIRECTION((0.0,0.0,1.0)); +#267=IFCEXTRUDEDAREASOLID(#264,#265,#266,1.3); +#268=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#267)); +#269=IFCPRODUCTDEFINITIONSHAPE($,$,(#268)); +#270=IFCOPENINGELEMENT('3019NCAwz8XX_nFDGXexp5',$,'Opening G-North 1',$,$,#262,#269,$,.OPENING.); +#271=IFCRELVOIDSELEMENT('2_vQbbkkkCFlk5Rrkd3COT',$,$,$,#259,#270); +#272=IFCAXIS2PLACEMENT3D(#260,$,$); +#273=IFCLOCALPLACEMENT(#250,#272); +#274=IFCAXIS2PLACEMENT2D(#48,$); +#275=IFCRECTANGLEPROFILEDEF(.AREA.,$,#274,1.4,0.1); +#276=IFCAXIS2PLACEMENT3D(#1,$,$); +#277=IFCDIRECTION((0.0,0.0,1.0)); +#278=IFCEXTRUDEDAREASOLID(#275,#276,#277,1.3); +#279=IFCSTYLEDITEM(#278,(#67),$); +#280=IFCAXIS2PLACEMENT2D(#48,$); +#281=IFCRECTANGLEPROFILEDEF(.AREA.,$,#280,1.2799999999999998,0.04); +#282=IFCAXIS2PLACEMENT3D(#71,$,$); +#283=IFCDIRECTION((0.0,0.0,1.0)); +#284=IFCEXTRUDEDAREASOLID(#281,#282,#283,1.1800000000000002); +#285=IFCSTYLEDITEM(#284,(#77),$); +#286=IFCAXIS2PLACEMENT2D(#48,$); +#287=IFCRECTANGLEPROFILEDEF(.AREA.,$,#286,0.05,0.12); +#288=IFCAXIS2PLACEMENT3D(#1,$,$); +#289=IFCDIRECTION((0.0,0.0,1.0)); +#290=IFCEXTRUDEDAREASOLID(#287,#288,#289,1.3); +#291=IFCSTYLEDITEM(#290,(#67),$); +#292=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#278,#284,#290)); +#293=IFCPRODUCTDEFINITIONSHAPE($,$,(#292)); +#294=IFCWINDOW('0oS0jKMLo82LoGhKedPaOa',$,'Window G-North 1',$,$,#273,#293,$,1.3,1.4,.WINDOW.,.NOTDEFINED.,$); +#295=IFCRELFILLSELEMENT('1i5hThQM6VBK4BP_6OKO1K',$,$,$,#270,#294); +#296=IFCCARTESIANPOINT((4.8999999999999995,0.0,0.9)); +#297=IFCAXIS2PLACEMENT3D(#296,$,$); +#298=IFCLOCALPLACEMENT(#250,#297); +#299=IFCAXIS2PLACEMENT2D(#48,$); +#300=IFCRECTANGLEPROFILEDEF(.AREA.,$,#299,1.6,0.5); +#301=IFCAXIS2PLACEMENT3D(#1,$,$); +#302=IFCDIRECTION((0.0,0.0,1.0)); +#303=IFCEXTRUDEDAREASOLID(#300,#301,#302,1.3); +#304=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#303)); +#305=IFCPRODUCTDEFINITIONSHAPE($,$,(#304)); +#306=IFCOPENINGELEMENT('3SAsukmp4NAjv2s$PDeNXo',$,'Opening G-North 2',$,$,#298,#305,$,.OPENING.); +#307=IFCRELVOIDSELEMENT('0aT3X54zxxpC6xWPNbWCXJ',$,$,$,#259,#306); +#308=IFCAXIS2PLACEMENT3D(#296,$,$); +#309=IFCLOCALPLACEMENT(#250,#308); +#310=IFCAXIS2PLACEMENT2D(#48,$); +#311=IFCRECTANGLEPROFILEDEF(.AREA.,$,#310,1.6,0.1); +#312=IFCAXIS2PLACEMENT3D(#1,$,$); +#313=IFCDIRECTION((0.0,0.0,1.0)); +#314=IFCEXTRUDEDAREASOLID(#311,#312,#313,1.3); +#315=IFCSTYLEDITEM(#314,(#67),$); +#316=IFCAXIS2PLACEMENT2D(#48,$); +#317=IFCRECTANGLEPROFILEDEF(.AREA.,$,#316,1.48,0.04); +#318=IFCAXIS2PLACEMENT3D(#71,$,$); +#319=IFCDIRECTION((0.0,0.0,1.0)); +#320=IFCEXTRUDEDAREASOLID(#317,#318,#319,1.1800000000000002); +#321=IFCSTYLEDITEM(#320,(#77),$); +#322=IFCAXIS2PLACEMENT2D(#48,$); +#323=IFCRECTANGLEPROFILEDEF(.AREA.,$,#322,0.05,0.12); +#324=IFCAXIS2PLACEMENT3D(#1,$,$); +#325=IFCDIRECTION((0.0,0.0,1.0)); +#326=IFCEXTRUDEDAREASOLID(#323,#324,#325,1.3); +#327=IFCSTYLEDITEM(#326,(#67),$); +#328=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#314,#320,#326)); +#329=IFCPRODUCTDEFINITIONSHAPE($,$,(#328)); +#330=IFCWINDOW('1DN3Cqgy2JDku2yCl19HgH',$,'Window G-North 2',$,$,#309,#329,$,1.3,1.6,.WINDOW.,.NOTDEFINED.,$); +#331=IFCRELFILLSELEMENT('17UEcDlHpXkczj6$lPqKXc',$,$,$,#306,#330); +#332=IFCCARTESIANPOINT((7.8,0.0,0.9)); +#333=IFCAXIS2PLACEMENT3D(#332,$,$); +#334=IFCLOCALPLACEMENT(#250,#333); +#335=IFCAXIS2PLACEMENT2D(#48,$); +#336=IFCRECTANGLEPROFILEDEF(.AREA.,$,#335,1.2,0.5); +#337=IFCAXIS2PLACEMENT3D(#1,$,$); +#338=IFCDIRECTION((0.0,0.0,1.0)); +#339=IFCEXTRUDEDAREASOLID(#336,#337,#338,1.3); +#340=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#339)); +#341=IFCPRODUCTDEFINITIONSHAPE($,$,(#340)); +#342=IFCOPENINGELEMENT('1GvQj4CBkJ4WWgKqT2uSC0',$,'Opening G-North 3',$,$,#334,#341,$,.OPENING.); +#343=IFCRELVOIDSELEMENT('0JU_wg7qwvlp1otF98NblZ',$,$,$,#259,#342); +#344=IFCAXIS2PLACEMENT3D(#332,$,$); +#345=IFCLOCALPLACEMENT(#250,#344); +#346=IFCAXIS2PLACEMENT2D(#48,$); +#347=IFCRECTANGLEPROFILEDEF(.AREA.,$,#346,1.2,0.1); +#348=IFCAXIS2PLACEMENT3D(#1,$,$); +#349=IFCDIRECTION((0.0,0.0,1.0)); +#350=IFCEXTRUDEDAREASOLID(#347,#348,#349,1.3); +#351=IFCSTYLEDITEM(#350,(#67),$); +#352=IFCAXIS2PLACEMENT2D(#48,$); +#353=IFCRECTANGLEPROFILEDEF(.AREA.,$,#352,1.08,0.04); +#354=IFCAXIS2PLACEMENT3D(#71,$,$); +#355=IFCDIRECTION((0.0,0.0,1.0)); +#356=IFCEXTRUDEDAREASOLID(#353,#354,#355,1.1800000000000002); +#357=IFCSTYLEDITEM(#356,(#77),$); +#358=IFCAXIS2PLACEMENT2D(#48,$); +#359=IFCRECTANGLEPROFILEDEF(.AREA.,$,#358,0.05,0.12); +#360=IFCAXIS2PLACEMENT3D(#1,$,$); +#361=IFCDIRECTION((0.0,0.0,1.0)); +#362=IFCEXTRUDEDAREASOLID(#359,#360,#361,1.3); +#363=IFCSTYLEDITEM(#362,(#67),$); +#364=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#350,#356,#362)); +#365=IFCPRODUCTDEFINITIONSHAPE($,$,(#364)); +#366=IFCWINDOW('1l1WYJnbe4sk7iu_FPFvbX',$,'Window G-North 3',$,$,#345,#365,$,1.3,1.2,.WINDOW.,.NOTDEFINED.,$); +#367=IFCRELFILLSELEMENT('1MBhC2ioH0LniEYsYMNQBf',$,$,$,#342,#366); +#368=IFCCARTESIANPOINT((0.0,8.0,0.0)); +#369=IFCDIRECTION((0.0,0.0,1.0)); +#370=IFCDIRECTION((0.0,-1.0,0.0)); +#371=IFCAXIS2PLACEMENT3D(#368,#369,#370); +#372=IFCLOCALPLACEMENT(#18,#371); +#373=IFCAXIS2PLACEMENT2D(#164,$); +#374=IFCRECTANGLEPROFILEDEF(.AREA.,$,#373,8.0,0.3); +#375=IFCAXIS2PLACEMENT3D(#1,$,$); +#376=IFCDIRECTION((0.0,0.0,1.0)); +#377=IFCEXTRUDEDAREASOLID(#374,#375,#376,2.8); +#378=IFCSTYLEDITEM(#377,(#40),$); +#379=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#377)); +#380=IFCPRODUCTDEFINITIONSHAPE($,$,(#379)); +#381=IFCWALL('2$5HCGzNGbNfTCNWZlSpES',$,'G-West',$,$,#372,#380,$,.STANDARD.); +#382=IFCCARTESIANPOINT((2.3,0.0,0.9)); +#383=IFCAXIS2PLACEMENT3D(#382,$,$); +#384=IFCLOCALPLACEMENT(#372,#383); +#385=IFCAXIS2PLACEMENT2D(#48,$); +#386=IFCRECTANGLEPROFILEDEF(.AREA.,$,#385,1.4,0.5); +#387=IFCAXIS2PLACEMENT3D(#1,$,$); +#388=IFCDIRECTION((0.0,0.0,1.0)); +#389=IFCEXTRUDEDAREASOLID(#386,#387,#388,1.3); +#390=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#389)); +#391=IFCPRODUCTDEFINITIONSHAPE($,$,(#390)); +#392=IFCOPENINGELEMENT('0gCNDsyjpqOqEDutl0fz1J',$,'Opening G-West 1',$,$,#384,#391,$,.OPENING.); +#393=IFCRELVOIDSELEMENT('0seu3$M405XcR77mnfTqHU',$,$,$,#381,#392); +#394=IFCAXIS2PLACEMENT3D(#382,$,$); +#395=IFCLOCALPLACEMENT(#372,#394); +#396=IFCAXIS2PLACEMENT2D(#48,$); +#397=IFCRECTANGLEPROFILEDEF(.AREA.,$,#396,1.4,0.1); +#398=IFCAXIS2PLACEMENT3D(#1,$,$); +#399=IFCDIRECTION((0.0,0.0,1.0)); +#400=IFCEXTRUDEDAREASOLID(#397,#398,#399,1.3); +#401=IFCSTYLEDITEM(#400,(#67),$); +#402=IFCAXIS2PLACEMENT2D(#48,$); +#403=IFCRECTANGLEPROFILEDEF(.AREA.,$,#402,1.2799999999999998,0.04); +#404=IFCAXIS2PLACEMENT3D(#71,$,$); +#405=IFCDIRECTION((0.0,0.0,1.0)); +#406=IFCEXTRUDEDAREASOLID(#403,#404,#405,1.1800000000000002); +#407=IFCSTYLEDITEM(#406,(#77),$); +#408=IFCAXIS2PLACEMENT2D(#48,$); +#409=IFCRECTANGLEPROFILEDEF(.AREA.,$,#408,0.05,0.12); +#410=IFCAXIS2PLACEMENT3D(#1,$,$); +#411=IFCDIRECTION((0.0,0.0,1.0)); +#412=IFCEXTRUDEDAREASOLID(#409,#410,#411,1.3); +#413=IFCSTYLEDITEM(#412,(#67),$); +#414=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#400,#406,#412)); +#415=IFCPRODUCTDEFINITIONSHAPE($,$,(#414)); +#416=IFCWINDOW('3n545Kq$Z$fA4BAquBsjMl',$,'Window G-West 1',$,$,#395,#415,$,1.3,1.4,.WINDOW.,.NOTDEFINED.,$); +#417=IFCRELFILLSELEMENT('3_67_H0UzhZqzd1VHkDhHB',$,$,$,#392,#416); +#418=IFCCARTESIANPOINT((5.7,0.0,0.9)); +#419=IFCAXIS2PLACEMENT3D(#418,$,$); +#420=IFCLOCALPLACEMENT(#372,#419); +#421=IFCAXIS2PLACEMENT2D(#48,$); +#422=IFCRECTANGLEPROFILEDEF(.AREA.,$,#421,1.4,0.5); +#423=IFCAXIS2PLACEMENT3D(#1,$,$); +#424=IFCDIRECTION((0.0,0.0,1.0)); +#425=IFCEXTRUDEDAREASOLID(#422,#423,#424,1.3); +#426=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#425)); +#427=IFCPRODUCTDEFINITIONSHAPE($,$,(#426)); +#428=IFCOPENINGELEMENT('23fstwY$XueauzWc36rbIu',$,'Opening G-West 2',$,$,#420,#427,$,.OPENING.); +#429=IFCRELVOIDSELEMENT('3Tp6w8__ErAA6ElBP084AX',$,$,$,#381,#428); +#430=IFCAXIS2PLACEMENT3D(#418,$,$); +#431=IFCLOCALPLACEMENT(#372,#430); +#432=IFCAXIS2PLACEMENT2D(#48,$); +#433=IFCRECTANGLEPROFILEDEF(.AREA.,$,#432,1.4,0.1); +#434=IFCAXIS2PLACEMENT3D(#1,$,$); +#435=IFCDIRECTION((0.0,0.0,1.0)); +#436=IFCEXTRUDEDAREASOLID(#433,#434,#435,1.3); +#437=IFCSTYLEDITEM(#436,(#67),$); +#438=IFCAXIS2PLACEMENT2D(#48,$); +#439=IFCRECTANGLEPROFILEDEF(.AREA.,$,#438,1.2799999999999998,0.04); +#440=IFCAXIS2PLACEMENT3D(#71,$,$); +#441=IFCDIRECTION((0.0,0.0,1.0)); +#442=IFCEXTRUDEDAREASOLID(#439,#440,#441,1.1800000000000002); +#443=IFCSTYLEDITEM(#442,(#77),$); +#444=IFCAXIS2PLACEMENT2D(#48,$); +#445=IFCRECTANGLEPROFILEDEF(.AREA.,$,#444,0.05,0.12); +#446=IFCAXIS2PLACEMENT3D(#1,$,$); +#447=IFCDIRECTION((0.0,0.0,1.0)); +#448=IFCEXTRUDEDAREASOLID(#445,#446,#447,1.3); +#449=IFCSTYLEDITEM(#448,(#67),$); +#450=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#436,#442,#448)); +#451=IFCPRODUCTDEFINITIONSHAPE($,$,(#450)); +#452=IFCWINDOW('063tGBYLFfwrEegUINghwH',$,'Window G-West 2',$,$,#431,#451,$,1.3,1.4,.WINDOW.,.NOTDEFINED.,$); +#453=IFCRELFILLSELEMENT('2gmXv3u1D4lBiK6BofrCBs',$,$,$,#428,#452); +#454=IFCCARTESIANPOINT((6.0,0.15,0.0)); +#455=IFCDIRECTION((0.0,0.0,1.0)); +#456=IFCDIRECTION((0.0,1.0,0.0)); +#457=IFCAXIS2PLACEMENT3D(#454,#455,#456); +#458=IFCLOCALPLACEMENT(#18,#457); +#459=IFCCARTESIANPOINT((3.8499999999999996,0.0)); +#460=IFCAXIS2PLACEMENT2D(#459,$); +#461=IFCRECTANGLEPROFILEDEF(.AREA.,$,#460,7.699999999999999,0.15); +#462=IFCAXIS2PLACEMENT3D(#1,$,$); +#463=IFCDIRECTION((0.0,0.0,1.0)); +#464=IFCEXTRUDEDAREASOLID(#461,#462,#463,2.8); +#465=IFCSTYLEDITEM(#464,(#40),$); +#466=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#464)); +#467=IFCPRODUCTDEFINITIONSHAPE($,$,(#466)); +#468=IFCWALL('1_zKZXP$5GnkYHpaJR3Bok',$,'G-Partition A',$,$,#458,#467,$,.STANDARD.); +#469=IFCCARTESIANPOINT((1.95,0.0,0.0)); +#470=IFCAXIS2PLACEMENT3D(#469,$,$); +#471=IFCLOCALPLACEMENT(#458,#470); +#472=IFCAXIS2PLACEMENT2D(#48,$); +#473=IFCRECTANGLEPROFILEDEF(.AREA.,$,#472,0.9,0.35); +#474=IFCAXIS2PLACEMENT3D(#1,$,$); +#475=IFCDIRECTION((0.0,0.0,1.0)); +#476=IFCEXTRUDEDAREASOLID(#473,#474,#475,2.05); +#477=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#476)); +#478=IFCPRODUCTDEFINITIONSHAPE($,$,(#477)); +#479=IFCOPENINGELEMENT('2Ktw7Uh8$_RS8ZDn3YpkjP',$,'Opening G-Partition A 1',$,$,#471,#478,$,.OPENING.); +#480=IFCRELVOIDSELEMENT('3TtEeNIix$_gqAI9qUH3xu',$,$,$,#468,#479); +#481=IFCAXIS2PLACEMENT3D(#469,$,$); +#482=IFCLOCALPLACEMENT(#458,#481); +#483=IFCAXIS2PLACEMENT2D(#48,$); +#484=IFCRECTANGLEPROFILEDEF(.AREA.,$,#483,0.8,0.06); +#485=IFCAXIS2PLACEMENT3D(#1,$,$); +#486=IFCDIRECTION((0.0,0.0,1.0)); +#487=IFCEXTRUDEDAREASOLID(#484,#485,#486,1.9999999999999998); +#488=IFCSTYLEDITEM(#487,(#146),$); +#489=IFCAXIS2PLACEMENT2D(#48,$); +#490=IFCRECTANGLEPROFILEDEF(.AREA.,$,#489,0.08,0.14); +#491=IFCCARTESIANPOINT((0.25,0.0,1.0)); +#492=IFCAXIS2PLACEMENT3D(#491,$,$); +#493=IFCDIRECTION((0.0,0.0,1.0)); +#494=IFCEXTRUDEDAREASOLID(#490,#492,#493,0.08); +#495=IFCSTYLEDITEM(#494,(#67),$); +#496=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#487,#494)); +#497=IFCPRODUCTDEFINITIONSHAPE($,$,(#496)); +#498=IFCDOOR('2LRwR_QGebxnxP4w0ovXsU',$,'Door G-Partition A 1',$,$,#482,#497,$,2.05,0.9,.DOOR.,.NOTDEFINED.,$); +#499=IFCRELFILLSELEMENT('0L07NwfSRO86g_eFux3$Io',$,$,$,#479,#498); +#500=IFCCARTESIANPOINT((5.45,0.0,0.0)); +#501=IFCAXIS2PLACEMENT3D(#500,$,$); +#502=IFCLOCALPLACEMENT(#458,#501); +#503=IFCAXIS2PLACEMENT2D(#48,$); +#504=IFCRECTANGLEPROFILEDEF(.AREA.,$,#503,0.9,0.35); +#505=IFCAXIS2PLACEMENT3D(#1,$,$); +#506=IFCDIRECTION((0.0,0.0,1.0)); +#507=IFCEXTRUDEDAREASOLID(#504,#505,#506,2.05); +#508=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#507)); +#509=IFCPRODUCTDEFINITIONSHAPE($,$,(#508)); +#510=IFCOPENINGELEMENT('3_sf3G4$baqZDY1cO4hHVC',$,'Opening G-Partition A 2',$,$,#502,#509,$,.OPENING.); +#511=IFCRELVOIDSELEMENT('3gRHN6Sk3cWrbFbUBIYwwT',$,$,$,#468,#510); +#512=IFCAXIS2PLACEMENT3D(#500,$,$); +#513=IFCLOCALPLACEMENT(#458,#512); +#514=IFCAXIS2PLACEMENT2D(#48,$); +#515=IFCRECTANGLEPROFILEDEF(.AREA.,$,#514,0.8,0.06); +#516=IFCAXIS2PLACEMENT3D(#1,$,$); +#517=IFCDIRECTION((0.0,0.0,1.0)); +#518=IFCEXTRUDEDAREASOLID(#515,#516,#517,1.9999999999999998); +#519=IFCSTYLEDITEM(#518,(#146),$); +#520=IFCAXIS2PLACEMENT2D(#48,$); +#521=IFCRECTANGLEPROFILEDEF(.AREA.,$,#520,0.08,0.14); +#522=IFCAXIS2PLACEMENT3D(#491,$,$); +#523=IFCDIRECTION((0.0,0.0,1.0)); +#524=IFCEXTRUDEDAREASOLID(#521,#522,#523,0.08); +#525=IFCSTYLEDITEM(#524,(#67),$); +#526=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#518,#524)); +#527=IFCPRODUCTDEFINITIONSHAPE($,$,(#526)); +#528=IFCDOOR('2Ir$8YdjkSgzAJtMARCZiF',$,'Door G-Partition A 2',$,$,#513,#527,$,2.05,0.9,.DOOR.,.NOTDEFINED.,$); +#529=IFCRELFILLSELEMENT('1RQEGsUydtIqbrsa0HlRw7',$,$,$,#510,#528); +#530=IFCCARTESIANPOINT((0.15,4.0,0.0)); +#531=IFCDIRECTION((0.0,0.0,1.0)); +#532=IFCDIRECTION((1.0,0.0,0.0)); +#533=IFCAXIS2PLACEMENT3D(#530,#531,#532); +#534=IFCLOCALPLACEMENT(#18,#533); +#535=IFCCARTESIANPOINT((2.925,0.0)); +#536=IFCAXIS2PLACEMENT2D(#535,$); +#537=IFCRECTANGLEPROFILEDEF(.AREA.,$,#536,5.85,0.15); +#538=IFCAXIS2PLACEMENT3D(#1,$,$); +#539=IFCDIRECTION((0.0,0.0,1.0)); +#540=IFCEXTRUDEDAREASOLID(#537,#538,#539,2.8); +#541=IFCSTYLEDITEM(#540,(#40),$); +#542=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#540)); +#543=IFCPRODUCTDEFINITIONSHAPE($,$,(#542)); +#544=IFCWALL('2ovn4oyBVFdbrWEG1M3Q88',$,'G-Partition B',$,$,#534,#543,$,.STANDARD.); +#545=IFCCARTESIANPOINT((1.45,0.0,0.0)); +#546=IFCAXIS2PLACEMENT3D(#545,$,$); +#547=IFCLOCALPLACEMENT(#534,#546); +#548=IFCAXIS2PLACEMENT2D(#48,$); +#549=IFCRECTANGLEPROFILEDEF(.AREA.,$,#548,0.9,0.35); +#550=IFCAXIS2PLACEMENT3D(#1,$,$); +#551=IFCDIRECTION((0.0,0.0,1.0)); +#552=IFCEXTRUDEDAREASOLID(#549,#550,#551,2.05); +#553=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#552)); +#554=IFCPRODUCTDEFINITIONSHAPE($,$,(#553)); +#555=IFCOPENINGELEMENT('0XfmV4cd$rC2fZoPux72SI',$,'Opening G-Partition B 1',$,$,#547,#554,$,.OPENING.); +#556=IFCRELVOIDSELEMENT('2GvAGiwPzlvFeOlNOhu1ng',$,$,$,#544,#555); +#557=IFCAXIS2PLACEMENT3D(#545,$,$); +#558=IFCLOCALPLACEMENT(#534,#557); +#559=IFCAXIS2PLACEMENT2D(#48,$); +#560=IFCRECTANGLEPROFILEDEF(.AREA.,$,#559,0.8,0.06); +#561=IFCAXIS2PLACEMENT3D(#1,$,$); +#562=IFCDIRECTION((0.0,0.0,1.0)); +#563=IFCEXTRUDEDAREASOLID(#560,#561,#562,1.9999999999999998); +#564=IFCSTYLEDITEM(#563,(#146),$); +#565=IFCAXIS2PLACEMENT2D(#48,$); +#566=IFCRECTANGLEPROFILEDEF(.AREA.,$,#565,0.08,0.14); +#567=IFCAXIS2PLACEMENT3D(#491,$,$); +#568=IFCDIRECTION((0.0,0.0,1.0)); +#569=IFCEXTRUDEDAREASOLID(#566,#567,#568,0.08); +#570=IFCSTYLEDITEM(#569,(#67),$); +#571=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#563,#569)); +#572=IFCPRODUCTDEFINITIONSHAPE($,$,(#571)); +#573=IFCDOOR('0p1yVrvamivbkLPsXW5OIR',$,'Door G-Partition B 1',$,$,#558,#572,$,2.05,0.9,.DOOR.,.NOTDEFINED.,$); +#574=IFCRELFILLSELEMENT('1x_8sow6ezjuOZk2uzYlWD',$,$,$,#555,#573); +#575=IFCDIRECTION((0.0,0.0,1.0)); +#576=IFCDIRECTION((1.0,0.0,0.0)); +#577=IFCAXIS2PLACEMENT3D(#1,#575,#576); +#578=IFCLOCALPLACEMENT(#22,#577); +#579=IFCAXIS2PLACEMENT2D(#32,$); +#580=IFCRECTANGLEPROFILEDEF(.AREA.,$,#579,10.0,0.3); +#581=IFCAXIS2PLACEMENT3D(#1,$,$); +#582=IFCDIRECTION((0.0,0.0,1.0)); +#583=IFCEXTRUDEDAREASOLID(#580,#581,#582,2.8); +#584=IFCSTYLEDITEM(#583,(#40),$); +#585=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#583)); +#586=IFCPRODUCTDEFINITIONSHAPE($,$,(#585)); +#587=IFCWALL('2$pTCPsWilX768UT$2Dprk',$,'F-South',$,$,#578,#586,$,.STANDARD.); +#588=IFCAXIS2PLACEMENT3D(#45,$,$); +#589=IFCLOCALPLACEMENT(#578,#588); +#590=IFCAXIS2PLACEMENT2D(#48,$); +#591=IFCRECTANGLEPROFILEDEF(.AREA.,$,#590,1.2,0.5); +#592=IFCAXIS2PLACEMENT3D(#1,$,$); +#593=IFCDIRECTION((0.0,0.0,1.0)); +#594=IFCEXTRUDEDAREASOLID(#591,#592,#593,1.3); +#595=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#594)); +#596=IFCPRODUCTDEFINITIONSHAPE($,$,(#595)); +#597=IFCOPENINGELEMENT('0KOk7mETOuhrXWQzkve9wf',$,'Opening F-South 1',$,$,#589,#596,$,.OPENING.); +#598=IFCRELVOIDSELEMENT('0d84PoY2VZwasiBw9lrcIq',$,$,$,#587,#597); +#599=IFCAXIS2PLACEMENT3D(#45,$,$); +#600=IFCLOCALPLACEMENT(#578,#599); +#601=IFCAXIS2PLACEMENT2D(#48,$); +#602=IFCRECTANGLEPROFILEDEF(.AREA.,$,#601,1.2,0.1); +#603=IFCAXIS2PLACEMENT3D(#1,$,$); +#604=IFCDIRECTION((0.0,0.0,1.0)); +#605=IFCEXTRUDEDAREASOLID(#602,#603,#604,1.3); +#606=IFCSTYLEDITEM(#605,(#67),$); +#607=IFCAXIS2PLACEMENT2D(#48,$); +#608=IFCRECTANGLEPROFILEDEF(.AREA.,$,#607,1.08,0.04); +#609=IFCAXIS2PLACEMENT3D(#71,$,$); +#610=IFCDIRECTION((0.0,0.0,1.0)); +#611=IFCEXTRUDEDAREASOLID(#608,#609,#610,1.1800000000000002); +#612=IFCSTYLEDITEM(#611,(#77),$); +#613=IFCAXIS2PLACEMENT2D(#48,$); +#614=IFCRECTANGLEPROFILEDEF(.AREA.,$,#613,0.05,0.12); +#615=IFCAXIS2PLACEMENT3D(#1,$,$); +#616=IFCDIRECTION((0.0,0.0,1.0)); +#617=IFCEXTRUDEDAREASOLID(#614,#615,#616,1.3); +#618=IFCSTYLEDITEM(#617,(#67),$); +#619=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#605,#611,#617)); +#620=IFCPRODUCTDEFINITIONSHAPE($,$,(#619)); +#621=IFCWINDOW('2zTLDJyCWWLb0bQ3sPyhWg',$,'Window F-South 1',$,$,#600,#620,$,1.3,1.2,.WINDOW.,.NOTDEFINED.,$); +#622=IFCRELFILLSELEMENT('1a0CL_q8ENRUQ3TtF2D6LH',$,$,$,#597,#621); +#623=IFCAXIS2PLACEMENT3D(#89,$,$); +#624=IFCLOCALPLACEMENT(#578,#623); +#625=IFCAXIS2PLACEMENT2D(#48,$); +#626=IFCRECTANGLEPROFILEDEF(.AREA.,$,#625,1.2,0.5); +#627=IFCAXIS2PLACEMENT3D(#1,$,$); +#628=IFCDIRECTION((0.0,0.0,1.0)); +#629=IFCEXTRUDEDAREASOLID(#626,#627,#628,1.3); +#630=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#629)); +#631=IFCPRODUCTDEFINITIONSHAPE($,$,(#630)); +#632=IFCOPENINGELEMENT('1yGAU7ZsBkP37y10YsugjN',$,'Opening F-South 2',$,$,#624,#631,$,.OPENING.); +#633=IFCRELVOIDSELEMENT('1XZmCcTzggoekzw8fxlwFn',$,$,$,#587,#632); +#634=IFCAXIS2PLACEMENT3D(#89,$,$); +#635=IFCLOCALPLACEMENT(#578,#634); +#636=IFCAXIS2PLACEMENT2D(#48,$); +#637=IFCRECTANGLEPROFILEDEF(.AREA.,$,#636,1.2,0.1); +#638=IFCAXIS2PLACEMENT3D(#1,$,$); +#639=IFCDIRECTION((0.0,0.0,1.0)); +#640=IFCEXTRUDEDAREASOLID(#637,#638,#639,1.3); +#641=IFCSTYLEDITEM(#640,(#67),$); +#642=IFCAXIS2PLACEMENT2D(#48,$); +#643=IFCRECTANGLEPROFILEDEF(.AREA.,$,#642,1.08,0.04); +#644=IFCAXIS2PLACEMENT3D(#71,$,$); +#645=IFCDIRECTION((0.0,0.0,1.0)); +#646=IFCEXTRUDEDAREASOLID(#643,#644,#645,1.1800000000000002); +#647=IFCSTYLEDITEM(#646,(#77),$); +#648=IFCAXIS2PLACEMENT2D(#48,$); +#649=IFCRECTANGLEPROFILEDEF(.AREA.,$,#648,0.05,0.12); +#650=IFCAXIS2PLACEMENT3D(#1,$,$); +#651=IFCDIRECTION((0.0,0.0,1.0)); +#652=IFCEXTRUDEDAREASOLID(#649,#650,#651,1.3); +#653=IFCSTYLEDITEM(#652,(#67),$); +#654=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#640,#646,#652)); +#655=IFCPRODUCTDEFINITIONSHAPE($,$,(#654)); +#656=IFCWINDOW('1iqUJP_dvw5DyvqFy4O8d0',$,'Window F-South 2',$,$,#635,#655,$,1.3,1.2,.WINDOW.,.NOTDEFINED.,$); +#657=IFCRELFILLSELEMENT('05EN1L4FtKBS$kHcPAJpFH',$,$,$,#632,#656); +#658=IFCCARTESIANPOINT((7.5,0.0,0.9)); +#659=IFCAXIS2PLACEMENT3D(#658,$,$); +#660=IFCLOCALPLACEMENT(#578,#659); +#661=IFCAXIS2PLACEMENT2D(#48,$); +#662=IFCRECTANGLEPROFILEDEF(.AREA.,$,#661,1.2,0.5); +#663=IFCAXIS2PLACEMENT3D(#1,$,$); +#664=IFCDIRECTION((0.0,0.0,1.0)); +#665=IFCEXTRUDEDAREASOLID(#662,#663,#664,1.3); +#666=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#665)); +#667=IFCPRODUCTDEFINITIONSHAPE($,$,(#666)); +#668=IFCOPENINGELEMENT('37bkjf70edmKDECiviecVM',$,'Opening F-South 3',$,$,#660,#667,$,.OPENING.); +#669=IFCRELVOIDSELEMENT('16u2Awk_33CIXbMdgrkw5z',$,$,$,#587,#668); +#670=IFCAXIS2PLACEMENT3D(#658,$,$); +#671=IFCLOCALPLACEMENT(#578,#670); +#672=IFCAXIS2PLACEMENT2D(#48,$); +#673=IFCRECTANGLEPROFILEDEF(.AREA.,$,#672,1.2,0.1); +#674=IFCAXIS2PLACEMENT3D(#1,$,$); +#675=IFCDIRECTION((0.0,0.0,1.0)); +#676=IFCEXTRUDEDAREASOLID(#673,#674,#675,1.3); +#677=IFCSTYLEDITEM(#676,(#67),$); +#678=IFCAXIS2PLACEMENT2D(#48,$); +#679=IFCRECTANGLEPROFILEDEF(.AREA.,$,#678,1.08,0.04); +#680=IFCAXIS2PLACEMENT3D(#71,$,$); +#681=IFCDIRECTION((0.0,0.0,1.0)); +#682=IFCEXTRUDEDAREASOLID(#679,#680,#681,1.1800000000000002); +#683=IFCSTYLEDITEM(#682,(#77),$); +#684=IFCAXIS2PLACEMENT2D(#48,$); +#685=IFCRECTANGLEPROFILEDEF(.AREA.,$,#684,0.05,0.12); +#686=IFCAXIS2PLACEMENT3D(#1,$,$); +#687=IFCDIRECTION((0.0,0.0,1.0)); +#688=IFCEXTRUDEDAREASOLID(#685,#686,#687,1.3); +#689=IFCSTYLEDITEM(#688,(#67),$); +#690=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#676,#682,#688)); +#691=IFCPRODUCTDEFINITIONSHAPE($,$,(#690)); +#692=IFCWINDOW('331kvpvGfQe36OyJxNqwg6',$,'Window F-South 3',$,$,#671,#691,$,1.3,1.2,.WINDOW.,.NOTDEFINED.,$); +#693=IFCRELFILLSELEMENT('1FR1EDrBglHPU4dC53_BZl',$,$,$,#668,#692); +#694=IFCDIRECTION((0.0,0.0,1.0)); +#695=IFCDIRECTION((0.0,1.0,0.0)); +#696=IFCAXIS2PLACEMENT3D(#159,#694,#695); +#697=IFCLOCALPLACEMENT(#22,#696); +#698=IFCAXIS2PLACEMENT2D(#164,$); +#699=IFCRECTANGLEPROFILEDEF(.AREA.,$,#698,8.0,0.3); +#700=IFCAXIS2PLACEMENT3D(#1,$,$); +#701=IFCDIRECTION((0.0,0.0,1.0)); +#702=IFCEXTRUDEDAREASOLID(#699,#700,#701,2.8); +#703=IFCSTYLEDITEM(#702,(#40),$); +#704=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#702)); +#705=IFCPRODUCTDEFINITIONSHAPE($,$,(#704)); +#706=IFCWALL('0qgiqCUxAtkftKs1Y$lDcW',$,'F-East',$,$,#697,#705,$,.STANDARD.); +#707=IFCAXIS2PLACEMENT3D(#174,$,$); +#708=IFCLOCALPLACEMENT(#697,#707); +#709=IFCAXIS2PLACEMENT2D(#48,$); +#710=IFCRECTANGLEPROFILEDEF(.AREA.,$,#709,1.3,0.5); +#711=IFCAXIS2PLACEMENT3D(#1,$,$); +#712=IFCDIRECTION((0.0,0.0,1.0)); +#713=IFCEXTRUDEDAREASOLID(#710,#711,#712,1.3); +#714=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#713)); +#715=IFCPRODUCTDEFINITIONSHAPE($,$,(#714)); +#716=IFCOPENINGELEMENT('3D0nqdnuRXaOio90htvOZ9',$,'Opening F-East 1',$,$,#708,#715,$,.OPENING.); +#717=IFCRELVOIDSELEMENT('0c3ZX0SPCtvrrGQt6voxwR',$,$,$,#706,#716); +#718=IFCAXIS2PLACEMENT3D(#174,$,$); +#719=IFCLOCALPLACEMENT(#697,#718); +#720=IFCAXIS2PLACEMENT2D(#48,$); +#721=IFCRECTANGLEPROFILEDEF(.AREA.,$,#720,1.3,0.1); +#722=IFCAXIS2PLACEMENT3D(#1,$,$); +#723=IFCDIRECTION((0.0,0.0,1.0)); +#724=IFCEXTRUDEDAREASOLID(#721,#722,#723,1.3); +#725=IFCSTYLEDITEM(#724,(#67),$); +#726=IFCAXIS2PLACEMENT2D(#48,$); +#727=IFCRECTANGLEPROFILEDEF(.AREA.,$,#726,1.1800000000000002,0.04); +#728=IFCAXIS2PLACEMENT3D(#71,$,$); +#729=IFCDIRECTION((0.0,0.0,1.0)); +#730=IFCEXTRUDEDAREASOLID(#727,#728,#729,1.1800000000000002); +#731=IFCSTYLEDITEM(#730,(#77),$); +#732=IFCAXIS2PLACEMENT2D(#48,$); +#733=IFCRECTANGLEPROFILEDEF(.AREA.,$,#732,0.05,0.12); +#734=IFCAXIS2PLACEMENT3D(#1,$,$); +#735=IFCDIRECTION((0.0,0.0,1.0)); +#736=IFCEXTRUDEDAREASOLID(#733,#734,#735,1.3); +#737=IFCSTYLEDITEM(#736,(#67),$); +#738=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#724,#730,#736)); +#739=IFCPRODUCTDEFINITIONSHAPE($,$,(#738)); +#740=IFCWINDOW('002llom_twcEPYR5Y4kBNH',$,'Window F-East 1',$,$,#719,#739,$,1.3,1.3,.WINDOW.,.NOTDEFINED.,$); +#741=IFCRELFILLSELEMENT('2Z0gnMHzIq$phuTBrzhDie',$,$,$,#716,#740); +#742=IFCAXIS2PLACEMENT3D(#210,$,$); +#743=IFCLOCALPLACEMENT(#697,#742); +#744=IFCAXIS2PLACEMENT2D(#48,$); +#745=IFCRECTANGLEPROFILEDEF(.AREA.,$,#744,1.3,0.5); +#746=IFCAXIS2PLACEMENT3D(#1,$,$); +#747=IFCDIRECTION((0.0,0.0,1.0)); +#748=IFCEXTRUDEDAREASOLID(#745,#746,#747,1.3); +#749=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#748)); +#750=IFCPRODUCTDEFINITIONSHAPE($,$,(#749)); +#751=IFCOPENINGELEMENT('0c4NidDPHU72Kza7upjM_d',$,'Opening F-East 2',$,$,#743,#750,$,.OPENING.); +#752=IFCRELVOIDSELEMENT('0FODem1ph_HwU64RfJ0hZD',$,$,$,#706,#751); +#753=IFCAXIS2PLACEMENT3D(#210,$,$); +#754=IFCLOCALPLACEMENT(#697,#753); +#755=IFCAXIS2PLACEMENT2D(#48,$); +#756=IFCRECTANGLEPROFILEDEF(.AREA.,$,#755,1.3,0.1); +#757=IFCAXIS2PLACEMENT3D(#1,$,$); +#758=IFCDIRECTION((0.0,0.0,1.0)); +#759=IFCEXTRUDEDAREASOLID(#756,#757,#758,1.3); +#760=IFCSTYLEDITEM(#759,(#67),$); +#761=IFCAXIS2PLACEMENT2D(#48,$); +#762=IFCRECTANGLEPROFILEDEF(.AREA.,$,#761,1.1800000000000002,0.04); +#763=IFCAXIS2PLACEMENT3D(#71,$,$); +#764=IFCDIRECTION((0.0,0.0,1.0)); +#765=IFCEXTRUDEDAREASOLID(#762,#763,#764,1.1800000000000002); +#766=IFCSTYLEDITEM(#765,(#77),$); +#767=IFCAXIS2PLACEMENT2D(#48,$); +#768=IFCRECTANGLEPROFILEDEF(.AREA.,$,#767,0.05,0.12); +#769=IFCAXIS2PLACEMENT3D(#1,$,$); +#770=IFCDIRECTION((0.0,0.0,1.0)); +#771=IFCEXTRUDEDAREASOLID(#768,#769,#770,1.3); +#772=IFCSTYLEDITEM(#771,(#67),$); +#773=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#759,#765,#771)); +#774=IFCPRODUCTDEFINITIONSHAPE($,$,(#773)); +#775=IFCWINDOW('23m5s1YUU3_tH_BBzjajvY',$,'Window F-East 2',$,$,#754,#774,$,1.3,1.3,.WINDOW.,.NOTDEFINED.,$); +#776=IFCRELFILLSELEMENT('2ES9o5HtjbyIN5hvgYPcy1',$,$,$,#751,#775); +#777=IFCDIRECTION((0.0,0.0,1.0)); +#778=IFCDIRECTION((-1.0,0.0,0.0)); +#779=IFCAXIS2PLACEMENT3D(#246,#777,#778); +#780=IFCLOCALPLACEMENT(#22,#779); +#781=IFCAXIS2PLACEMENT2D(#32,$); +#782=IFCRECTANGLEPROFILEDEF(.AREA.,$,#781,10.0,0.3); +#783=IFCAXIS2PLACEMENT3D(#1,$,$); +#784=IFCDIRECTION((0.0,0.0,1.0)); +#785=IFCEXTRUDEDAREASOLID(#782,#783,#784,2.8); +#786=IFCSTYLEDITEM(#785,(#40),$); +#787=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#785)); +#788=IFCPRODUCTDEFINITIONSHAPE($,$,(#787)); +#789=IFCWALL('3zgU70GqTpMKnrvDjPqJnZ',$,'F-North',$,$,#780,#788,$,.STANDARD.); +#790=IFCAXIS2PLACEMENT3D(#260,$,$); +#791=IFCLOCALPLACEMENT(#780,#790); +#792=IFCAXIS2PLACEMENT2D(#48,$); +#793=IFCRECTANGLEPROFILEDEF(.AREA.,$,#792,1.4,0.5); +#794=IFCAXIS2PLACEMENT3D(#1,$,$); +#795=IFCDIRECTION((0.0,0.0,1.0)); +#796=IFCEXTRUDEDAREASOLID(#793,#794,#795,1.3); +#797=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#796)); +#798=IFCPRODUCTDEFINITIONSHAPE($,$,(#797)); +#799=IFCOPENINGELEMENT('0WZrhOah6iFLrcoVGqx4ms',$,'Opening F-North 1',$,$,#791,#798,$,.OPENING.); +#800=IFCRELVOIDSELEMENT('3KqU$zffwZS1Kx$H_h2cGd',$,$,$,#789,#799); +#801=IFCAXIS2PLACEMENT3D(#260,$,$); +#802=IFCLOCALPLACEMENT(#780,#801); +#803=IFCAXIS2PLACEMENT2D(#48,$); +#804=IFCRECTANGLEPROFILEDEF(.AREA.,$,#803,1.4,0.1); +#805=IFCAXIS2PLACEMENT3D(#1,$,$); +#806=IFCDIRECTION((0.0,0.0,1.0)); +#807=IFCEXTRUDEDAREASOLID(#804,#805,#806,1.3); +#808=IFCSTYLEDITEM(#807,(#67),$); +#809=IFCAXIS2PLACEMENT2D(#48,$); +#810=IFCRECTANGLEPROFILEDEF(.AREA.,$,#809,1.2799999999999998,0.04); +#811=IFCAXIS2PLACEMENT3D(#71,$,$); +#812=IFCDIRECTION((0.0,0.0,1.0)); +#813=IFCEXTRUDEDAREASOLID(#810,#811,#812,1.1800000000000002); +#814=IFCSTYLEDITEM(#813,(#77),$); +#815=IFCAXIS2PLACEMENT2D(#48,$); +#816=IFCRECTANGLEPROFILEDEF(.AREA.,$,#815,0.05,0.12); +#817=IFCAXIS2PLACEMENT3D(#1,$,$); +#818=IFCDIRECTION((0.0,0.0,1.0)); +#819=IFCEXTRUDEDAREASOLID(#816,#817,#818,1.3); +#820=IFCSTYLEDITEM(#819,(#67),$); +#821=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#807,#813,#819)); +#822=IFCPRODUCTDEFINITIONSHAPE($,$,(#821)); +#823=IFCWINDOW('2wOOChS6nnhKUrpK6Dq1Gh',$,'Window F-North 1',$,$,#802,#822,$,1.3,1.4,.WINDOW.,.NOTDEFINED.,$); +#824=IFCRELFILLSELEMENT('3U6OjNOYKjtM12uu4t0Wxf',$,$,$,#799,#823); +#825=IFCAXIS2PLACEMENT3D(#296,$,$); +#826=IFCLOCALPLACEMENT(#780,#825); +#827=IFCAXIS2PLACEMENT2D(#48,$); +#828=IFCRECTANGLEPROFILEDEF(.AREA.,$,#827,1.6,0.5); +#829=IFCAXIS2PLACEMENT3D(#1,$,$); +#830=IFCDIRECTION((0.0,0.0,1.0)); +#831=IFCEXTRUDEDAREASOLID(#828,#829,#830,1.3); +#832=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#831)); +#833=IFCPRODUCTDEFINITIONSHAPE($,$,(#832)); +#834=IFCOPENINGELEMENT('2BM$FRnGUjT0nR8MOFUwgr',$,'Opening F-North 2',$,$,#826,#833,$,.OPENING.); +#835=IFCRELVOIDSELEMENT('2t_bTVgk_QcDDZyGonp6s4',$,$,$,#789,#834); +#836=IFCAXIS2PLACEMENT3D(#296,$,$); +#837=IFCLOCALPLACEMENT(#780,#836); +#838=IFCAXIS2PLACEMENT2D(#48,$); +#839=IFCRECTANGLEPROFILEDEF(.AREA.,$,#838,1.6,0.1); +#840=IFCAXIS2PLACEMENT3D(#1,$,$); +#841=IFCDIRECTION((0.0,0.0,1.0)); +#842=IFCEXTRUDEDAREASOLID(#839,#840,#841,1.3); +#843=IFCSTYLEDITEM(#842,(#67),$); +#844=IFCAXIS2PLACEMENT2D(#48,$); +#845=IFCRECTANGLEPROFILEDEF(.AREA.,$,#844,1.48,0.04); +#846=IFCAXIS2PLACEMENT3D(#71,$,$); +#847=IFCDIRECTION((0.0,0.0,1.0)); +#848=IFCEXTRUDEDAREASOLID(#845,#846,#847,1.1800000000000002); +#849=IFCSTYLEDITEM(#848,(#77),$); +#850=IFCAXIS2PLACEMENT2D(#48,$); +#851=IFCRECTANGLEPROFILEDEF(.AREA.,$,#850,0.05,0.12); +#852=IFCAXIS2PLACEMENT3D(#1,$,$); +#853=IFCDIRECTION((0.0,0.0,1.0)); +#854=IFCEXTRUDEDAREASOLID(#851,#852,#853,1.3); +#855=IFCSTYLEDITEM(#854,(#67),$); +#856=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#842,#848,#854)); +#857=IFCPRODUCTDEFINITIONSHAPE($,$,(#856)); +#858=IFCWINDOW('1ljo0GQZqFlIj4dXF6QxiE',$,'Window F-North 2',$,$,#837,#857,$,1.3,1.6,.WINDOW.,.NOTDEFINED.,$); +#859=IFCRELFILLSELEMENT('371qgXisk_XHZSavQa9hM$',$,$,$,#834,#858); +#860=IFCAXIS2PLACEMENT3D(#332,$,$); +#861=IFCLOCALPLACEMENT(#780,#860); +#862=IFCAXIS2PLACEMENT2D(#48,$); +#863=IFCRECTANGLEPROFILEDEF(.AREA.,$,#862,1.2,0.5); +#864=IFCAXIS2PLACEMENT3D(#1,$,$); +#865=IFCDIRECTION((0.0,0.0,1.0)); +#866=IFCEXTRUDEDAREASOLID(#863,#864,#865,1.3); +#867=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#866)); +#868=IFCPRODUCTDEFINITIONSHAPE($,$,(#867)); +#869=IFCOPENINGELEMENT('3y2jAgq7jtBgZm_SAx8LgS',$,'Opening F-North 3',$,$,#861,#868,$,.OPENING.); +#870=IFCRELVOIDSELEMENT('0gkGeOwDFEXZehxMk1jwOQ',$,$,$,#789,#869); +#871=IFCAXIS2PLACEMENT3D(#332,$,$); +#872=IFCLOCALPLACEMENT(#780,#871); +#873=IFCAXIS2PLACEMENT2D(#48,$); +#874=IFCRECTANGLEPROFILEDEF(.AREA.,$,#873,1.2,0.1); +#875=IFCAXIS2PLACEMENT3D(#1,$,$); +#876=IFCDIRECTION((0.0,0.0,1.0)); +#877=IFCEXTRUDEDAREASOLID(#874,#875,#876,1.3); +#878=IFCSTYLEDITEM(#877,(#67),$); +#879=IFCAXIS2PLACEMENT2D(#48,$); +#880=IFCRECTANGLEPROFILEDEF(.AREA.,$,#879,1.08,0.04); +#881=IFCAXIS2PLACEMENT3D(#71,$,$); +#882=IFCDIRECTION((0.0,0.0,1.0)); +#883=IFCEXTRUDEDAREASOLID(#880,#881,#882,1.1800000000000002); +#884=IFCSTYLEDITEM(#883,(#77),$); +#885=IFCAXIS2PLACEMENT2D(#48,$); +#886=IFCRECTANGLEPROFILEDEF(.AREA.,$,#885,0.05,0.12); +#887=IFCAXIS2PLACEMENT3D(#1,$,$); +#888=IFCDIRECTION((0.0,0.0,1.0)); +#889=IFCEXTRUDEDAREASOLID(#886,#887,#888,1.3); +#890=IFCSTYLEDITEM(#889,(#67),$); +#891=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#877,#883,#889)); +#892=IFCPRODUCTDEFINITIONSHAPE($,$,(#891)); +#893=IFCWINDOW('0dO3MxU3q2fqdzvRsS0QhI',$,'Window F-North 3',$,$,#872,#892,$,1.3,1.2,.WINDOW.,.NOTDEFINED.,$); +#894=IFCRELFILLSELEMENT('3AukMzNDA5myYT7ws$MPel',$,$,$,#869,#893); +#895=IFCDIRECTION((0.0,0.0,1.0)); +#896=IFCDIRECTION((0.0,-1.0,0.0)); +#897=IFCAXIS2PLACEMENT3D(#368,#895,#896); +#898=IFCLOCALPLACEMENT(#22,#897); +#899=IFCAXIS2PLACEMENT2D(#164,$); +#900=IFCRECTANGLEPROFILEDEF(.AREA.,$,#899,8.0,0.3); +#901=IFCAXIS2PLACEMENT3D(#1,$,$); +#902=IFCDIRECTION((0.0,0.0,1.0)); +#903=IFCEXTRUDEDAREASOLID(#900,#901,#902,2.8); +#904=IFCSTYLEDITEM(#903,(#40),$); +#905=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#903)); +#906=IFCPRODUCTDEFINITIONSHAPE($,$,(#905)); +#907=IFCWALL('3RKLb7TIZW5$F3WSTt6aUT',$,'F-West',$,$,#898,#906,$,.STANDARD.); +#908=IFCAXIS2PLACEMENT3D(#382,$,$); +#909=IFCLOCALPLACEMENT(#898,#908); +#910=IFCAXIS2PLACEMENT2D(#48,$); +#911=IFCRECTANGLEPROFILEDEF(.AREA.,$,#910,1.4,0.5); +#912=IFCAXIS2PLACEMENT3D(#1,$,$); +#913=IFCDIRECTION((0.0,0.0,1.0)); +#914=IFCEXTRUDEDAREASOLID(#911,#912,#913,1.3); +#915=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#914)); +#916=IFCPRODUCTDEFINITIONSHAPE($,$,(#915)); +#917=IFCOPENINGELEMENT('2hD0dFWUVDlBvttDgrqeNj',$,'Opening F-West 1',$,$,#909,#916,$,.OPENING.); +#918=IFCRELVOIDSELEMENT('1qkV45hHoA2KsX2TkNDyWj',$,$,$,#907,#917); +#919=IFCAXIS2PLACEMENT3D(#382,$,$); +#920=IFCLOCALPLACEMENT(#898,#919); +#921=IFCAXIS2PLACEMENT2D(#48,$); +#922=IFCRECTANGLEPROFILEDEF(.AREA.,$,#921,1.4,0.1); +#923=IFCAXIS2PLACEMENT3D(#1,$,$); +#924=IFCDIRECTION((0.0,0.0,1.0)); +#925=IFCEXTRUDEDAREASOLID(#922,#923,#924,1.3); +#926=IFCSTYLEDITEM(#925,(#67),$); +#927=IFCAXIS2PLACEMENT2D(#48,$); +#928=IFCRECTANGLEPROFILEDEF(.AREA.,$,#927,1.2799999999999998,0.04); +#929=IFCAXIS2PLACEMENT3D(#71,$,$); +#930=IFCDIRECTION((0.0,0.0,1.0)); +#931=IFCEXTRUDEDAREASOLID(#928,#929,#930,1.1800000000000002); +#932=IFCSTYLEDITEM(#931,(#77),$); +#933=IFCAXIS2PLACEMENT2D(#48,$); +#934=IFCRECTANGLEPROFILEDEF(.AREA.,$,#933,0.05,0.12); +#935=IFCAXIS2PLACEMENT3D(#1,$,$); +#936=IFCDIRECTION((0.0,0.0,1.0)); +#937=IFCEXTRUDEDAREASOLID(#934,#935,#936,1.3); +#938=IFCSTYLEDITEM(#937,(#67),$); +#939=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#925,#931,#937)); +#940=IFCPRODUCTDEFINITIONSHAPE($,$,(#939)); +#941=IFCWINDOW('0jFVZnl4$Tgb5qecjO$9JC',$,'Window F-West 1',$,$,#920,#940,$,1.3,1.4,.WINDOW.,.NOTDEFINED.,$); +#942=IFCRELFILLSELEMENT('3l_P2i$TyMZZqei1lgnmpZ',$,$,$,#917,#941); +#943=IFCAXIS2PLACEMENT3D(#418,$,$); +#944=IFCLOCALPLACEMENT(#898,#943); +#945=IFCAXIS2PLACEMENT2D(#48,$); +#946=IFCRECTANGLEPROFILEDEF(.AREA.,$,#945,1.4,0.5); +#947=IFCAXIS2PLACEMENT3D(#1,$,$); +#948=IFCDIRECTION((0.0,0.0,1.0)); +#949=IFCEXTRUDEDAREASOLID(#946,#947,#948,1.3); +#950=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#949)); +#951=IFCPRODUCTDEFINITIONSHAPE($,$,(#950)); +#952=IFCOPENINGELEMENT('0kawJDw0PEeeccgkLgP$M4',$,'Opening F-West 2',$,$,#944,#951,$,.OPENING.); +#953=IFCRELVOIDSELEMENT('1AVhqB0s0HSb1L74eOpLcr',$,$,$,#907,#952); +#954=IFCAXIS2PLACEMENT3D(#418,$,$); +#955=IFCLOCALPLACEMENT(#898,#954); +#956=IFCAXIS2PLACEMENT2D(#48,$); +#957=IFCRECTANGLEPROFILEDEF(.AREA.,$,#956,1.4,0.1); +#958=IFCAXIS2PLACEMENT3D(#1,$,$); +#959=IFCDIRECTION((0.0,0.0,1.0)); +#960=IFCEXTRUDEDAREASOLID(#957,#958,#959,1.3); +#961=IFCSTYLEDITEM(#960,(#67),$); +#962=IFCAXIS2PLACEMENT2D(#48,$); +#963=IFCRECTANGLEPROFILEDEF(.AREA.,$,#962,1.2799999999999998,0.04); +#964=IFCAXIS2PLACEMENT3D(#71,$,$); +#965=IFCDIRECTION((0.0,0.0,1.0)); +#966=IFCEXTRUDEDAREASOLID(#963,#964,#965,1.1800000000000002); +#967=IFCSTYLEDITEM(#966,(#77),$); +#968=IFCAXIS2PLACEMENT2D(#48,$); +#969=IFCRECTANGLEPROFILEDEF(.AREA.,$,#968,0.05,0.12); +#970=IFCAXIS2PLACEMENT3D(#1,$,$); +#971=IFCDIRECTION((0.0,0.0,1.0)); +#972=IFCEXTRUDEDAREASOLID(#969,#970,#971,1.3); +#973=IFCSTYLEDITEM(#972,(#67),$); +#974=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#960,#966,#972)); +#975=IFCPRODUCTDEFINITIONSHAPE($,$,(#974)); +#976=IFCWINDOW('0Tftab_icdnHrieaUXNTy6',$,'Window F-West 2',$,$,#955,#975,$,1.3,1.4,.WINDOW.,.NOTDEFINED.,$); +#977=IFCRELFILLSELEMENT('387Uk216V_6AQDuTnSrlTs',$,$,$,#952,#976); +#978=IFCDIRECTION((0.0,0.0,1.0)); +#979=IFCDIRECTION((0.0,1.0,0.0)); +#980=IFCAXIS2PLACEMENT3D(#454,#978,#979); +#981=IFCLOCALPLACEMENT(#22,#980); +#982=IFCAXIS2PLACEMENT2D(#459,$); +#983=IFCRECTANGLEPROFILEDEF(.AREA.,$,#982,7.699999999999999,0.15); +#984=IFCAXIS2PLACEMENT3D(#1,$,$); +#985=IFCDIRECTION((0.0,0.0,1.0)); +#986=IFCEXTRUDEDAREASOLID(#983,#984,#985,2.8); +#987=IFCSTYLEDITEM(#986,(#40),$); +#988=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#986)); +#989=IFCPRODUCTDEFINITIONSHAPE($,$,(#988)); +#990=IFCWALL('1cqN1nF4rR22Cfk9xtU0Ed',$,'F-Partition A',$,$,#981,#989,$,.STANDARD.); +#991=IFCAXIS2PLACEMENT3D(#469,$,$); +#992=IFCLOCALPLACEMENT(#981,#991); +#993=IFCAXIS2PLACEMENT2D(#48,$); +#994=IFCRECTANGLEPROFILEDEF(.AREA.,$,#993,0.9,0.35); +#995=IFCAXIS2PLACEMENT3D(#1,$,$); +#996=IFCDIRECTION((0.0,0.0,1.0)); +#997=IFCEXTRUDEDAREASOLID(#994,#995,#996,2.05); +#998=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#997)); +#999=IFCPRODUCTDEFINITIONSHAPE($,$,(#998)); +#1000=IFCOPENINGELEMENT('1A7Jx9Rc_bCKL8WXfiMKGo',$,'Opening F-Partition A 1',$,$,#992,#999,$,.OPENING.); +#1001=IFCRELVOIDSELEMENT('33SN7gElzYmGXOKqISIqCA',$,$,$,#990,#1000); +#1002=IFCAXIS2PLACEMENT3D(#469,$,$); +#1003=IFCLOCALPLACEMENT(#981,#1002); +#1004=IFCAXIS2PLACEMENT2D(#48,$); +#1005=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1004,0.8,0.06); +#1006=IFCAXIS2PLACEMENT3D(#1,$,$); +#1007=IFCDIRECTION((0.0,0.0,1.0)); +#1008=IFCEXTRUDEDAREASOLID(#1005,#1006,#1007,1.9999999999999998); +#1009=IFCSTYLEDITEM(#1008,(#146),$); +#1010=IFCAXIS2PLACEMENT2D(#48,$); +#1011=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1010,0.08,0.14); +#1012=IFCAXIS2PLACEMENT3D(#491,$,$); +#1013=IFCDIRECTION((0.0,0.0,1.0)); +#1014=IFCEXTRUDEDAREASOLID(#1011,#1012,#1013,0.08); +#1015=IFCSTYLEDITEM(#1014,(#67),$); +#1016=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1008,#1014)); +#1017=IFCPRODUCTDEFINITIONSHAPE($,$,(#1016)); +#1018=IFCDOOR('0fef_ZKXAjXWfcIzwdMFtE',$,'Door F-Partition A 1',$,$,#1003,#1017,$,2.05,0.9,.DOOR.,.NOTDEFINED.,$); +#1019=IFCRELFILLSELEMENT('24avWnKV6QfEdOyOlVrIVb',$,$,$,#1000,#1018); +#1020=IFCAXIS2PLACEMENT3D(#500,$,$); +#1021=IFCLOCALPLACEMENT(#981,#1020); +#1022=IFCAXIS2PLACEMENT2D(#48,$); +#1023=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1022,0.9,0.35); +#1024=IFCAXIS2PLACEMENT3D(#1,$,$); +#1025=IFCDIRECTION((0.0,0.0,1.0)); +#1026=IFCEXTRUDEDAREASOLID(#1023,#1024,#1025,2.05); +#1027=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1026)); +#1028=IFCPRODUCTDEFINITIONSHAPE($,$,(#1027)); +#1029=IFCOPENINGELEMENT('2Ia3e1oW2LLwQLqE9RhVwf',$,'Opening F-Partition A 2',$,$,#1021,#1028,$,.OPENING.); +#1030=IFCRELVOIDSELEMENT('3ifvMT1yUoC7ZDWDbtOB8v',$,$,$,#990,#1029); +#1031=IFCAXIS2PLACEMENT3D(#500,$,$); +#1032=IFCLOCALPLACEMENT(#981,#1031); +#1033=IFCAXIS2PLACEMENT2D(#48,$); +#1034=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1033,0.8,0.06); +#1035=IFCAXIS2PLACEMENT3D(#1,$,$); +#1036=IFCDIRECTION((0.0,0.0,1.0)); +#1037=IFCEXTRUDEDAREASOLID(#1034,#1035,#1036,1.9999999999999998); +#1038=IFCSTYLEDITEM(#1037,(#146),$); +#1039=IFCAXIS2PLACEMENT2D(#48,$); +#1040=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1039,0.08,0.14); +#1041=IFCAXIS2PLACEMENT3D(#491,$,$); +#1042=IFCDIRECTION((0.0,0.0,1.0)); +#1043=IFCEXTRUDEDAREASOLID(#1040,#1041,#1042,0.08); +#1044=IFCSTYLEDITEM(#1043,(#67),$); +#1045=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1037,#1043)); +#1046=IFCPRODUCTDEFINITIONSHAPE($,$,(#1045)); +#1047=IFCDOOR('3dTXGyheoV$V3_9RdivWVr',$,'Door F-Partition A 2',$,$,#1032,#1046,$,2.05,0.9,.DOOR.,.NOTDEFINED.,$); +#1048=IFCRELFILLSELEMENT('0Cov0_Zpt9Rs9u4dv7fsf2',$,$,$,#1029,#1047); +#1049=IFCDIRECTION((0.0,0.0,1.0)); +#1050=IFCDIRECTION((1.0,0.0,0.0)); +#1051=IFCAXIS2PLACEMENT3D(#530,#1049,#1050); +#1052=IFCLOCALPLACEMENT(#22,#1051); +#1053=IFCAXIS2PLACEMENT2D(#535,$); +#1054=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1053,5.85,0.15); +#1055=IFCAXIS2PLACEMENT3D(#1,$,$); +#1056=IFCDIRECTION((0.0,0.0,1.0)); +#1057=IFCEXTRUDEDAREASOLID(#1054,#1055,#1056,2.8); +#1058=IFCSTYLEDITEM(#1057,(#40),$); +#1059=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1057)); +#1060=IFCPRODUCTDEFINITIONSHAPE($,$,(#1059)); +#1061=IFCWALL('1hq$nFp8YYtC3UTELD_Uv7',$,'F-Partition B',$,$,#1052,#1060,$,.STANDARD.); +#1062=IFCAXIS2PLACEMENT3D(#545,$,$); +#1063=IFCLOCALPLACEMENT(#1052,#1062); +#1064=IFCAXIS2PLACEMENT2D(#48,$); +#1065=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1064,0.9,0.35); +#1066=IFCAXIS2PLACEMENT3D(#1,$,$); +#1067=IFCDIRECTION((0.0,0.0,1.0)); +#1068=IFCEXTRUDEDAREASOLID(#1065,#1066,#1067,2.05); +#1069=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1068)); +#1070=IFCPRODUCTDEFINITIONSHAPE($,$,(#1069)); +#1071=IFCOPENINGELEMENT('2c83NhPnPXLIbej7lXvPXw',$,'Opening F-Partition B 1',$,$,#1063,#1070,$,.OPENING.); +#1072=IFCRELVOIDSELEMENT('0W72NcfsqpExiWuS17yp5l',$,$,$,#1061,#1071); +#1073=IFCAXIS2PLACEMENT3D(#545,$,$); +#1074=IFCLOCALPLACEMENT(#1052,#1073); +#1075=IFCAXIS2PLACEMENT2D(#48,$); +#1076=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1075,0.8,0.06); +#1077=IFCAXIS2PLACEMENT3D(#1,$,$); +#1078=IFCDIRECTION((0.0,0.0,1.0)); +#1079=IFCEXTRUDEDAREASOLID(#1076,#1077,#1078,1.9999999999999998); +#1080=IFCSTYLEDITEM(#1079,(#146),$); +#1081=IFCAXIS2PLACEMENT2D(#48,$); +#1082=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1081,0.08,0.14); +#1083=IFCAXIS2PLACEMENT3D(#491,$,$); +#1084=IFCDIRECTION((0.0,0.0,1.0)); +#1085=IFCEXTRUDEDAREASOLID(#1082,#1083,#1084,0.08); +#1086=IFCSTYLEDITEM(#1085,(#67),$); +#1087=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1079,#1085)); +#1088=IFCPRODUCTDEFINITIONSHAPE($,$,(#1087)); +#1089=IFCDOOR('1dNPk$DGVG$_TfbF1v2zh9',$,'Door F-Partition B 1',$,$,#1074,#1088,$,2.05,0.9,.DOOR.,.NOTDEFINED.,$); +#1090=IFCRELFILLSELEMENT('1H$h4uimJ_fnSqpROw3nhT',$,$,$,#1071,#1089); +#1091=IFCCARTESIANPOINT((5.0,4.0)); +#1092=IFCAXIS2PLACEMENT2D(#1091,$); +#1093=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1092,10.3,8.3); +#1094=IFCCARTESIANPOINT((0.0,0.0,-0.2)); +#1095=IFCAXIS2PLACEMENT3D(#1094,$,$); +#1096=IFCDIRECTION((0.0,0.0,1.0)); +#1097=IFCEXTRUDEDAREASOLID(#1093,#1095,#1096,0.2); +#1098=IFCCOLOURRGB($,0.62,0.62,0.6); +#1099=IFCSURFACESTYLERENDERING(#1098,0.0,$,$,$,$,$,$,.FLAT.); +#1100=IFCSURFACESTYLE('Concrete',.BOTH.,(#1099)); +#1101=IFCSTYLEDITEM(#1097,(#1100),$); +#1102=IFCAXIS2PLACEMENT3D(#1,$,$); +#1103=IFCLOCALPLACEMENT(#18,#1102); +#1104=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1097)); +#1105=IFCPRODUCTDEFINITIONSHAPE($,$,(#1104)); +#1106=IFCSLAB('3uW8_5KuqrHFDQqcV_sUwS',$,'Ground slab',$,$,#1103,#1105,$,.BASESLAB.); +#1107=IFCCARTESIANPOINT((-0.15,-0.15)); +#1108=IFCCARTESIANPOINT((10.15,-0.15)); +#1109=IFCCARTESIANPOINT((10.15,8.15)); +#1110=IFCCARTESIANPOINT((-0.15,8.15)); +#1111=IFCPOLYLINE((#1107,#1108,#1109,#1110,#1107)); +#1112=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#1111); +#1113=IFCCARTESIANPOINT((0.0,0.0,2.8)); +#1114=IFCAXIS2PLACEMENT3D(#1113,$,$); +#1115=IFCDIRECTION((0.0,0.0,1.0)); +#1116=IFCEXTRUDEDAREASOLID(#1112,#1114,#1115,0.2); +#1117=IFCSTYLEDITEM(#1116,(#1100),$); +#1118=IFCAXIS2PLACEMENT3D(#1,$,$); +#1119=IFCLOCALPLACEMENT(#18,#1118); +#1120=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1116)); +#1121=IFCPRODUCTDEFINITIONSHAPE($,$,(#1120)); +#1122=IFCSLAB('1JroyyVJjHzn1vqdj4iASO',$,'Floor slab',$,$,#1119,#1121,$,.FLOOR.); +#1123=IFCCARTESIANPOINT((8.2,-0.8)); +#1124=IFCAXIS2PLACEMENT2D(#1123,$); +#1125=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1124,4.0,1.4); +#1126=IFCAXIS2PLACEMENT3D(#1113,$,$); +#1127=IFCDIRECTION((0.0,0.0,1.0)); +#1128=IFCEXTRUDEDAREASOLID(#1125,#1126,#1127,0.15); +#1129=IFCSTYLEDITEM(#1128,(#1100),$); +#1130=IFCAXIS2PLACEMENT3D(#1,$,$); +#1131=IFCLOCALPLACEMENT(#18,#1130); +#1132=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1128)); +#1133=IFCPRODUCTDEFINITIONSHAPE($,$,(#1132)); +#1134=IFCSLAB('0_KD9qIz8ZVasBE2JIVZf7',$,'Porch roof',$,$,#1131,#1133,$,.ROOF.); +#1135=IFCAXIS2PLACEMENT2D(#48,$); +#1136=IFCCIRCLEPROFILEDEF(.AREA.,$,#1135,0.15); +#1137=IFCAXIS2PLACEMENT3D(#1,$,$); +#1138=IFCDIRECTION((0.0,0.0,1.0)); +#1139=IFCEXTRUDEDAREASOLID(#1136,#1137,#1138,2.8); +#1140=IFCCOLOURRGB($,0.9,0.9,0.9); +#1141=IFCSURFACESTYLERENDERING(#1140,0.0,$,$,$,$,$,$,.FLAT.); +#1142=IFCSURFACESTYLE('Column',.BOTH.,(#1141)); +#1143=IFCSTYLEDITEM(#1139,(#1142),$); +#1144=IFCCARTESIANPOINT((6.4,-1.3,0.0)); +#1145=IFCAXIS2PLACEMENT3D(#1144,$,$); +#1146=IFCLOCALPLACEMENT(#18,#1145); +#1147=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1139)); +#1148=IFCPRODUCTDEFINITIONSHAPE($,$,(#1147)); +#1149=IFCCOLUMN('0jBmRafpDIHsHe86WbER21',$,'Porch column 1',$,$,#1146,#1148,$,.COLUMN.); +#1150=IFCAXIS2PLACEMENT2D(#48,$); +#1151=IFCCIRCLEPROFILEDEF(.AREA.,$,#1150,0.15); +#1152=IFCAXIS2PLACEMENT3D(#1,$,$); +#1153=IFCDIRECTION((0.0,0.0,1.0)); +#1154=IFCEXTRUDEDAREASOLID(#1151,#1152,#1153,2.8); +#1155=IFCSTYLEDITEM(#1154,(#1142),$); +#1156=IFCCARTESIANPOINT((10.0,-1.3,0.0)); +#1157=IFCAXIS2PLACEMENT3D(#1156,$,$); +#1158=IFCLOCALPLACEMENT(#18,#1157); +#1159=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1154)); +#1160=IFCPRODUCTDEFINITIONSHAPE($,$,(#1159)); +#1161=IFCCOLUMN('0oREbHPhoml9VoeBJ0D39C',$,'Porch column 2',$,$,#1158,#1160,$,.COLUMN.); +#1162=IFCCARTESIANPOINT((-0.6,0.0)); +#1163=IFCCARTESIANPOINT((8.6,0.0)); +#1164=IFCCARTESIANPOINT((4.0,2.7)); +#1165=IFCPOLYLINE((#1162,#1163,#1164,#1162)); +#1166=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#1165); +#1167=IFCDIRECTION((1.0,0.0,0.0)); +#1168=IFCDIRECTION((0.0,1.0,0.0)); +#1169=IFCAXIS2PLACEMENT3D(#1,#1167,#1168); +#1170=IFCDIRECTION((0.0,0.0,1.0)); +#1171=IFCEXTRUDEDAREASOLID(#1166,#1169,#1170,11.2); +#1172=IFCCOLOURRGB($,0.7,0.28,0.2); +#1173=IFCSURFACESTYLERENDERING(#1172,0.0,$,$,$,$,$,$,.FLAT.); +#1174=IFCSURFACESTYLE('Tiles',.BOTH.,(#1173)); +#1175=IFCSTYLEDITEM(#1171,(#1174),$); +#1176=IFCCARTESIANPOINT((-0.6,0.0,3.0)); +#1177=IFCAXIS2PLACEMENT3D(#1176,$,$); +#1178=IFCLOCALPLACEMENT(#22,#1177); +#1179=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1171)); +#1180=IFCPRODUCTDEFINITIONSHAPE($,$,(#1179)); +#1181=IFCROOF('1BQq88wgrCSySlkWj6H5xP',$,'Gable roof',$,$,#1178,#1180,$,.GABLE_ROOF.); +#1182=IFCCARTESIANPOINT((0.0,0.14)); +#1183=IFCAXIS2PLACEMENT2D(#1182,$); +#1184=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1183,1.0,0.28); +#1185=IFCAXIS2PLACEMENT3D(#1,$,$); +#1186=IFCDIRECTION((0.0,0.0,1.0)); +#1187=IFCEXTRUDEDAREASOLID(#1184,#1185,#1186,0.25); +#1188=IFCCOLOURRGB($,0.6,0.42,0.25); +#1189=IFCSURFACESTYLERENDERING(#1188,0.0,$,$,$,$,$,$,.FLAT.); +#1190=IFCSURFACESTYLE('Wood',.BOTH.,(#1189)); +#1191=IFCSTYLEDITEM(#1187,(#1190),$); +#1192=IFCCARTESIANPOINT((0.0,0.42000000000000004)); +#1193=IFCAXIS2PLACEMENT2D(#1192,$); +#1194=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1193,1.0,0.28); +#1195=IFCAXIS2PLACEMENT3D(#1,$,$); +#1196=IFCDIRECTION((0.0,0.0,1.0)); +#1197=IFCEXTRUDEDAREASOLID(#1194,#1195,#1196,0.5); +#1198=IFCSTYLEDITEM(#1197,(#1190),$); +#1199=IFCCARTESIANPOINT((0.0,0.7000000000000001)); +#1200=IFCAXIS2PLACEMENT2D(#1199,$); +#1201=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1200,1.0,0.28); +#1202=IFCAXIS2PLACEMENT3D(#1,$,$); +#1203=IFCDIRECTION((0.0,0.0,1.0)); +#1204=IFCEXTRUDEDAREASOLID(#1201,#1202,#1203,0.75); +#1205=IFCSTYLEDITEM(#1204,(#1190),$); +#1206=IFCCARTESIANPOINT((0.0,0.9800000000000001)); +#1207=IFCAXIS2PLACEMENT2D(#1206,$); +#1208=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1207,1.0,0.28); +#1209=IFCAXIS2PLACEMENT3D(#1,$,$); +#1210=IFCDIRECTION((0.0,0.0,1.0)); +#1211=IFCEXTRUDEDAREASOLID(#1208,#1209,#1210,1.0); +#1212=IFCSTYLEDITEM(#1211,(#1190),$); +#1213=IFCCARTESIANPOINT((0.0,1.2600000000000002)); +#1214=IFCAXIS2PLACEMENT2D(#1213,$); +#1215=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1214,1.0,0.28); +#1216=IFCAXIS2PLACEMENT3D(#1,$,$); +#1217=IFCDIRECTION((0.0,0.0,1.0)); +#1218=IFCEXTRUDEDAREASOLID(#1215,#1216,#1217,1.25); +#1219=IFCSTYLEDITEM(#1218,(#1190),$); +#1220=IFCCARTESIANPOINT((0.0,1.54)); +#1221=IFCAXIS2PLACEMENT2D(#1220,$); +#1222=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1221,1.0,0.28); +#1223=IFCAXIS2PLACEMENT3D(#1,$,$); +#1224=IFCDIRECTION((0.0,0.0,1.0)); +#1225=IFCEXTRUDEDAREASOLID(#1222,#1223,#1224,1.5); +#1226=IFCSTYLEDITEM(#1225,(#1190),$); +#1227=IFCCARTESIANPOINT((0.0,1.8200000000000003)); +#1228=IFCAXIS2PLACEMENT2D(#1227,$); +#1229=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1228,1.0,0.28); +#1230=IFCAXIS2PLACEMENT3D(#1,$,$); +#1231=IFCDIRECTION((0.0,0.0,1.0)); +#1232=IFCEXTRUDEDAREASOLID(#1229,#1230,#1231,1.75); +#1233=IFCSTYLEDITEM(#1232,(#1190),$); +#1234=IFCCARTESIANPOINT((0.0,2.1)); +#1235=IFCAXIS2PLACEMENT2D(#1234,$); +#1236=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1235,1.0,0.28); +#1237=IFCAXIS2PLACEMENT3D(#1,$,$); +#1238=IFCDIRECTION((0.0,0.0,1.0)); +#1239=IFCEXTRUDEDAREASOLID(#1236,#1237,#1238,2.0); +#1240=IFCSTYLEDITEM(#1239,(#1190),$); +#1241=IFCCARTESIANPOINT((0.0,2.3800000000000003)); +#1242=IFCAXIS2PLACEMENT2D(#1241,$); +#1243=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1242,1.0,0.28); +#1244=IFCAXIS2PLACEMENT3D(#1,$,$); +#1245=IFCDIRECTION((0.0,0.0,1.0)); +#1246=IFCEXTRUDEDAREASOLID(#1243,#1244,#1245,2.25); +#1247=IFCSTYLEDITEM(#1246,(#1190),$); +#1248=IFCCARTESIANPOINT((0.0,2.6600000000000006)); +#1249=IFCAXIS2PLACEMENT2D(#1248,$); +#1250=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1249,1.0,0.28); +#1251=IFCAXIS2PLACEMENT3D(#1,$,$); +#1252=IFCDIRECTION((0.0,0.0,1.0)); +#1253=IFCEXTRUDEDAREASOLID(#1250,#1251,#1252,2.5); +#1254=IFCSTYLEDITEM(#1253,(#1190),$); +#1255=IFCCARTESIANPOINT((0.0,2.9400000000000004)); +#1256=IFCAXIS2PLACEMENT2D(#1255,$); +#1257=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1256,1.0,0.28); +#1258=IFCAXIS2PLACEMENT3D(#1,$,$); +#1259=IFCDIRECTION((0.0,0.0,1.0)); +#1260=IFCEXTRUDEDAREASOLID(#1257,#1258,#1259,2.75); +#1261=IFCSTYLEDITEM(#1260,(#1190),$); +#1262=IFCCARTESIANPOINT((6.9,4.3,0.0)); +#1263=IFCAXIS2PLACEMENT3D(#1262,$,$); +#1264=IFCLOCALPLACEMENT(#18,#1263); +#1265=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1187,#1197,#1204,#1211,#1218,#1225,#1232,#1239,#1246,#1253,#1260)); +#1266=IFCPRODUCTDEFINITIONSHAPE($,$,(#1265)); +#1267=IFCSTAIR('2S8F5STq7u_$iRCyHmIalm',$,'Stair',$,$,#1264,#1266,$,.STRAIGHT_RUN_STAIR.); +#1268=IFCAXIS2PLACEMENT2D(#48,$); +#1269=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1268,0.45,0.45); +#1270=IFCCARTESIANPOINT((0.0,0.0,0.45)); +#1271=IFCAXIS2PLACEMENT3D(#1270,$,$); +#1272=IFCDIRECTION((0.0,0.0,1.0)); +#1273=IFCEXTRUDEDAREASOLID(#1269,#1271,#1272,0.05); +#1274=IFCCOLOURRGB($,0.75,0.2,0.2); +#1275=IFCSURFACESTYLERENDERING(#1274,0.0,$,$,$,$,$,$,.FLAT.); +#1276=IFCSURFACESTYLE('Chair',.BOTH.,(#1275)); +#1277=IFCSTYLEDITEM(#1273,(#1276),$); +#1278=IFCCARTESIANPOINT((0.0,-0.2)); +#1279=IFCAXIS2PLACEMENT2D(#1278,$); +#1280=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1279,0.45,0.05); +#1281=IFCCARTESIANPOINT((0.0,0.0,0.5)); +#1282=IFCAXIS2PLACEMENT3D(#1281,$,$); +#1283=IFCDIRECTION((0.0,0.0,1.0)); +#1284=IFCEXTRUDEDAREASOLID(#1280,#1282,#1283,0.5); +#1285=IFCSTYLEDITEM(#1284,(#1276),$); +#1286=IFCCARTESIANPOINT((-0.19,-0.19)); +#1287=IFCAXIS2PLACEMENT2D(#1286,$); +#1288=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1287,0.05,0.05); +#1289=IFCAXIS2PLACEMENT3D(#1,$,$); +#1290=IFCDIRECTION((0.0,0.0,1.0)); +#1291=IFCEXTRUDEDAREASOLID(#1288,#1289,#1290,0.45); +#1292=IFCCOLOURRGB($,0.3,0.2,0.15); +#1293=IFCSURFACESTYLERENDERING(#1292,0.0,$,$,$,$,$,$,.FLAT.); +#1294=IFCSURFACESTYLE('Chair legs',.BOTH.,(#1293)); +#1295=IFCSTYLEDITEM(#1291,(#1294),$); +#1296=IFCCARTESIANPOINT((-0.19,0.19)); +#1297=IFCAXIS2PLACEMENT2D(#1296,$); +#1298=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1297,0.05,0.05); +#1299=IFCAXIS2PLACEMENT3D(#1,$,$); +#1300=IFCDIRECTION((0.0,0.0,1.0)); +#1301=IFCEXTRUDEDAREASOLID(#1298,#1299,#1300,0.45); +#1302=IFCSTYLEDITEM(#1301,(#1294),$); +#1303=IFCCARTESIANPOINT((0.19,-0.19)); +#1304=IFCAXIS2PLACEMENT2D(#1303,$); +#1305=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1304,0.05,0.05); +#1306=IFCAXIS2PLACEMENT3D(#1,$,$); +#1307=IFCDIRECTION((0.0,0.0,1.0)); +#1308=IFCEXTRUDEDAREASOLID(#1305,#1306,#1307,0.45); +#1309=IFCSTYLEDITEM(#1308,(#1294),$); +#1310=IFCCARTESIANPOINT((0.19,0.19)); +#1311=IFCAXIS2PLACEMENT2D(#1310,$); +#1312=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1311,0.05,0.05); +#1313=IFCAXIS2PLACEMENT3D(#1,$,$); +#1314=IFCDIRECTION((0.0,0.0,1.0)); +#1315=IFCEXTRUDEDAREASOLID(#1312,#1313,#1314,0.45); +#1316=IFCSTYLEDITEM(#1315,(#1294),$); +#1317=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1273,#1284,#1291,#1301,#1308,#1315)); +#1318=IFCAXIS2PLACEMENT3D(#1,$,$); +#1319=IFCREPRESENTATIONMAP(#1318,#1317); +#1320=IFCAXIS2PLACEMENT2D(#48,$); +#1321=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1320,1.6,0.9); +#1322=IFCCARTESIANPOINT((0.0,0.0,0.72)); +#1323=IFCAXIS2PLACEMENT3D(#1322,$,$); +#1324=IFCDIRECTION((0.0,0.0,1.0)); +#1325=IFCEXTRUDEDAREASOLID(#1321,#1323,#1324,0.06); +#1326=IFCSTYLEDITEM(#1325,(#1190),$); +#1327=IFCCARTESIANPOINT((-0.72,-0.36)); +#1328=IFCAXIS2PLACEMENT2D(#1327,$); +#1329=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1328,0.07,0.07); +#1330=IFCAXIS2PLACEMENT3D(#1,$,$); +#1331=IFCDIRECTION((0.0,0.0,1.0)); +#1332=IFCEXTRUDEDAREASOLID(#1329,#1330,#1331,0.72); +#1333=IFCSTYLEDITEM(#1332,(#1190),$); +#1334=IFCCARTESIANPOINT((-0.72,0.36)); +#1335=IFCAXIS2PLACEMENT2D(#1334,$); +#1336=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1335,0.07,0.07); +#1337=IFCAXIS2PLACEMENT3D(#1,$,$); +#1338=IFCDIRECTION((0.0,0.0,1.0)); +#1339=IFCEXTRUDEDAREASOLID(#1336,#1337,#1338,0.72); +#1340=IFCSTYLEDITEM(#1339,(#1190),$); +#1341=IFCCARTESIANPOINT((0.72,-0.36)); +#1342=IFCAXIS2PLACEMENT2D(#1341,$); +#1343=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1342,0.07,0.07); +#1344=IFCAXIS2PLACEMENT3D(#1,$,$); +#1345=IFCDIRECTION((0.0,0.0,1.0)); +#1346=IFCEXTRUDEDAREASOLID(#1343,#1344,#1345,0.72); +#1347=IFCSTYLEDITEM(#1346,(#1190),$); +#1348=IFCCARTESIANPOINT((0.72,0.36)); +#1349=IFCAXIS2PLACEMENT2D(#1348,$); +#1350=IFCRECTANGLEPROFILEDEF(.AREA.,$,#1349,0.07,0.07); +#1351=IFCAXIS2PLACEMENT3D(#1,$,$); +#1352=IFCDIRECTION((0.0,0.0,1.0)); +#1353=IFCEXTRUDEDAREASOLID(#1350,#1351,#1352,0.72); +#1354=IFCSTYLEDITEM(#1353,(#1190),$); +#1355=IFCSHAPEREPRESENTATION(#4,'Body','SweptSolid',(#1325,#1332,#1339,#1346,#1353)); +#1356=IFCAXIS2PLACEMENT3D(#1,$,$); +#1357=IFCREPRESENTATIONMAP(#1356,#1355); +#1358=IFCCARTESIANPOINT((3.0,6.0,0.0)); +#1359=IFCAXIS2PLACEMENT3D(#1358,$,$); +#1360=IFCLOCALPLACEMENT(#18,#1359); +#1361=IFCCARTESIANTRANSFORMATIONOPERATOR3D($,$,#1,1.0,$); +#1362=IFCMAPPEDITEM(#1357,#1361); +#1363=IFCSHAPEREPRESENTATION(#4,'Body','MappedRepresentation',(#1362)); +#1364=IFCPRODUCTDEFINITIONSHAPE($,$,(#1363)); +#1365=IFCFURNISHINGELEMENT('23emMOrFixFBz6b1LSbkTz',$,'Table',$,$,#1360,#1364,$); +#1366=IFCCARTESIANPOINT((2.4,6.0,0.0)); +#1367=IFCDIRECTION((0.0,0.0,1.0)); +#1368=IFCDIRECTION((6.123233995736766e-17,1.0,0.0)); +#1369=IFCAXIS2PLACEMENT3D(#1366,#1367,#1368); +#1370=IFCLOCALPLACEMENT(#18,#1369); +#1371=IFCCARTESIANTRANSFORMATIONOPERATOR3D($,$,#1,1.0,$); +#1372=IFCMAPPEDITEM(#1319,#1371); +#1373=IFCSHAPEREPRESENTATION(#4,'Body','MappedRepresentation',(#1372)); +#1374=IFCPRODUCTDEFINITIONSHAPE($,$,(#1373)); +#1375=IFCFURNISHINGELEMENT('3G$SrKgftfRZnuLGl2A24u',$,'Chair 1',$,$,#1370,#1374,$); +#1376=IFCCARTESIANPOINT((3.6,6.0,0.0)); +#1377=IFCDIRECTION((0.0,0.0,1.0)); +#1378=IFCDIRECTION((6.123233995736766e-17,-1.0,0.0)); +#1379=IFCAXIS2PLACEMENT3D(#1376,#1377,#1378); +#1380=IFCLOCALPLACEMENT(#18,#1379); +#1381=IFCCARTESIANTRANSFORMATIONOPERATOR3D($,$,#1,1.0,$); +#1382=IFCMAPPEDITEM(#1319,#1381); +#1383=IFCSHAPEREPRESENTATION(#4,'Body','MappedRepresentation',(#1382)); +#1384=IFCPRODUCTDEFINITIONSHAPE($,$,(#1383)); +#1385=IFCFURNISHINGELEMENT('3eSe6_fq7qr1vguEGIUDoM',$,'Chair 2',$,$,#1380,#1384,$); +#1386=IFCCARTESIANPOINT((3.0,5.2,0.0)); +#1387=IFCDIRECTION((0.0,0.0,1.0)); +#1388=IFCDIRECTION((-1.0,1.2246467991473532e-16,0.0)); +#1389=IFCAXIS2PLACEMENT3D(#1386,#1387,#1388); +#1390=IFCLOCALPLACEMENT(#18,#1389); +#1391=IFCCARTESIANTRANSFORMATIONOPERATOR3D($,$,#1,1.0,$); +#1392=IFCMAPPEDITEM(#1319,#1391); +#1393=IFCSHAPEREPRESENTATION(#4,'Body','MappedRepresentation',(#1392)); +#1394=IFCPRODUCTDEFINITIONSHAPE($,$,(#1393)); +#1395=IFCFURNISHINGELEMENT('0d$KI4yAjD7xYvVgT8q4zG',$,'Chair 3',$,$,#1390,#1394,$); +#1396=IFCCARTESIANPOINT((3.0,6.8,0.0)); +#1397=IFCDIRECTION((0.0,0.0,1.0)); +#1398=IFCDIRECTION((1.0,0.0,0.0)); +#1399=IFCAXIS2PLACEMENT3D(#1396,#1397,#1398); +#1400=IFCLOCALPLACEMENT(#18,#1399); +#1401=IFCCARTESIANTRANSFORMATIONOPERATOR3D($,$,#1,1.0,$); +#1402=IFCMAPPEDITEM(#1319,#1401); +#1403=IFCSHAPEREPRESENTATION(#4,'Body','MappedRepresentation',(#1402)); +#1404=IFCPRODUCTDEFINITIONSHAPE($,$,(#1403)); +#1405=IFCFURNISHINGELEMENT('0KudeHLcXeHkPVKDQ4sVh1',$,'Chair 4',$,$,#1400,#1404,$); +#1406=IFCAXIS2PLACEMENT3D(#1,$,$); +#1407=IFCLOCALPLACEMENT(#18,#1406); +#1408=IFCSPACE('2KNKWx9yNmqWh_dBhsSwYr',$,'Living room',$,$,#1407,$,$,.ELEMENT.,.INTERNAL.,$); +#1409=IFCAXIS2PLACEMENT3D(#1,$,$); +#1410=IFCLOCALPLACEMENT(#18,#1409); +#1411=IFCSPACE('0f2Avw7pTSvALFiOeiSXIX',$,'Kitchen',$,$,#1410,$,$,.ELEMENT.,.INTERNAL.,$); +#1412=IFCAXIS2PLACEMENT3D(#1,$,$); +#1413=IFCLOCALPLACEMENT(#18,#1412); +#1414=IFCSPACE('0EOHNmkQ4Z8RvOIEJDWAaL',$,'Hall',$,$,#1413,$,$,.ELEMENT.,.INTERNAL.,$); +#1415=IFCAXIS2PLACEMENT3D(#1,$,$); +#1416=IFCLOCALPLACEMENT(#22,#1415); +#1417=IFCSPACE('1x4u81T7gJE8bMsUhdF3CW',$,'Bedroom',$,$,#1416,$,$,.ELEMENT.,.INTERNAL.,$); +#1418=IFCAXIS2PLACEMENT3D(#1,$,$); +#1419=IFCLOCALPLACEMENT(#22,#1418); +#1420=IFCSPACE('1ayJFSQ8Utto_pkXiX9oEX',$,'Bath',$,$,#1419,$,$,.ELEMENT.,.INTERNAL.,$); +#1421=IFCRELAGGREGATES('2szUB7fVbu2CEN4ckI58jC',$,$,$,#19,(#1408,#1411,#1414)); +#1422=IFCRELAGGREGATES('1yGO1uoLb4mNBKRmU$T6EQ',$,$,$,#23,(#1417,#1420)); +#1423=IFCPROPERTYSINGLEVALUE('IsExternal',$,IFCBOOLEAN(.T.),$); +#1424=IFCPROPERTYSINGLEVALUE('FireRating',$,IFCLABEL('REI 60'),$); +#1425=IFCPROPERTYSET('0RRZV4WWZWebmvRwxlAQ_q',$,'Pset_WallCommon',$,(#1423,#1424)); +#1426=IFCRELDEFINESBYPROPERTIES('1YEys40ud$n1qd689ytAX4',$,$,$,(#44,#173,#259,#381),#1425); +#1427=IFCRELASSOCIATESMATERIAL('068JfRdA0RlTPo3hAQRmU6',$,$,$,(#44,#173,#259,#381,#468,#544,#587,#706,#789,#907,#990,#1061),#27); +#1428=IFCRELCONTAINEDINSPATIALSTRUCTURE('3WgMEO8b_SdrznzovE6AH2',$,$,$,(#44,#87,#123,#157,#173,#208,#244,#259,#294,#330,#366,#381,#416,#452,#468,#498,#528,#544,#573,#1106,#1122,#1134,#1149,#1161,#1267,#1365,#1375,#1385,#1395,#1405),#19); +#1429=IFCRELCONTAINEDINSPATIALSTRUCTURE('2YZ2VvhXdDGsswuOVwGmcq',$,$,$,(#587,#621,#656,#692,#706,#740,#775,#789,#823,#858,#893,#907,#941,#976,#990,#1018,#1047,#1061,#1089,#1181),#23); +ENDSEC; +END-ISO-10303-21; diff --git a/crates/exav-viewer/demo/examples/files/images/bounce.gif b/crates/exav-viewer/demo/examples/files/images/bounce.gif new file mode 100644 index 0000000..30fd84b Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/bounce.gif differ diff --git a/crates/exav-viewer/demo/examples/files/images/bounce.jxl b/crates/exav-viewer/demo/examples/files/images/bounce.jxl new file mode 100644 index 0000000..0bbdca1 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/bounce.jxl differ diff --git a/crates/exav-viewer/demo/examples/files/images/bounce.png b/crates/exav-viewer/demo/examples/files/images/bounce.png new file mode 100644 index 0000000..01c991a Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/bounce.png differ diff --git a/crates/exav-viewer/demo/examples/files/images/bounce.webp b/crates/exav-viewer/demo/examples/files/images/bounce.webp new file mode 100644 index 0000000..b5ece6e Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/bounce.webp differ diff --git a/crates/exav-viewer/demo/examples/files/images/fax-g3-1d.tif b/crates/exav-viewer/demo/examples/files/images/fax-g3-1d.tif new file mode 100644 index 0000000..49466f8 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/fax-g3-1d.tif differ diff --git a/crates/exav-viewer/demo/examples/files/images/fax-g4-3pages.tif b/crates/exav-viewer/demo/examples/files/images/fax-g4-3pages.tif new file mode 100644 index 0000000..7dedd65 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/fax-g4-3pages.tif differ diff --git a/crates/exav-viewer/demo/examples/files/images/fax-g4.tif b/crates/exav-viewer/demo/examples/files/images/fax-g4.tif new file mode 100644 index 0000000..6a78d9e Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/fax-g4.tif differ diff --git a/crates/exav-viewer/demo/examples/files/images/gradient-grey16.png b/crates/exav-viewer/demo/examples/files/images/gradient-grey16.png new file mode 100644 index 0000000..98a80f4 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/gradient-grey16.png differ diff --git a/crates/exav-viewer/demo/examples/files/images/gradient-grey16.tif b/crates/exav-viewer/demo/examples/files/images/gradient-grey16.tif new file mode 100644 index 0000000..a281394 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/gradient-grey16.tif differ diff --git a/crates/exav-viewer/demo/examples/files/images/icon-legacy.ico b/crates/exav-viewer/demo/examples/files/images/icon-legacy.ico new file mode 100644 index 0000000..896bbce Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/icon-legacy.ico differ diff --git a/crates/exav-viewer/demo/examples/files/images/icon.ico b/crates/exav-viewer/demo/examples/files/images/icon.ico new file mode 100644 index 0000000..9501b50 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/icon.ico differ diff --git a/crates/exav-viewer/demo/examples/files/images/page-generic.jb2 b/crates/exav-viewer/demo/examples/files/images/page-generic.jb2 new file mode 100644 index 0000000..1fc9b92 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/page-generic.jb2 differ diff --git a/crates/exav-viewer/demo/examples/files/images/page-symbol.jb2 b/crates/exav-viewer/demo/examples/files/images/page-symbol.jb2 new file mode 100644 index 0000000..3799888 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/page-symbol.jb2 differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-1bit.bmp b/crates/exav-viewer/demo/examples/files/images/scene-1bit.bmp new file mode 100644 index 0000000..0043fc2 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-1bit.bmp differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-24.bmp b/crates/exav-viewer/demo/examples/files/images/scene-24.bmp new file mode 100644 index 0000000..0ea356d Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-24.bmp differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-32.bmp b/crates/exav-viewer/demo/examples/files/images/scene-32.bmp new file mode 100644 index 0000000..02109d3 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-32.bmp differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-8.bmp b/crates/exav-viewer/demo/examples/files/images/scene-8.bmp new file mode 100644 index 0000000..78da761 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-8.bmp differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-alpha.jp2 b/crates/exav-viewer/demo/examples/files/images/scene-alpha.jp2 new file mode 100644 index 0000000..f2144a6 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-alpha.jp2 differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-alpha.jxl b/crates/exav-viewer/demo/examples/files/images/scene-alpha.jxl new file mode 100644 index 0000000..2742bd2 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-alpha.jxl differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-alpha.pam b/crates/exav-viewer/demo/examples/files/images/scene-alpha.pam new file mode 100644 index 0000000..66f2ce5 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-alpha.pam differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-alpha.png b/crates/exav-viewer/demo/examples/files/images/scene-alpha.png new file mode 100644 index 0000000..d009fdf Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-alpha.png differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-alpha.qoi b/crates/exav-viewer/demo/examples/files/images/scene-alpha.qoi new file mode 100644 index 0000000..ed18491 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-alpha.qoi differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-alpha.webp b/crates/exav-viewer/demo/examples/files/images/scene-alpha.webp new file mode 100644 index 0000000..3aa27ad Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-alpha.webp differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-ascii.ppm b/crates/exav-viewer/demo/examples/files/images/scene-ascii.ppm new file mode 100644 index 0000000..3e0f6c0 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/images/scene-ascii.ppm @@ -0,0 +1,40 @@ +P3 +# an ASCII pixmap +48 36 +255 +29 31 92 30 32 93 30 31 92 30 31 92 30 31 92 29 31 92 29 31 92 29 31 92 29 31 92 32 34 95 30 32 93 29 31 92 30 31 92 29 31 92 29 31 92 29 31 92 30 31 92 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 30 32 92 29 31 92 30 32 93 30 32 93 30 32 93 30 32 93 29 31 92 29 31 92 29 31 92 30 32 93 30 32 93 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 29 31 92 +42 35 93 43 36 94 42 35 94 42 35 93 42 35 93 42 35 93 42 35 93 42 35 93 42 35 93 42 35 93 42 35 94 43 36 94 42 35 93 42 35 94 43 36 94 42 35 93 42 35 93 43 36 95 43 37 95 42 35 93 42 35 93 42 35 93 42 35 93 42 35 93 42 35 93 42 35 94 42 35 93 42 36 94 43 36 94 43 37 94 42 36 94 42 35 94 42 35 94 42 35 93 42 35 94 43 36 94 42 36 94 42 35 93 43 36 94 42 35 94 42 35 93 42 35 93 42 35 93 42 35 93 42 35 93 42 35 93 42 35 93 42 35 93 +55 40 95 56 40 96 55 39 95 56 40 96 56 40 96 55 39 95 55 39 95 55 39 95 55 39 95 55 39 95 55 39 95 56 40 96 55 40 95 55 39 95 55 39 95 55 39 95 55 39 95 56 40 95 56 40 95 55 39 95 55 39 95 55 39 95 55 39 95 56 40 95 55 39 95 55 39 95 55 39 95 56 40 96 57 41 96 55 39 94 55 40 95 56 41 96 55 39 95 55 40 95 56 41 96 56 41 96 56 40 95 55 39 95 56 40 95 55 39 95 55 39 95 55 39 95 55 39 95 55 39 95 55 39 95 55 39 95 55 39 95 55 39 95 +68 44 96 68 44 97 68 44 96 69 45 97 71 46 99 68 43 96 68 43 96 68 43 96 68 43 96 68 43 96 68 43 96 69 44 97 68 44 97 69 45 97 68 44 96 68 43 96 68 43 96 68 44 96 70 45 97 68 43 96 68 43 96 68 44 96 68 43 96 69 45 97 69 44 97 69 44 97 68 43 96 68 43 96 68 44 96 68 43 96 68 43 96 68 43 96 68 44 97 68 44 96 68 43 96 69 45 97 68 44 96 68 43 96 68 43 96 68 44 96 68 43 96 68 44 96 68 44 96 68 43 96 68 43 96 68 44 96 68 43 96 68 43 96 +81 47 97 81 47 97 81 47 97 81 48 98 81 48 98 81 47 97 81 48 98 81 47 97 81 47 97 81 48 98 81 48 98 81 47 97 81 47 97 81 47 97 81 47 97 80 47 97 82 48 98 81 47 97 81 48 98 82 49 99 82 49 99 81 47 97 81 47 97 81 47 97 81 48 98 82 48 98 81 48 98 81 47 97 81 48 97 81 48 98 81 48 98 81 47 97 82 48 98 81 48 98 81 47 97 80 47 97 81 47 97 81 48 98 81 48 98 81 47 97 81 47 97 81 48 98 81 48 98 81 48 98 81 48 98 81 47 97 81 48 98 81 48 98 +94 51 99 94 52 99 94 52 99 94 51 99 94 51 99 94 51 99 94 51 99 94 52 99 94 52 99 94 51 99 94 51 99 94 51 99 94 52 99 95 52 100 95 52 100 95 53 100 94 52 99 94 51 99 94 51 99 94 51 99 94 52 99 94 51 99 94 51 99 95 53 100 94 52 99 93 51 99 95 53 100 94 52 99 94 52 99 96 54 101 94 52 99 94 52 99 94 51 99 94 51 99 94 51 99 94 52 100 94 52 99 94 51 99 94 52 99 94 51 99 94 52 99 95 52 100 94 51 99 94 52 99 94 52 99 94 51 99 94 51 99 94 52 99 +107 56 100 107 56 100 107 55 100 107 56 100 109 58 103 107 56 101 106 55 100 107 56 101 107 56 101 107 56 101 107 56 101 106 55 100 107 56 100 107 56 100 108 57 101 108 57 102 107 56 100 106 55 100 107 56 100 107 56 100 107 56 100 107 56 100 107 56 100 107 56 101 107 56 100 107 56 100 106 55 100 106 55 100 107 56 100 107 56 100 107 56 100 107 56 100 107 56 100 107 56 100 107 56 100 107 56 101 107 56 101 107 56 100 107 56 100 107 56 100 107 56 100 107 56 101 107 56 100 106 56 100 106 56 100 107 56 100 108 57 101 107 56 100 +120 61 102 119 60 101 119 59 101 120 60 102 120 61 103 119 60 101 119 59 101 120 61 103 120 60 102 120 60 102 119 60 101 119 60 101 119 59 101 120 60 102 120 61 102 119 59 101 120 60 102 120 60 102 120 60 102 120 60 102 119 60 101 119 60 101 119 60 101 119 59 101 119 60 102 119 60 101 120 60 102 121 61 102 121 60 102 121 61 102 122 62 102 123 63 103 123 61 102 122 61 102 122 61 102 122 61 102 121 60 102 120 60 102 120 60 102 120 60 102 119 59 101 119 60 101 119 60 101 119 60 102 119 60 101 120 60 102 120 60 102 119 60 101 +132 64 103 132 64 103 132 64 103 132 63 103 132 63 103 132 64 103 133 65 104 132 63 103 133 64 103 133 65 104 132 63 103 133 64 103 133 64 103 132 64 103 132 64 103 132 64 103 133 64 103 133 64 103 132 63 103 132 64 103 132 64 103 132 64 103 132 64 103 132 64 103 132 64 103 132 64 103 134 65 103 135 65 104 137 67 105 138 67 104 138 67 104 139 68 104 140 68 104 141 69 105 140 68 105 138 68 104 136 66 103 135 65 103 134 64 103 133 65 103 133 65 104 132 64 103 132 64 103 132 64 103 132 64 103 133 64 104 133 64 103 132 64 103 +145 68 104 146 68 105 146 69 105 146 69 105 145 68 104 145 68 104 145 68 104 146 69 105 146 69 105 145 67 104 145 68 104 146 68 105 146 68 105 145 68 104 145 68 105 145 68 104 145 68 104 145 67 104 147 70 106 146 69 105 145 68 104 145 68 104 145 68 104 145 68 104 146 68 105 147 69 105 148 69 105 150 71 105 153 73 106 155 74 107 157 75 107 157 75 106 158 75 106 158 75 107 157 74 106 155 74 106 153 73 106 151 71 105 149 70 105 148 71 106 147 69 105 145 68 104 145 68 104 145 68 104 145 68 104 145 68 104 145 68 104 145 68 104 +159 72 106 158 72 106 158 72 106 159 74 107 158 72 106 158 72 106 158 72 106 158 72 106 158 72 106 158 72 106 158 72 106 158 72 106 158 72 105 159 72 106 158 72 106 158 72 106 158 72 106 158 72 106 158 72 106 158 72 106 158 72 106 158 72 105 159 72 106 159 73 106 160 73 106 162 75 107 165 76 107 168 79 108 170 79 107 174 81 109 175 82 108 177 83 109 177 83 109 177 83 109 176 82 108 174 81 108 172 80 109 169 78 108 166 76 107 163 74 107 160 73 106 159 72 106 158 72 106 158 72 106 158 72 106 158 72 106 158 72 106 158 72 106 +171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 172 77 107 174 78 107 177 80 108 181 82 109 185 84 109 189 86 110 193 88 111 196 90 111 198 92 111 199 92 112 198 92 111 196 91 111 194 89 111 190 87 110 186 85 109 182 82 109 178 80 108 175 78 108 173 77 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 171 76 107 +184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 185 80 108 187 81 109 190 83 109 194 85 110 198 88 111 203 91 112 209 94 112 214 97 113 218 99 114 220 101 114 222 102 115 221 102 115 218 100 114 215 98 114 210 95 113 205 92 112 200 89 111 195 86 110 191 83 109 187 82 109 185 80 109 184 80 108 184 80 108 184 80 108 184 80 108 184 80 108 +196 85 110 196 85 110 196 85 110 196 85 110 196 85 110 196 85 110 196 85 110 196 85 110 196 85 110 195 85 110 196 85 110 196 85 110 195 85 110 196 85 110 196 85 110 196 85 110 196 85 110 196 85 110 196 85 110 196 85 110 196 85 110 196 85 110 197 86 110 200 88 110 204 90 111 209 93 112 215 96 113 221 100 114 227 104 115 234 107 116 240 111 117 244 113 117 246 114 118 245 114 117 241 111 117 235 108 116 229 104 115 222 101 114 216 97 113 210 93 112 205 90 111 201 88 110 198 86 110 196 85 110 196 85 110 196 85 110 196 85 110 196 85 110 +203 96 110 203 96 110 203 96 110 203 96 110 203 96 110 203 96 110 203 96 110 203 96 110 203 96 110 205 96 108 203 97 110 204 97 109 205 96 108 203 96 110 202 96 111 203 96 110 203 96 110 203 96 110 203 96 110 203 96 110 203 96 110 203 97 110 205 98 110 209 100 110 213 103 111 219 106 112 226 110 113 233 114 115 242 119 116 250 124 117 254 128 119 255 132 120 255 134 122 255 133 121 255 129 119 251 125 118 244 120 116 235 116 115 228 111 114 220 107 113 214 103 112 210 100 111 206 98 110 203 97 111 203 96 110 203 96 110 203 96 110 203 96 110 +209 109 110 209 109 110 209 109 110 209 109 110 209 109 110 209 109 110 209 108 110 210 108 110 211 109 109 194 111 126 181 115 141 183 114 140 196 110 123 210 108 108 211 109 108 209 108 110 208 108 110 208 108 110 209 108 110 209 109 110 209 109 110 210 109 110 213 111 110 217 113 111 222 116 112 228 120 113 236 124 114 246 129 116 254 135 117 255 141 119 255 147 121 255 149 118 255 148 115 254 147 116 255 148 121 255 143 119 254 136 118 247 130 116 237 125 115 233 121 112 227 118 110 218 114 111 216 112 108 213 110 108 209 108 110 209 108 111 209 108 111 209 108 110 +216 120 110 216 120 110 216 120 110 216 120 110 216 120 110 216 120 110 216 120 110 217 121 109 189 117 134 178 120 153 179 119 150 177 118 150 180 121 153 188 118 138 206 118 117 216 120 109 220 122 108 221 123 109 217 121 109 215 120 110 215 120 111 217 121 110 220 123 110 224 125 111 230 129 112 237 133 113 246 137 115 253 143 116 254 149 118 255 157 121 255 162 119 255 185 143 254 217 187 255 203 161 255 167 121 252 158 122 255 154 117 255 148 114 253 142 113 227 130 119 194 120 135 183 118 142 189 118 135 205 119 119 218 121 109 219 122 107 219 122 108 217 121 109 +222 132 110 223 132 110 223 132 110 223 132 110 222 132 110 223 133 110 224 133 108 191 121 135 178 120 153 159 105 133 124 82 109 119 79 106 139 92 119 169 113 145 184 121 153 190 122 143 189 119 129 195 119 117 217 130 115 228 136 111 226 134 107 227 135 108 228 135 110 231 137 111 237 140 112 245 145 113 255 151 114 255 160 115 255 167 117 255 172 120 254 180 124 255 243 213 255 255 243 235 218 206 192 129 143 184 122 144 198 129 140 211 134 133 201 127 137 177 117 147 173 116 149 173 115 147 175 117 150 179 119 151 183 118 138 196 122 130 205 125 123 216 130 114 +229 144 110 228 143 110 227 143 110 227 142 110 227 143 108 229 144 107 194 126 136 178 119 153 144 95 122 102 69 94 101 68 94 107 71 97 108 71 98 80 57 79 59 47 66 103 71 98 118 79 110 106 71 101 119 79 104 174 113 128 207 132 132 216 136 118 231 146 112 241 151 109 248 156 110 254 159 112 248 158 118 235 155 124 238 162 125 252 181 120 255 198 123 253 244 209 218 190 191 173 111 143 171 112 146 173 115 146 171 113 147 170 113 148 172 115 148 176 117 147 176 116 145 187 123 154 174 115 144 161 108 136 187 124 157 175 117 151 175 117 150 180 119 147 +238 158 110 242 160 111 244 162 110 245 163 110 248 164 116 205 134 141 171 114 149 134 89 115 100 67 93 105 71 96 110 73 100 92 63 88 43 38 56 10 20 34 4 16 29 12 20 34 52 42 60 99 67 91 104 70 96 103 69 98 156 104 137 181 120 152 181 119 142 193 127 137 199 131 135 194 128 137 179 119 144 173 115 148 173 115 147 183 124 143 198 140 138 191 135 150 178 114 148 185 122 152 187 124 154 187 123 153 187 123 153 187 123 152 183 120 150 179 118 148 185 122 152 139 95 121 43 39 56 20 26 40 107 76 99 173 114 143 175 115 145 170 112 143 +130 87 99 139 94 100 167 113 106 197 135 107 139 99 95 120 82 114 126 83 109 105 70 96 112 74 101 113 75 102 82 58 81 42 37 54 23 27 42 14 22 36 17 24 38 14 22 36 27 29 45 47 40 58 93 64 88 107 71 97 106 71 96 156 103 132 181 120 152 177 117 151 177 117 152 182 120 155 183 121 153 181 119 149 184 122 152 184 121 154 177 115 152 168 109 142 153 102 130 129 87 113 108 73 98 104 70 95 103 69 95 83 58 81 57 45 64 66 47 69 62 49 68 13 21 35 7 18 31 11 20 34 6 17 31 41 37 54 89 62 86 111 74 100 +104 70 99 102 68 99 76 54 83 29 28 51 1 14 31 9 19 31 56 44 64 90 63 86 47 39 58 74 54 76 108 72 99 84 59 82 28 29 45 13 22 35 15 22 37 13 21 35 40 36 53 95 65 90 107 72 98 108 72 99 108 72 98 109 73 99 139 92 120 159 105 133 151 100 128 124 83 109 91 62 86 73 51 73 88 60 84 100 68 92 88 60 83 67 47 69 46 33 54 38 29 49 37 28 48 38 28 48 25 24 41 7 17 31 5 17 30 11 19 34 21 23 39 21 25 40 15 23 37 14 22 36 20 25 40 61 47 67 92 63 88 104 70 96 +87 59 82 85 58 81 52 41 59 20 26 39 15 23 36 15 23 37 15 22 36 17 23 37 7 18 31 11 20 34 53 41 60 71 51 73 53 43 62 14 22 36 13 21 35 20 25 40 52 41 60 56 41 62 65 45 67 60 42 64 65 45 67 77 53 76 82 56 80 77 53 76 56 39 61 39 29 49 40 29 49 42 30 51 40 29 49 39 28 49 41 30 50 44 32 52 48 34 55 50 35 56 50 36 57 50 36 57 38 31 50 19 24 39 15 22 36 22 25 40 35 30 48 25 26 42 13 22 36 13 22 36 18 23 38 59 45 65 109 73 99 111 74 100 +40 31 53 41 31 53 37 32 52 19 24 40 13 22 35 14 22 36 25 27 44 24 26 43 14 22 36 19 24 39 34 29 49 44 34 55 27 28 46 15 22 37 14 22 35 16 23 38 28 28 46 43 33 54 41 32 53 42 32 54 41 32 53 39 31 52 40 31 53 40 31 53 43 33 55 46 35 57 45 35 57 45 34 56 45 35 57 46 35 57 45 34 56 45 34 56 44 34 55 44 33 55 44 33 55 44 34 56 42 33 54 21 25 41 12 21 35 26 27 44 42 33 55 24 26 44 14 22 37 14 22 35 20 25 41 37 31 52 58 42 66 85 59 85 +41 36 61 41 36 61 42 37 61 30 31 49 13 21 35 15 22 37 28 28 49 25 27 47 13 22 36 19 24 41 35 32 56 45 38 64 41 37 59 14 22 36 14 22 36 17 23 38 36 33 56 34 32 56 32 31 55 32 30 54 32 31 55 36 33 57 40 35 60 36 33 57 32 31 55 34 32 56 36 33 57 36 33 57 36 33 57 36 33 57 35 33 57 35 33 57 35 32 56 34 32 56 34 32 56 34 32 56 35 33 57 25 27 46 13 21 34 29 29 50 36 33 57 29 29 50 17 23 38 14 22 37 23 26 44 42 37 62 63 49 76 69 53 81 +76 57 85 78 58 85 82 61 89 51 43 65 13 22 36 21 26 42 60 48 73 60 48 74 11 17 28 39 36 56 74 56 84 79 59 87 68 53 79 32 32 51 9 19 32 42 38 58 71 54 81 70 54 81 62 49 75 60 47 73 62 49 75 71 54 81 73 55 83 73 56 84 60 48 74 36 33 57 30 28 52 28 28 51 29 28 52 30 29 52 30 29 53 31 29 53 33 31 54 36 32 56 36 33 57 36 33 57 38 33 58 33 30 52 17 20 32 36 32 57 37 33 57 32 31 54 14 21 36 7 17 29 50 42 65 81 60 88 80 60 88 78 59 87 +73 55 86 71 54 85 72 54 86 67 53 80 12 19 33 29 30 46 77 58 86 80 60 89 45 37 56 70 53 79 80 60 89 77 58 86 78 58 87 34 33 51 9 16 26 46 40 62 81 60 89 78 59 87 80 60 88 80 60 88 78 59 87 82 61 89 110 80 109 122 88 117 123 88 117 114 82 111 90 67 95 77 59 86 91 68 95 96 71 98 85 64 91 66 52 78 44 38 63 33 30 54 29 28 52 29 28 52 29 28 52 28 27 51 25 25 45 30 29 53 29 28 52 38 34 59 55 45 65 41 35 51 73 56 83 75 57 85 75 57 84 75 57 85 +101 74 88 107 79 89 134 98 91 160 117 96 88 67 65 84 62 91 95 70 98 73 55 83 81 60 89 78 58 87 76 58 86 77 58 86 76 58 86 74 56 83 59 46 69 78 58 87 76 58 85 77 58 86 77 58 86 75 57 84 80 60 88 119 85 114 129 92 123 124 89 122 124 89 122 126 90 123 131 93 125 133 94 125 133 94 124 129 92 124 125 90 125 126 89 122 122 88 117 106 78 106 93 69 97 92 68 96 90 67 95 80 61 88 64 51 77 56 45 70 75 58 84 117 84 114 126 90 120 123 88 117 112 81 111 83 62 90 82 61 89 83 62 89 +170 119 97 174 122 95 174 122 96 173 121 95 171 120 96 145 102 114 125 89 123 98 72 100 73 56 83 77 58 86 78 58 86 77 58 86 78 58 87 78 58 87 78 59 88 76 57 85 77 58 85 78 58 86 75 57 85 76 58 88 114 82 115 127 91 123 128 92 117 139 98 113 142 100 112 137 97 115 129 92 118 123 88 120 121 87 120 135 95 117 154 106 113 139 101 121 124 88 120 130 93 123 133 94 125 132 94 124 133 94 124 133 95 124 131 93 123 130 92 123 132 94 124 129 92 122 126 90 120 127 91 121 128 91 121 126 90 120 124 89 119 127 91 117 +161 109 96 163 109 95 162 109 95 162 109 95 164 110 95 163 110 94 136 95 113 126 91 124 101 73 102 73 55 83 76 57 85 76 57 85 74 56 84 77 58 85 82 61 89 83 62 91 77 58 88 73 57 87 82 61 89 119 85 109 145 100 111 154 104 101 164 111 97 173 116 94 177 118 95 181 120 96 182 121 99 177 118 104 183 122 106 207 135 103 225 148 105 191 179 162 152 138 149 123 84 115 123 88 119 125 89 119 122 88 120 121 87 120 123 89 120 126 90 119 125 89 119 125 90 120 126 90 120 126 90 119 125 89 120 124 89 121 124 89 122 128 91 119 +159 103 95 159 103 95 159 103 95 159 103 95 159 103 95 160 103 94 158 103 95 132 92 115 127 91 123 107 77 106 81 61 89 81 60 89 90 67 95 115 83 113 123 89 121 128 91 118 127 88 110 129 88 103 151 99 98 161 104 97 161 104 93 163 105 94 163 105 95 165 106 96 169 108 96 175 112 97 182 116 98 192 122 98 201 127 100 208 130 101 214 138 107 185 181 169 182 194 184 160 151 156 130 92 120 126 90 120 136 95 117 143 98 115 133 93 117 124 89 121 125 90 121 126 90 120 125 90 120 124 90 122 129 91 118 134 93 114 140 95 109 153 100 99 +155 95 95 156 96 95 156 96 96 156 96 96 156 96 96 155 96 96 157 96 95 153 96 97 130 91 117 128 93 125 125 89 119 124 89 118 127 93 124 130 93 121 142 93 108 154 96 98 159 98 96 160 98 95 158 97 95 155 95 95 155 95 95 156 95 95 158 97 95 161 99 95 165 101 96 170 104 97 176 107 98 183 111 99 191 116 101 199 122 103 211 125 101 203 151 131 184 178 168 201 165 146 204 125 106 191 117 105 193 118 102 188 115 99 178 109 98 153 98 106 130 91 118 126 90 121 128 91 118 140 92 108 153 95 97 157 96 94 158 96 93 157 96 94 +151 88 95 149 85 93 147 82 91 148 84 92 148 83 92 149 85 93 147 82 91 149 84 91 145 83 94 127 83 110 122 87 119 123 87 118 129 84 110 145 84 95 150 83 89 149 84 91 148 83 92 147 83 92 147 82 91 150 86 94 151 88 95 152 88 95 154 89 95 157 91 95 160 93 96 165 96 97 171 99 98 177 103 99 184 107 100 192 112 101 199 116 103 207 118 101 209 121 104 208 117 100 203 117 102 197 114 101 186 108 100 178 104 99 173 100 98 169 97 96 161 94 97 151 91 100 152 90 97 155 89 93 152 88 94 151 88 95 150 87 95 151 88 95 +145 78 93 155 93 104 166 109 116 161 102 111 163 104 112 156 94 105 165 107 115 161 102 111 165 106 113 167 111 117 154 107 121 164 116 126 165 106 113 159 98 107 166 111 117 164 106 114 165 108 116 160 101 110 167 110 117 153 89 101 146 79 94 148 81 95 149 82 95 152 83 95 155 85 96 159 88 97 164 91 97 170 94 98 176 98 99 183 101 100 189 105 101 193 107 103 195 108 103 193 108 103 189 105 102 184 102 101 178 98 100 172 95 99 166 91 98 160 88 97 156 86 96 154 84 94 150 82 94 147 81 95 147 80 95 147 80 95 147 80 95 147 80 95 +140 68 92 159 97 112 176 122 131 171 116 126 172 117 127 159 97 113 174 120 129 171 115 125 176 123 131 169 112 123 180 126 132 175 119 128 171 115 126 171 115 125 176 123 131 167 109 121 170 113 124 172 116 126 174 119 129 154 88 107 141 69 93 143 73 96 144 73 95 146 75 95 149 76 96 153 79 96 157 81 97 162 84 98 168 87 99 173 90 100 178 93 100 181 95 101 182 95 101 181 95 101 178 93 100 174 91 100 169 88 99 164 85 98 159 82 97 154 79 96 150 77 96 147 75 95 145 73 95 143 73 95 143 72 95 143 72 95 143 72 95 143 72 95 +138 67 95 136 64 92 134 61 91 135 63 92 135 62 91 135 64 92 134 62 91 135 63 91 135 62 91 134 61 91 138 68 95 135 63 92 134 62 91 139 69 96 134 62 91 135 63 92 135 63 92 135 63 92 134 61 90 136 65 93 138 67 95 137 67 94 139 67 94 140 68 95 142 70 95 146 71 96 150 74 96 154 76 97 158 79 98 162 81 98 165 83 99 168 84 99 169 85 100 169 85 99 166 83 99 163 81 99 159 79 98 155 77 97 150 74 96 146 72 96 143 70 95 141 68 95 139 67 94 138 67 94 137 67 94 137 67 94 137 67 94 137 67 94 diff --git a/crates/exav-viewer/demo/examples/files/images/scene-bc1.dds b/crates/exav-viewer/demo/examples/files/images/scene-bc1.dds new file mode 100644 index 0000000..82a08ef Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-bc1.dds differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-bc3.dds b/crates/exav-viewer/demo/examples/files/images/scene-bc3.dds new file mode 100644 index 0000000..cbf0d71 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-bc3.dds differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-cmyk-packbits.tif b/crates/exav-viewer/demo/examples/files/images/scene-cmyk-packbits.tif new file mode 100644 index 0000000..c8994cb Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-cmyk-packbits.tif differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-cmyk.jpg b/crates/exav-viewer/demo/examples/files/images/scene-cmyk.jpg new file mode 100644 index 0000000..7bf4049 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-cmyk.jpg differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-grey.jp2 b/crates/exav-viewer/demo/examples/files/images/scene-grey.jp2 new file mode 100644 index 0000000..ddfcf03 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-grey.jp2 differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-grey.jpg b/crates/exav-viewer/demo/examples/files/images/scene-grey.jpg new file mode 100644 index 0000000..d3cc8ac Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-grey.jpg differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-grey16.pgm b/crates/exav-viewer/demo/examples/files/images/scene-grey16.pgm new file mode 100644 index 0000000..cb72f39 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/images/scene-grey16.pgm @@ -0,0 +1,4 @@ +P5 +128 96 +65535 +$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$((,,$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$))$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&''--**&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&%%--''&&&&&&))&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&))))))))))(())))))))))))))))))))))))))))))))))))(((((())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))(())))))))((,,))))))))(())))))))))))))))))))))((..++(())))))))))))))))))))))))))))))))))))))))))))++++++..11**++++++++++++++++++++++++++++++++++++++++++++++++**++++++++++**,,--**++++++++++++****++--**++++++++++++++++++++++++++++++++++++++++++++++****++++,,66**++++++++**++++++++++++++++++**++++++++++******++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------..11------------//11--------------1144--22------------------------------------------------0033----....------------------------------11..--------..//--------------------------------------------------00000000000000000000000000000000000000000000000000000000000077//0000000000////000000000000000000////0000000000000000000000000000000000000000000000000022000000//0000000000000000000000330000//7700000000//1133//0000000000000000000000000000000000000000000000002222223333222222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222222222222222222222222222222222222222443322222222222222::3322222222222299332222112222222222222222222222222222222222222222222222222222222222222222444444;;884444444444997744444444444444444444444444444444444444444444444444444444444444444444444433444444444444444444444444444444444444444444444444449977444444444444444444444444444444444444555544444444444444444444444444444444444444444444444444444444444444447777777777777766>>7766==::777777777777777777777777777777777777??77777777::6677777777777777777777??77777777777777777777777766::==667777777777777777776666777777777777777777777777777777777766>>;;6677777777777777777777777777777777777777777777777777777777777777999999::::999999::9999==@@999999999999999999999999999999999999::999999::AA9999999999999999999999>>::999999999999999999999999;;<<99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;;<<<<<<<<<<<<;;;;<<<<<<;;;;<<<<<<;;<<<<<<<<<<<<<<<<;;;;<<;;@@<>;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>CC??>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BB@@>>>>>>>>>>CC@@==????>>>>>>>>>>>>>>>>>>>>>>AA>>??>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>==DDAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>CC>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>AAAAAAAAAAAAAAAAAAAA@@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@@CCAA@@AAAAAAAA@@@@@@GGDD@@AAAAAAAAAAAA@@@@AAAA@@@@AAAA@@@@AAAAAAAAAA@@AA@@@@AAAAAAAAAAAA@@@@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@@@@AA@@AAAAAAAA@@@@AAAAAAAAAAAAAAAAAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBCCCCCCCCCCCCCCCCDDFFCCCCCCCCCCCCIIFFCCCCCCCCCCDDCCGGCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDCCCCCCCCCCCCGGEECCCCCCCCCCCCCCCCCCEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGGHHEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFFGGEEEEEEEEEEDDHHGGEEEEEEEEEEPPGGIIEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEHHGGDDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEGGGGGGGGGGGGGGGGGGGGGGGGGGHHGGGGGGGGGGGGGGGGHHGGGGGGGGGGGGGGGGGGGGGGJJMMGGGGMMJJNNHHHHGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGHHGGGGGGGGGGGGHHGGGGGGGGGGGGHHGGIIKKGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGOOLLGGGGGGGGGGGGGGGGGGGGGGHHGGGGGGHHGGGGGGGGHHHHGGGGGGGGGGGGGGGGGGJJJJJJJJJJJJJJJJJJJJJJKKJJJJJJJJJJJJJJJJKKSSJJJJJJJJKKJJJJJJJJJJJJJJJJJJJJJJLLLLMMKKTTIIJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJRRKKJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJKKJJJJJJJJJJJJJJJJJJJJJJJJJJJJKKOOJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJLLLLLLLLLLLLLLLLLLLLLLUUNNRRLLLLLLLLLLLLLLMMLLLLLLLLUUMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMMMMMMMMMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLLLOORRKKLLLLOOOOOOOOOOOOOOOOOOOOPPQQOORROOOOOOOOOOOONNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONNOOOOOOOOOOOOOOOOOOOOOOOOQQOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOPPPPPPPPPPPPPPPPOOOOOOOOOOOOOOOOOOOONNNNOONNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOQQRRNNOOOOXXQQQQQQQQQQQQQQQQPPTTWWPPQQQQQQQQQQQQRRXXQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQPPXXUUPPQQQQQQQQPPQQQQQQQQRRUUQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRRRRRRRRRRRRRRRTTUURRSSSSSSSSSSSSSSRRRRRRRRRRRRRRRRQQQQQQQQUUSSPPQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQTTTTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTWWTTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTTTSSSSSSSSSSYYTTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSUUWWTTTTTTTTUUUUUUVVVVXX[[UUVVVVVVVVVVVVVVUUUUUUUUUUTTTTTTTTTTTTSSVVTTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSUUVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVUUVVVVVVVVVVVVYYUUVVVVVVVVVVVVVVVVVVVVVVUUVVVVVVVVVVUUYYVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVYY\\WWWWXXWWWWYYYYYYYYXXXXYYYYZZZZYYYYYYYYYYYYXXXXWWWWXXWWWWWWWWVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV[[UUVVVVVVVVXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYYYXXXXXXXXXXYY^^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYYYXXYYYYYYZZZZZZ[[cc[[[[\\\\\\]]]]]]]]]]]]bb\\\\]]dd[[[[[[[[[[ZZZZYYYYYYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYY[[XXXXXXXXXXZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ__aaZZZZZZZZZZZZZZ[[ZZZZZZZZZZ\\\\ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ[[[[[[[[\\[[\\\\\\]]^^^^________````````aaaaaaaaddee``__________^^]]^^\\\\\\[[[[]]]]__]]ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ]]]]]]]]]]\\]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]^^]]]]]]]]]]]]]]]]]]aacc]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\\\\]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]^^^^__````````hheeaabbcceeccddddddddddddddddddccccccccbbaaaaaa``__````__^^aabb__^^]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]````````__hh````````__``````````````````__ii``````````````````____``````____````````````````````__cckk^^````````````````````````````__``aaaabbccccccddddeeeeeeffkkgggggghhhhhhhhhhhhgghhggggffffeeeeeeddccccccaaaaaa````````````````````````````````````````````ccddbbbbbbccbbbbeehhaabbbbbbbbbbbbbbbbbbbbaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbffbbbbbbbbbbbbbbbbbbbbbbccffbbbbbbbbbbbbbbbbbbbbaabbbbbbbbjjddddddeeffeeffgghhiiiinnjjjjkkllkkllllllllllllkkllkkjjjjiiiiiiggggffffffddjjggccccccbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbffhhddddddddddddddiiggddddddddddddddddddddddddddddddddddddddddddddddddddeeggddddddddddddddddddddddddddddddddddddddddddddddjjeeeeeeeeiigggggggghhppjjjjkkllmmppnnnnooooppppppqqqqppppppoooonnnnmmssookkjjkkllhhggggffffeeeeeeeeeeddddddddddddddddddddddddddddddddffffggffffffffffffiihhffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffggjjgggghhhhhhiijjkkkkllppnnnnooppqqqqrrssssssttuuuuuuuuuuuuttssssssrrqqppppoonnnnnnllkkkkjjiihhhhhhggggggggffffffffffffffffffffffffffffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjkkllllllnnooooppqqrrssssttuuvvwwwwxxxxyyyyyyyyyyyyxxxxwwwwvvuuttssssrrppppoooonnllllllkkjjjjiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiillllllllllllllllllkkkkllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllkkllllmmmmmmooooooqqrrrrttuuvvwwwwyyzzzz{{{{||||}}}}~~~~}}}}||||{{{{zzzzyywwwwvvuuttrrqqqqppoooommmmmmllllkkllllllllllllllllllllllllllllnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooppqqqqrrssttuuvvwwyyzz{{||}}~~€€��‚‚‚‚‚‚‚‚‚‚‚‚‚‚����€€~~}}||{{zzxxwwvvuuttssrrqqqqppoooooonnnnnnnnnnnnnnnnnnnnnnnnnnnnnnppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppqqqqrrrrssttuuuuwwxxyyzz{{||}}~~€€€€‚‚ƒƒ„„……††††‡‡‡‡‡‡‡‡‡‡‡‡††††……„„ƒƒ‚‚€€€€~~}}||zzzzyyxxwwuuuuttssrrrrqqqqpppppppppppppppppppppppppppprrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrssssssssttuuuuvvvvxxxxzz{{||}}~~€€��ƒƒ„„……††‡‡‰‰ŠŠŠŠŠŠ‹‹ŒŒŒŒŒŒŒŒ‹‹ŠŠŠŠŠŠ‰‰‡‡††……„„ƒƒ��€€~~}}||{{zzxxxxvvvvuuuuttssssssssrrrrrrrrrrrrrrrrrrrrrruuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuvvvvwwxxxxzzzz||}}~~��‚‚„„……‡‡ˆˆŠŠ‹‹ŒŒ��������‘‘‘‘‘‘‘‘‘‘‘‘��������ŒŒ‹‹ŠŠˆˆ‡‡……„„‚‚��~~}}||zzzzxxxxwwvvvvuuuuuuuuuuuuuuuuuuuuuuuuuuuuwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxyyzzzz{{||}}~~€€��ƒƒ„„††ˆˆ‰‰ŠŠŒŒŽŽ��‘‘’’““””••––––————––––••””““’’‘‘��ŽŽŒŒŠŠ‰‰ˆˆ††„„ƒƒ‚‚€€€€~~}}||{{zzzzyyxxxxxxxxwwwwwwwwwwwwwwwwwwwwzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz{{{{||||}}}}~~€€‚‚ƒƒ„„……‡‡ˆˆŠŠ������’’““””––——™™ššœœœœœœ����œœœœœœšš™™——––””““‘‘��ŽŽŒŒŠŠˆˆ‡‡……„„ƒƒ‚‚€€~~}}}}||||{{{{zzzzzzzzzzzzzzzzzzzzzz}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}~~~~€€€€��‚‚ƒƒ„„††‡‡‰‰ŠŠ‹‹����‘‘““••——˜˜ššœœžžŸŸ¡¡¡¡¢¢££££££££¢¢¡¡¡¡ŸŸžžœœšš˜˜––••““‘‘����‹‹ŠŠˆˆ‡‡††„„ƒƒ‚‚��€€€€~~~~}}}}}}}}}}}}}}}}}}}}������������������������������������������������������������������������������������������������������������������‚‚ƒƒƒƒƒƒ„„……††‡‡ˆˆ‰‰‹‹��ŽŽ��’’””––——™™œœžž  ¢¢££¤¤¦¦¦¦§§§§§§§§§§§§¦¦¦¦¤¤££¢¢  žž››™™——––””‘‘��ŽŽ��‹‹‰‰ˆˆ‡‡††……„„ƒƒƒƒƒƒ‚‚����������������������………………………………………………………………………………………………………………………………………………„„…………„„……………………………………………………………………………………………………………………………………„„……††††‡‡ˆˆ‰‰ŠŠ‹‹ŒŒ����‘‘’’••––˜˜ššœœžž¡¡££¥¥§§¨¨©©ªª««««¬¬¬¬¬¬¬¬««««ªª¨¨¨¨¦¦¥¥££¡¡žž��››˜˜––••’’‘‘����ŒŒ‹‹ŠŠ‰‰ˆˆ‡‡††††……„„……………………………………………………ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆŠŠŠŠˆˆ‰‰ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ‰‰‰‰ŠŠ‹‹ŒŒŽŽ����’’““••——™™››��ŸŸ¢¢££¦¦¨¨©©ªª¬¬¬¬®®¯¯°°°°±±±±°°°°¯¯®®­­¬¬ªª©©¨¨¦¦££¡¡ŸŸœœ››™™––••““‘‘����ŽŽŒŒ‹‹ŠŠ‰‰‰‰ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ŠŠŠŠŠŠ‹‹‹‹ŠŠ‹‹ŠŠ‹‹ŒŒ‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ŒŒ����ŽŽ����‘‘““””••——™™››��ŸŸ¡¡¤¤¦¦¨¨ªª««­­®®°°±±²²³³µµ´´µµµµ´´´´³³²²±±°°®®­­««ªª¨¨¦¦££¡¡ŸŸ��››™™——––””““’’����ŽŽ����ŒŒ‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹����������������������������������������������ŽŽ‹‹ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŒŒŽŽ����ŽŽŽŽ��������������������������������������‘‘’’““““••––——™™››��ŸŸ¡¡££¥¥¨¨ªª¬¬®®¯¯±±²²´´µµ¶¶··¹¹¸¸¸¸¸¸¸¸¹¹··¶¶µµ´´²²±±¯¯®®¬¬ªª¨¨¦¦££¡¡ŸŸ��››šš˜˜––””““’’’’‘‘��������������������������’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’��‹‹ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ‹‹��’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’““““””••••––——™™šš››��ŸŸ  ¢¢¥¥§§ªª¬¬®®¯¯±±³³´´¶¶¸¸¹¹»»¼¼»»ÅÅÎÎÎÎÅÅ»»»»»»¹¹¸¸¶¶´´³³±±¯¯®®¬¬ªª§§¥¥¢¢¢¢ŸŸ˜˜��ŒŒ‹‹‹‹����““””””““’’’’’’’’’’’’’’’’’’’’••••••••••••••••••••••••••••••••••••••••––��ŠŠŠŠŠŠŠŠŠŠŠŠŒŒŒŒŒŒ‹‹ŠŠŠŠŠŠŠŠŠŠ��’’––––––••••••••••••••••••••••••••––––————˜˜™™šš››œœžžŸŸ¡¡££¥¥¦¦©©««®®¯¯±±³³µµ¶¶··¹¹»»½½¾¾ÁÁÝÝööúúúúööÝÝÀÀ¿¿¾¾¾¾¼¼¹¹··µµ³³°°°°®®««ªª¨¨ŸŸ��ŠŠ‰‰ŠŠŠŠŠŠŠŠŠŠ‹‹��””——––••••••••••••••••••™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™““ŠŠŠŠŠŠŠŠ‹‹ŒŒ‰‰��||}}††‹‹ŒŒ‹‹ŠŠŠŠŠŠŠŠ��’’••˜˜™™™™™™™™™™™™™™™™™™™™™™™™™™šššššš››œœ��žž  ¡¡¢¢¥¥§§©©ªª¬¬¯¯±±²²³³¶¶¸¸¹¹»»½½¿¿ÀÀÁÁÞÞüüúúùùùùúúüüáá»»««¤¤££¥¥®®´´¶¶¶¶´´³³¯¯§§——‹‹‰‰ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ��••˜˜™™™™™™™™™™™™™™™™œœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœ��••ŠŠŠŠŠŠŠŠŒŒ‰‰vv^^UUSSTTXXeeww‰‰��‹‹ŠŠŠŠŠŠŠŠŠŠŒŒ��””˜˜œœžž������œœœœœœœœœœ������ŸŸŸŸ¡¡¢¢££¥¥¦¦¨¨ªª¬¬®®°°³³´´µµ··¹¹ºº¼¼¾¾ÀÀÂÂÃÃÌÌööúúùùùùùùûûøøÆÆ��ˆˆ‡‡ˆˆ‰‰ŠŠ��™™  ŸŸžž““‹‹‰‰ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ‰‰ŠŠŒŒ��””——ššœœ������                                    ——ŠŠŠŠŠŠŠŠ��€€``RRRRTTTTTTSSRRRR]]pp‚‚ŒŒ��������‹‹‰‰††}}„„’’œœ  ¡¡¡¡        ¡¡¡¡¢¢££¤¤¥¥§§©©ªª¬¬­­¯¯²²´´µµ··¸¸ºº¼¼½½¾¾ÁÁÃÃÅÅÆÆÖÖúúùùùùùùüüíí¨¨††‰‰ŠŠŠŠŠŠŠŠŠŠ‰‰‰‰ˆˆˆˆˆˆ‰‰ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ‰‰ŠŠŠŠ‹‹ŽŽ’’ššŸŸ££££££££££££££££££££££££££££££££¤¤™™ŠŠŠŠŠŠŠŠ��vvWWRRTTTTTTTTTTTTTTTTSSRRYY^^ZZoorrppii__XXTTRRTTZZooŠŠ––››¡¡¤¤¤¤¤¤¤¤¥¥¥¥§§§§©©ªª¬¬®®¯¯±±³³µµ¶¶¸¸¹¹»»½½¾¾ÀÀÁÁÃÃÆÆÇÇÈÈØØúúùùúúýýàà™™††ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ‰‰ŠŠŽŽ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦§§››ŠŠŠŠŠŠŠŠ‹‹rrSSSSTTTTTTTTTTTTTTTTTTVVUU>>""EETTSSSSSSTTTTTTSSRRZZzzŒŒ��’’šš  ¦¦©©ªªªªªª¬¬­­®®±±²²´´¶¶¹¹»»»»»»¹¹ºº½½ÂÂÆÆÈÈÈÈÊÊËËÓÓ÷÷üüûûÌÌ��‡‡ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŒŒ��‹‹��ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ‰‰©©©©©©©©©©©©©©©©©©©©©©©©©©ªª««��ŠŠŠŠŠŠ‹‹‹‹jjRRTTTTTTTTTTTTTTTTTTUUWWII''00PPWWTTTTTTTTTTTTSSTTuuŒŒ‰‰‰‰‹‹ŽŽ––ŸŸ§§­­°°²²´´¶¶··¹¹¸¸´´©©��••ŽŽŽŽ��™™¨¨¹¹ÆÆÍÍÑÑÐÐååææ¯¯ˆˆ‰‰ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ‹‹����EE66ww��ŒŒŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ­­­­­­­­­­­­­­­­­­­­­­­­­­¯¯ŸŸŠŠŠŠŠŠŒŒ‡‡ffRRTTTTTTTTTTTTTTTTTTWWPP44==TTVVTTTTTTTTTTSSTTuu��ŠŠŠŠŠŠ‰‰‰‰‹‹��——ŸŸŸŸ  ¢¢��””ŒŒˆˆˆˆ‰‰‰‰‰‰‰‰ˆˆ‡‡‰‰’’œœ¬¬©©šš��‡‡ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŽŽ‹‹^^""NNƒƒ��‹‹ŠŠŠŠŠŠŠŠŠŠŠŠŠŠ´´´´³³²²²²±±°°±±±±±±±±±±³³¡¡ŠŠŠŠ‹‹��€€^^RRTTTTTTTTTTTTTTTTVVVV??%%GGWWUUTTTTTTTTSSTTuu��ŠŠŠŠŠŠŠŠŠŠ‰‰‰‰‰‰ˆˆˆˆˆˆˆˆ‰‰ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ‰‰ˆˆ‡‡‡‡ˆˆ‰‰ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ‹‹‹‹����������‹‹ŒŒ��rr33&&bb����‹‹‹‹‹‹‹‹‹‹‹‹››ššŸŸ¬¬­­µµ¸¸¸¸¶¶µµ´´¶¶§§ŒŒ‹‹��ŠŠssWWRRTTTTTTTTTTTTTTUUWWII''00PPWWTTTTTTTTSSTTuu��ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŒŒ��������������ŽŽ����ˆˆ„„vvqqqqppuuˆˆ��GG77[[ddccbbbbbbbbRRRRUU\\]]ll’’££¯¯¸¸¨¨lluu††rr^^RRTTTTTTTTTTTTTTTTUUNN11::QQUUTTTTTTSSTTuu��‹‹ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ‹‹ŒŒŒŒŒŒŽŽ‹‹��ssjjYYYYYYYYZZXXDDCC::++$$''&&))..!!22OOUUSSRRRRTTTTTTSSSSQQPPQQUU__aa;;88PPUUTTTTTTTTTTVVVVTTTTSS??224455557711556655554433EEUUTTTTTTTTSSSSll‹‹ŒŒŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ‹‹ŒŒŽŽ����ŽŽ��ŒŒ‹‹‹‹ŒŒŒŒŒŒ‰‰‚‚wwoo__NN??//''&&$$$$$$$$$$$$&&$$!!$$==TTTTTTTTTTTTTTTTTTTTWWSS88 BBVVVVTTUUWWJJDDWWUUTTVVWWWWWWZZII!!**QQYYWWWWWWUUTTTTTTTTTTTTTTRRcc��ŒŒŒŒŒŒŒŒŒŒŒŒŒŒŒŒ��‰‰~~oo[[XX``qq~~„„††ttgg]]PPBB44))%%%%''(((((((((((())((!!$$$$$$!!22FFEEDDCCCCRRTTTTTTTTTTTTTTUUWWDD##++KKXXSS66--NNWWUUTTUUUU99CCVVUUTTTTTTTTTTTTTTTTTTTTRRVVeevv}}||}}ssppccVV==--&&$$$$$$&&--228833222211**&&&&''((((((((((((((((((##&&""33UUXXVVVVTTTTTTTTTTTTTTVVMM,,11!!99SSWWKK$$//RRWWVVUUUUUUUUVVVVVVUUTTSSRRSSSSTTUUQQAA..&&&&''((((((((((''''&&''''''''((((((((((((((((((((((((&& ""IIUUTTTTTTTTTTVVVVWW@@ ""CC>>44555566..337777660077@@774444443399AALLRRUUUUVVVVUUPPCC00&&''(((((((((((((((((((((((((((((((((((((((((((((((((((((())**&&''$$))JJUUTTTTTT1199>>AABBBBHHNN99 99NNVVZZII''LLGG9900))&&&&''''''''&&'')),,3377??9933++''''((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((%%''**(('';;OOWWUUTTTTTTTT''&&&&''(())**""!!&&))''((1188&&''((((((((((((((((((((((''''&&&&&&''''(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((())((!!))(())''##++88IIUUVVUUTT(((((((())&&%%))(($$))(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((())(())$$!!''((22CCPPUU--$$%%%%%%$$####$$ $$$$##$$%%%%%%$$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%####$$##%%!!   $$$$"""",,CC''$$$$$$$$$$$$##$$!!$$$$$$####''&&$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%%%% %%%%$$##,,44::AA<<))""""######$$##""##########**99;;--####$$$$$$$$$$$$$$$$$$$$$$######""####$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$##  $$$$$$$$!!##$$33DDDDDDCC@@//223355::::<>CCDDDDDDDDDDDDDDEE((11AA::44,,##%%..>>DDDDDDDD;;++,,--$$--,,--@@DD??::4411,,,,,,,,,,44>>BBDDDDDDCCBB>>77//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$  $$$$$$$$$$$$$$## ++@@EEDDCCCCCCCCCCBBCCCCCCCCCCCCCCDD44<>$$AA??AACCCC??--))::DDCCCCCCCCCCCCCCEE''11EECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBAAEELLUUUUVVSSLLCC::--!!!!""""!!!!""##%%$$%%&&&&####$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%% %%$$$$$$$$$$$$!!00DDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDEE,,77EECCCCCCDDFFAADDCCCCCCCCCCCCCCEE55 ==DDCCCCCCCCCCCCCCCCCCCCCCCCCCBBMM]]cchhjjjjjjiiiihhggccPP==5555AAHHUUWWYYQQHHAA??55))##""##$$$$$$$$$$$$$$$$$$$$$$$$$$!!""$$$$$$$$$$$$$$ ((LL 5566::CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBAA@@<<$$DDCCCCCCCCCC8855AACCCCCCCCCCCCCCCCDD44++-- $$--++::DDCCCCCCCCCCCCCCCCCCCCCCCCBBCCYYjjiihhhhhhhhhhhhhhhhiikkkkjjjjkkkkjjjjjjjjiiaa]]VVMM??55++!!!!""##############$$$$$$$$%%$$$$$$$$$$$$!!""((FFmm$$\\RRDDCCCCCCCCCCCCCCCCCCBBBBBBAAAAAAGGTTbbggllWWIIBBBBBBCCCCCCCCDDEECCCCCCCCCCCCCCCCCCCCDDEEHH)) 66GGEEDDCCCCCCCCCCCCCCCCCCCCCCCCCCTTcchhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiijjiiff``^^QQ==55,,))))))))))))##""""""""########!!&&==SScciiiiWWRRhhccFFBBBBCCCCCCCCCCCCCCHHHHHHQQTTii��‰‰ŠŠ‹‹ŒŒ}}##kkee\\HHBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDD<<44??DDCCCCCCCCCCCCCCCCCCCCCCCCCCBBCC__jjhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiijjjjjjddccccccccccbbWWWWQQ7722))))))))22VVkkkkiihhhhjjkkhhhhee\\FFAAAAAAAAAAAAAA€€€€€€……‡‡‡‡††………………††„„__WWhhiijj]]DDBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDEEDDCCCCCCCCCCCCCCCCCCCCCCCCCCBBNNbbgghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiijjjjjjjjhhcccccccchhjjhhhhhhhhhhhhhhhhhhiijjbbVVVVVVVVVVUU__}}„„„„ƒƒƒƒƒƒƒƒƒƒƒƒƒƒ‚‚ƒƒ††€€oogghhiieeXXDDBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBBBZZjjhhhhhhhhhhggggggggffgggggghhhhhhhhhhhhhhhhhhhhggffeeeegghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiihhhhhhhhhhhhhhhhhhhhhhhhhhiijjjjjjjjjjjjkk€€‚‚����������������������‚‚rrhhhhhhiiccIIBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBII``hhhhhhhhggggiioouuwwxxxxxxrrlljjggffggggggggggffhhttˆˆ}}ppjjeegghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhooyy~~zzkkhhhhiiff[[DDBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCRRiihhgghhjjnntt||ƒƒƒƒ……††††ˆˆˆˆˆˆ††‚‚{{rrkkkkkkrrzz‹‹ŸŸ££¦¦§§©©ªª••jjgghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhii||}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}nnhhhhhhiihhKKBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBCCCCCCCCCCCCAAII``ggggkkuuxx||~~€€€€��‚‚ƒƒ…………‡‡‰‰‹‹������ŽŽ��‘‘——››žžžž¡¡££««¶¶¹¹¶¶}}ffgghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhmmvv{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{zzttiihhhhiigg[[DDBBCCCCCCCCCCCCCCCCCCAABBFFKKMMLLMMKKEEAAAAAABBBBHHXXllnnttzz||{{||||||}}~~€€����ƒƒ„„……‡‡‰‰ŠŠŒŒ��‘‘’’••——˜˜››žž  ¥¥´´¶¶¶¶´´¥¥ssffhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhggiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyywwkkhhhhhhhhiiQQCCAACCCCCCCCCCCCBBBBRR__eehhiiiiiihhcc[[UUTT\\ffrrwwxxyyyyyyxxyyyyzzzz{{||}}}}~~€€��‚‚„„††‡‡‰‰‹‹����‘‘““––——šš��ŸŸ¬¬··¶¶¶¶··»»““ggffhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhggggllssvvwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwvvoohhhhhhhhii``PPAABBBBBBBBCCGGRRggiiiihhhhhhhhhhiikkllnnssxxxxwwwwwwwwwwwwwwxxxxxxyyzzzz||||}}~~€€��ƒƒ„„††ˆˆŠŠŒŒŽŽ��’’••——™™œœ¡¡³³¶¶¶¶¶¶¶¶··¨¨……eeggggggggffgghhkkkkkkgggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiikklloouuwwwwttttttttttttttttttttttttttttttttttttttrriihhhhhhhhiiggVVMMLLQQZZ``ffiihhhhhhhhhhjjmmppqqssttuuttttttttttttttttuuuuuuuuvvwwwwyyyy{{||}}~~��ƒƒ……††ˆˆŠŠŒŒŽŽ‘‘““––˜˜šš¡¡³³··¶¶¶¶¶¶¶¶ºº¥¥wwnnkkkkooyy��„„‡‡„„ƒƒwwnniihhhhhhhhhhhhhhhhhhhhhhhhhhmmppqqssttttuuttttttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrllhhhhhhhhhhjjiihhjjiiiihhhhhhhhhhiikkqqssssrrrrrrrrrrrrrrrrrrrrrrrrssrrssttssttuuvvwwxxyyzz||}}~~€€��ƒƒ……‡‡‰‰‹‹����’’””––™™žž³³¸¸¶¶¶¶··¶¶ªª››••’’��������‹‹ˆˆ‡‡„„ƒƒ��}}qqffhhhhhhhhhhhhhhhhhhiinnssssrrrrrrrrrrrrrrrrpppppppppppppppppppppppppppppppppppppppppplliihhhhhhhhhhhhhhhhhhhhhhhhhhiinnooppppppppppppppppppppppppppppppppppqqqqqqrrrrssttuuvvwwxxzz{{}}~~€€‚‚ƒƒ††‡‡‰‰‹‹ŽŽ��’’••——˜˜§§±±´´µµ««��˜˜••““’’����‹‹‰‰‡‡……‚‚��}}}}xxmmjjhhhhhhhhhhhhkkooqqppppppppppppppppppppppnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnmmjjhhhhhhhhhhhhhhhhhhhhhhiillnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnoonnooppppppqqrrssttuuvvxxyyzz||~~€€��ƒƒ††‡‡‰‰‹‹����‘‘““””––™™™™––••””’’��ŽŽ��ŠŠˆˆ††……‚‚€€}}{{zzyywwuuqqmmkkkkkkmmoooooonnnnnnnnnnnnnnnnnnnnnnlllllllllllllllllllllllllllllllllllllllllllllljjiihhhhhhhhhhhhhhhhhhjjllllllllllllllllllllllllllllllllllllllllllllmmmmnnnnooppqqrrrrssuuvvxxyy{{||~~€€‚‚ƒƒ……ˆˆ‰‰‹‹����‘‘‘‘’’’’’’’’‘‘��ŽŽŒŒŠŠ‰‰‡‡……ƒƒ€€}}{{zzxxwwvvttssrrqqppppoonnmmmmllmmlllllllllllllllllllliiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjiiiiiihhhhhhggffhhiijjiiiiiiiiiijjjjiiiijjiiiiiiiiiijjiiiiiiiijjjjjjjjjjkkllmmnnooooppqqssttuuwwyyzz||~~��ƒƒ……††ˆˆŠŠ‹‹ŒŒ����ŽŽ����‹‹ŠŠ‰‰‡‡……„„‚‚€€||{{zzxxvvuussrrqqoooonnmmllllkkjjkkjjjjiiiiiiiiiiiiiiiiiihhhhhhhhggeeffffffggeeggffggffhheeeeffggggffeeggeeeeeeggeeddlluuffeegghheeeehhkkffeegghhffggffffeeffeehhhhhhhhhhhhiiiiiijjjjjjllllmmnnooqqrrssuuwwxxzz{{}}��‚‚ƒƒ……††ˆˆ‰‰‰‰‰‰‰‰‰‰ˆˆ‡‡††„„ƒƒ‚‚€€~~||zzyyxxvvttssqqppoonnnnllkkkkjjiiiihhhhhhhhhhhhhhhhhhhhhhhhhhffffffeell€€rrppssnnppsshhttcczzxxuullssvvyynn‚‚zzll~~xx››hh��jjhh~~€€rr„„qqyy¡¡ssiissvvzzrr~~ffeeffffffffffgggggghhhhiijjkkkkmmnnpppprrttttvvxxzz{{||~~€€��‚‚ƒƒ„„……………………„„ƒƒ‚‚��€€}}{{zzxxwwuussssqqppoommllkkjjiiiiiiggggffffffffffffffffffffffffffccccccaaŸŸššœœ  ––{{¥¥šš––‚‚††ww££  ””ªªzz’’ªª••ŸŸ««™™••¨¨‰‰¡¡””››šš––pp¬¬‰‰  ��šš……‹‹  ™™rr››££��££žž……``ccccccccccddeeeeeeffggggiijjkkllmmnnooqqrrttuuvvxxyyzz||}}~~€€€€€€€€€€~~}}{{zzyywwuuttssqqppoommllkkjjiihhhhffffeeeeddccccccccccccccccccccccccccaaaaaaaaªª——‘‘££••��¡¡��……ªªff€€§§™™ŠŠ³³zzžž««™™……šš‚‚››žžyy§§˜˜¦¦——��oo¢¢yy¥¥¤¤››qq˜˜––��§§››{{¬¬˜˜€€^^aaaaaabbbbbbbbcccccceeeeffgghhiijjllmmmmoopprrssttuuwwxxyyzz{{||||||||||||||{{zzyywwvvttssrrqqppnnmmllkkiihhggffeeeeddccccbbbbbbbbaaaaaaaaaaaaaaaaaaaa______^^ssŠŠ{{vvzz{{��}}iiˆˆ\\bb……��}}pp||……‹‹zzqq{{ooƒƒ­­ˆˆnn‚‚ss‹‹llmm°°ˆˆppxx~~ŒŒkk††tt��‡‡{{ff||ˆˆff^^____________````aaaabbcccceeeegghhhhiikkllmmooppqqrrssttuuvvwwwwxxxxxxxxxxwwvvuuttssrrppoonnmmlljjiihhggffeeddddbbbbaaaa``````________________________]]]]]]]][[ZZZZ[[[[[[YY[[\\YY]]\\ZZZZZZ[[[[ZZYY[[[[ZZZZddxxXX[[ZZ[[ZZ[[ffwwWW[[[[ZZYY\\ZZ[[YYZZZZ\\ZZYY\\]]]]]]]]]]]]]]^^^^^^____``aabbbbccddffffhhiijjkkllmmooppppqqrrssssttttttttttssssqqqqppoonnmmkkjjiihhggeeeeddbbbbaa``______^^]]^^]]]]]]]]]]]]]]]]]]]]]]]][[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[YY[[[[[[[[[[[[[[YY[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\\\\\\]]]]^^__````aabbddddeeggggiijjkkllmmmmooooppppppppppppppoooonnmmllkkkkiihhggffeeddccbbaa``__^^^^]]]]\\\\\\[[[[[[[[[[[[[[[[[[[[[[[[[[ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ[[[[[[[[\\^^^^____aabbbbddddeeffgghhiijjkkllllmmmmmmmmmmmmmmllkkjjiiiihhggffeeddccbbbb``____^^]]\\\\\\[[ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ \ No newline at end of file diff --git a/crates/exav-viewer/demo/examples/files/images/scene-indexed.png b/crates/exav-viewer/demo/examples/files/images/scene-indexed.png new file mode 100644 index 0000000..8000ff6 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-indexed.png differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-jpeg.tif b/crates/exav-viewer/demo/examples/files/images/scene-jpeg.tif new file mode 100644 index 0000000..7d5071b Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-jpeg.tif differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-lossless.jxl b/crates/exav-viewer/demo/examples/files/images/scene-lossless.jxl new file mode 100644 index 0000000..5b8e86d Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-lossless.jxl differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-lossless.webp b/crates/exav-viewer/demo/examples/files/images/scene-lossless.webp new file mode 100644 index 0000000..d6b2f4b Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-lossless.webp differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-lossy.jxl b/crates/exav-viewer/demo/examples/files/images/scene-lossy.jxl new file mode 100644 index 0000000..689ab28 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-lossy.jxl differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-lzw.tif b/crates/exav-viewer/demo/examples/files/images/scene-lzw.tif new file mode 100644 index 0000000..f24dda6 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-lzw.tif differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-orientation6.jpg b/crates/exav-viewer/demo/examples/files/images/scene-orientation6.jpg new file mode 100644 index 0000000..a4cecc4 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-orientation6.jpg differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-pages.tif b/crates/exav-viewer/demo/examples/files/images/scene-pages.tif new file mode 100644 index 0000000..ae66182 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-pages.tif differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-progressive.jpg b/crates/exav-viewer/demo/examples/files/images/scene-progressive.jpg new file mode 100644 index 0000000..62537ea Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-progressive.jpg differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene-rle8.bmp b/crates/exav-viewer/demo/examples/files/images/scene-rle8.bmp new file mode 100644 index 0000000..5be0f4c Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene-rle8.bmp differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene.ff b/crates/exav-viewer/demo/examples/files/images/scene.ff new file mode 100644 index 0000000..ced27a4 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene.ff differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene.gif b/crates/exav-viewer/demo/examples/files/images/scene.gif new file mode 100644 index 0000000..6258014 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene.gif differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene.j2k b/crates/exav-viewer/demo/examples/files/images/scene.j2k new file mode 100644 index 0000000..242e061 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene.j2k differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene.jp2 b/crates/exav-viewer/demo/examples/files/images/scene.jp2 new file mode 100644 index 0000000..641aa67 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene.jp2 differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene.jpg b/crates/exav-viewer/demo/examples/files/images/scene.jpg new file mode 100644 index 0000000..b4d2d4a Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene.jpg differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene.pbm b/crates/exav-viewer/demo/examples/files/images/scene.pbm new file mode 100644 index 0000000..a18f24b Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene.pbm differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene.png b/crates/exav-viewer/demo/examples/files/images/scene.png new file mode 100644 index 0000000..faf9cd8 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene.png differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene.ppm b/crates/exav-viewer/demo/examples/files/images/scene.ppm new file mode 100644 index 0000000..2baa2fe --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/images/scene.ppm @@ -0,0 +1,23 @@ +P6 +# exav example +128 96 +255 +\\\\\\\\\\\\\\\\\\\\\\\\\#a"&d[\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\[\\\\$b]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ \ \\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ ]%'c"$`\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\%&c ]\ \\!#_ \\ \ \ \ \ \ \ \ \ \\ ] \\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \#!]#!]#!]$"]$"^#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]" [" \#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]"!\#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]" \#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]" \#!]#!]#!]#!]#!]'%a#"]#!]#!]#!]" \#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]" \(&b&$`" \#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!]#!](#](#]'"\+&a.)d'!\(#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#]("]'!\(#](#](#](#](#]'"])$_*%`'"](#](#](#](#](#](#]'"]'"\(#^+&`("](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#]'"\'!\(#]("])$^3.g'"\(#](#](#](#]'"\("](#](#](#](#](#](#](#](#]'!\("](#](#](#](#]("]'"]'"]("](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#](#]-$^-$^-$^,$^,$]-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^,$^-%^1)b,$^-$^-$^-$^-$^,$]/'a1)c,#]-$^-$^-$^-$^-$^,#]1(b4+e,#]2*d,$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^,#]0(a3+d+#]-$^-$^.&_,$^-$^-$^,$^-$^-$^-$^-$^-$^-$^-$^,#],$^-$^,$^1)b-%^,$^-$^-$^,$^.%_/&`,$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^-$^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%^2'_:.f1%^2&^1&^1&^1&^2&^1%^1%]2&^1&^1&^1&^1&^1&^1%^2&_2'_1%^0%]1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1%^3'_5)a1%^1&^1&^1%^1&^1&^1%^2'_2&^1&^1&^1&^1&^2&^1%^6*b2&_1&^1%^9.f2'_1%^1&^1&^1%^3'`5)b1%^2&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^1&^6'_6'_6'_7(`7(_6'_6'_6'_6'_6'_6'^6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_5&]7(_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_7(_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'^9*a7(`6'_6'_6'_6'_6'_6'_6&^>/g7(`6'_6'_6'_6'_6'_6'^>.f7(`6'_6'_5%]6'_6'_6'_6'_6'_6'_6'^6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_6'_;)_;)_:'^C0g@-c:(^;)_;)_;(_:'^@.d>+a:(^;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_<)_:(^;(_;)_;)_;(_:(^;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_:'^;(_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_:(^:'^;)_;)_;)_;)_;)_;)_;)_;)_;)_:(^@.d>,b:(^;)_;)_;)_;)_;)_;)_;(^;(_;)_;)_;)_;)_;)_;)_:'^;(_;(_<*`<)`;(_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_;)_@*`@*`@*`?*_@*`@*`@*`?)_H2hA+a?)_G1gC-c?)_@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`?)_I3hA+a@*`@*`A+`D.d@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`?)_I3gA+a@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`?)_D.cG1f?)_@*`@*`@*`@*`@*`@*`@*`@*`@*`?)_?*_@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`?)^H2gE/d?)_@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`@*`E,`E,`E,`E,`E,`E,`E,`E,`F-aE,aC*_I0eL3gC*_E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`F-aE,`E,`E,`F-aL3hD+`E,`E,`E,`E,`E,`E,`E,`E,`E,`D+`J1dE-aE,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`D+`G.bI0cD+_E,`D+_E,`D+`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`D+_D+`E,`E,`E,`E,`E,`D+_D+`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`D+_E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`E,`J-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aI-aJ-aJ.bJ.aJ.bI-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aI-aJ-aJ-aJ-aI-aH,_J-aJ-aJ-aJ-aJ-aJ-aI,`I-`J-aJ-aJ-aH,`I-aJ.bJ.aJ-aI-aI-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aI-`I,`J.aI-aO3fJ-aO3fJ.bI-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aI,`M1dL/cI-`J-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aI-aJ.aL0dI-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aJ-aN/aN/aN/aN/aN/aN/aN/aN/aN/aN.aT4fO/bN.aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aO/aN/aN/aN/aN/aO/aN.`S3eQ1dN.aN/aN/aO/aM.`S4fQ2dM.`O0bO/bN/aN/aN/aN/aN/aN/aN/aO/aO/aN/aN/aR2dO/aO/bN/aO/aO/aN/aN/aN/aN/aN/aN/aN/aO/aN/aN/aN/aN/aN/aO/aM-`U6gR3dM.`O/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aO/bS4fN.aO/aN/aN/aO/aN/aN/aN/aN/aN/aN/aN/aN/aN/aN/aS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0aS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0aV3dU2cS0bS0bS0bS0bS0bS0aS0bR/a[8iX5fR/aS0bS0bS0bS0bS0bS0bS0bS0aS0bS0bR/aS0bS0bS0bR/aS/aS0bS0bS0bS0bS0bS0bS0bR/aS0bS0bS0bS0bS0bS0bS0bR/aR/aS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bS0aS0bS0bR/aS0bS0bS0bS0bS0aS0bS0bS0bS0bS0bS0bS0bS0bS0bS0bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX1bW1aX2bX2bX2bX2bX2bX2bX2bW1aX1bX2bX2bX2bX2bX2bX2bX2bX2bW1aX1bX2bX2bX2bX2bX2bX2bW1bZ4d[5fW1aX2bX2bX2bX2bW0a^9h[6eW1aX2bX2bX2bX2bY4dW1a]7gY3cX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX2bX1bZ4dY3cX2bX2bX2bX2bX2bW1a]7g[5eW1aX2bX2bX2bX2bX2bX2bX2bX2b]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3b_5e`6f\2b]4c\2b\3b\2b]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c^4d_5e]3b]3c]3c]3c]3c\2ba7f_5e]3b]3c]3c]3c\2bg?l_6eb8h]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c\2b]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c]3c\2ba7g_5e]3b]3c]3c]3c]3c]3c^4d]4c]3c]3c]3c]3c]3c]3c]3c]3c]3cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb4cb5cb5cb5cb5cb5cb5cb5cb5cb5ca4bb5cb5cb5cb5cb4cb5cb5cb5cb5cb5cb5ca4be8fg:ia4ba4bh;id8fh;jc6dc6db5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cc6da4cb5cb5cb5cb5cb5cb5ca4ba4cb5cb5cb5cb5cb5c`3bd7ee8fa4bb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5c`3bi>jf:ga4bb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5ca4ba4ca4cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cb5cg6dg6dg6dg6dg6dg6dg6dg6dg6dg6dg6dh8eg6de5cg7dg6dg6dg6dg6df6dh8ep@mf5cg7dg6dg6dh8eg7dg6dg6dg6dg6dg6dg7df6cf5cg7df6cj:gh8ej:gh8fpBmf5cg7dg6dg6dg6dg6dg6dg7dg6dg6dg6dg6dg6dg6dg6dg6dg6dg7df6co?lh7ef6dg6dg6dg6dg6dg6dg7dg7dg6dg6dg6dg6dg6dg7df6cf6cg7dg6dg6dg6dg6dg6dg6dg6dg6dg6dg6dg6dg7dg7dg6dh8eg7df6dg6dg6dg6dg6dg6dg6dg6dg6dg6dg6dg6dg6dg7eljk7dl8dk8dk8dk8dk8dl8el9ek8dk8dl8dk7ctAml9ek8dk8dk8dk8dk8dk8dl8dl8dk8dl8dk7ck7dk7ck8dk7ck8dk8dk8dk8dk8dk8dk8dk7dk8dk8dk8dk8dk8dk8dk8dk8dk8dk8dk8dk7ck8dk8dk8dk8dk8dk8dk8dk8dk8dk8dk8dk8dk8dl8dl8dl8dl8dl8dl8dl9dl9dl8el9el9el9el9el9el9dl8dl8dl8dl8dk8dk8dl8dk8dk8dk8dk8dk8dk8dl8dk8dk8dk8dk8dk8dk8dl9ek8dk8dk8dk8dk8dk8dk8dk8dk8dl8dk7cnhp9dp:ep9e|Blvf|>f|>f}>f}>g|=f€Bj‚El}=e~?g~?g~>g~?g~?g}>f~?f}>f}>f}>f|>f|=f|>f{>f{=f{=f{=fz=fzgyf>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f~=e>f>f>g‚Bj~>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f~>f‚Ai>g>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f=f‚Bj…El>e�?g�@g�?g�?f‚@g‚@gƒ@gƒAgƒ@fƒ?f„Ag„Ag„Ag„Ag„Agƒ@f„AgƒAgƒAg„Bh‚@g‚@g‚@g�@g�@g�?g€?f€>f€>f>f~=f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f>f€?g…Dl~=f>f>f>f>f„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„@g„@hƒ?g„?g„@g„?gƒ?g„@h‰Fnƒ?f„@g„?g„?g„?g„?g„?gƒ?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?gƒ?f„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„@g„@g„@g…@g…@f…?f†Ag†Ag†AgˆBh�Jo‡Bg‰Ch‰Ch‰ChŠChŠDhŠChŠChŠChŠCh‹Di�In‰BgŠChŠDi�KpˆBgˆBhˆBgˆBh‡Bg†Ag†Ag…Ag…Ag…@g„@g„?gƒ?fƒ>fƒ?f„@g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„?g„@g‡Cjƒ?g„?g„?g„?g„?gˆAgˆAgˆAgˆAgˆAg‰AgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAhˆ@fŒFkŽJn‡?f‰AhˆAgˆAgˆAgˆAg‡@f‰AgˆAgˆAgˆAgˆAgˆAg‰Bh‰BhˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAg‰AgˆAgˆAgˆAgˆAgˆAg‰AhˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAg‰Ag‰Ag‰BhŠBgŠBh‹Ch‹ChŒChŒCh�DiŽEi�Ei�Dh�Eh�Dh�Ei�Fi�Fi‘Fi‘Fi‘Fi‘Fi‘Fi•Jm–Kn�Eh�Eh�Dh�Ei�DhŽDh�Dh�ChŒChŒCh‹Ch‹ChŠBh‰Ag‹Dj‹Ci�Gl‹Ekˆ@gˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆAgˆ@fˆAgˆAgˆAgˆAgˆAg�Ch�Ch�Bh�Bh�Ch�Bg�Bh�Ch�Bh�Bh�Ch�Bh�Bh�Bh�Bh�Ch�Bh�Bg�Ch�Ch�BhŽDi�Ch�Bh�Ch�Bh�Ch�Bh�Bh�ChŒBg�Gl“JoŒAg�Ch�Bh�Ch�Ch�Bh�Bh�Bh�Bh�Bh�Bh�Bh�Bh�Bh�Bh�Ch�BgŒAf�Ch�Bh�Bh�Bh�Bh�Bh�Bh�Bh�Bh�Bh�Bh�Ch�Ch�Ch�ChŽChŽCh�Ch�Ch�Dh�Eh‘Di’Ei‘Dg˜Mp–Km“Fh•Gi–Hj™Kl–Hi—Hj—Hj˜Ii˜Ii˜Ii˜Ij˜Ii—Hi˜Ij—Hi—Hi–Hi–Gi•Gi”Gi”Fi“Fi“Fi‘Eh‘Di�Dh�DhŽCg‘Gk’Hm�Ej�Ej�Bh�Ch�Ch�Bh�Bh�Bh�Bh�Bh�Bh�Bh�Bh�Bh�Ch�Ch�Bh�Ch�Bh�Bh�Bh’Dh’Dh’Dh’Dh’Ch˜Nq“Ej’Dh’Ei“Ei’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Di’Ch™Oq“Ei’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Ch’Dh’Dh’Dh’Dh‘Cg’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Di‘Cg–ImœRv‘Bf’Di’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Di’Dh’Dh’Dh“Ei’Cg”Ei”Ei•Fi•Fi–Fi—Gi˜Gi™Hj™HišHi›Ij›Hi�Kk¢Oo�JjžKjžKjŸKkŸKkŸKkŸKjŸKkŸKkžKjžKj�Kj�JjœJjœJj›IjšIj™Hi™Hj˜Gi—Gi–Gi•Fi–Fj”Eh“Dh“Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh’Dh˜Gj™Gk–Ei—Fi—Ei˜Gj—Fi–DhšKm›Mo•Cg—Fi—Ei—Fi—Fi—Fi—Fi—Fi—Fi—Ei—Fi–Eh—Ei—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Ei—Fi—Fi—Ei—Fi—Ei—Fj›Jm–Ei—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Ei—FjšJn–Ei—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Ei—Fi–Dh—Ei—Fi˜Fi˜Eh�OpšHjšGišHj›HiœIjœGižJjŸJj Kj¡Kj¢Lk§Qp£Lj£Lj¥Nk¥Nk¥Nk¦Nk¦Ok¦Nl¦Nl¦Ok¦Nk¥Nk¥Nk¥Nk¤Mk£Mk¢Lk¢Ml¡Lk JjŸJj�IjœHi�IjšGhŸNp�Km™Fh˜Gi˜Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—Fi—FižIkŸJm›FhœGiœGiœGiœGiœGj›EhŸMnžKl›FhœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGjžIlœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGi›FhœGiœGiœGiœGiœGiœGiœGiœGiœGi›Fi Np�HjœGi�Hj�Hi MnŸJjŸIj Ij¡Jk¢Jj§Tr¥Ml¥Lk¦Mk§Nk©Ol¬RoªOl«Pl¬Pl¬Ql­Ql­Ql®Ql®Rl®Rl®Ql­Ql­Ql¬Ql¬Pl«PlªPl©Mj¬WrªSo¦Lj¥Lk¦Nm§On¢Jj¢Kj IjŸIjžIjžIj�Hj�HjœGjœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGiœGi Hj Hi¡Ij¡Hj¡Hj¡Ij¡Ij¡Ij Hi£Mm¢Kl Hj¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Hj Hi¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Hj¡Ij¡Ij¡Hj¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij Hj£Mn¡Ij¢Ij¢Jj£Jj£Ii¤Jj¥Kk¦Lk¨Mk¨Mk¬So«Ol¬Ol­Pl®Ql¯Ql°Ql²Sm²Sm³Sm´TmµTmµTmµUm¶Um¶UmµUmµTmµTm´Tm³Sm³Sm±Rm°Rm¯Ql®Pl­Pl¬Ok¬Pm«Pm¨Mk§Mk¦Lk¥Kk¤Kj£Jj£Jj¢Jj¢Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¡Ij¥Jj¦Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¦Jj¥Ii¥Ij¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¦Jj¥Ii¦Jj§Kk§Kk¨Lk©LkªLk«Mk¬Nk®Ol¯Pl°Ok±Ql³Rm´Rm¶Sm·Tm¸Un¹VnºVn»Wn¼Wn¼Xn½Xn½Xn½Xn½Xn½Xn½Xn¼Xn¼Wn»WnºVn¹Vn¸Um·Tm¶Tm´Rm³Rm±Ql°Pl¯Pl®Ol¬Nk«MkªLk©Lk¨Lk§Kk§Kk¦Jk¦Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥Jj¥JjªLkªLkªLkªLkªLkªLkªLkªLkªKkªLkªLkªKkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLk«Lk«Lk¬Mk­Mk®Ml¯Nl°Ol±Pl³Pl´QmµRm·Sm¸TmºTn»Vn½Vn¾Wn¿XoÁYnÂYoÃZoÄZoÄ[oÅ[oÅ[oÆ[oÆ[oÅ[oÅ[oÄ[oÄZoÃZoÂYoÁYn¿Xo¾Wn½Vn»VnºTn¸Tm·SmµRm´Qm³Pl±Pl°Ol¯Nl®Ml­Mk¬Mk«Lk«LkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLkªLk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk°Ml°Nl±Nl²Ol²Ol´Ol´Pl¶Qm·Rm¸SmºTm¼Tn½Vn¿VnÁWnÂXnÄYoÅZoÇ[oÈ\oÊ]pË]pÌ^pÍ^pÍ^pÎ_qÎ_qÎ_qÎ_qÍ^pÍ^pÌ^pË]pÊ]pÈ\oÇ[oÅZoÄYoÂXnÁWn¿Vn½Vn¼TnºTm¸Sm¸Rm¶Qm´Pl´Ol²Ol²Ol±Nl°Nl°Ml¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk¯Mk´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´OlµOlµPl¶Pl·Pl¸Ql¹RmºSm»Sm½Tn¿UnÀVnÂWnÄXnÆYoÈZoÉ[pË\pÍ]pÏ^pÐ_qÑ`qÓaqÔbqÕbqÖcrÖbrÖbrÖbrÖbrÖcrÕbqÔbqÓaqÒ`qÐ_qÏ^pÍ]pË\pÉ[pÈZoÆYoÄXnÂWnÀVn¿Un½Tn¼SmºSm¹Rm¸Ql·Pl¶PlµPlµOl´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol´Ol¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹QmºQmºQm»Rm½Rm½Sm¿TnÀTnÂUnÃWnÅXnÇXoÉZoË[pÍ\pÏ]pÑ^qÓ_qÔaq×bqØcrÚdrÛdrÝerÞesÞfsßgsßgsßgsßgsÞfsÞesÜerÛdrÚdrØcr×bqÔ`qÓ_qÑ^qÏ]pÍ\pË[pÉYoÇXoÅXnÃWnÂUnÀTn¿Tn¾Sm¼Rm»RmºQmºQm¹Qm¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl¹Pl½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm¾Rm¾Rm¾Rm¿RmÀSmÁSnÂTnÃUnÅVnÆWnÈXoÊYoËZoÎ[oÏ\pÒ]pÔ^qÖ`qØaqÚcrÜdrßeràfsâgsähsåitæjtèjtèktèjtèjtèktèjtæjtåitähsâgsàfsßerÜdrÚcrØaqÖ`qÔ^qÒ]pÏ\pÎ[oËZoÊYoÈXoÆWnÅVnÃUnÂTnÁSnÀSm¿Rm¾Rm¾Rm¾Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½Rm½RmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÃSmÃSmÃTmÄTnÄUnÅUnÆVnÇVnÉWoÊXoÌYoÍZoÐ[pÒ\pÔ]pÖ_qÙ`qÛbrÝcràdrâfsägsçhtèitëjtìkuîmuïmuðnuñnuñouñouñnuðnuïmuîmuìkuëjtèitçhtägsâfsßdrÝcrÛarÙ`qÖ_qÔ]pÒ\pÐ[pÍZoÌYoÊXoÉWoÇVnÆVnÅUnÄUnÄTnÃTmÂSmÃSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÂSmÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÆWnÆWnÆWnÇXnÈXnÉYnÊYnËZnÍ[oÎ\oÐ]oÒ^pÔ_p×apÙbqÛcqÞeràfrãhråisèksêltíntïotñpuóruõsv÷tvøtvùuvùuvùuvùuvøtv÷tvõsvôruñpuïotíntêltèksåisãhràfrÞerÛcqÙbq×apÔ_pÒ^pÐ]oÎ\oÍ[oËZnÊYnÉYnÈXnÇXnÆWnÆWnÆWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÅWnÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÉ\nÊ]nÊ]nÌ^nÍ^nÎ_oÐ`oÒaoÔboÖcpØepÚfqÜgqßiqâkrålrènsêpsíqtðstòtuõvuøxvúyvüzvþ{wþ{wÿ|wÿ|wÿ|wÿ|wþ{wþ{wüzvúyvøwvõvuòtuðstíqtêpsènsålrâkrßiqÜgqÚfq×epÖcpÔboÒaoÐ`oÎ_oÍ^nÌ]nÊ]nÊ]nÉ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÈ\nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`oÊ`nÊ`nÊ`oÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nË`nË`nÌanÌanÎbnÎbnÐcnÒdoÓeoÕfo×gpÙipÛjpßkqámqãorçprérsìssïutówtõyuù{uü}vþ~vÿwÿ�wÿ‚wÿƒxÿƒxÿ„xÿ„xÿƒxÿƒxÿ‚wÿ�wÿwþ~vü}vø{uõyuówtïutìssérsçprãorámqßkqÛjpÚip×gpÕfoÓeoÒdoÐcnÎbnÎbnÌanÌanË`nË`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÊ`nÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÌdoÎdlÏdkÎdlÎdlÏdkÏdlÍdnÌdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍenÎenÎenÏfnÐfnÒgnÓhoÕioÖjoØkoÚlpÝnpàoqâqqårrçtrêvsîwsñytô{t÷}uûuþ�vÿƒvÿ…wÿ†wÿˆxÿ‰xÿŠxÿ‹xÿ‹yÿ‹yÿ‹xÿŠxÿ‰xÿˆxÿ†wÿ…wÿƒvþ�vûu÷}uô{tñytîwsêvrçtrårrâqqàoqÝnpÚlpØkoÖjoÕioÓhoÒgnÐfnÏfnÎenÎenÍenÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÍdnÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏioÐhmÒhkÉkv¾oƒ¸rЏrнp„ÇkxÑhlÑhlÏioÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÏinÐinÐinÐinÑjnÒjnÓknÕlnÖmo×noÚooÜppÞqpàspãtqåvqèwrëyrï{sò}sötù‚tý„uÿ…vÿˆvÿ‰wÿ‹xÿ�xÿ�xÿ‘yÿ’yÿ“zÿ“yÿ“yÿ“zÿ’yÿ‘yÿ�xÿ�xÿ‹xÿ‰wÿ‡vÿ…vý„uù‚tõtò}sï{sëyrèwråvqãtqàspÞqpÜppÙoo×noÖmoÔlnÓknÒjnÑjnÐinÐinÐinÏinÏinÏinÏinÏinÏinÏinÏinÏinÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÑmnÔmlÏnp½r…°u”¯v–¯v•¯v•¯v–°u•¹sŠÊowÔmkÓmmÑmoÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒnnÓnnÔnnÕonÖpn×pnÙqoÛroÝtoßupávpäxqæyqê{qí}rï~rô�söƒtú„tþ‡uÿ‰vÿ‹vÿŽwÿ�xÿ’xÿ”yÿ–yÿ˜zÿ™zÿš{ÿœ|ÿœ|ÿš{ÿ™zÿ˜zÿ–yÿ”yÿ’xÿ�xÿ�wÿ‹vÿ‰vþ‡uú…töƒtó�sï~rí}rê{qæyqäxqávpÞuqÝtoÛrnÚqn×pnÕooÕonÔnnÓnnÒnnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÒmnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqo×rkÍrv³u‘®v–±u“²u’±u“±u“²u’±u“¯u•¯u•Às„Órp×rkÔqnÔqoÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÕrnÕrnÖsnÖsnØsnÙtnÚuoÜvoÞwoàxoâzpä{pç}qê~qí€rð‚rô„sö†sûˆtþŠuÿŒuÿ�vÿ‘wÿ”wÿ–xÿ™yÿ›yÿ�zÿŸ{ÿ¢|ÿ yÿŸvÿŸvÿ yÿ¢|ÿŸ{ÿ�zÿ›yÿ™yÿ–xÿ”wÿ‘wÿ�vÿŒuþŠuûˆtö†sô„sð‚rí€ré~qæ|qç|næznÞxpÛwrÙvqÛunÜukÙtmÖsoÕrnÕrnÕrnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqnÔqn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vnÖvoÚwkÈv|°u”°u”²u’±u“±u“°u“°t’°t’±u“±u’±u“®u–´u�Éu|ØvlÙwl×vnÖvoÖvn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vn×vnØwnØwnÙwnÚxnÛynÝzoß{oá|oã}på~pè€pê�qíƒqð…rô‡r÷‰sû‹sÿ�tÿ�uÿ’uÿ•vÿ—wÿšxÿœxÿŸyÿ¡zÿ¤{ÿ¦{ÿ¤uÿ²‡ÿ¿—ÿ¿—ÿ²‡ÿ£uÿ¦{ÿ¤{þ¡zþžyþœyþ™xþ—wÿ”vÿ’uÿ�uÿ�tû‹s÷‰só‡rï„sð„píƒoÙ}yÄx†¶v�´u‘´u‘ºvŒÈwÖxqÜxlÚwl×vo×vn×vn×vn×vn×vn×vn×vn×vn×vn×vnÙznÙznÙznÙznÙznÙznÙznÙznÙznÙznÙznÙznÙznÙznÙznÙznÙznÙznÙznÙzoÝ{kÊx|¯u•±u“±u“±u“°t’±u“´w•µx–µw–²v”°t’°t’±u’°u”®u–»vŠÏywÚ{mÝ{kÛ{lÚ{nÙznÙzoÙznÙznÙznÙznÙznÙznÙznÙznÙznÙ{nÚ{nÚ{nÛ|nÜ|nÝ}nÞ~nà~oáoã€oæ‚pèƒpë…pí†qðˆqôŠr÷ŒsûŽsþ�tÿ“tÿ•uÿ—vÿšwÿ�wÿŸxÿ¢yÿ¥zÿ¨{ÿ«{ÿ¬zÿÔ¯ÿøßÿþæÿþæÿøßÿÔ®þªyÿ¬zÿ¬yÿ©xÿ¦wÿ£vÿŸvÿšvþ—vþ”uþ’uý�túŽsú�qùŒoä„xÀyНt•®t–°u”°u”°u”¯u•®u–²u’Áw…Ô{sÝ|kÜ{lÚ{nÙznÙzoÙznÙznÙznÙznÙznÙznÜnÜnÜnÜnÜnÜnÜnÜnÜnÜnÜnÜnÜnÜnÜnÜnÜnÜnÛo߀kË{|¯u•±u“±u“°t’±u“¶x–²u“¥mŠži… j‡¬r�´w–¶x–±u“°t’±u’¯u•¯u•¸v�ÈzÓ|uÛoÞ€l߀kÞkÜlÚ~nÛnÛnÜnÜnÜnÜnÜnÜ€nÝ€nÞ€nÞ€nß�ná‚nãƒoä„oæ…oé†pëˆpí‰qð‹qó�q÷�rú‘rþ“sÿ•tÿ—uÿšuÿ�vÿŸwÿ¢xÿ¥xÿ¨yÿ«zÿ¯}ÿ­uÿÖ®ÿÿíÿúáÿùàÿùàÿùáþÿìÿß³øªxà˜†×�‡×ކÜ�„î™}üžxÿŸtÿ�sÿšrÿ˜rÿ”rîŒxË~†±u“­t•²u“²u’±u“±u“±u“±u“²u’±u“®u–±u“Àx†Ñ|wÛoÞ€l߀kÞ€lÝmÜnÛoÛnÜnÞ„nÞ„nÞ„nÞ„nÞ„nÞ„nÞ„nÞ„nÞ„nÞ„nÞ„nÞ„nÞ„nÞ„nÞ„nÞ„nÞƒn݃oâ…kÌ~|¯t•±u“±u“°t’´w•²u”–c€vOijGafE^hE_nJd~To˜e�°u“¶x—³w•°t’¯t‘®t”­t•¯t“µv޽y‰É}�Õ�zÞ…uä‡nâ…là„kÞƒn݃oÞƒnÞƒnÞƒnß„nß„nà…ná…nâ†nã†nå‡oç‰oéŠoë‹pîŒpðŽqó�qö‘qù“rý–sÿ˜sÿštÿœtÿŸuÿ¡vÿ¤wÿ§xÿªxÿ­zÿ±{ÿ²yÿ¾‡ÿùßÿúáÿúàÿúáþøàÿûâÿþäÝÁ¾µw�¬q•«q•«q•«r•¯t”¹z�ÊƒŠØŠ„Øˆ„ׇ„Ã}Œ±u“¬s•±u“²u“±u“±u“±u“±u“±u“±u“±u“±u“²u’±u“®t–°u”¶v�¿y‡Ë}~Ó€wÙ‚rÞ„nâ…ká…lÞ„náˆnáˆnáˆnáˆnáˆnáˆnáˆnáˆnáˆnáˆnáˆnáˆnáˆnáˆnáˆnáˆnàˆoåŠk΀|®t•±u“±u“°t’¶x—¥m‹wPjeD]gE_jGakHbkGaiF`fD^fD^tMh�^z¦n‹µx–¼{š¶x–¶x•·y—´x—¯u–©q“ k‹Ÿi„®pÆ|Û†zâ‰oä‰jä‰láˆmàˆnàˆoáˆnâ‰nãŠnäŠnæ‹nèŒoé�oëŽoî�pð‘pó“qö”qù–qü˜rÿšsÿœsÿžtÿ¡uÿ£uÿ¦vÿ©wÿ¬xÿ¯yÿ²yÿ¶|ÿµvÿÌ—ÿýæÿùàÿúáþ÷ßÿÿåúóÞا¬lްt”²v“²v“²v“²v“±u“¯t”¬r•«r•«r•«r•­s•±u“²u’±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“²u’±u“°u”®t•®t–¯t•²v’¸xŽÂ{…Ôƒwáˆnã�nã�nã�nã�nã�nã�nã�nã�nã�nã�nã�nã�nã�nã�nãŒnâŒoè�kЃ|®t•±u“±u“°u“·y——d�kGafE^kHbkGajGajGajGajGakHbkHbgE_dC\sLfwPjnMe�_|’`}�^z†YtxPjoJdjF`fD_fEbnJiŒ]{µvŠË‚…Ó…xà‹pæŽlè�kæ�låŽnå�oæŽoè�nê�oì‘oî’oð”pó–põ—qø™qûšqþœrþžsþ sÿ£tÿ¦uÿ©tÿ«vþ­wþ¯xþ³yÿ¶yÿ»|ÿºvÿЗÿýæþøßþøàÿÿçïàÒº„œ¬m޲w”±u“±u“±u“±u“±u“±u“±u“²v“²v’²v’²v’²u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“°t’°t’°t’¯t’±u“±u“±u“²u’²u’±u“±u“¯t”®t–¯u”¹y�æ‘næ‘næ‘næ‘næ‘næ‘næ‘næ‘næ‘næ‘næ‘næ‘næ‘næ‘nå�oê“kц|®t•±u“±u’±u“´w–’a}gE^iF`kHbjGajGajGajGajGajGajGahF`nIdpJeK7M)/S:QkGbgE_eD^iF`jGakHakGaiF_eD]nJf›g‰³w˜³v�Á}ˆÏ„~ÛŒuå‘oì•lí•kí•mí•oí•oï–pñ˜qô™qö›rúœrþžqÿ£qÿ§qÿ©qÿ¨tú¦wú©wú«xÿ´vÿºvÿ»wÿ»yþ½{þ¿zþɇÿøßÿÿåÿÿæàÇòw”®p�³x•±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“®s‘µw–¸y˜¶x—¸y˜®s‘°u“±u“±u“±u“±u“±u“±u“²u’±u“¯t”è•nè•nè•nè•nè•nè•nè•nè•nè•nè•nè•nè•nè•nç•oí™kÓ‰|®t•±u“°t’²v”µx–†YudC\kGajGajGajGajGajGajGajGahF`kHbqKe\@X'#5 ! #& +"$6,?fE_qKfjGaiG`jGajGajGakHbiF_gE]–c¶x˜­s”­s–°u”·x�Æ�…ÖŠ|ä“tïšoô�møŸlú mý¢mÿ£nÿ¥oÿ¤qõ vá”~͈‡À�¶y‘¶y‘·y‘Å…Œ×–…í«~ü¼zÿÅyÿË{ÿÊsÿå®ñæÜË¡¬­mްs’²w”±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“¯t’°t’¼|›ªqŽN;P7.@™gƒ½|›³v”®s‘±u“±u“±u“±u“±u“±u“±u“±u“é™né™né™nê™nê™nëšnëšnëšnëšnëšnëšnëšné™oï�kÔ‹|®s•±u“°t’µw–¯s’�VqfD^kHbjGajGajGajGajGajGaiG`iF`pJegF_:.A$ !%%$%$ )H5JmIcnIdiF`jGajGajGakHbjGafE^–c·y—±u‘±u“°t”­s•­s•±u“»{�Ç‚‡ÓŠ�Ô‹‚Õ‹‚×��·†À~�³w’¬r•¬q•®s”°t”°t”°t”­r”«p•¯s”º~�Æ‹Œ×�‡Ó›ˆÀ‡Ž±v”¬m޲v”±v“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“°u“°t’¯t’¯t’¯t’°t’±u“°u’®s‘¸y˜·x—tRj-$\DY¬r�¼{›¯t’¯t’°u“°u“°u“°u“°u“°u“ô£oõ¤oó£oï nï nìžnë�në�nìžnìžnížnìžoð¡iÔ�{­s•°t’±u“·y—¦m‹uNieD]kHbjGajGajGajGajGajGahF`mIcoJdL7M+$%$$$$$% # $"2X=UqKekHbhF`jGajGajGajGafE^–c€¶y—°t’±u“²u’²u’±u“¯t”­r•¬r–¬r–¬r–«q–¬r•®s”°t“²v“²v“²u“±u“±u“±u“²v“²v“±u“¯s”­q”«o•¬o•®q”±u“²w”±u“±u“±u“°u“°t’¯t’¯t‘¯t‘¯t‘¯t‘¯t‘¯t‘°t’°t’²u“³v”¶x—¸z˜¸y˜¸z˜·y—±u“´w•½|›‘c~5-> "&%$""2{Vn¹z™¸y˜²v”´w•´w•´w•´w•´w•΋kÌŠjÔ�kè�mè�mõ¦nù©où©oõ§oò¤nï¢nó¥ià•‚³v™±u“¶y–±u””b~kHbgE_lHbjGajGajGajGajGajGamHcrLf^AY)$6 +" #&$$$$$$$$%& "$7,?gE_rKfkGbjGajGajGajGafE^–c€·y—°t’±u“±u“±u“²u“²v“²v’²v’²v’²v’²v’²u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“²v“²v“²v’±v“°u’°t’°t’¯t’°u’´w•¸y˜¹z™»{š»{š»{š»{š»{š»{š·y—¸y˜¯t’ªpŽ™e‚�_{�`|Ž_z•c±t“¨p�S>S "&%$$$&  <1CtOi‚Vq~To{Rm|Sn|Sn|SndC`cB`hFasMbuNbŠ^d¤pg¿ƒiוkç l÷«oäš„‚Yw”d±t’‘`|tNheD^iG`kHbjGajGaiG`iF`jGajGakHb`BZ3*=  $$$$$$$$ #  $A1FfE^kGajGajGajGajGafE^•c·y˜°u“°t’±u“±u“±u“±u“±u“±u“±u“±u“±u“±u“°t’¯t’¯t‘¯t‘¯t’¯t’°t’±u“±u“°t’°t’°t’±u“³v•µx–¶x–¶x–¹z˜µx–§nŒ“b~‡ZuoKdpLepLepLepLenJcQ8OR8PG0G/$8+%0,4*3, 55)=.$&$$$$$$%% +!7,?dD]mHcfD^fD^fE^kHakHajGahEagEacB``@``@_hFayQf|V`B3I &@1EeD]mHcjGaiGajGajGahF`mIcoJdiF`iGajGaJ6L4*=<.B=/C:.AA1F8,@' $$$$$$ #,?0E>0D;.B>/D:-A5+>TVS;QS;RO9ON8OfE^kHajGajGajGajGajGaiF`lHbqKeT/D& +"1(;cC\qKeiG`gE_lHbnIdB2F # "%$$$$$$$% )R:QpJejGagE_iF`jGaiGaiGaiGaiF`iF`jGakHbfE^kHaUp—d� j‡ži†Ÿi†’a}�_{~TomIcI2I4%:(2&0%0&1)33%:;*@C.E;*@9(>:)?9(>1#8, 5-!5/"71#80#80"7/"7/"7/"7/"7/"7/"7%1& ! #$$$$$ # #*-"6%1%$$$$$$$$%VkHbhF`jGajGajGakHbnIdnJdpKeM8N-%),& $$$$$ #(& ! +!%$$% #.R:QI6K9-@>/D:.AA1F3*=$$$$$ #(<.B@1E@1E@1F2)<@/DQ7OA-D=+A>+B>,B=+AE0GQ7O^?XgE_lHbmIcpKenJdmIceD^T9Q:(>, 5.!60#80#8/"7/"7/"7/"7/"7/"7/"70"80#80"80"70"80"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"72#9,!5) #$$$$ $$+,))))$$$$$$'.+&7#!2'#4Z>WlIciGajGajGa;)?F0GM5LO6NQ9PR9P\?WfD^E4I& $$$$$ #*.!/"0( $$$ $& /,+F1HgD^oJeyOk_AZ- $$$$$$ #*%7eD]\=VH1I=*A0"7*4, 5, 5, 5, 5, 5+ 4+4.!64%;=+AB.DN5ME0G=+A2$9+4-!50#80"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"70"7) 4)()$$$ $%*'+."72#9/"7* $$$$$$'-"6K3JfD^qKflHbjGaiF`jGajGa-!5+ 4*4+ 4/"7/"71#8"1 " "$$$$$$ "%$1- #$$$$ #(-!63#9*4+ 5:(>C0F'  %$$$$$$!&)3, 5, 5/"70#80"80"80"80"80"70#80#8/"7.!6, 5+ 4*4+ 4, 5.!60#8/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7/"7."70#81#8, #$$$ $#03$9/"70#8."6( #$$$$$$ #$$01"8C/E[>VlHbnJdkHbjGa.!61#81#80#80#8,!5) #%&$$$$$%&$$$($$$$(()* 41#80#8- " # #$$$$$ # # "%( 31#8/"70"70"70"70"70"70"70"70"70"70"70#70#81#80#80#70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"70"7."6)$%$$$%$-1#8(2% "#$$$$$$# #$"/, 4.!6=*@S9PeD]kGa1'@% 7'!8&!8&!8$ 7#6% 7'!9/#$$$$% 3&!8% 7% 7+ #$$ #(' 7(!9& 7'!8% 6./..* #$$$$-./-/&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8&!8% 7# 6% 7' $$ #+& 8"6&!84234+ #$$ #(4333'!9% 7 3 3.&=P:U(#<# 8# 9# 9# 8# 9$ 9# 8. # #$$$$ #%2# 9*$%$$%%&5$!9# 9# 8# 8"7(#<(#;&$$$$ #*%!:# 8%!:%!:" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8# 8# 8# 9# 9# 8# 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8" 8# 8$ 9+ "$$$ "/$!9" 8$ 9$!9%!: 5$$$$$ #1&";%!:$!9 6-'@:.IB3NK9UA3N)#<5 6 6!7!6# 8/%(' $$$$% #$1# 8"7' #$$4# 8"6!6 6!6+%>A2MG6Q. #%$$$% "/1(B!6!6# 8$ 8$ 8$ 8$ 8$ 8$ 8$ 8$ 8$ 8# 8"7!6 6 6!6"7# 8$ 8$ 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8"723& $)42# 8# 8# 8# 8 5 # " $$$$ # "0!7!68-GO;XP0K*$=$!9!6 6 6!6!6!6!6!6 6# 8*$=.'@5,E8-G/'@*$=# 8 6 6# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8&!;.    3%!:# 8# 8# 8$ 9-(*'$$%)'.5+ED5PO;WM:VL:UL:VM:VG6RN;WP1L3*C$ 9# 8$!9$ 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 8# 71! '3$ 8# 8# 8# 8# 8# 8$!9# 8&$%$4-&@J8TQ[M:V) #& !"!4T>\Q=ZR=ZM:VM:VN;WO;XP    #>2JR=ZM:VM:VM:VM:UU?]$ N;WP445!6"7!7!7!7!7"7$ 9$!9$!9%!:%";$ 9# 8# 8# 8$!9# 835&":Q=XŽd…"+ tSpcHfN:WM:VM:VM:VM:VM:VM:VM:VM:VM:VK9VK9VL9VI7VH6VH7VR>WdJXwXZ^X†c_jMg  )YB^J8SJ8TL9UM:VM:VM:VM:VPWS?WR>WaHXdJX�_[¥x^°€_²‚`³‚`¶„b¢v` #+‡`~{XvpPnR=YK9TN;WM:VM:VL:UL9UM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VL:VL9UM:VD4N:.DH7RM:VL9UM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VK9TK9TsSqƒ]{}Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx}Zx}Yw~Zx~Zx€[y€\z„^|„]|‚]{{XvxVtxVtxVtxVtxVtwUshLhhLh_Fc<0I6,E(#<)$<)$<(#<5+EgKh†_~ƒ]{[y}Zx~Zxƒ]|„^}~Zx}Zx{XvoPnPZJ8TM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VN:VK9UT>[tSr~Zx~Zw~Zx}Zy|YyzXz[w‰ar“gm—jl—jl˜jl˜jmŽdr…^u€[w{XyzWz{Xy}Yx}Yx}Yx{XyxWy{Xy�et¢pq±ypŸms‰aw~[y{Tt~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx}Yw}Yw}Yw}Yw~Yw|Yx‰ap›ke¦r^¥q_¥q_¥q_¥q_¥q_¥q_¥q_¥q_¥q_¥q_¥q_¥q_¥q`�ldƒ]u}Zx~Zx~Zx}YwmOlL:UM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VN:VN:VN:VM:VM:VM:VM:VM:VM:VM:VN:VM:VJ8SaGc‚\z}Yy|Yy}Zx�\v‰`q’fl¢oc¬u^®w^°x^²y^³z^µ{_¶{`´zb±xd©sh�lm�csƒ]vƒ]w‚]w�ct›kq·{kÙ�fß“fä—gè–eÕœz­«§ž‘˜~[x~Zx~[x~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx€[w£n`¤o_¤o_¤o_¤o_¤o_¤o_¤o_¤o_¤o_¤o_¤o_¤o_¤o_¤o_¦p^ˆ_q{Yz~Zx~Zx[y[yWA]I7SM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VM:VN:VM:VL:VK9TJ8TJ8TJ8TK9TM:VN:VN;WN;WN:VO:VI7SS>[tTs|Yz{Yyƒ]u–gh�kd£o`§q^ªr]©r^¨q_©r`«s`­t`®t`°va²wa¶ya¹{a¾~aÁ€a€b¿eÁ€eÃ�f͇eÕ‹eØ�eÖŒgÙŽiߎeÓžµ¹°·¼±¸¼±�r†{Tu}Yw~[x~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx~Zx}Zxˆ_r™hf¤m^¢l_¢l_¢l_¢l_¢l_¢l_¢l_¢l_¢l_¢l_¢l_¢l_¢l_¢l_¢l`–eh}Zx~Zx~Zx~Zx~ZxmOlL:UL9UN:VM:VM:VM:VM:VM:VM:VM:VN:VJ8TK9TP[‰?[Š@\‰@\‰?[‡=Z‰?[‹C^‡[‰?[‰?[ŠA\‰?[ˆ>[ˆ=Z‰?[ŠA]‰@\ˆ>Z’Le ct„8VŠB]‰?[ŠA]ˆ>Zˆ>[”Qh bt„8WŠB]‰@\‰?[‡[Š@\‡Z‹C^ŒE_ŒD_ŒD_ŒD_ŒD_�E_�E_�E_ŽE_ŽF_�F_�G_‘G_’H_“H`”I`–J`˜K`™La›MaœNažOa Pb¢Qb£Rb¥Sc§Tc¨UcªVc«Vd¬Wd®Xd®Xd¯Yd¯Yd¯Yd¯Yd¯Xd®Xd­Xd¬WdªVd©Uc§Tc¦Sc¤Rb¢Qb¡PbŸOb�Na›MašLa˜Ka—J`•J`”I`“H`’G_�G_�F_�F_ŽF_ŽE_�E_�E_ŒE_ŒD_ŒD_ŒD_ŒD_ŒD_ŒD_ŒD_ŒD_ŒD_ŒD_ŠC^ŠC^ŠC^ŠC^‹D_‹D_‹D_‹D_‹D_‹D_‹E_‹D_ŠC^‹D_ŠC^ŠC^‹D_‹D_‹D_‹D_‹D_‹D_‹D_‹D_‹D_‹D_‹D_‰B]‡>[ŒE`ŠC_‹D_‹D_‹D_‹D_‰A]‡?[ŒE`‹C_‹D_‹D_‹D_ŠC^‹D_‹D_‹E_‹D_‹D_ŠC^‹D_‹D_ŠC^ŠC^ŠC^ŠC^ŠC^ŠC^ŠC^ŠC^‹C^‹D_ŒD_ŒD_ŽE_ŽE_�F_‘G_’G`”H`•I`—J`˜KašLa›Ma�NaŸOb Ob¢Qb£Qc¥Rc¦Sc§Tc¨Td©UdªUdªUdªVdªVdªUdªUd©Ud¨Tc§Tc¥Sc¤Rc£Qb¡Pb ObžNbœMa›La™Ka—K`–I`”I`“H`’G`‘G_�F_�E_�E_�D_ŒD_‹D^‹C^ŠC^ŠC^ŠC^ŠC^ŠC^ŠC^ŠC^ŠC^ŠC^ŠC^ŠC^ŠC^ŠC^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^†B^‡B^‡C_†B^‡B^‡B^‡B^‡B^†B^‡B^‡C_†B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^ˆB^ˆB^‰C^‰C^ŠD_‹D_ŒE_�F_ŽF_�G`‘H`’I`”I`•J`—Ka˜LašMa›Na�NbžObŸPb Qb¡Qb¢Rc£Rc¤Sc¤Sc¤Sc¤Sc£Sc£Rc¢Rb¡Qc PbŸPbžObœNb›Ma™Ma˜La–Ka•J`“I`’H`‘G`�G`ŽF_�E_ŒD_‹D_ŠC_‰C^ˆC^ˆB^ˆB^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^‡B^ \ No newline at end of file diff --git a/crates/exav-viewer/demo/examples/files/images/scene.qoi b/crates/exav-viewer/demo/examples/files/images/scene.qoi new file mode 100644 index 0000000..c1adea3 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene.qoi differ diff --git a/crates/exav-viewer/demo/examples/files/images/scene.webp b/crates/exav-viewer/demo/examples/files/images/scene.webp new file mode 100644 index 0000000..6c58647 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/scene.webp differ diff --git a/crates/exav-viewer/demo/examples/files/images/sunset-flat.hdr b/crates/exav-viewer/demo/examples/files/images/sunset-flat.hdr new file mode 100644 index 0000000..c136e96 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/images/sunset-flat.hdr @@ -0,0 +1,7 @@ +#?RADIANCE +# written by exav's make-images.py +FORMAT=32-bit_rle_rgbe +EXPOSURE=1.0 + +-Y 96 +X 128 +Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}Û}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}' à}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$å}1$å}1$å}1$å}1$å}1$å}1$å}bY³€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$å}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$å}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$å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}E:€€<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}<%å}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}F)ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}S+ê}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}b/ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}r1ï}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}„5ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}—7ô}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¨<ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}¾>ú}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ÖCÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}î˜ô€ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}—Wœ€ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}ïFÿ}…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~…%‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“(‚~“(‚~“(‚~“(‚~“(‚~“(‚~“(‚~“(‚~“(‚~“(‚~“(‚~“(‚~“(‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~“'‚~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~¢)…~¢)…~¢)…~¢)…~£)…~£)…~£*…~£*…~¦*…~¦+†~§+†~§+†~§+†~§+†~§+†~§+†~§+†~¦*†~¦*…~£*…~£*…~£)…~¢)…~¢)…~¢)…~¢)…~¢)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~Ÿ)…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~€k€�¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~²,…~³,…~³,…~³,…~³-†~·-†~¸-†~¸-†~¸-‡~¹/‡~¹/‡~¹/ˆ~½/ˆ~½/ˆ~½/ˆ~¹/‡~¹/‡~¹-‡~¸-‡~¸-†~·-†~·-†~³-…~³,…~³,…~³,…~²,…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~¯+…~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~Ä.ˆ~Ä.ˆ~Ä.ˆ~Å0‰~É0‰~Ê0Š~Ë0Š~Ï0‹~Ð1Œ~Ñ3Œ~…{…�Ó3�~Ô3Ž~Ô3Ž~Ô3Ž~Ô3Ž~Ô3Ž~Ó3�~Ò3�~Ñ1Œ~Ð1Œ~Ì0‹~Ë0Š~Ê0Š~É0‰~Å0‰~Ä.ˆ~Ä.ˆ~Ä.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~À.ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò1ˆ~Ò1ˆ~€h€�Ö1ˆ~×1‰~Ü2‰~Ý3Š~ß4Ž~ä4�~æ5�~è5’~î7“~ð8”~ò8•~ó8–~ø9—~ù9—~ù9—~ù9—~ô9—~ó8–~ñ8•~ð8”~î7“~è5‘~æ5�~ä4�~Þ4Ž~Ý3Š~Ü1‰~×1‰~Ö1ˆ~Ö1ˆ~Ò1ˆ~Ò1ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~Ò/ˆ~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2‹~å3‹~é3‹~ê4Œ~ï5Œ~ñ5�~ó6�~ú8�~ý9’~‚J„KˆLŠM‹O�P� Q‘ Q’ R’ R’ R‘ Q�QŒP‹O‰M…KƒJ�Iü8‘~ù8�~ò5Ž~ð5�~ë5Œ~ê4‹~é3‹~å2‹~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ä2Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø6Š~ø6‹~ø6‹~ý6‹~ÿ6Œ~‚F„I‡I‰KŽL‘M–!O™!QŸ"R¢#T§$Uª%W¬%X­&Y±&Y±&Y®&Y­&X«%W©%V§#U¡#Sž"R˜!P• O�M�L‰J‡IƒH‚Fþ6Œ~ý6‹~ø6‹~ø6‹~ø6Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~ø4Š~„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F†F†F†G†G‰GŠHŽH�I”JšL�!N¤"R«$T°%V¸&Y½([Å*^Ê+`Ñ+bÔ,c×.eØ.eÙ.fØ.eÖ.dÓ,cÐ+aÈ*_Ä)]¼'[¶&X¯%Vª#S£"Qœ!M™L”J�I�HŠG‰G€c€�†F†F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„F„FŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽF‘F‘G‘G”G–HšJŸK¢!M©"O°$Q¹%TÀ(WÊ)[Õ+`à.dé0gô3kû4n‚8€…9€‡:€ˆ;€ˆ;€ˆ;€‡:€„9€€8€ù4mò1jç/gÛ-cÓ+_È)Z¾&Vµ%S¯$Q¨"N¡!MœK™J•H”G‘G‘F‘FŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽFŽF™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™HœH�H I¡ I¦!J¬"L³#N¹%RÂ'UÍ)YÚ,]ç.aö2fƒ5€‰9€‘<€™>€Ÿ @€¦!B€ª"D€­#E€¯#F€±#F€®#F€¬"E€©"D€¥!B€� @€˜=€�;€‡7€ÿ3jó0eå-`×*\Ë(XÀ&T·$P¯"M«!L¥!J¡I IœHœH™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H™H¥Hò`“€¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥ H¥ H¨ H¨ H¬ I®!K³"Lº$NÂ%PÌ'SØ)Wå,[õ/bƒ4€�7€–:€¡ >€­"A€¸$F€Ä&J€Ì)M€Ö*O€Ü+R€ã,S€æ-T€æ-T€å-T€â,S€Ú+Q€Ô*O€Ê'L€Á&I€¶$D€ª!@€Ÿ=€”9€‰6€€3€ï.aß,ZÒ)VÇ'R¾%P¸$M²"L­!K© I¨ H¥ H¥ H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H¥H±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I´"J¶"Jº"KÀ$LÇ%NÑ'QÜ)Vê,Zû0_‡2€’6€Ÿ;€­!?€¼$D€Ë(I€Ü*N€ì.R€ü1X€….�Œ0�‘1�”2�˜3�˜3�•3�“2��1�‰/�„.�ù0W€é-Q€Ø*L€È&G€¸#C€ª >€œ:€�5€…2€÷.^ä+Y×(UÌ'PÃ%N¿$Lº"Kµ"J´"J±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I±!I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾#I¾#IÁ#JÂ#JÇ$LÍ%NÕ'Pà(Sí+Vý/[ˆ1€”5€¡9€³">€Å$C€Ø)J€í-P€ƒ+�Ž.�š1�¥5�°!8�·#;�À$=�Ä&>�Ç&?�È&?�Æ&?�Ã%>�¾$<�µ":�«!7�¡4�—1�Š-�þ0U€è,N€Ô(H€Á$A€­ <€ž8€‘4€†0€ö-Zç+UÛ(RÑ'OÉ%MÆ$LÂ#J¾#J¾#I¾#I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"I¾"IÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KË$KË$KË%KÏ%KÔ%LØ'Nà(Pë*Rù.X‡.€’2€ 6€²!;€Å$A€Û(G€ö-N€ˆ+�˜/�§4�·"8�Ç%<�Ö(A�å+E�ò-H�þ0J�‚&‚„&‚„'‚ƒ&‚�&‚ü/J�ð,G�â*D�Ó'?�Ã%;�´!7�¤2�“.�…*�ð,L€Õ'E€À#?€¬9€�4€�1€ƒ.€ö,Wé*RÞ(O×'MÑ%LÏ%KË$KË$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÈ$KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KØ&KÙ&KÚ&Kß'Lå(Oî*Qù+T„,€Ž.€œ3€«7€À"<€Ö&B€ò+K€‡)�š.�®2�Â#9�Ù(>�î+C�‚$‚Œ'‚–*‚Ÿ,‚§.‚¬ /‚°!/‚±!0‚°!/‚«.‚¦-‚ž+‚”)‚Š&‚ÿ/G�é*B�Ñ&=�½"7�§1�–,�„(�é*I€Ð%A€¹!;€§6€—2€‹-€‚+€÷+Sì*Pä(NÞ'LÙ&KÙ&KÖ&KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%KÕ%Kã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lç'Lç(Mì(Mò)Nø+Pƒ)€‹,€•/€¢2€µ7€É#=€ä(D€‚&�•*�©0�Á"6�Ü'<�ù-D�Š%‚š)‚©,‚·!0‚Ç$3‚Ó&6‚Ü(8‚ä*:‚è*:‚é*;‚ç*:‚ã)9‚Ú(7‚Ï&5‚Â$2‚´!/‚¦+‚•(‚‡$‚ð+B�Ó%:�»!4�¤/��)�ú,J€Þ&B€Ä"<€±5€Ÿ1€“.€‡+€€)€ö*Pî(Nì(Mç(Mä'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lã'Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lö)M÷)Mý*O‚(€ˆ)€�+€œ.€©2€» 7€Ó$=€ð)D€Š&�Ÿ+�¶1�Ò$9�ñ+@�Š#‚�(‚²-‚Ç#1‚Û'5‚ñ+;‚�ƒŠ!ƒ‘"ƒ—#ƒ™$ƒš$ƒ™$ƒ”#ƒ�"ƒˆ ƒÿ-=‚ê*:‚Ö'4‚À#0‚«,‚™&‚†"‚ê)>�Ë#7�°0�˜*�„%�ç(B€Í#;€¶6€¦0€—-€Ž+€‡)€‚(€ü*O÷)Mõ)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)Lò)L€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€‚'€…'€‡(€�)€–+€ .€­1€Á 6€Ú$;€÷)C€Ž&�¥+�À!2�à&9�‚ ‚˜%‚¯*‚È#0‚ã(6‚ÿ-;‚Œ ƒ›#ƒ§&ƒ´ (ƒ¾!*ƒÄ#+ƒÉ$,ƒÊ$-ƒÈ$,ƒÂ#+ƒº!)ƒ° 'ƒ¤%ƒ˜#ƒ‰ƒ÷+:‚Û'4‚À".‚¨)‚’$‚û+?�Ø%7�º 0�Ÿ*�‰%�ï(A€Ò#:€º4€ª0€�-€’*€Œ)€‡(€ƒ'€‚'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€€'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€‹'€Ž(€“)€š+€£-€²0€Ä 5€Ý%:€ü*A€’%�ª+�Ç!1�ê(:�‰!‚¢&‚¼ ,‚Ú&2‚ú+9‚� ƒ¢#ƒµ 'ƒÈ#*ƒØ&.ƒé)0ƒö+3ƒþ.5ƒƒ„ƒ„‚„ý-5ƒò+2ƒä(0ƒÕ&-ƒÂ"*ƒ¯&ƒœ"ƒŠƒó*6‚Ó$0‚´*‚›$‚„ ‚ß&8�¾ /�¢)�‹$�ò(?€Õ#9€¿4€­/€¡,€˜*€’)€Ž(€‹'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€ˆ'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€Ž'€�'€‘(€’(€–)€œ*€¥,€³/€Ã!3€Û%8€ú*?€�$�©)�Ç"/�í(8�Œ ‚¥&‚Ä",‚å)2‚†ƒ›!ƒ³ &ƒÊ$*ƒã).ƒû-3ƒ‰„”„�„¤ „§ „¨!„¦ „£ „›„‘„‡„ö,2ƒÝ'-ƒÅ#)ƒ¬$ƒ– ƒ�ƒÞ&1‚»!*‚Ÿ%‚…‚â'6�¿ .�¡(�Š#�ð)=€Õ$7€¿ 2€®.€£+€›)€•(€’(€�(€�'€Ž'€�'€�'€�'€�'€�'€�'€�'€�'€�'€�'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€”(€•(€˜(€�)€¤+€±-€À"1€Ö&5€ó,;€Œ"�£'�Á#-�å*6�‰‚£%‚Ä$+‚ê+2‚‰ƒ¡!ƒ½$'ƒØ)+ƒø01ƒ�„œ„¬! „º$#„Å&$„Î(&„Ô)'„Õ*'„Ò('„Ì'%„Ã%$„¶#"„§ „—„ˆ„ï-0ƒÒ(*ƒµ"%ƒ› ƒ„ƒß*0‚»#)‚�#‚ƒ‚Ü(3�¸!+�œ&�†!�é*:€Î%4€¼"0€¬,€£*€œ)€—(€”(€”'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€’'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€—'€—'€—(€š(€ž)€¤*€­!+€¼$/€Î(3€è-8€…�›%�·#*�Ü+2�ƒ‚Ÿ"‚À%)‚ä-0‚‰ƒ£ !ƒÀ''ƒâ.,ƒƒ„—„«# „¿'#„Ó,&„á/)„í3+„ö5-„ü7.„ý7.„û7.„ô4-„ê2+„Þ/(„Ï*%„»&"„¦!„‘„ü31ƒÚ,+ƒº%%ƒ� ƒƒƒÛ,.‚¶$'‚—!‚ü19�Ñ(/�°")�•#���á,7€É'2€·#-€«!+€£)€ž(€š(€—(€—'€•'€•'€•'€•'€•'€•'€•'€•'€•'€•'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€œ'€� (€ !(€¥!)€¬#*€·&,€È)0€ß.5€û4;€‘"�­#'�Î+.�ù47�• ‚¶&'‚Ý..‚…ƒ " ƒ¿(&ƒã0+ƒ‡„�"„µ'!„Ë-$„à2)„ó9,„‚…Š!…�#…“$…”$…’$…Ž#…ˆ!…€…î7,„Û1(„Æ+#„®% „— „�„Û/*ƒ¶'$ƒ˜ ƒý54‚Ñ-,‚¬$%‚�‚ì24�Ã),�¥"&�Œ!�ô29€×,4€Â(/€´%,€ª#*€¤!)€Ÿ!(€œ (€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€š'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€Ÿ"'€ "(€¢#(€¦$(€¬%)€´(+€Á+-€Ô.2€ï47€‰� #$�¾**�æ32�Š‚©&#‚Î.*‚ü82‚˜"ƒº)$ƒß2*ƒ…„ž#„·*!„Ï1%„ç8*„ÿA/„‹$…–(…Ÿ+…¦-…«/ …¬0 …ª/ …¥-…�*…“'…ˆ#…ù?.„á7)„È/$„±( „—"„ÿ:0ƒÔ0(ƒ±("ƒ’!ƒï60‚Ä,(‚ #!‚„‚Ú0/�¶((�™"#�ƒ�æ25€Í-1€¾)-€²&*€©%)€¤$(€¢#(€Ÿ"'€Ÿ"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€ž"'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€á[•á[•á[•á[•á[•á[•á[•£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€¥&(€¦&(€«((€±**€½++€Ë//€á43€€�”#!�®)&�Ò1,�ý<5�›$ ‚¾,&‚è7.‚Ž"ƒ®)!ƒÓ2'ƒ€„™$„²+ „Ì4$„ç=*„‚#…�(…ž.…¬2 …·7#…À;%…Æ>&…Ç>&…Ä<&…¾:%…´7#…¨1 …›,…Œ'…üD.„à:)„Å2#„«*„’#„ô:,ƒÉ/&ƒ¥'ƒ† ƒÜ4,‚³*%‚’"‚ð83�Ç/*�§&$��!�ö97€Ú32€Ç.-€¸++€°()€ª'(€¦&(€¥&(€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€£&'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€á[•á[•á[•á[•á[•á[•á[•á[•á[•¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¨)'€©*(€¬*(€±,)€¸-*€Å0,€Õ50€ï;5€ˆ!�Ÿ'"�¼/(�ä8/�‹"‚ª*"‚Ó4)‚� ƒŸ'ƒÃ0$ƒí;+ƒ�$„¨,„Ã4#„à?)„ÿJ/„�+…¡2…²9"…Ã@%…ÑF(…ÜL+…ãO-…åP-…âN,…ÚJ+…ÍE(…¾>%…®7!…�0…Œ*…÷G-„Ø<'„¼2"„¢)„‰"„á9)ƒ¹."ƒ–&ƒõ=/‚Ç2'‚¢( ‚„ ‚Ø6-�µ,&�—%!�‚ �æ93€Ñ4/€Á0+€·-*€°+(€¬*(€©)(€¨)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¦)'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬-'€¬-'€®-(€²/(€·0)€À2*€Ì6-€à;1€üB6€�&�©,#�Ê5)�ö@2�—'‚º0$‚æ<,‚�%ƒ¯. ƒÙ9&ƒƒ#„›*„µ4 „Ó>&„ôK-„‹,…ž4…²="…ÇF&…ÛP+…íY.…û`2…‚2†ƒ3†�2†ø^2…èV.…ÖM*…ÁD%…­;!…™2…‡*…ëG+„Ë;$„®1„•(„üB,ƒÍ6%ƒ¦,ƒ‡#ƒÙ9)‚°."‚�%‚é=/�Â2(�¡*"�£Bl€’;a€…6X€É4,€¾2*€´/)€±.(€®-(€¬-'€¬-'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¬,'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€¯0'€±0'€±1'€´2(€¶2(€¼4)€Ç6+€Õ:-€ë@2€„$�™*�´2$�×;+�ƒ$‚¢-‚È7&‚øD.‚š*ƒÀ4!ƒëA)ƒ‹(„¤0„Á;#„áH)„‚+…–4…¬> …ÃI%…ÛT+…óa0…„6†Žˆk†”Žp†–�q†“�o†Œ;†‚5†ì^.…ÔR*…½F$…¦;…‘1…üS.„ÙE(„¹8!„ž.„…%„Þ='ƒµ2 ƒ’(ƒìA,‚½4#‚™*‚…5X�á[•€ÀM€§Co€•"ƒ“;a‚ôc¢�ÊR†�¨Do�Œ8]�ë_œ€ÈQ„€­Fs€™=e€Š7[€€3T€òb é^›ä\—â[–á[•á[•¹9'€¹9'€¹9'€¹9'€¹9'€¹9'€¹9'€¹9'€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€á[•á[•á[•á[•á[•á[•á[•“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€¾='€Á>(€Â>(€Ç@(€ÎB)€ÙE+€ëK/€‚)�”/�¬6!�ÌA&�ùO-�™0‚½eƒ�4UƒØW�‚´Iw‚•f€‹8\€€3U€òb¡ê^›å\˜â[–á[•á[•á[•á[•á[•á[•á[•¾='€¾='€¾='€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€ÂB'€á[•á[•á[•á[•á[•á[•á[•“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~á[•á[•á[•á[•á[•á[•á[•“@z~“@z~“@z~“@z~“@z~á[•á[•ÂB'€ÂB'€ÂB'€ÂB'€ÄB'€ÅB(€ÈC(€ÍD(€ÔG)€ßK+€òP/€…,�—3�°;!�ÓF&�þU.�œ3‚Á@!‚ðO)‚•1ƒ³=ƒØL%ƒ�/„š:„·G!„ØX'„þk.„”A…¬N!…Ç^&…æq-…„D†–�q†«¤�†Âº’†ÛÒ¥†î䳆ÕË †¥Cn…’;`…€3U…àZ”„ÃN�„©Dp„’;`„úe¦ƒÖVŽƒ¶Ixƒš>fƒ�4VƒÙW�‚µIx‚–f€‹8\€€4U€ób¡ê^›å\˜â[–á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€ÈF'€á[•á[•á[•á[•á[•á[•“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~#A�{#A�{“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~á[•á[•á[•ÈF'€ÈF'€ÉG(€ÌG(€ÑJ(€ØK)€ãP+€÷V/€‰/�›6�´>!�ÖK&�‚-‚Ÿ7‚ÅD!‚õS)‚”4ƒ²AƒÖP%ƒ€1„™=„µJ „Ö['„ûo.„’C…ªQ …Åb&…âv,…�F†“�o†§Ÿ}†»³�†ÍÄš†ÕË †±Gu… @j…Ž9^…ûe¦„ÜY’„ÀM„§Cn„�:_„ød¤ƒÔUŒƒ´Iwƒ˜=eƒ€4Uƒ×W�‚³Hw‚•f€Š8\€€3U€òb¡ê^›å\˜â[–á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€ÌK'€á[•á[•á[•á[•á[•á[•“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~#A�{#A�{#A�{#A�{#A�{“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~á[•á[•á[•á[•á[•â[–ÔN(€ÞQ)€éU+€ú[/€Š2��8�¶B �×N&�‚/‚ 9‚ÆG!‚ñX(‚‘6ƒ¯CƒÒS$ƒÝY’‚ƒ5Wƒœ?gƒÑ^%„õr-„ŽE…¥S…¾c%…Úu+…øŠ2…ŒQ†œ–v†¬¥�†¢Ak…¥Cn… @j…”f„…6X„ç]™ƒÆPƒƒ©Dpƒ�:_ƒób¡‚ÌR‡‚ªEq‚Ž9^‚ì_��ÄO‚�£Bl�ˆ7Z�å]˜€ÄO‚€ªDp€–=d€ˆ7Z€þf¨&Fš{%D•{$B’{â[–á[•á[•á[•á[•á[•á[•á[•á[•á[•á[•ÖV'€ÖV'€ÖV'€ÖV'€ÖV'€ÖV'€ÖV'€ÖV'€ÖV'€ÖV'€ÖV'€ÖV'€ÖV'€ÖV'€á[•á[•á[•á[•á[•á[•“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~á[•á[•á[•â[–å\—é^›òb €3T€Š7[€˜=e€¬Er€ÆP„€é^š€Š7[�¥Bm�ÆPƒ�î`ž��9_‚«Eq‚ÌR‡‚òb ‚�9^ƒ§CoƒÃO�ƒâ[–ƒ‚4V„”e„ªEq„»K|„ÊQ†„ÖVŽ„ÞY“„àZ”„ÜY’„ÓUŒ„ÆPƒ„·Jy„¦Cn„•f‚�4V‚ØW��´Iw�—=d�þf¨€×W�€¹K{€3^Ð{.Tº{*M«{'H {&E˜{$C”{$B’{$A‘{$A�{#A�{#A�{á[•á[•á[•á[•á[•á[•á[•“@z~“@z~“@z~“@z~“@z~áa'€áa'€áa'€áa'€áa'€áa'€áa'€á[•á[•á[•á[•á[•“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~á[•â[•ã\—ç]™î`žùe¥…6X€‘;`€¢Al€¹K{€×W�€ýf¨€––€c7…€®bë˜UÍ„J±q?˜a6‚2]Ì}+N¬}$B‘}b7„~¥]ß}ŒN¼}$C“|?sý{7dÝ{0YÄ{,Q²{)K¥{&Gœ{%D–{$C“{$B‘{$A�{#A�{#A�{#A�{#A�{#A�{#A�{“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~#A�{#A�{#A�{#A�{#A�{“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~”A{~å\˜ê^›ób¡€3U€Š7[€—=d€ªDq€ÂN�€á[•€„5W�›?g�¸Jz�ÚX‘��4U‚˜=d‚²Hv‚ÏS‰‚ðaŸ‚‰7[ƒœ?hƒ°GuƒÅO‚ƒÙX�ƒí`�ƒ§I‹‚±M“‚¹Q™‚–TÉ€—UË€•TÈ€�Q€ŠM¹€�I®€xC¡€m=“€c7…€±cîœXÒ‰M¸wC g:Š6cÛ}.U»}'Hž}!=†}8gâ|/W¿|(J¢|"?‹|•Gª¶O—�ÌY©�ãc¼�úmÏ�‡;p‚r@š€yD¢€}F©€€H­€�H®€€H¬€|F§€wC €p?—€h;�€`6�€®bêœXÒ‹N»zE¤!<…~9hæ}1ZÆ}*M©}$A�}=oõ|3^Ð|,P±|%D—| ;‚|·g÷|£[Û|“SÆ|*L©{'HŸ{%E˜{$C”{$B’{$A‘{$A�{#A�{#A�{“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{“@z~“@z~#A�{#A�{#A�{#A�{#A�{“@z~“@z~“@z~“@z~“@z~#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~”@z~•A{~—B}~›C€~¡F…~ªJ�~¸P™~ÊX¨~ãc¼~�8kuBž}ˆM¸} Z×}»iû}m=“~H¬~”SÇ~«`æ~b7„p?–~Gª�O¾œXÒ«`æ¹høb7„€g:‹€k<�€n>”€n>”€m=“€j<�€f9Š€a6‚€µfô§^á˜U͉M¸%E˜~!=†~:kì}3]Í},P±}&E˜} ;‚}7eß|/V¾|(J£|#?Œ|”zE¥‡Lµ“SÆžYÕ©_ã±cî·gö»iû¼jýºiú¶fô¯bë¦]ßœWÑ�Q„J±wC k<�¾kÿ~§^á~-Rµ}'G�}!=ˆ}:jê|2[É|+N­|%D•|h;Œ}¸g÷|2\Ì{.T¸{*Mª{'I {&E™{%C•{$B’{$B‘{$A�{#A�{#A�{#A�{#A�{#A�{#A�{“@z~“@z~“@z~“@z~“@z~tAœ|“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~#A�{#A�{#A�{#A�{#A�{#A�{#A�{“@z~#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{“@z~“@z~“@z~“@z~“@z~“@z~#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{“@z~“@z~“@z~“@z~tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|“@z~”@z~•A{~—B}~›D�~H«|‡Lµ|‘QÃ|ŸYÖ|±cî|d8†}r@™}ƒI°}—UË}¯bë}e8‡~tAœ~„J²~—UË~ª`å~_5€i;ŽtAœ~G©‡L¶�PÁ–TÊ›WÑžYÕŸYÖ�XÔšVÏ”SÈ�O¾…J³{E¦q?˜g:йhù~¥]Þ~-Rµ}'HŸ}"?‹}ˆ|;mð{5aÕ{›WÐ|ŽP¿|…J²|~G©|%D—{$C“{$B‘{$A‘{$A�{#A�{#A�{tAœ|“@z~“@z~“@z~“@z~“@z~“@z~“@z~“@z~tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{tAœ|tAœ|#A�{#A�{#A�{#A�{#A�{#A�{#A�{tAœ|tAœ|tAœ|tAœ|tAœ|“@z~“@z~#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|tAœ|uB�|vBŸ|yD¢|}F¨|‚I°|‹N»|–TÊ|¥]Þ|¸gø|h:Œ}vBŸ}‡L¶}›WÐ}²dï}e9ˆ~sA›~ƒI°~“RÆ~¤\Ü~µfó~c7…k<�r@šyD£GªƒI°…K³†K´…J²‚I®}F©wC¡q?—i;�a6‚°cí~ŸYÖ~�PÀ~Gª~p?–~–p?—o>•m=’i;�d8‡_5€²dï~¤\Ý~–TÊ~ˆL·~zE¥~m=“~ª|J@¯|NC·|RFÂ|XKÏ|_Qà|gYô|91†}>6“}E;£}LA´}THÇ}\OÚ}eWî}7/�~;3‹~?6•~C9�~F<¥~H>«~J@°~KA²~LA³~KA²~J?¯~H>ª~E;£~B8›~>5’~:2‰~k\þ}cUé}ZMÕ}RFÂ}'G�|#@Ž| :€|:jé{5`Õ{0YÃ{-Rµ{QE¿|MBµ|J?®|G=©|F<¥|E;£|$B‘{$A�{#A�{#A�{#A�{#A�{#A�{D;¡|D;¡|D;¡|D;¡|—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|—V¾}—V¾}—V¾}—V¾}#A�{#A�{#A�{#A�{#A�{D;¡|D;¡|D;¡|D;¡|D;¡|#A�{#A�{#A�{#A�{#A�{D;¡|D;¡|D;¡|D;¡|D;¡|—V¾}—V¾}—V¾}#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¢|E;¢|E;£|F<¤|G=§|H>«|K@°|NC¸|RGÂ|XKÏ|^QÞ|fXñ|7/ƒ}=4�}B9œ}H>«}ODº}VJÊ}]OÚ}cUê}j[ù}70ƒ~:2‰~<3Ž~=5‘~>6“~?6”~>5“~=4‘~;3�~91ˆ~7/�~hYõ}aTæ}[NÖ}THÆ}MB¶}G=§}A8™};3Œ}9hå{4_Ò{0XÂ{VJË|QF¿|MB¶|J?¯|H>ª|F<¦|E;¤|$B‘{$A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{D;¡|D;¡|—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}#A�{#A�{#A�{#A�{#A�{#A�{—V¾}—V¾}D;¡|D;¡|#A�{#A�{#A�{#A�{#A�{#A�{#A�{D;¡|—V¾}—V¾}—V¾}—V¾}—V¾}#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{—V¾}—V¾}—V¾}D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|D;¡|—V¾}—V¾}—V¾}—V¾}˜V¾}˜V¾}˜V¿}E;£|F<¥|G=§|H>«|K@±|NC¸|RFÁ|WKÍ|]PÛ|dVë|l\þ|:2‰}?6”}D: }I?­}NC¹}THÅ}XLÑ}]PÛ}aSå}dVì}fXñ}hYõ}hYö}gYô}fWð}cUê}`Râ}\OÙ}WKÎ}RGÂ}MB¶}H>©}B9�}=5‘}91†}i[ù|3]Î{B_®z>Y¤z*Mª{MB¶|J@¯|H>ª|F<¦|E<¤|E;£|E;¢|D;¢|D;¡|#A�{#A�{#A�{D;¡|D;¡|D;¡|—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}#A�{#A�{#A�{#A�{#A�{#A�{#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}#A�{1Gƒz#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}#A�{#A�{#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}˜V¾}˜V¾}˜W¿}™WÀ}›XÂ}G=§|H>«|K@°|MB·|QF¿|UIÊ|[NÖ|`Sä|gYó|7/‚};2‹}?6”}C9ž}G=§}K@°}NC¸}QF¿}SHÅ}UIÉ}VJÌ}WJÌ}VJË}UIÈ}SGÄ}PE½}MB¶}J?®}F<¥}B8›}>5’}:2‰}6.€}eWï|_Qà|YMÒ|=X¡z:T™zMBµ|J?¯|H>ª|F=§|F<¤|E;£|E;¢|D;¢|D;¢|#A�{#A�{#A�{#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}#A�{#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}#A�{#A�{1Gƒz#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}#A�{#A�{#A�{#A�{#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}˜V¾}˜V¾}˜W¿}™WÀ}›XÂ}G=§|H>«|J@¯|MBµ|PD¼|SHÅ|XKÏ|]PÛ|bTç|hYõ|7/�}:1ˆ}=4�}?6–}B9œ}D;¡}F<¦}G=©}H>«}H>«}H>ª}G=¨}F<¥}D: }A8›}?6”}<3Ž}91†}l]ÿ|fXñ|aSä|[NØ|WJÍ|RGÃ|9R—z7O‘zJ?®|H>ª|F<¦|F<¤|E;£|E;¢|D;¢|D;¢|#A�{#A�{#A�{1Gƒz#A�{#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}#A�{#A�{#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}1Gƒz—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}#A�{#A�{#A�{1Gƒz1Gƒz#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÖiÁ~×iÂ~ÙjÃ~ÜlÆ~ŸZÈ}I?®|LA³|NC¹|QFÀ|UIÈ|YLÑ|]PÛ|k=‡~p@�~uB“~zE™~~Gž~:2Š}<3�}=4�}=5‘}=5‘}=5‘}<4�};3Œ}:2‰}80…}6/€}iZ÷|dVí|`Râ|\OØ|XKÏ|THÆ|PE¾|MC·|6N�z5LŒzG=©|F<¦|E<¤|E;£|E;¢|D;¢|D;¢|D;¡|#A�{#A�{#A�{1Gƒz#A�{#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}#A�{1Gƒz1Gƒz#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}1Gƒz—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}#A�{#A�{#A�{1Gƒz1Gƒz#A�{#A�{#A�{—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÖiÁ~×iÁ~ÙjÃ~ÛkÅ~ÞmÈ~ãoÌ~èqÑ~îuÖ~öxÝ~þ|å~ƒ@vˆBz�E’Gƒ–I‡n>Š~q@�~sA�~tB’~j[û|j[û|j[ú|iZø|gYô|eWï|cUé|`Rã|]PÛ|ZMÔ|WJÍ|THÆ|QE¿|NC¹|LA³|J?¯|H>«|G=¨|F<¥|E;¤|E;£|E;¢|D;¢|D;¢|D;¡|D;¡|D;¡|ÕhÀ~ÕhÀ~1GƒzÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}1Gƒz1Gƒz—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}1Gƒz1Gƒz—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÖiÀ~×iÁ~ØjÂ~ÚkÄ~ÜlÆ~àmÉ~äoÍ~érÑ~îuÖ~ôxÜ~û{â~�?t„@w‡BzŠC|�E�F�‘G‚g;‚~h;‚~]PÝ|]PÛ|\OØ|ZMÕ|XLÑ|VJÌ|THÇ|RGÂ|PE½|NC¸|LA³|J@¯|I>¬|G=©|F<¦|F<¥|E;£|E;¢|E;¢|D;¢|D;¢|D;¡|D;¡|ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~1GƒzÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}Ój:Ój:Ój:Ój:Ój:1Gƒz1GƒzÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}1Gƒz1Gƒz—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÖhÀ~ÖiÁ~×iÂ~ÙjÃ~ÛkÅ~ÝlÇ~ànÊ~äoÍ~èqÐ~ìsÔ~ðuØ~õxÜ~ùzà~ý|ä~€?s‚?uƒ@vƒ@vƒ@vƒ@v‚@u�?t€>sü{ã~øyß~ôwÛ~ïu×~ësÓ~æqÏ~I>¬|H=©|G=§|F<¥|E<¤|E;£|E;¢|D;¢|D;¢|D;¢|D;¡|ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}Ðe:Ðe:Ðe:Ðe:Ðe:Ðe:Ðe:Ðe:Ðe:Ðe:Ðe:Ðe:1Gƒz1GƒzÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÖiÁ~×iÁ~ØiÂ~ÙjÃ~ÛkÅ~ÝlÇ~ßmÉ~ânË~äpÎ~çqÐ~êrÓ~ítÕ~ïu×~ñvÙ~òwÚ~ówÛ~ówÛ~ówÛ~òvÚ~ðvØ~îu×~ìsÔ~érÒ~çqÏ~äoÍ~ánÊ~ÞmÈ~ÜlÆ~ÚkÄ~ÙjÃ~×iÂ~ÖiÁ~ÖiÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}Ë`:Ë`:Ë`:Ë`:Ë`:Ë`:Ë`:Ë`:Ë`:Ë`:Ë`:Ë`:Ë`:Ë`:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÖhÀ~ÖiÁ~×iÁ~ØiÂ~ÙjÃ~ÚkÄ~ÛkÅ~ÝlÇ~ßmÈ~ànÊ~ânË~ãoÍ~åpÎ~åpÎ~æpÏ~æpÏ~æpÏ~åpÎ~äpÍ~ãoÌ~ânË~àmÊ~ÞmÈ~ÝlÇ~ÛkÅ~ÚjÄ~ØjÃ~×iÂ~ÖiÁ~ÖiÁ~ÖhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~È\:È\:È\:È\:È\:È\:È\:È\:È\:È\:È\:È\:È\:È\:È\:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÖhÀ~ÖiÁ~ÖiÁ~×iÂ~ØjÂ~ÙjÃ~ÚjÄ~ÚkÅ~ÛkÅ~ÜlÆ~ÝlÇ~ÝlÇ~ÞlÇ~ÞlÈ~ÞlÇ~ÝlÇ~ÝlÇ~ÜlÆ~ÛkÅ~ÚkÄ~ÙjÄ~ØjÃ~ØiÂ~×iÁ~ÖiÁ~ÖiÀ~ÖhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÃW:ÃW:ÃW:ÃW:ÃW:ÃW:ÃW:ÃW:ÃW:ÃW:ÃW:ÃW:ÃW:ÃW:ÃW:ÃW:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~Í[:Ð\:Õ^;Ø^;Þ`;ãa;éc=ïg=õi=ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÖhÀ~ÖiÁ~«E"€³G"€¹J#€ÁL#€ÉP$€ðùÞÙjÃ~ÙjÃ~ÙjÃ~ÙjÃ~ÙjÃ~ØjÃ~ØjÂ~ØiÂ~×iÂ~×iÁ~ÖiÁ~ÖiÁ~ÖhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:¾Q:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÀR:ÃR:ÅT:ÈT:ËV:ÍW:ÐW;ÕY;Ø[;Þ\;ã^=éa=ïc>øe>þi>ƒ5€ˆ7€�9 €’; €—=!€œ>!€£A"€ªC"€°E"€·G#€¿I#€íöÜíöÜíöÜîöÜÖiÁ~ÖiÁ~ÖiÁ~ÖiÁ~ÖiÁ~ÖiÁ~ÖhÀ~ÖhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~»N:»N:»N:»N:»N:»N:»N:»N:»N:»N:»N:»N:»N:»N:»N:»N:»N:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~»N:»N:»N:¾O:ÀO:ÀO:ÃQ:ÅR:ËR:ÍT;ÐV;ÕW;ÛY;á[=æ\=ì`>õa>ûe>‚3€†5€‹7 €�8 €•:!€œ"€¨A"€¯C"€·E#€¾H$€ìõÛìõÛìõÛìõÛìõÛÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~¶I:¶I:¶I:¶I:¶I:¶I:¶I:¶I:¶I:¶I:¶I:¶I:¶I:¶I:¶I:¶I:¶I:¶I:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~¶I:¶I:¶I:¶I:¶I:¸I:¸K:»K:¾K:ÀL:ÃN:ÅN:ÈO;ÍQ;ÐR;ÕT;ÛV=áW=é[>ï\>ø`>þa?ƒ2€ˆ4 €�5 €“7!€˜9!€Ÿ;"€¤>"€¬@"€³B#€¼E$€ìõÛìõÛìõÛìõÛìõÛìõÛÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~³F:³F:³F:³F:³F:³F:³F:³F:³F:³F:³F:³F:³F:³F:³F:³F:³F:³F:³F:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~³F:³F:³F:³F:³F:³F:³F:³F:³F:¶F:¸H:¸H:»I:¾I:ÃK:ÅL;ÈN;ÍO;ÓQ;ØR=ÞT=ãV>ìY>ò[>û^?‚0€†1 €‹3 €�5!€—7!€œ9"€£;"€ª>"€±@#€¹B$€ìõÛìõÛìõÛìõÛìõÛìõÛìõÛÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~³F:³F:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~—V¾}—V¾}—V¾}—V¾}—V¾}—V¾}ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:¯B:±B:±B:³B:¶D:¶D:»E:¾F:ÀH;ÅH;ÈI;ÍK;ÓN=ØO=ÞQ>æT>ìV>õY?þ[?ƒ/ €ˆ0 €�2!€“4!€˜6"€Ÿ8"€¦:"€¬<#€³?$€ìõÛìõÛìõÛìõÛìõÛìõÛìõÛìõÛÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~†0 €‚. €û[?ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~¯B:¯B:¯B:¯B:¯B:¯B:¯B:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:¬=:¬>:¬>:¯>:±?:±?:³A:¸A:»B;¾D;ÃE;ÈF;ÍH=ÓI=ØK=ÞN>æO>ìR?õT?þWAƒ- €ˆ/!€�0!€“2"€˜4"€Ÿ6"€¤8"€¬:#€³<$€ìõÛìõÛìõÛìõÛìõÛìõÛìõÛµ=$€­;#€¦8#€¡6"€š4"€“2"€Ž0!€Š/!€…- €€, €øV?ïR?æQ>áN>ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~¬>:¬=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:ª=:§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::§::ª::ª;:¬;:¯;:±=:³>:¶>:¸?;¾A;ÀB;ÅD;ËE=ÐF=ÕI>ÞK>ãL>ìO?õR?ûTA‚+ €ˆ-!€�/!€’0"€˜2"€ž4"€¤6#€ª8#€¯:$€ìõÛìõÛìõÛìõÛìõÛìõÛ±:$€¬8#€¤6#€Ÿ4"€˜2"€“0"€Ž/!€ˆ-!€ƒ, €þVAõR?ìO?æN>ÞK>ØI>ÓH=ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ª;:ª::§::§::§::§::§::§::§::§::§::§::£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:£6:¥6:¥6:¥6:§8:§8:ª9:¬9:¯::±:;¶;;¸=;¾>;Ã?=ÈA=ÍD=ÓE>ÛF>áI>éK?ïN?øQA€) €…+!€Š,!€�."€•0"€š0"€Ÿ2"€¤4#€ª5#€­7$€¯8$€±8$€±8$€­7$€ª6#€¦4#€¡3#€œ1"€—0"€�."€‹,!€†+!€‚* €ûQAòN?éL?ãI?ÛH>ÕE>ÍD=ÈB=Ã?=ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ª9:ª8:§8:¥6:¥6:¥6:£6:£6:£6:£6:£6:£6:£6:£6: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4:£4:£4:¥4:¥5:§5:ª6:¬8:±8;³9;¸:;»;;À==Å>=ËA=ÓB>ØD>ÞF?æH?ïK?øLAþOAƒ)!€ˆ+!€�+"€’-"€—/"€œ0"€¡1#€¤2#€¦3#€¨4$€¨4$€¨3#€¤2#€¡1#€ž0"€˜/"€“."€Ž,"€Š+!€…)!€€(!€øNAïKAéI?áF?ÛE>ÓB>ÍA=È?=Ã>=¾;;¸:;³9;±9;¯8:ª6:§6:§5:¥5:£4:£4: 4: 4: 4: 4: 4: 4: 4: 4: 4: 4:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:ž0:ž0:ž0: 0:£1:¥1:§3:ª4:¬4;±5;³6;¸8;¾9=Ã;=È==Í>>Õ?>ÛB?áD?éF?òHAûKA€'!€…'!€Š)"€Ž*"€’+"€•,"€˜-"€œ.#€ž/#€ž/#€ž/#€œ/#€š."€—-"€“+"€Ž+"€‹)"€†(!€‚'!€ûKAòIAìFAãE?ÞB?ÕA>Ð>>È=>Ã;=¾:=¸9=¶6;±6;¯5;ª4:§3:¥3:£1: 1: 0:ž0:ž0:œ0:œ/:œ/:œ/:œ/:œ/:œ/:œ/:œ/:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~ÕhÀ~™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:™-:™-:œ-:œ-:ž.: .:£/:¥0:ª1;¬1;±3;¶4;¸5=¾8=Ã9=Ë:>Ð;>Õ>?Þ??ãB?ìDAòFAûHB€%!€…&"€ˆ'"€‹("€Ž)"€’*"€“*"€•+"€•+"€“*"€’*"€�)"€�("€Š'"€†&"€‚%!€þHBõFAìDAæBAÞ??Ø>?Ð=>Ë:>Å9>À8=»6=¶5=±4;¯3;ª1;§0;¥/: /: .:ž.:œ-:™-:™-:™,:™,:™,:™,:™,:™,:™,:™,:™,:™,:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:ôÔ¤€•*:•*:•*:•*:•*:•*:•*:Ä“z€•*:•*:•*:†LI€•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:•*:—*:—*:™+:™+:œ,:ž,: -:¥.;§.;ª/;¯0;³1=¶3=»4=À6>È8>Í9>Ó:?Û=?á>?æAAïBAõEBþFB‚$!€…$"€ˆ%"€Š&"€‹'"€�'"€�'"€�'"€�'"€‹'"€ˆ&"€…%"€‚$!€þFBøEBïBAéAAá?AÛ=?Õ;?Í9>È8>Ã6>¾5=¸4=³1=¯0;¬/;§/;¥.;£-:ž,:œ,:œ+:™+:—+:—*:—*:•*:•*:•*:•*:•*:•*:•*:•*:•*:“':“':“':“':“':Â’y€òУ€ß·’€“':“':ëÈœ€ôÔ¤€†JI€“':ôÔ¤€“':•\U€†KI€“':¥4FôÔ¤€—*=ø~‚“':ẕ€Ð£…€’VQ€Ÿf]€ôÔ¤€†KI€¹…q€ôÔ¤€“':Â’y€òУ€“':ôÔ¤€†KI€¹…q€ôÔ¤€“':û‚„û„†ẕ€“':“':“':“':Ô¨ˆ€“':ƒGF€ágp“':“':“':“':“':“':•':•(:—(:™):œ):ž*: +;¥,;§,;¬-;¯.=³/=¸1=¾3>Ã4>È5>Ð6?Õ9?Û:?á;Aé>Aï?BõABûBBþDB‚""€ƒ#"€…#"€…#"€…#"€ƒ#"€ƒ#"€€""€þDBøBBòABì?Aæ=Aá;AÛ:?Ó8?Í6?È5>Ã4>¾1>¸0=³/=¯.=ª-;§,;£+; +;ž*:œ):™):—(:•(:•':“':“':“':“':“':“':“':“':“':“':“':“':Ž%:Ž%:Ž%:Ž%:Ž%:ôÔ¤€ôÔ¤€Ž%:Êž‚€Ž%:ôÔ¤€ëÈœ€Ž%:Ž%:³ARŽ%:ôÔ¤€ôÔ¤€‹QN€�QO€Ž%: 1F±|l€Ž%:Ú¯�€Ž%:Ž%:ôÔ¤€ôÔ¤€Ž%:ß¹“€ôÔ¤€Ž%:ôÔ¤€ôÔ¤€Ž%:ôÔ¤€Ž%:ß¹“€ôÔ¤€ðС€Ž%:Ž%:د�€Ž%:Ž%:Ž%:Ž%:Ž%:ðС€ôÔ¤€ôÔ¤€Ž%:Ž%:Ž%:Ž%:Ž%:Ž%:�%:�%:“%:•%:•%:—':™':ž(; );£*;§+;¬,=¯-=³.=¸/=¾0>Ã1>È3>Í5?Ó6?Ø8Aá9Aæ:Aé=Bï>Bõ>Bø?BûABþADþADþADûADûABø?Bò>Bï=Bé;Aã:AÞ9AØ8?Ó6?Í4?È3>À1>»0>¶/=³-=¯,=ª+;¥*;£*; );œ(:™':—':•%:“%:“%:�%:�%:Ž%:Ž%:Ž%:Ž%:Ž%:Ž%:Ž%:Ž%:Ž%:Ž%:Œ!:Œ!:Œ!:Œ!:Œ!:¨pe€òÒ£€éÆœ€Œ!:Œ!:·‚q€Ø­�€Œ!:òÒ£€Œ!:Œ!:¹ƒq€ƒFH€Œ!:Ž";ôÔ¤€¡h`€‹PO€—)BØ­�€Œ!:Œ!:ôÔ¤€ôÔ¤€€CF€˜]X€îÊž€Œ!:¨pe€òÒ£€Œ!:ôÔ¤€€CF€˜]X€ôÔ¤€�$=òx‚Ø^n¼ˆv€Œ!:ẕ€Ìžƒ€Œ!:Œ!:Ž#;õ|„ìr~Œ!:Œ!:Œ!:Œ!:Œ!:Œ":Œ":Ž":Ž#:�#:“#:•$:—%:œ%;ž%; ';¥(;§)=¬*=±+=¶,>»->À.>Å/?Ë1?Ð3?Ó4?Ø5AÞ6Aá8Aæ9Bé9Bì:Bì:Bï:Bï:Bì:Bì:Bé9Bã8Aá8AÛ6AØ5AÓ4?Í1?È0?Ã/>¾.>¸->³,=±+=¬*=§)=£(; ';ž%;™%;—%:•$:“#:�#:Ž":Ž":Œ":Œ":Œ!:Œ!:Œ!:Œ!:Œ!:Œ!:Œ!:Œ!:Œ!:Œ!:Œ!:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ôÔ¤€ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ôÔ¤€ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:Š:Š:Œ :Ž :�!:“!:•";—#;œ#;ž$;£%;¥%=ª'=¯(=±)>¶*>»+>À,?Å-?È.?Í/?Ð0AÕ1AØ3AÛ3AÞ4AÞ4Aá4Aá4AÞ4AÞ4AÛ3AØ3AÕ1AÐ0AÍ/?È.?Ã-?¾,>»+>¶*>±)>¬(=ª'=¥%= %;ž$;™#;—";•";“!:�!:Ž :Œ :Š:Š:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:ˆ:„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9„9†9†:†:ˆ:ˆ:Š:Œ:Ž:� :“ ;—!;™";œ#; $=¥$=§%=¬%=¯'>³(>¸)>¾*>À+?Å,?È-?Ë.?Í.AÐ/AÓ/AÓ0AÕ0AÕ0AÓ/AÓ/AÐ/AÍ.AË-?È-?Ã,?À+?»*>¶)>³(>¯'>ª%=§%=£$= #;œ";™";•!;“ ;�:Ž:Œ:Š:ˆ:ˆ:†:†:„9„9„9„9„9„9„9„9„9„9„9„9ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~€9€9‚9‚:„:†:ˆ:Š:Œ:� ;“!;•";™#;œ$= $=£%=§%=¬'>¯(>±)>¶*>¸*>»+?¾,?À,?Ã,?Ã-?Ã-?Ã-?Ã-?À,?À,?¾+?»+?¸*>³)>±)>¯(>ª'=§%=£%=ž$=œ#;—";•";“!;Ž ;Œ:Š:ˆ:†:„:‚9‚9€9€9ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ü7r~ \ No newline at end of file diff --git a/crates/exav-viewer/demo/examples/files/images/sunset.hdr b/crates/exav-viewer/demo/examples/files/images/sunset.hdr new file mode 100644 index 0000000..4e99f89 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/images/sunset.hdr differ diff --git a/crates/exav-viewer/demo/examples/files/media/canon.flac b/crates/exav-viewer/demo/examples/files/media/canon.flac new file mode 100644 index 0000000..3bfd35f Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/media/canon.flac differ diff --git a/crates/exav-viewer/demo/examples/files/media/canon.m4a b/crates/exav-viewer/demo/examples/files/media/canon.m4a new file mode 100644 index 0000000..aac119b Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/media/canon.m4a differ diff --git a/crates/exav-viewer/demo/examples/files/media/canon.mp3 b/crates/exav-viewer/demo/examples/files/media/canon.mp3 new file mode 100644 index 0000000..a8a5fdd Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/media/canon.mp3 differ diff --git a/crates/exav-viewer/demo/examples/files/media/canon.ogg b/crates/exav-viewer/demo/examples/files/media/canon.ogg new file mode 100644 index 0000000..8a153fb Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/media/canon.ogg differ diff --git a/crates/exav-viewer/demo/examples/files/media/canon.opus b/crates/exav-viewer/demo/examples/files/media/canon.opus new file mode 100644 index 0000000..e12cb94 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/media/canon.opus differ diff --git a/crates/exav-viewer/demo/examples/files/media/canon.wav b/crates/exav-viewer/demo/examples/files/media/canon.wav new file mode 100644 index 0000000..484a9dd Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/media/canon.wav differ diff --git a/crates/exav-viewer/demo/examples/files/media/testcard.mp4 b/crates/exav-viewer/demo/examples/files/media/testcard.mp4 new file mode 100644 index 0000000..49a7b38 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/media/testcard.mp4 differ diff --git a/crates/exav-viewer/demo/examples/files/media/testcard.webm b/crates/exav-viewer/demo/examples/files/media/testcard.webm new file mode 100644 index 0000000..23b44b2 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/media/testcard.webm differ diff --git a/crates/exav-viewer/demo/examples/files/models/arm.glb b/crates/exav-viewer/demo/examples/files/models/arm.glb new file mode 100644 index 0000000..4b57871 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/models/arm.glb differ diff --git a/crates/exav-viewer/demo/examples/files/models/bracket-ascii.stl b/crates/exav-viewer/demo/examples/files/models/bracket-ascii.stl new file mode 100644 index 0000000..31f3f09 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/models/bracket-ascii.stl @@ -0,0 +1,254 @@ +solid bracket + facet normal 0.000000e+00 0.000000e+00 -1.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 0.000000e+00 + vertex 0.000000e+00 2.500000e+01 0.000000e+00 + vertex 4.000000e+01 2.500000e+01 0.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 0.000000e+00 -1.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 0.000000e+00 + vertex 4.000000e+01 2.500000e+01 0.000000e+00 + vertex 4.000000e+01 0.000000e+00 0.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 0.000000e+00 1.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 4.000000e+00 + vertex 4.000000e+01 0.000000e+00 4.000000e+00 + vertex 4.000000e+01 2.500000e+01 4.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 0.000000e+00 1.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 4.000000e+00 + vertex 4.000000e+01 2.500000e+01 4.000000e+00 + vertex 0.000000e+00 2.500000e+01 4.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 -1.000000e+00 0.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 0.000000e+00 + vertex 4.000000e+01 0.000000e+00 0.000000e+00 + vertex 4.000000e+01 0.000000e+00 4.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 -1.000000e+00 0.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 0.000000e+00 + vertex 4.000000e+01 0.000000e+00 4.000000e+00 + vertex 0.000000e+00 0.000000e+00 4.000000e+00 + endloop + endfacet + facet normal 1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 4.000000e+01 0.000000e+00 0.000000e+00 + vertex 4.000000e+01 2.500000e+01 0.000000e+00 + vertex 4.000000e+01 2.500000e+01 4.000000e+00 + endloop + endfacet + facet normal 1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 4.000000e+01 0.000000e+00 0.000000e+00 + vertex 4.000000e+01 2.500000e+01 4.000000e+00 + vertex 4.000000e+01 0.000000e+00 4.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 1.000000e+00 0.000000e+00 + outer loop + vertex 4.000000e+01 2.500000e+01 0.000000e+00 + vertex 0.000000e+00 2.500000e+01 0.000000e+00 + vertex 0.000000e+00 2.500000e+01 4.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 1.000000e+00 -0.000000e+00 + outer loop + vertex 4.000000e+01 2.500000e+01 0.000000e+00 + vertex 0.000000e+00 2.500000e+01 4.000000e+00 + vertex 4.000000e+01 2.500000e+01 4.000000e+00 + endloop + endfacet + facet normal -1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 0.000000e+00 2.500000e+01 0.000000e+00 + vertex 0.000000e+00 0.000000e+00 0.000000e+00 + vertex 0.000000e+00 0.000000e+00 4.000000e+00 + endloop + endfacet + facet normal -1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 0.000000e+00 2.500000e+01 0.000000e+00 + vertex 0.000000e+00 0.000000e+00 4.000000e+00 + vertex 0.000000e+00 2.500000e+01 4.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 0.000000e+00 -1.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 4.000000e+00 + vertex 0.000000e+00 2.500000e+01 4.000000e+00 + vertex 4.000000e+00 2.500000e+01 4.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 0.000000e+00 -1.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 4.000000e+00 + vertex 4.000000e+00 2.500000e+01 4.000000e+00 + vertex 4.000000e+00 0.000000e+00 4.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 0.000000e+00 1.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 3.000000e+01 + vertex 4.000000e+00 0.000000e+00 3.000000e+01 + vertex 4.000000e+00 2.500000e+01 3.000000e+01 + endloop + endfacet + facet normal 0.000000e+00 0.000000e+00 1.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 3.000000e+01 + vertex 4.000000e+00 2.500000e+01 3.000000e+01 + vertex 0.000000e+00 2.500000e+01 3.000000e+01 + endloop + endfacet + facet normal 0.000000e+00 -1.000000e+00 0.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 4.000000e+00 + vertex 4.000000e+00 0.000000e+00 4.000000e+00 + vertex 4.000000e+00 0.000000e+00 3.000000e+01 + endloop + endfacet + facet normal 0.000000e+00 -1.000000e+00 0.000000e+00 + outer loop + vertex 0.000000e+00 0.000000e+00 4.000000e+00 + vertex 4.000000e+00 0.000000e+00 3.000000e+01 + vertex 0.000000e+00 0.000000e+00 3.000000e+01 + endloop + endfacet + facet normal 1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 4.000000e+00 0.000000e+00 4.000000e+00 + vertex 4.000000e+00 2.500000e+01 4.000000e+00 + vertex 4.000000e+00 2.500000e+01 3.000000e+01 + endloop + endfacet + facet normal 1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 4.000000e+00 0.000000e+00 4.000000e+00 + vertex 4.000000e+00 2.500000e+01 3.000000e+01 + vertex 4.000000e+00 0.000000e+00 3.000000e+01 + endloop + endfacet + facet normal 0.000000e+00 1.000000e+00 0.000000e+00 + outer loop + vertex 4.000000e+00 2.500000e+01 4.000000e+00 + vertex 0.000000e+00 2.500000e+01 4.000000e+00 + vertex 0.000000e+00 2.500000e+01 3.000000e+01 + endloop + endfacet + facet normal 0.000000e+00 1.000000e+00 -0.000000e+00 + outer loop + vertex 4.000000e+00 2.500000e+01 4.000000e+00 + vertex 0.000000e+00 2.500000e+01 3.000000e+01 + vertex 4.000000e+00 2.500000e+01 3.000000e+01 + endloop + endfacet + facet normal -1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 0.000000e+00 2.500000e+01 4.000000e+00 + vertex 0.000000e+00 0.000000e+00 4.000000e+00 + vertex 0.000000e+00 0.000000e+00 3.000000e+01 + endloop + endfacet + facet normal -1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 0.000000e+00 2.500000e+01 4.000000e+00 + vertex 0.000000e+00 0.000000e+00 3.000000e+01 + vertex 0.000000e+00 2.500000e+01 3.000000e+01 + endloop + endfacet + facet normal 0.000000e+00 0.000000e+00 -1.000000e+00 + outer loop + vertex 4.000000e+00 0.000000e+00 4.000000e+00 + vertex 4.000000e+00 2.500000e+01 4.000000e+00 + vertex 6.000000e+00 2.500000e+01 4.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 0.000000e+00 -1.000000e+00 + outer loop + vertex 4.000000e+00 0.000000e+00 4.000000e+00 + vertex 6.000000e+00 2.500000e+01 4.000000e+00 + vertex 6.000000e+00 0.000000e+00 4.000000e+00 + endloop + endfacet + facet normal 0.000000e+00 0.000000e+00 1.000000e+00 + outer loop + vertex 4.000000e+00 0.000000e+00 1.200000e+01 + vertex 6.000000e+00 0.000000e+00 1.200000e+01 + vertex 6.000000e+00 2.500000e+01 1.200000e+01 + endloop + endfacet + facet normal 0.000000e+00 0.000000e+00 1.000000e+00 + outer loop + vertex 4.000000e+00 0.000000e+00 1.200000e+01 + vertex 6.000000e+00 2.500000e+01 1.200000e+01 + vertex 4.000000e+00 2.500000e+01 1.200000e+01 + endloop + endfacet + facet normal 0.000000e+00 -1.000000e+00 0.000000e+00 + outer loop + vertex 4.000000e+00 0.000000e+00 4.000000e+00 + vertex 6.000000e+00 0.000000e+00 4.000000e+00 + vertex 6.000000e+00 0.000000e+00 1.200000e+01 + endloop + endfacet + facet normal 0.000000e+00 -1.000000e+00 0.000000e+00 + outer loop + vertex 4.000000e+00 0.000000e+00 4.000000e+00 + vertex 6.000000e+00 0.000000e+00 1.200000e+01 + vertex 4.000000e+00 0.000000e+00 1.200000e+01 + endloop + endfacet + facet normal 1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 6.000000e+00 0.000000e+00 4.000000e+00 + vertex 6.000000e+00 2.500000e+01 4.000000e+00 + vertex 6.000000e+00 2.500000e+01 1.200000e+01 + endloop + endfacet + facet normal 1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 6.000000e+00 0.000000e+00 4.000000e+00 + vertex 6.000000e+00 2.500000e+01 1.200000e+01 + vertex 6.000000e+00 0.000000e+00 1.200000e+01 + endloop + endfacet + facet normal 0.000000e+00 1.000000e+00 0.000000e+00 + outer loop + vertex 6.000000e+00 2.500000e+01 4.000000e+00 + vertex 4.000000e+00 2.500000e+01 4.000000e+00 + vertex 4.000000e+00 2.500000e+01 1.200000e+01 + endloop + endfacet + facet normal 0.000000e+00 1.000000e+00 -0.000000e+00 + outer loop + vertex 6.000000e+00 2.500000e+01 4.000000e+00 + vertex 4.000000e+00 2.500000e+01 1.200000e+01 + vertex 6.000000e+00 2.500000e+01 1.200000e+01 + endloop + endfacet + facet normal -1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 4.000000e+00 2.500000e+01 4.000000e+00 + vertex 4.000000e+00 0.000000e+00 4.000000e+00 + vertex 4.000000e+00 0.000000e+00 1.200000e+01 + endloop + endfacet + facet normal -1.000000e+00 0.000000e+00 0.000000e+00 + outer loop + vertex 4.000000e+00 2.500000e+01 4.000000e+00 + vertex 4.000000e+00 0.000000e+00 1.200000e+01 + vertex 4.000000e+00 2.500000e+01 1.200000e+01 + endloop + endfacet +endsolid bracket diff --git a/crates/exav-viewer/demo/examples/files/models/gear.stl b/crates/exav-viewer/demo/examples/files/models/gear.stl new file mode 100644 index 0000000..fade395 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/models/gear.stl differ diff --git a/crates/exav-viewer/demo/examples/files/models/icosphere-ascii.ply b/crates/exav-viewer/demo/examples/files/models/icosphere-ascii.ply new file mode 100644 index 0000000..7bacbe7 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/models/icosphere-ascii.ply @@ -0,0 +1,499 @@ +ply +format ascii 1.0 +comment an icosphere, colours from the position +element vertex 162 +property float x +property float y +property float z +property float nx +property float ny +property float nz +property uchar red +property uchar green +property uchar blue +property uchar alpha +element face 320 +property list uchar uint vertex_indices +end_header +-0.52573 0.85065 0.00000 -0.52573 0.85065 0.00000 60 235 127 255 +0.52573 0.85065 0.00000 0.52573 0.85065 0.00000 194 235 127 255 +-0.52573 -0.85065 0.00000 -0.52573 -0.85065 0.00000 60 19 127 255 +0.52573 -0.85065 0.00000 0.52573 -0.85065 0.00000 194 19 127 255 +0.00000 -0.52573 0.85065 0.00000 -0.52573 0.85065 127 60 235 255 +0.00000 0.52573 0.85065 0.00000 0.52573 0.85065 127 194 235 255 +0.00000 -0.52573 -0.85065 0.00000 -0.52573 -0.85065 127 60 19 255 +0.00000 0.52573 -0.85065 0.00000 0.52573 -0.85065 127 194 19 255 +0.85065 0.00000 -0.52573 0.85065 0.00000 -0.52573 235 127 60 255 +0.85065 0.00000 0.52573 0.85065 0.00000 0.52573 235 127 194 255 +-0.85065 0.00000 -0.52573 -0.85065 0.00000 -0.52573 19 127 60 255 +-0.85065 0.00000 0.52573 -0.85065 0.00000 0.52573 19 127 194 255 +-0.80902 0.50000 0.30902 -0.80902 0.50000 0.30902 24 191 166 255 +-0.50000 0.30902 0.80902 -0.50000 0.30902 0.80902 63 166 230 255 +-0.30902 0.80902 0.50000 -0.30902 0.80902 0.50000 88 230 191 255 +0.30902 0.80902 0.50000 0.30902 0.80902 0.50000 166 230 191 255 +0.00000 1.00000 0.00000 0.00000 1.00000 0.00000 127 255 127 255 +0.30902 0.80902 -0.50000 0.30902 0.80902 -0.50000 166 230 63 255 +-0.30902 0.80902 -0.50000 -0.30902 0.80902 -0.50000 88 230 63 255 +-0.50000 0.30902 -0.80902 -0.50000 0.30902 -0.80902 63 166 24 255 +-0.80902 0.50000 -0.30902 -0.80902 0.50000 -0.30902 24 191 88 255 +-1.00000 0.00000 0.00000 -1.00000 0.00000 0.00000 0 127 127 255 +0.50000 0.30902 0.80902 0.50000 0.30902 0.80902 191 166 230 255 +0.80902 0.50000 0.30902 0.80902 0.50000 0.30902 230 191 166 255 +-0.50000 -0.30902 0.80902 -0.50000 -0.30902 0.80902 63 88 230 255 +0.00000 0.00000 1.00000 0.00000 0.00000 1.00000 127 127 255 255 +-0.80902 -0.50000 -0.30902 -0.80902 -0.50000 -0.30902 24 63 88 255 +-0.80902 -0.50000 0.30902 -0.80902 -0.50000 0.30902 24 63 166 255 +0.00000 0.00000 -1.00000 0.00000 0.00000 -1.00000 127 127 0 255 +-0.50000 -0.30902 -0.80902 -0.50000 -0.30902 -0.80902 63 88 24 255 +0.80902 0.50000 -0.30902 0.80902 0.50000 -0.30902 230 191 88 255 +0.50000 0.30902 -0.80902 0.50000 0.30902 -0.80902 191 166 24 255 +0.80902 -0.50000 0.30902 0.80902 -0.50000 0.30902 230 63 166 255 +0.50000 -0.30902 0.80902 0.50000 -0.30902 0.80902 191 88 230 255 +0.30902 -0.80902 0.50000 0.30902 -0.80902 0.50000 166 24 191 255 +-0.30902 -0.80902 0.50000 -0.30902 -0.80902 0.50000 88 24 191 255 +0.00000 -1.00000 0.00000 0.00000 -1.00000 0.00000 127 0 127 255 +-0.30902 -0.80902 -0.50000 -0.30902 -0.80902 -0.50000 88 24 63 255 +0.30902 -0.80902 -0.50000 0.30902 -0.80902 -0.50000 166 24 63 255 +0.50000 -0.30902 -0.80902 0.50000 -0.30902 -0.80902 191 88 24 255 +0.80902 -0.50000 -0.30902 0.80902 -0.50000 -0.30902 230 63 88 255 +1.00000 0.00000 0.00000 1.00000 0.00000 0.00000 255 127 127 255 +-0.69378 0.70205 0.16062 -0.69378 0.70205 0.16062 39 217 147 255 +-0.58779 0.68819 0.42533 -0.58779 0.68819 0.42533 52 215 181 255 +-0.43389 0.86267 0.25989 -0.43389 0.86267 0.25989 72 237 160 255 +-0.70205 0.16062 0.69378 -0.70205 0.16062 0.69378 37 147 215 255 +-0.68819 0.42533 0.58779 -0.68819 0.42533 0.58779 39 181 202 255 +-0.86267 0.25989 0.43389 -0.86267 0.25989 0.43389 17 160 182 255 +-0.16062 0.69378 0.70205 -0.16062 0.69378 0.70205 107 215 217 255 +-0.42533 0.58779 0.68819 -0.42533 0.58779 0.68819 73 202 215 255 +-0.25989 0.43389 0.86267 -0.25989 0.43389 0.86267 94 182 237 255 +-0.16246 0.95106 0.26287 -0.16246 0.95106 0.26287 106 248 161 255 +-0.27327 0.96194 0.00000 -0.27327 0.96194 0.00000 92 250 127 255 +0.16062 0.69378 0.70205 0.16062 0.69378 0.70205 147 215 217 255 +0.00000 0.85065 0.52573 0.00000 0.85065 0.52573 127 235 194 255 +0.27327 0.96194 0.00000 0.27327 0.96194 0.00000 162 250 127 255 +0.16246 0.95106 0.26287 0.16246 0.95106 0.26287 148 248 161 255 +0.43389 0.86267 0.25989 0.43389 0.86267 0.25989 182 237 160 255 +-0.16246 0.95106 -0.26287 -0.16246 0.95106 -0.26287 106 248 93 255 +-0.43389 0.86267 -0.25989 -0.43389 0.86267 -0.25989 72 237 94 255 +0.43389 0.86267 -0.25989 0.43389 0.86267 -0.25989 182 237 94 255 +0.16246 0.95106 -0.26287 0.16246 0.95106 -0.26287 148 248 93 255 +-0.16062 0.69378 -0.70205 -0.16062 0.69378 -0.70205 107 215 37 255 +0.00000 0.85065 -0.52573 0.00000 0.85065 -0.52573 127 235 60 255 +0.16062 0.69378 -0.70205 0.16062 0.69378 -0.70205 147 215 37 255 +-0.58779 0.68819 -0.42533 -0.58779 0.68819 -0.42533 52 215 73 255 +-0.69378 0.70205 -0.16062 -0.69378 0.70205 -0.16062 39 217 107 255 +-0.25989 0.43389 -0.86267 -0.25989 0.43389 -0.86267 94 182 17 255 +-0.42533 0.58779 -0.68819 -0.42533 0.58779 -0.68819 73 202 39 255 +-0.86267 0.25989 -0.43389 -0.86267 0.25989 -0.43389 17 160 72 255 +-0.68819 0.42533 -0.58779 -0.68819 0.42533 -0.58779 39 181 52 255 +-0.70205 0.16062 -0.69378 -0.70205 0.16062 -0.69378 37 147 39 255 +-0.85065 0.52573 0.00000 -0.85065 0.52573 0.00000 19 194 127 255 +-0.96194 0.00000 -0.27327 -0.96194 0.00000 -0.27327 4 127 92 255 +-0.95106 0.26287 -0.16246 -0.95106 0.26287 -0.16246 6 161 106 255 +-0.95106 0.26287 0.16246 -0.95106 0.26287 0.16246 6 161 148 255 +-0.96194 0.00000 0.27327 -0.96194 0.00000 0.27327 4 127 162 255 +0.58779 0.68819 0.42533 0.58779 0.68819 0.42533 202 215 181 255 +0.69378 0.70205 0.16062 0.69378 0.70205 0.16062 215 217 147 255 +0.25989 0.43389 0.86267 0.25989 0.43389 0.86267 160 182 237 255 +0.42533 0.58779 0.68819 0.42533 0.58779 0.68819 181 202 215 255 +0.86267 0.25989 0.43389 0.86267 0.25989 0.43389 237 160 182 255 +0.68819 0.42533 0.58779 0.68819 0.42533 0.58779 215 181 202 255 +0.70205 0.16062 0.69378 0.70205 0.16062 0.69378 217 147 215 255 +-0.26287 0.16246 0.95106 -0.26287 0.16246 0.95106 93 148 248 255 +0.00000 0.27327 0.96194 0.00000 0.27327 0.96194 127 162 250 255 +-0.70205 -0.16062 0.69378 -0.70205 -0.16062 0.69378 37 107 215 255 +-0.52573 0.00000 0.85065 -0.52573 0.00000 0.85065 60 127 235 255 +0.00000 -0.27327 0.96194 0.00000 -0.27327 0.96194 127 92 250 255 +-0.26287 -0.16246 0.95106 -0.26287 -0.16246 0.95106 93 106 248 255 +-0.25989 -0.43389 0.86267 -0.25989 -0.43389 0.86267 94 72 237 255 +-0.95106 -0.26287 0.16246 -0.95106 -0.26287 0.16246 6 93 148 255 +-0.86267 -0.25989 0.43389 -0.86267 -0.25989 0.43389 17 94 182 255 +-0.86267 -0.25989 -0.43389 -0.86267 -0.25989 -0.43389 17 94 72 255 +-0.95106 -0.26287 -0.16246 -0.95106 -0.26287 -0.16246 6 93 106 255 +-0.69378 -0.70205 0.16062 -0.69378 -0.70205 0.16062 39 37 147 255 +-0.85065 -0.52573 0.00000 -0.85065 -0.52573 0.00000 19 60 127 255 +-0.69378 -0.70205 -0.16062 -0.69378 -0.70205 -0.16062 39 37 107 255 +-0.52573 0.00000 -0.85065 -0.52573 0.00000 -0.85065 60 127 19 255 +-0.70205 -0.16062 -0.69378 -0.70205 -0.16062 -0.69378 37 107 39 255 +0.00000 0.27327 -0.96194 0.00000 0.27327 -0.96194 127 162 4 255 +-0.26287 0.16246 -0.95106 -0.26287 0.16246 -0.95106 93 148 6 255 +-0.25989 -0.43389 -0.86267 -0.25989 -0.43389 -0.86267 94 72 17 255 +-0.26287 -0.16246 -0.95106 -0.26287 -0.16246 -0.95106 93 106 6 255 +0.00000 -0.27327 -0.96194 0.00000 -0.27327 -0.96194 127 92 4 255 +0.42533 0.58779 -0.68819 0.42533 0.58779 -0.68819 181 202 39 255 +0.25989 0.43389 -0.86267 0.25989 0.43389 -0.86267 160 182 17 255 +0.69378 0.70205 -0.16062 0.69378 0.70205 -0.16062 215 217 107 255 +0.58779 0.68819 -0.42533 0.58779 0.68819 -0.42533 202 215 73 255 +0.70205 0.16062 -0.69378 0.70205 0.16062 -0.69378 217 147 39 255 +0.68819 0.42533 -0.58779 0.68819 0.42533 -0.58779 215 181 52 255 +0.86267 0.25989 -0.43389 0.86267 0.25989 -0.43389 237 160 72 255 +0.69378 -0.70205 0.16062 0.69378 -0.70205 0.16062 215 37 147 255 +0.58779 -0.68819 0.42533 0.58779 -0.68819 0.42533 202 39 181 255 +0.43389 -0.86267 0.25989 0.43389 -0.86267 0.25989 182 17 160 255 +0.70205 -0.16062 0.69378 0.70205 -0.16062 0.69378 217 107 215 255 +0.68819 -0.42533 0.58779 0.68819 -0.42533 0.58779 215 73 202 255 +0.86267 -0.25989 0.43389 0.86267 -0.25989 0.43389 237 94 182 255 +0.16062 -0.69378 0.70205 0.16062 -0.69378 0.70205 147 39 217 255 +0.42533 -0.58779 0.68819 0.42533 -0.58779 0.68819 181 52 215 255 +0.25989 -0.43389 0.86267 0.25989 -0.43389 0.86267 160 72 237 255 +0.16246 -0.95106 0.26287 0.16246 -0.95106 0.26287 148 6 161 255 +0.27327 -0.96194 0.00000 0.27327 -0.96194 0.00000 162 4 127 255 +-0.16062 -0.69378 0.70205 -0.16062 -0.69378 0.70205 107 39 217 255 +0.00000 -0.85065 0.52573 0.00000 -0.85065 0.52573 127 19 194 255 +-0.27327 -0.96194 0.00000 -0.27327 -0.96194 0.00000 92 4 127 255 +-0.16246 -0.95106 0.26287 -0.16246 -0.95106 0.26287 106 6 161 255 +-0.43389 -0.86267 0.25989 -0.43389 -0.86267 0.25989 72 17 160 255 +0.16246 -0.95106 -0.26287 0.16246 -0.95106 -0.26287 148 6 93 255 +0.43389 -0.86267 -0.25989 0.43389 -0.86267 -0.25989 182 17 94 255 +-0.43389 -0.86267 -0.25989 -0.43389 -0.86267 -0.25989 72 17 94 255 +-0.16246 -0.95106 -0.26287 -0.16246 -0.95106 -0.26287 106 6 93 255 +0.16062 -0.69378 -0.70205 0.16062 -0.69378 -0.70205 147 39 37 255 +0.00000 -0.85065 -0.52573 0.00000 -0.85065 -0.52573 127 19 60 255 +-0.16062 -0.69378 -0.70205 -0.16062 -0.69378 -0.70205 107 39 37 255 +0.58779 -0.68819 -0.42533 0.58779 -0.68819 -0.42533 202 39 73 255 +0.69378 -0.70205 -0.16062 0.69378 -0.70205 -0.16062 215 37 107 255 +0.25989 -0.43389 -0.86267 0.25989 -0.43389 -0.86267 160 72 17 255 +0.42533 -0.58779 -0.68819 0.42533 -0.58779 -0.68819 181 52 39 255 +0.86267 -0.25989 -0.43389 0.86267 -0.25989 -0.43389 237 94 72 255 +0.68819 -0.42533 -0.58779 0.68819 -0.42533 -0.58779 215 73 52 255 +0.70205 -0.16062 -0.69378 0.70205 -0.16062 -0.69378 217 107 39 255 +0.85065 -0.52573 0.00000 0.85065 -0.52573 0.00000 235 60 127 255 +0.96194 0.00000 -0.27327 0.96194 0.00000 -0.27327 250 127 92 255 +0.95106 -0.26287 -0.16246 0.95106 -0.26287 -0.16246 248 93 106 255 +0.95106 -0.26287 0.16246 0.95106 -0.26287 0.16246 248 93 148 255 +0.96194 0.00000 0.27327 0.96194 0.00000 0.27327 250 127 162 255 +0.26287 -0.16246 0.95106 0.26287 -0.16246 0.95106 161 106 248 255 +0.52573 0.00000 0.85065 0.52573 0.00000 0.85065 194 127 235 255 +0.26287 0.16246 0.95106 0.26287 0.16246 0.95106 161 148 248 255 +-0.58779 -0.68819 0.42533 -0.58779 -0.68819 0.42533 52 39 181 255 +-0.42533 -0.58779 0.68819 -0.42533 -0.58779 0.68819 73 52 215 255 +-0.68819 -0.42533 0.58779 -0.68819 -0.42533 0.58779 39 73 202 255 +-0.42533 -0.58779 -0.68819 -0.42533 -0.58779 -0.68819 73 52 39 255 +-0.58779 -0.68819 -0.42533 -0.58779 -0.68819 -0.42533 52 39 73 255 +-0.68819 -0.42533 -0.58779 -0.68819 -0.42533 -0.58779 39 73 52 255 +0.52573 0.00000 -0.85065 0.52573 0.00000 -0.85065 194 127 19 255 +0.26287 -0.16246 -0.95106 0.26287 -0.16246 -0.95106 161 106 6 255 +0.26287 0.16246 -0.95106 0.26287 0.16246 -0.95106 161 148 6 255 +0.95106 0.26287 0.16246 0.95106 0.26287 0.16246 248 161 148 255 +0.95106 0.26287 -0.16246 0.95106 0.26287 -0.16246 248 161 106 255 +0.85065 0.52573 0.00000 0.85065 0.52573 0.00000 235 194 127 255 +3 0 42 44 +3 12 43 42 +3 14 44 43 +3 42 43 44 +3 11 45 47 +3 13 46 45 +3 12 47 46 +3 45 46 47 +3 5 48 50 +3 14 49 48 +3 13 50 49 +3 48 49 50 +3 12 46 43 +3 13 49 46 +3 14 43 49 +3 46 49 43 +3 0 44 52 +3 14 51 44 +3 16 52 51 +3 44 51 52 +3 5 53 48 +3 15 54 53 +3 14 48 54 +3 53 54 48 +3 1 55 57 +3 16 56 55 +3 15 57 56 +3 55 56 57 +3 14 54 51 +3 15 56 54 +3 16 51 56 +3 54 56 51 +3 0 52 59 +3 16 58 52 +3 18 59 58 +3 52 58 59 +3 1 60 55 +3 17 61 60 +3 16 55 61 +3 60 61 55 +3 7 62 64 +3 18 63 62 +3 17 64 63 +3 62 63 64 +3 16 61 58 +3 17 63 61 +3 18 58 63 +3 61 63 58 +3 0 59 66 +3 18 65 59 +3 20 66 65 +3 59 65 66 +3 7 67 62 +3 19 68 67 +3 18 62 68 +3 67 68 62 +3 10 69 71 +3 20 70 69 +3 19 71 70 +3 69 70 71 +3 18 68 65 +3 19 70 68 +3 20 65 70 +3 68 70 65 +3 0 66 42 +3 20 72 66 +3 12 42 72 +3 66 72 42 +3 10 73 69 +3 21 74 73 +3 20 69 74 +3 73 74 69 +3 11 47 76 +3 12 75 47 +3 21 76 75 +3 47 75 76 +3 20 74 72 +3 21 75 74 +3 12 72 75 +3 74 75 72 +3 1 57 78 +3 15 77 57 +3 23 78 77 +3 57 77 78 +3 5 79 53 +3 22 80 79 +3 15 53 80 +3 79 80 53 +3 9 81 83 +3 23 82 81 +3 22 83 82 +3 81 82 83 +3 15 80 77 +3 22 82 80 +3 23 77 82 +3 80 82 77 +3 5 50 85 +3 13 84 50 +3 25 85 84 +3 50 84 85 +3 11 86 45 +3 24 87 86 +3 13 45 87 +3 86 87 45 +3 4 88 90 +3 25 89 88 +3 24 90 89 +3 88 89 90 +3 13 87 84 +3 24 89 87 +3 25 84 89 +3 87 89 84 +3 11 76 92 +3 21 91 76 +3 27 92 91 +3 76 91 92 +3 10 93 73 +3 26 94 93 +3 21 73 94 +3 93 94 73 +3 2 95 97 +3 27 96 95 +3 26 97 96 +3 95 96 97 +3 21 94 91 +3 26 96 94 +3 27 91 96 +3 94 96 91 +3 10 71 99 +3 19 98 71 +3 29 99 98 +3 71 98 99 +3 7 100 67 +3 28 101 100 +3 19 67 101 +3 100 101 67 +3 6 102 104 +3 29 103 102 +3 28 104 103 +3 102 103 104 +3 19 101 98 +3 28 103 101 +3 29 98 103 +3 101 103 98 +3 7 64 106 +3 17 105 64 +3 31 106 105 +3 64 105 106 +3 1 107 60 +3 30 108 107 +3 17 60 108 +3 107 108 60 +3 8 109 111 +3 31 110 109 +3 30 111 110 +3 109 110 111 +3 17 108 105 +3 30 110 108 +3 31 105 110 +3 108 110 105 +3 3 112 114 +3 32 113 112 +3 34 114 113 +3 112 113 114 +3 9 115 117 +3 33 116 115 +3 32 117 116 +3 115 116 117 +3 4 118 120 +3 34 119 118 +3 33 120 119 +3 118 119 120 +3 32 116 113 +3 33 119 116 +3 34 113 119 +3 116 119 113 +3 3 114 122 +3 34 121 114 +3 36 122 121 +3 114 121 122 +3 4 123 118 +3 35 124 123 +3 34 118 124 +3 123 124 118 +3 2 125 127 +3 36 126 125 +3 35 127 126 +3 125 126 127 +3 34 124 121 +3 35 126 124 +3 36 121 126 +3 124 126 121 +3 3 122 129 +3 36 128 122 +3 38 129 128 +3 122 128 129 +3 2 130 125 +3 37 131 130 +3 36 125 131 +3 130 131 125 +3 6 132 134 +3 38 133 132 +3 37 134 133 +3 132 133 134 +3 36 131 128 +3 37 133 131 +3 38 128 133 +3 131 133 128 +3 3 129 136 +3 38 135 129 +3 40 136 135 +3 129 135 136 +3 6 137 132 +3 39 138 137 +3 38 132 138 +3 137 138 132 +3 8 139 141 +3 40 140 139 +3 39 141 140 +3 139 140 141 +3 38 138 135 +3 39 140 138 +3 40 135 140 +3 138 140 135 +3 3 136 112 +3 40 142 136 +3 32 112 142 +3 136 142 112 +3 8 143 139 +3 41 144 143 +3 40 139 144 +3 143 144 139 +3 9 117 146 +3 32 145 117 +3 41 146 145 +3 117 145 146 +3 40 144 142 +3 41 145 144 +3 32 142 145 +3 144 145 142 +3 4 120 88 +3 33 147 120 +3 25 88 147 +3 120 147 88 +3 9 83 115 +3 22 148 83 +3 33 115 148 +3 83 148 115 +3 5 85 79 +3 25 149 85 +3 22 79 149 +3 85 149 79 +3 33 148 147 +3 22 149 148 +3 25 147 149 +3 148 149 147 +3 2 127 95 +3 35 150 127 +3 27 95 150 +3 127 150 95 +3 4 90 123 +3 24 151 90 +3 35 123 151 +3 90 151 123 +3 11 92 86 +3 27 152 92 +3 24 86 152 +3 92 152 86 +3 35 151 150 +3 24 152 151 +3 27 150 152 +3 151 152 150 +3 6 134 102 +3 37 153 134 +3 29 102 153 +3 134 153 102 +3 2 97 130 +3 26 154 97 +3 37 130 154 +3 97 154 130 +3 10 99 93 +3 29 155 99 +3 26 93 155 +3 99 155 93 +3 37 154 153 +3 26 155 154 +3 29 153 155 +3 154 155 153 +3 8 141 109 +3 39 156 141 +3 31 109 156 +3 141 156 109 +3 6 104 137 +3 28 157 104 +3 39 137 157 +3 104 157 137 +3 7 106 100 +3 31 158 106 +3 28 100 158 +3 106 158 100 +3 39 157 156 +3 28 158 157 +3 31 156 158 +3 157 158 156 +3 9 146 81 +3 41 159 146 +3 23 81 159 +3 146 159 81 +3 8 111 143 +3 30 160 111 +3 41 143 160 +3 111 160 143 +3 1 78 107 +3 23 161 78 +3 30 107 161 +3 78 161 107 +3 41 160 159 +3 30 161 160 +3 23 159 161 +3 160 161 159 diff --git a/crates/exav-viewer/demo/examples/files/models/knot.obj b/crates/exav-viewer/demo/examples/files/models/knot.obj new file mode 100644 index 0000000..f2f5f66 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/models/knot.obj @@ -0,0 +1,2944 @@ +# A trefoil knot with a colour per vertex, and a base: two objects. +o knot +v 3.3200 0.0006 0.0000 1.000 0.000 0.000 +v 3.2587 0.0846 -0.1682 1.000 0.000 0.000 +v 3.0986 0.1363 -0.2722 1.000 0.000 0.000 +v 2.9009 0.1359 -0.2722 1.000 0.000 0.000 +v 2.7410 0.0837 -0.1682 1.000 0.000 0.000 +v 2.6800 -0.0006 -0.0000 1.000 0.000 0.000 +v 2.7413 -0.0846 0.1682 1.000 0.000 0.000 +v 2.9014 -0.1363 0.2722 1.000 0.000 0.000 +v 3.0991 -0.1359 0.2722 1.000 0.000 0.000 +v 3.2590 -0.0837 0.1682 1.000 0.000 0.000 +v 3.2596 0.4923 0.2079 1.000 0.067 0.000 +v 3.1801 0.5577 0.0390 1.000 0.067 0.000 +v 3.0125 0.5684 -0.0654 1.000 0.067 0.000 +v 2.8207 0.5203 -0.0654 1.000 0.067 0.000 +v 2.6779 0.4318 0.0390 1.000 0.067 0.000 +v 2.6388 0.3366 0.2079 1.000 0.067 0.000 +v 2.7182 0.2713 0.3768 1.000 0.067 0.000 +v 2.8858 0.2606 0.4812 1.000 0.067 0.000 +v 3.0776 0.3087 0.4812 1.000 0.067 0.000 +v 3.2204 0.3972 0.3768 1.000 0.067 0.000 +v 3.0834 0.9529 0.4067 1.000 0.133 0.000 +v 2.9926 0.9938 0.2359 1.000 0.133 0.000 +v 2.8285 0.9618 0.1303 1.000 0.133 0.000 +v 2.6537 0.8692 0.1303 1.000 0.133 0.000 +v 2.5351 0.7513 0.2359 1.000 0.133 0.000 +v 2.5179 0.6532 0.4067 1.000 0.133 0.000 +v 2.6088 0.6124 0.5776 1.000 0.133 0.000 +v 2.7729 0.6444 0.6832 1.000 0.133 0.000 +v 2.9476 0.7370 0.6832 1.000 0.133 0.000 +v 3.0662 0.8549 0.5776 1.000 0.133 0.000 +v 2.8057 1.3547 0.5878 1.000 0.200 0.000 +v 2.7125 1.3678 0.4139 1.000 0.200 0.000 +v 2.5634 1.2948 0.3064 1.000 0.200 0.000 +v 2.4153 1.1637 0.3064 1.000 0.200 0.000 +v 2.3249 1.0245 0.4139 1.000 0.200 0.000 +v 2.3266 0.9304 0.5878 1.000 0.200 0.000 +v 2.4198 0.9173 0.7617 1.000 0.200 0.000 +v 2.5689 0.9902 0.8692 1.000 0.200 0.000 +v 2.7170 1.1213 0.8692 1.000 0.200 0.000 +v 2.8075 1.2605 0.7617 1.000 0.200 0.000 +v 2.4482 1.6758 0.7431 1.000 0.267 0.000 +v 2.3626 1.6614 0.5654 1.000 0.267 0.000 +v 2.2392 1.5527 0.4556 1.000 0.267 0.000 +v 2.1251 1.3911 0.4556 1.000 0.267 0.000 +v 2.0639 1.2385 0.5654 1.000 0.267 0.000 +v 2.0789 1.1531 0.7431 1.000 0.267 0.000 +v 2.1645 1.1675 0.9209 1.000 0.267 0.000 +v 2.2879 1.2762 1.0307 1.000 0.267 0.000 +v 2.4020 1.4377 1.0307 1.000 0.267 0.000 +v 2.4632 1.5903 0.9209 1.000 0.267 0.000 +v 2.0373 1.9027 0.8660 1.000 0.333 0.000 +v 1.9694 1.8647 0.6842 1.000 0.333 0.000 +v 1.8807 1.7282 0.5719 1.000 0.333 0.000 +v 1.8051 1.5454 0.5719 1.000 0.333 0.000 +v 1.7716 1.3861 0.6842 1.000 0.333 0.000 +v 1.7929 1.3112 0.8660 1.000 0.333 0.000 +v 1.8609 1.3493 1.0478 1.000 0.333 0.000 +v 1.9495 1.4857 1.1602 1.000 0.333 0.000 +v 2.0251 1.6685 1.1602 1.000 0.333 0.000 +v 2.0586 1.8278 1.0478 1.000 0.333 0.000 +v 1.6017 2.0309 0.9511 1.000 0.400 0.000 +v 1.5599 1.9763 0.7656 1.000 0.400 0.000 +v 1.5123 1.8223 0.6510 1.000 0.400 0.000 +v 1.4773 1.6277 0.6510 1.000 0.400 0.000 +v 1.4681 1.4667 0.7656 1.000 0.400 0.000 +v 1.4883 1.4010 0.9511 1.000 0.400 0.000 +v 1.5302 1.4556 1.1365 1.000 0.400 0.000 +v 1.5777 1.6096 1.2511 1.000 0.400 0.000 +v 1.6128 1.8042 1.2511 1.000 0.400 0.000 +v 1.6219 1.9651 1.1365 1.000 0.400 0.000 +v 1.1690 2.0646 0.9945 1.000 0.467 0.000 +v 1.1592 2.0033 0.8068 1.000 0.467 0.000 +v 1.1562 1.8431 0.6907 1.000 0.467 0.000 +v 1.1611 1.6454 0.6907 1.000 0.467 0.000 +v 1.1720 1.4856 0.8068 1.000 0.467 0.000 +v 1.1847 1.4248 0.9945 1.000 0.467 0.000 +v 1.1945 1.4862 1.1823 1.000 0.467 0.000 +v 1.1975 1.6463 1.2983 1.000 0.467 0.000 +v 1.1926 1.8440 1.2983 1.000 0.467 0.000 +v 1.1817 2.0038 1.1823 1.000 0.467 0.000 +v 0.7629 2.0163 0.9945 1.000 0.533 0.000 +v 0.7880 1.9592 0.8068 1.000 0.533 0.000 +v 0.8295 1.8045 0.6908 1.000 0.533 0.000 +v 0.8715 1.6113 0.6908 1.000 0.533 0.000 +v 0.8981 1.4533 0.8068 1.000 0.533 0.000 +v 0.8990 1.3910 0.9945 1.000 0.533 0.000 +v 0.8739 1.4480 1.1822 1.000 0.533 0.000 +v 0.8324 1.6028 1.2982 1.000 0.533 0.000 +v 0.7903 1.7960 1.2982 1.000 0.533 0.000 +v 0.7638 1.9540 1.1822 1.000 0.533 0.000 +v 0.4015 1.9045 0.9511 1.000 0.600 0.000 +v 0.4605 1.8625 0.7670 1.000 0.600 0.000 +v 0.5432 1.7235 0.6533 1.000 0.600 0.000 +v 0.6180 1.5404 0.6533 1.000 0.600 0.000 +v 0.6563 1.3832 0.7670 1.000 0.600 0.000 +v 0.6436 1.3120 0.9511 1.000 0.600 0.000 +v 0.5846 1.3539 1.1351 1.000 0.600 0.000 +v 0.5019 1.4930 1.2489 1.000 0.600 0.000 +v 0.4271 1.6760 1.2489 1.000 0.600 0.000 +v 0.3888 1.8332 1.1351 1.000 0.600 0.000 +v 0.0959 1.7516 0.8660 1.000 0.667 0.000 +v 0.1845 1.7335 0.6902 1.000 0.667 0.000 +v 0.3022 1.6175 0.5815 1.000 0.667 0.000 +v 0.4039 1.4479 0.5815 1.000 0.667 0.000 +v 0.4508 1.2895 0.6902 1.000 0.667 0.000 +v 0.4250 1.2028 0.8660 1.000 0.667 0.000 +v 0.3364 1.2209 1.0419 1.000 0.667 0.000 +v 0.2188 1.3369 1.1506 1.000 0.667 0.000 +v 0.1171 1.5065 1.1506 1.000 0.667 0.000 +v 0.0701 1.6649 1.0419 1.000 0.667 0.000 +v -0.1505 1.5823 0.7431 1.000 0.733 0.000 +v -0.0386 1.5922 0.5804 1.000 0.733 0.000 +v 0.1059 1.5019 0.4799 1.000 0.733 0.000 +v 0.2276 1.3461 0.4799 1.000 0.733 0.000 +v 0.2801 1.1841 0.5804 1.000 0.733 0.000 +v 0.2434 1.0779 0.7431 1.000 0.733 0.000 +v 0.1315 1.0680 0.9059 1.000 0.733 0.000 +v -0.0130 1.1582 1.0064 1.000 0.733 0.000 +v -0.1347 1.3140 1.0064 1.000 0.733 0.000 +v -0.1873 1.4760 0.9059 1.000 0.733 0.000 +v -0.3408 1.4203 0.5878 1.000 0.800 0.000 +v -0.2116 1.4559 0.4424 1.000 0.800 0.000 +v -0.0491 1.3879 0.3525 1.000 0.800 0.000 +v 0.0846 1.2421 0.3525 1.000 0.800 0.000 +v 0.1385 1.0744 0.4424 1.000 0.800 0.000 +v 0.0918 0.9487 0.5878 1.000 0.800 0.000 +v -0.0374 0.9130 0.7332 1.000 0.800 0.000 +v -0.1999 0.9811 0.8230 1.000 0.800 0.000 +v -0.3336 1.1268 0.8230 1.000 0.800 0.000 +v -0.3874 1.2946 0.7332 1.000 0.800 0.000 +v -0.4823 1.2870 0.4067 1.000 0.863 0.000 +v -0.3390 1.3381 0.2803 1.000 0.863 0.000 +v -0.1667 1.2807 0.2022 1.000 0.863 0.000 +v -0.0310 1.1368 0.2022 1.000 0.863 0.000 +v 0.0161 0.9613 0.2803 1.000 0.863 0.000 +v -0.0434 0.8213 0.4067 1.000 0.863 0.000 +v -0.1866 0.7703 0.5331 1.000 0.863 0.000 +v -0.3590 0.8277 0.6113 1.000 0.863 0.000 +v -0.4947 0.9716 0.6113 1.000 0.863 0.000 +v -0.5418 1.1470 0.5331 1.000 0.863 0.000 +v -0.5838 1.1964 0.2079 1.000 0.933 0.000 +v -0.4271 1.2444 0.0973 1.000 0.933 0.000 +v -0.2534 1.1790 0.0289 1.000 0.933 0.000 +v -0.1292 1.0251 0.0289 1.000 0.933 0.000 +v -0.1018 0.8416 0.0973 1.000 0.933 0.000 +v -0.1818 0.6985 0.2079 1.000 0.933 0.000 +v -0.3385 0.6505 0.3185 1.000 0.933 0.000 +v -0.5122 0.7159 0.3869 1.000 0.933 0.000 +v -0.6364 0.8697 0.3869 1.000 0.933 0.000 +v -0.6638 1.0533 0.3185 1.000 0.933 0.000 +v -0.6597 1.1434 0.0000 1.000 1.000 0.000 +v -0.4935 1.1685 -0.1043 1.000 1.000 0.000 +v -0.3299 1.0781 -0.1688 1.000 1.000 0.000 +v -0.2312 0.9067 -0.1688 1.000 1.000 0.000 +v -0.2352 0.7197 -0.1043 1.000 1.000 0.000 +v -0.3403 0.5887 0.0000 1.000 1.000 0.000 +v -0.5065 0.5636 0.1043 1.000 1.000 0.000 +v -0.6701 0.6540 0.1688 1.000 1.000 0.000 +v -0.7688 0.8254 0.1688 1.000 1.000 0.000 +v -0.7648 1.0123 0.1043 1.000 1.000 0.000 +v -0.7437 1.1040 -0.2079 0.933 1.000 0.000 +v -0.5799 1.1014 -0.3187 0.933 1.000 0.000 +v -0.4349 0.9856 -0.3872 0.933 1.000 0.000 +v -0.3641 0.8009 -0.3872 0.933 1.000 0.000 +v -0.3945 0.6179 -0.3187 0.933 1.000 0.000 +v -0.5146 0.5064 -0.2079 0.933 1.000 0.000 +v -0.6783 0.5091 -0.0971 0.933 1.000 0.000 +v -0.8233 0.6249 -0.0286 0.933 1.000 0.000 +v -0.8941 0.8095 -0.0286 0.933 1.000 0.000 +v -0.8637 0.9925 -0.0971 0.933 1.000 0.000 +v -0.8733 1.0613 -0.4067 0.867 1.000 0.000 +v -0.7226 1.0426 -0.5334 0.867 1.000 0.000 +v -0.5944 0.9140 -0.6117 0.867 1.000 0.000 +v -0.5376 0.7245 -0.6117 0.867 1.000 0.000 +v -0.5741 0.5466 -0.5334 0.867 1.000 0.000 +v -0.6897 0.4482 -0.4067 0.867 1.000 0.000 +v -0.8405 0.4668 -0.2801 0.867 1.000 0.000 +v -0.9687 0.5954 -0.2018 0.867 1.000 0.000 +v -1.0254 0.7849 -0.2018 0.867 1.000 0.000 +v -0.9890 0.9628 -0.2801 0.867 1.000 0.000 +v -1.0598 1.0052 -0.5878 0.796 1.000 0.000 +v -0.9279 0.9827 -0.7334 0.796 1.000 0.000 +v -0.8096 0.8523 -0.8235 0.796 1.000 0.000 +v -0.7501 0.6637 -0.8235 0.796 1.000 0.000 +v -0.7721 0.4890 -0.7334 0.796 1.000 0.000 +v -0.8673 0.3949 -0.5878 0.796 1.000 0.000 +v -0.9991 0.4173 -0.4421 0.796 1.000 0.000 +v -1.1174 0.5478 -0.3521 0.796 1.000 0.000 +v -1.1769 0.7364 -0.3521 0.796 1.000 0.000 +v -1.1549 0.9111 -0.4421 0.796 1.000 0.000 +v -1.2954 0.9213 -0.7431 0.733 1.000 0.000 +v -1.1854 0.9000 -0.9061 0.733 1.000 0.000 +v -1.0714 0.7736 -1.0068 0.733 1.000 0.000 +v -0.9970 0.5904 -1.0068 0.733 1.000 0.000 +v -0.9907 0.4203 -0.9061 0.733 1.000 0.000 +v -1.0547 0.3283 -0.7431 0.733 1.000 0.000 +v -1.1648 0.3496 -0.5802 0.733 1.000 0.000 +v -1.2787 0.4760 -0.4795 0.733 1.000 0.000 +v -1.3531 0.6593 -0.4795 0.733 1.000 0.000 +v -1.3595 0.8293 -0.5802 0.733 1.000 0.000 +v -1.5655 0.7925 -0.8660 0.667 1.000 0.000 +v -1.4778 0.7714 -1.0420 0.667 1.000 0.000 +v -1.3641 0.6517 -1.1508 0.667 1.000 0.000 +v -1.2677 0.4790 -1.1508 0.667 1.000 0.000 +v -1.2255 0.3193 -1.0420 0.667 1.000 0.000 +v -1.2536 0.2336 -0.8660 0.667 1.000 0.000 +v -1.3413 0.2547 -0.6900 0.667 1.000 0.000 +v -1.4550 0.3744 -0.5812 0.667 1.000 0.000 +v -1.5514 0.5471 -0.5812 0.667 1.000 0.000 +v -1.5936 0.7068 -0.6900 0.667 1.000 0.000 +v -1.8507 0.6040 -0.9511 0.600 1.000 0.000 +v -1.7828 0.5794 -1.1352 0.600 1.000 0.000 +v -1.6658 0.4677 -1.2490 0.600 1.000 0.000 +v -1.5443 0.3117 -1.2490 0.600 1.000 0.000 +v -1.4647 0.1709 -1.1352 0.600 1.000 0.000 +v -1.4574 0.0991 -0.9511 0.600 1.000 0.000 +v -1.5252 0.1238 -0.7669 0.600 1.000 0.000 +v -1.6423 0.2354 -0.6531 0.600 1.000 0.000 +v -1.7638 0.3914 -0.6531 0.600 1.000 0.000 +v -1.8434 0.5322 -0.7669 0.600 1.000 0.000 +v -2.1282 0.3469 -0.9945 0.533 1.000 0.000 +v -2.0748 0.3148 -1.1822 0.533 1.000 0.000 +v -1.9511 0.2130 -1.2982 0.533 1.000 0.000 +v -1.8045 0.0803 -1.2982 0.533 1.000 0.000 +v -1.6908 -0.0325 -1.1822 0.533 1.000 0.000 +v -1.6535 -0.0824 -0.9945 0.533 1.000 0.000 +v -1.7069 -0.0504 -0.8068 0.533 1.000 0.000 +v -1.8306 0.0515 -0.6908 0.533 1.000 0.000 +v -1.9772 0.1841 -0.6908 0.533 1.000 0.000 +v -2.0909 0.2970 -0.8068 0.533 1.000 0.000 +v -2.3730 0.0192 -0.9945 0.467 1.000 0.000 +v -2.3267 -0.0224 -1.1823 0.467 1.000 0.000 +v -2.1937 -0.1115 -1.2983 0.467 1.000 0.000 +v -2.0246 -0.2141 -1.2983 0.467 1.000 0.000 +v -1.8841 -0.2910 -1.1823 0.467 1.000 0.000 +v -1.8258 -0.3128 -0.9945 0.467 1.000 0.000 +v -1.8721 -0.2712 -0.8068 0.467 1.000 0.000 +v -2.0052 -0.1821 -0.6908 0.467 1.000 0.000 +v -2.1742 -0.0795 -0.6908 0.467 1.000 0.000 +v -2.3147 -0.0026 -0.8068 0.467 1.000 0.000 +v -2.5600 -0.3726 -0.9511 0.396 1.000 0.000 +v -2.5131 -0.4231 -1.1364 0.396 1.000 0.000 +v -2.3690 -0.4953 -1.2510 0.396 1.000 0.000 +v -2.1827 -0.5617 -1.2510 0.396 1.000 0.000 +v -2.0254 -0.5970 -1.1364 0.396 1.000 0.000 +v -1.9571 -0.5875 -0.9511 0.396 1.000 0.000 +v -2.0040 -0.5371 -0.7657 0.396 1.000 0.000 +v -2.1481 -0.4648 -0.6511 0.396 1.000 0.000 +v -2.3344 -0.3984 -0.6511 0.396 1.000 0.000 +v -2.4917 -0.3632 -0.7657 0.396 1.000 0.000 +v -2.6666 -0.8140 -0.8660 0.329 1.000 0.000 +v -2.6122 -0.8699 -1.0478 0.329 1.000 0.000 +v -2.4574 -0.9202 -1.1601 0.329 1.000 0.000 +v -2.2612 -0.9455 -1.1601 0.329 1.000 0.000 +v -2.0987 -0.9363 -1.0478 0.329 1.000 0.000 +v -2.0319 -0.8961 -0.8660 0.329 1.000 0.000 +v -2.0863 -0.8402 -0.6843 0.329 1.000 0.000 +v -2.2411 -0.7899 -0.5720 0.329 1.000 0.000 +v -2.4372 -0.7646 -0.5720 0.329 1.000 0.000 +v -2.5998 -0.7738 -0.6843 0.329 1.000 0.000 +v -2.6753 -1.2833 -0.7431 0.267 1.000 0.000 +v -2.6086 -1.3390 -0.9208 0.267 1.000 0.000 +v -2.4457 -1.3619 -1.0306 0.267 1.000 0.000 +v -2.2488 -1.3432 -1.0306 0.267 1.000 0.000 +v -2.0931 -1.2901 -0.9208 0.267 1.000 0.000 +v -2.0381 -1.2228 -0.7431 0.267 1.000 0.000 +v -2.1048 -1.1671 -0.5655 0.267 1.000 0.000 +v -2.2677 -1.1443 -0.4557 0.267 1.000 0.000 +v -2.4646 -1.1630 -0.4557 0.267 1.000 0.000 +v -2.6203 -1.2161 -0.5655 0.267 1.000 0.000 +v -2.5757 -1.7535 -0.5878 0.200 1.000 0.000 +v -2.4948 -1.8019 -0.7617 0.200 1.000 0.000 +v -2.3291 -1.7927 -0.8691 0.200 1.000 0.000 +v -2.1417 -1.7294 -0.8691 0.200 1.000 0.000 +v -2.0043 -1.6362 -0.7617 0.200 1.000 0.000 +v -1.9694 -1.5487 -0.5878 0.200 1.000 0.000 +v -2.0502 -1.5003 -0.4139 0.200 1.000 0.000 +v -2.2160 -1.5095 -0.3065 0.200 1.000 0.000 +v -2.4034 -1.5728 -0.3065 0.200 1.000 0.000 +v -2.5408 -1.6660 -0.4139 0.200 1.000 0.000 +v -2.3664 -2.1948 -0.4067 0.129 1.000 0.000 +v -2.2727 -2.2287 -0.5776 0.129 1.000 0.000 +v -2.1115 -2.1844 -0.6832 0.129 1.000 0.000 +v -1.9442 -2.0788 -0.6832 0.129 1.000 0.000 +v -1.8349 -1.9522 -0.5776 0.129 1.000 0.000 +v -1.8253 -1.8531 -0.4067 0.129 1.000 0.000 +v -1.9190 -1.8192 -0.2359 0.129 1.000 0.000 +v -2.0802 -1.8635 -0.1303 0.129 1.000 0.000 +v -2.2474 -1.9691 -0.1303 0.129 1.000 0.000 +v -2.3567 -2.0956 -0.2359 0.129 1.000 0.000 +v -2.0553 -2.5775 -0.2079 0.063 1.000 0.000 +v -1.9533 -2.5908 -0.3768 0.063 1.000 0.000 +v -1.8055 -2.5109 -0.4812 0.063 1.000 0.000 +v -1.6684 -2.3684 -0.4812 0.063 1.000 0.000 +v -1.5944 -2.2176 -0.3768 0.063 1.000 0.000 +v -1.6117 -2.1162 -0.2079 0.063 1.000 0.000 +v -1.7138 -2.1028 -0.0390 0.063 1.000 0.000 +v -1.8615 -2.1827 0.0654 0.063 1.000 0.000 +v -1.9986 -2.3253 0.0654 0.063 1.000 0.000 +v -2.0726 -2.4760 -0.0390 0.063 1.000 0.000 +v -1.6595 -2.8755 -0.0000 0.000 1.000 0.000 +v -1.5561 -2.8644 -0.1682 0.000 1.000 0.000 +v -1.4313 -2.7516 -0.2722 0.000 1.000 0.000 +v -1.3327 -2.5802 -0.2722 0.000 1.000 0.000 +v -1.2980 -2.4156 -0.1682 0.000 1.000 0.000 +v -1.3405 -2.3207 -0.0000 0.000 1.000 0.000 +v -1.4439 -2.3317 0.1682 0.000 1.000 0.000 +v -1.5687 -2.4445 0.2722 0.000 1.000 0.000 +v -1.6673 -2.6160 0.2722 0.000 1.000 0.000 +v -1.7020 -2.7806 0.1682 0.000 1.000 0.000 +v -1.2034 -3.0690 0.2079 0.000 1.000 0.063 +v -1.1071 -3.0329 0.0390 0.000 1.000 0.063 +v -1.0140 -2.8931 -0.0654 0.000 1.000 0.063 +v -0.9598 -2.7029 -0.0654 0.000 1.000 0.063 +v -0.9650 -2.5350 0.0390 0.000 1.000 0.063 +v -1.0278 -2.4536 0.2079 0.000 1.000 0.063 +v -1.1242 -2.4896 0.3768 0.000 1.000 0.063 +v -1.2172 -2.6295 0.4812 0.000 1.000 0.063 +v -1.2715 -2.8197 0.4812 0.000 1.000 0.063 +v -1.2662 -2.9875 0.3768 0.000 1.000 0.063 +v -0.7164 -3.1468 0.4067 0.000 1.000 0.129 +v -0.6357 -3.0886 0.2359 0.000 1.000 0.129 +v -0.5813 -2.9304 0.1303 0.000 1.000 0.129 +v -0.5742 -2.7328 0.1303 0.000 1.000 0.129 +v -0.6169 -2.5711 0.2359 0.000 1.000 0.129 +v -0.6933 -2.5072 0.4067 0.000 1.000 0.129 +v -0.7740 -2.5654 0.5776 0.000 1.000 0.129 +v -0.8284 -2.7236 0.6832 0.000 1.000 0.129 +v -0.8355 -2.9212 0.6832 0.000 1.000 0.129 +v -0.7928 -3.0829 0.5776 0.000 1.000 0.129 +v -0.2297 -3.1072 0.5878 0.000 1.000 0.196 +v -0.1717 -3.0330 0.4139 0.000 1.000 0.196 +v -0.1603 -2.8674 0.3064 0.000 1.000 0.196 +v -0.1998 -2.6736 0.3064 0.000 1.000 0.196 +v -0.2752 -2.5257 0.4139 0.000 1.000 0.196 +v -0.3575 -2.4801 0.5878 0.000 1.000 0.196 +v -0.4155 -2.5543 0.7617 0.000 1.000 0.196 +v -0.4269 -2.7199 0.8692 0.000 1.000 0.196 +v -0.3874 -2.9137 0.8692 0.000 1.000 0.196 +v -0.3121 -3.0616 0.7617 0.000 1.000 0.196 +v 0.2272 -2.9581 0.7431 0.000 1.000 0.263 +v 0.2575 -2.8768 0.5654 0.000 1.000 0.263 +v 0.2250 -2.7156 0.4556 0.000 1.000 0.263 +v 0.1422 -2.5360 0.4556 0.000 1.000 0.263 +v 0.0406 -2.4066 0.5654 0.000 1.000 0.263 +v -0.0409 -2.3769 0.7431 0.000 1.000 0.263 +v -0.0712 -2.4582 0.9209 0.000 1.000 0.263 +v -0.0387 -2.6194 1.0307 0.000 1.000 0.263 +v 0.0441 -2.7990 1.0307 0.000 1.000 0.263 +v 0.1457 -2.9284 0.9209 0.000 1.000 0.263 +v 0.6291 -2.7157 0.8660 0.000 1.000 0.333 +v 0.6302 -2.6379 0.6842 0.000 1.000 0.333 +v 0.5563 -2.4928 0.5719 0.000 1.000 0.333 +v 0.4358 -2.3360 0.5719 0.000 1.000 0.333 +v 0.3146 -2.2273 0.6842 0.000 1.000 0.333 +v 0.2391 -2.2083 0.8660 0.000 1.000 0.333 +v 0.2381 -2.2862 1.0478 0.000 1.000 0.333 +v 0.3119 -2.4312 1.1602 0.000 1.000 0.333 +v 0.4324 -2.5880 1.1602 0.000 1.000 0.333 +v 0.5536 -2.6967 1.0478 0.000 1.000 0.333 +v 0.9579 -2.4026 0.9511 0.000 1.000 0.400 +v 0.9316 -2.3390 0.7656 0.000 1.000 0.400 +v 0.8220 -2.2209 0.6510 0.000 1.000 0.400 +v 0.6709 -2.0932 0.6510 0.000 1.000 0.400 +v 0.5362 -2.0048 0.7656 0.000 1.000 0.400 +v 0.4691 -1.9894 0.9511 0.000 1.000 0.400 +v 0.4955 -2.0530 1.1365 0.000 1.000 0.400 +v 0.6051 -2.1711 1.2511 0.000 1.000 0.400 +v 0.7561 -2.2988 1.2511 0.000 1.000 0.400 +v 0.8909 -2.3872 1.1365 0.000 1.000 0.400 +v 1.2035 -2.0447 0.9945 0.000 1.000 0.467 +v 1.1553 -2.0055 0.8068 0.000 1.000 0.467 +v 1.0181 -1.9229 0.6907 0.000 1.000 0.467 +v 0.8444 -1.8282 0.6907 0.000 1.000 0.467 +v 0.7006 -1.7578 0.8068 0.000 1.000 0.467 +v 0.6416 -1.7384 0.9945 0.000 1.000 0.467 +v 0.6899 -1.7775 1.1823 0.000 1.000 0.467 +v 0.8270 -1.8602 1.2983 0.000 1.000 0.467 +v 1.0007 -1.9548 1.2983 0.000 1.000 0.467 +v 1.1445 -2.0253 1.1823 0.000 1.000 0.467 +v 1.3647 -1.6688 0.9945 0.000 1.000 0.529 +v 1.3028 -1.6620 0.8068 0.000 1.000 0.529 +v 1.1480 -1.6206 0.6908 0.000 1.000 0.529 +v 0.9596 -1.5604 0.6908 0.000 1.000 0.529 +v 0.8096 -1.5044 0.8068 0.000 1.000 0.529 +v 0.7551 -1.4740 0.9945 0.000 1.000 0.529 +v 0.8171 -1.4808 1.1822 0.000 1.000 0.529 +v 0.9718 -1.5222 1.2982 0.000 1.000 0.529 +v 1.1602 -1.5824 1.2982 0.000 1.000 0.529 +v 1.3103 -1.6384 1.1822 0.000 1.000 0.529 +v 1.4485 -1.3000 0.9511 0.000 1.000 0.600 +v 1.3827 -1.3301 0.7670 0.000 1.000 0.600 +v 1.2210 -1.3322 0.6533 0.000 1.000 0.600 +v 1.0250 -1.3054 0.6533 0.000 1.000 0.600 +v 0.8697 -1.2600 0.7670 0.000 1.000 0.600 +v 0.8144 -1.2133 0.9511 0.000 1.000 0.600 +v 0.8802 -1.1832 1.1351 0.000 1.000 0.600 +v 1.0420 -1.1811 1.2489 0.000 1.000 0.600 +v 1.2380 -1.2079 1.2489 0.000 1.000 0.600 +v 1.3932 -1.2533 1.1351 0.000 1.000 0.600 +v 1.4690 -0.9589 0.8660 0.000 1.000 0.663 +v 1.4090 -1.0266 0.6902 0.000 1.000 0.663 +v 1.2497 -1.0705 0.5815 0.000 1.000 0.663 +v 1.0520 -1.0737 0.5815 0.000 1.000 0.663 +v 0.8913 -1.0352 0.6902 0.000 1.000 0.663 +v 0.8291 -0.9695 0.8660 0.000 1.000 0.663 +v 0.8891 -0.9018 1.0419 0.000 1.000 0.663 +v 1.0484 -0.8579 1.1506 0.000 1.000 0.663 +v 1.2461 -0.8546 1.1506 0.000 1.000 0.663 +v 1.4068 -0.8932 1.0419 0.000 1.000 0.663 +v 1.4455 -0.6608 0.7431 0.000 1.000 0.733 +v 1.3981 -0.7627 0.5804 0.000 1.000 0.733 +v 1.2478 -0.8427 0.4799 0.000 1.000 0.733 +v 1.0519 -0.8702 0.4799 0.000 1.000 0.733 +v 0.8854 -0.8347 0.5804 0.000 1.000 0.733 +v 0.8117 -0.7497 0.7431 0.000 1.000 0.733 +v 0.8592 -0.6478 0.9059 0.000 1.000 0.733 +v 1.0095 -0.5678 1.0064 0.000 1.000 0.733 +v 1.2053 -0.5403 1.0064 0.000 1.000 0.733 +v 1.3719 -0.5758 0.9059 0.000 1.000 0.733 +v 1.4004 -0.4150 0.5878 0.000 1.000 0.796 +v 1.3666 -0.5447 0.4424 0.000 1.000 0.796 +v 1.2264 -0.6514 0.3525 0.000 1.000 0.796 +v 1.0334 -0.6944 0.3525 0.000 1.000 0.796 +v 0.8612 -0.6571 0.4424 0.000 1.000 0.796 +v 0.7756 -0.5539 0.5878 0.000 1.000 0.796 +v 0.8094 -0.4241 0.7332 0.000 1.000 0.796 +v 0.9496 -0.3174 0.8230 0.000 1.000 0.796 +v 1.1426 -0.2745 0.8230 0.000 1.000 0.796 +v 1.3148 -0.3117 0.7332 0.000 1.000 0.796 +v 1.3558 -0.2258 0.4067 0.000 1.000 0.867 +v 1.3284 -0.3754 0.2803 0.000 1.000 0.867 +v 1.1925 -0.4960 0.2022 0.000 1.000 0.867 +v 1.0000 -0.5415 0.2022 0.000 1.000 0.867 +v 0.8245 -0.4946 0.2803 0.000 1.000 0.867 +v 0.7330 -0.3731 0.4067 0.000 1.000 0.867 +v 0.7604 -0.2235 0.5331 0.000 1.000 0.867 +v 0.8963 -0.1029 0.6113 0.000 1.000 0.867 +v 1.0887 -0.0574 0.6113 0.000 1.000 0.867 +v 1.2643 -0.1043 0.5331 0.000 1.000 0.867 +v 1.3280 -0.0926 0.2079 0.000 1.000 0.929 +v 1.2913 -0.2523 0.0973 0.000 1.000 0.929 +v 1.1478 -0.3700 0.0289 0.000 1.000 0.929 +v 0.9524 -0.4007 0.0289 0.000 1.000 0.929 +v 0.7797 -0.3326 0.0973 0.000 1.000 0.929 +v 0.6958 -0.1918 0.2079 0.000 1.000 0.929 +v 0.7326 -0.0321 0.3185 0.000 1.000 0.929 +v 0.8761 0.0856 0.3869 0.000 1.000 0.929 +v 1.0714 0.1163 0.3869 0.000 1.000 0.929 +v 1.2441 0.0482 0.3185 0.000 1.000 0.929 +v 1.3200 -0.0004 0.0000 0.000 1.000 1.000 +v 1.2587 -0.1568 -0.1043 0.000 1.000 1.000 +v 1.0986 -0.2533 -0.1688 0.000 1.000 1.000 +v 0.9008 -0.2531 -0.1688 0.000 1.000 1.000 +v 0.7409 -0.1562 -0.1043 0.000 1.000 1.000 +v 0.6800 0.0004 0.0000 0.000 1.000 1.000 +v 0.7413 0.1568 0.1043 0.000 1.000 1.000 +v 0.9014 0.2533 0.1688 0.000 1.000 1.000 +v 1.0992 0.2531 0.1688 0.000 1.000 1.000 +v 1.2591 0.1562 0.1043 0.000 1.000 1.000 +v 1.3279 0.0920 -0.2079 0.000 0.933 1.000 +v 1.2438 -0.0485 -0.3187 0.000 0.933 1.000 +v 1.0710 -0.1162 -0.3872 0.000 0.933 1.000 +v 0.8757 -0.0852 -0.3872 0.000 0.933 1.000 +v 0.7324 0.0327 -0.3187 0.000 0.933 1.000 +v 0.6959 0.1924 -0.2079 0.000 0.933 1.000 +v 0.7801 0.3329 -0.0971 0.000 0.933 1.000 +v 0.9528 0.4006 -0.0286 0.000 0.933 1.000 +v 1.1481 0.3696 -0.0286 0.000 0.933 1.000 +v 1.2914 0.2517 -0.0971 0.000 0.933 1.000 +v 1.3557 0.2257 -0.4067 0.000 0.863 1.000 +v 1.2642 0.1045 -0.5334 0.000 0.863 1.000 +v 1.0887 0.0578 -0.6117 0.000 0.863 1.000 +v 0.8963 0.1033 -0.6117 0.000 0.863 1.000 +v 0.7604 0.2238 -0.5334 0.000 0.863 1.000 +v 0.7330 0.3732 -0.4067 0.000 0.863 1.000 +v 0.8245 0.4944 -0.2801 0.000 0.863 1.000 +v 1.0000 0.5412 -0.2018 0.000 0.863 1.000 +v 1.1925 0.4956 -0.2018 0.000 0.863 1.000 +v 1.3283 0.3751 -0.2801 0.000 0.863 1.000 +v 1.4004 0.4152 -0.5878 0.000 0.796 1.000 +v 1.3150 0.3122 -0.7334 0.000 0.796 1.000 +v 1.1429 0.2750 -0.8235 0.000 0.796 1.000 +v 0.9498 0.3178 -0.8235 0.000 0.796 1.000 +v 0.8095 0.4242 -0.7334 0.000 0.796 1.000 +v 0.7756 0.5536 -0.5878 0.000 0.796 1.000 +v 0.8610 0.6566 -0.4421 0.000 0.796 1.000 +v 1.0331 0.6938 -0.3521 0.000 0.796 1.000 +v 1.2262 0.6510 -0.3521 0.000 0.796 1.000 +v 1.3665 0.5446 -0.4421 0.000 0.796 1.000 +v 1.4456 0.6612 -0.7431 0.000 0.733 1.000 +v 1.3721 0.5766 -0.9061 0.000 0.733 1.000 +v 1.2057 0.5411 -1.0068 0.000 0.733 1.000 +v 1.0098 0.5683 -1.0068 0.000 0.733 1.000 +v 0.8593 0.6478 -0.9061 0.000 0.733 1.000 +v 0.8117 0.7493 -0.7431 0.000 0.733 1.000 +v 0.8851 0.8339 -0.5802 0.000 0.733 1.000 +v 1.0516 0.8694 -0.4795 0.000 0.733 1.000 +v 1.2475 0.8422 -0.4795 0.000 0.733 1.000 +v 1.3980 0.7627 -0.5802 0.000 0.733 1.000 +v 1.4690 0.9595 -0.8660 0.000 0.663 1.000 +v 1.4070 0.8941 -1.0420 0.000 0.663 1.000 +v 1.2464 0.8555 -1.1508 0.000 0.663 1.000 +v 1.0486 0.8584 -1.1508 0.000 0.663 1.000 +v 0.8892 0.9017 -1.0420 0.000 0.663 1.000 +v 0.8291 0.9689 -0.8660 0.000 0.663 1.000 +v 0.8912 1.0343 -0.6900 0.000 0.663 1.000 +v 1.0518 1.0729 -0.5812 0.000 0.663 1.000 +v 1.2495 1.0700 -0.5812 0.000 0.663 1.000 +v 1.4089 1.0267 -0.6900 0.000 0.663 1.000 +v 1.4484 1.3007 -0.9511 0.000 0.600 1.000 +v 1.3932 1.2543 -1.1352 0.000 0.600 1.000 +v 1.2380 1.2088 -1.2490 0.000 0.600 1.000 +v 1.0421 1.1815 -1.2490 0.000 0.600 1.000 +v 0.8804 1.1830 -1.1352 0.000 0.600 1.000 +v 0.8145 1.2126 -0.9511 0.000 0.600 1.000 +v 0.8698 1.2590 -0.7669 0.000 0.600 1.000 +v 1.0250 1.3045 -0.6531 0.000 0.600 1.000 +v 1.2209 1.3318 -0.6531 0.000 0.600 1.000 +v 1.3826 1.3303 -0.7669 0.000 0.600 1.000 +v 1.3645 1.6696 -0.9945 0.000 0.533 1.000 +v 1.3100 1.6394 -1.1822 0.000 0.533 1.000 +v 1.1600 1.5833 -1.2982 0.000 0.533 1.000 +v 0.9718 1.5226 -1.2982 0.000 0.533 1.000 +v 0.8172 1.4805 -1.1822 0.000 0.533 1.000 +v 0.7554 1.4732 -0.9945 0.000 0.533 1.000 +v 0.8099 1.5034 -0.8068 0.000 0.533 1.000 +v 0.9599 1.5596 -0.6908 0.000 0.533 1.000 +v 1.1481 1.6203 -0.6908 0.000 0.533 1.000 +v 1.3026 1.6623 -0.8068 0.000 0.533 1.000 +v 1.2031 2.0455 -0.9945 0.000 0.467 1.000 +v 1.1440 2.0262 -1.1823 0.000 0.467 1.000 +v 1.0003 1.9555 -1.2983 0.000 0.467 1.000 +v 0.8269 1.8604 -1.2983 0.000 0.467 1.000 +v 0.6900 1.7772 -1.1823 0.000 0.467 1.000 +v 0.6420 1.7376 -0.9945 0.000 0.467 1.000 +v 0.7012 1.7569 -0.8068 0.000 0.467 1.000 +v 0.8449 1.8276 -0.6908 0.000 0.467 1.000 +v 1.0183 1.9227 -0.6908 0.000 0.467 1.000 +v 1.1551 2.0059 -0.8068 0.000 0.467 1.000 +v 0.9573 2.4033 -0.9511 0.000 0.400 1.000 +v 0.8901 2.3879 -1.1364 0.000 0.400 1.000 +v 0.7555 2.2993 -1.2510 0.000 0.400 1.000 +v 0.6049 2.1711 -1.2510 0.000 0.400 1.000 +v 0.4957 2.0525 -1.1364 0.000 0.400 1.000 +v 0.4697 1.9887 -0.9511 0.000 0.400 1.000 +v 0.5369 2.0041 -0.7657 0.000 0.400 1.000 +v 0.6715 2.0928 -0.6511 0.000 0.400 1.000 +v 0.8222 2.2209 -0.6511 0.000 0.400 1.000 +v 0.9313 2.3395 -0.7657 0.000 0.400 1.000 +v 0.6283 2.7163 -0.8660 0.000 0.329 1.000 +v 0.5527 2.6972 -1.0478 0.000 0.329 1.000 +v 0.4318 2.5882 -1.1601 0.000 0.329 1.000 +v 0.3117 2.4311 -1.1601 0.000 0.329 1.000 +v 0.2385 2.2857 -1.0478 0.000 0.329 1.000 +v 0.2399 2.2077 -0.8660 0.000 0.329 1.000 +v 0.3155 2.2268 -0.6843 0.000 0.329 1.000 +v 0.4365 2.3358 -0.5720 0.000 0.329 1.000 +v 0.5565 2.4930 -0.5720 0.000 0.329 1.000 +v 0.6298 2.6383 -0.6843 0.000 0.329 1.000 +v 0.2262 2.9585 -0.7431 0.000 0.263 1.000 +v 0.1447 2.9286 -0.9208 0.000 0.263 1.000 +v 0.0434 2.7990 -1.0306 0.000 0.263 1.000 +v -0.0388 2.6191 -1.0306 0.000 0.263 1.000 +v -0.0707 2.4577 -0.9208 0.000 0.263 1.000 +v -0.0399 2.3765 -0.7431 0.000 0.263 1.000 +v 0.0416 2.4064 -0.5655 0.000 0.263 1.000 +v 0.1429 2.5360 -0.4557 0.000 0.263 1.000 +v 0.2251 2.7159 -0.4557 0.000 0.263 1.000 +v 0.2570 2.8773 -0.5655 0.000 0.263 1.000 +v -0.2308 3.1074 -0.5878 0.000 0.200 1.000 +v -0.3131 3.0616 -0.7617 0.000 0.200 1.000 +v -0.3880 2.9134 -0.8691 0.000 0.200 1.000 +v -0.4269 2.7195 -0.8691 0.000 0.200 1.000 +v -0.4148 2.5539 -0.7617 0.000 0.200 1.000 +v -0.3565 2.4799 -0.5878 0.000 0.200 1.000 +v -0.2741 2.5257 -0.4139 0.000 0.200 1.000 +v -0.1992 2.6739 -0.3065 0.000 0.200 1.000 +v -0.1604 2.8678 -0.3065 0.000 0.200 1.000 +v -0.1724 3.0334 -0.4139 0.000 0.200 1.000 +v -0.7175 3.1467 -0.4067 0.000 0.129 1.000 +v -0.7937 3.0826 -0.5776 0.000 0.129 1.000 +v -0.8360 2.9208 -0.6832 0.000 0.129 1.000 +v -0.8282 2.7231 -0.6832 0.000 0.129 1.000 +v -0.7732 2.5652 -0.5776 0.000 0.129 1.000 +v -0.6922 2.5073 -0.4067 0.000 0.129 1.000 +v -0.6160 2.5714 -0.2359 0.000 0.129 1.000 +v -0.5737 2.7332 -0.1303 0.000 0.129 1.000 +v -0.5815 2.9309 -0.1303 0.000 0.129 1.000 +v -0.6365 3.0888 -0.2359 0.000 0.129 1.000 +v -1.2045 3.0687 -0.2079 0.000 0.063 1.000 +v -1.2670 2.9870 -0.3768 0.000 0.063 1.000 +v -1.2718 2.8191 -0.4812 0.000 0.063 1.000 +v -1.2168 2.6291 -0.4812 0.000 0.063 1.000 +v -1.1233 2.4896 -0.3768 0.000 0.063 1.000 +v -1.0268 2.4539 -0.2079 0.000 0.063 1.000 +v -0.9642 2.5356 -0.0390 0.000 0.063 1.000 +v -0.9595 2.7035 0.0654 0.000 0.063 1.000 +v -1.0144 2.8935 0.0654 0.000 0.063 1.000 +v -1.1080 3.0330 -0.0390 0.000 0.063 1.000 +v -1.6605 2.8749 -0.0000 0.000 0.000 1.000 +v -1.7026 2.7799 -0.1682 0.000 0.000 1.000 +v -1.6673 2.6154 -0.2722 0.000 0.000 1.000 +v -1.5682 2.4443 -0.2722 0.000 0.000 1.000 +v -1.4429 2.3319 -0.1682 0.000 0.000 1.000 +v -1.3395 2.3212 -0.0000 0.000 0.000 1.000 +v -1.2974 2.4163 0.1682 0.000 0.000 1.000 +v -1.3327 2.5808 0.2722 0.000 0.000 1.000 +v -1.4318 2.7519 0.2722 0.000 0.000 1.000 +v -1.5571 2.8642 0.1682 0.000 0.000 1.000 +v -2.0561 2.5767 0.2079 0.063 0.000 1.000 +v -2.0731 2.4752 0.0390 0.063 0.000 1.000 +v -1.9985 2.3247 -0.0654 0.063 0.000 1.000 +v -1.8609 2.1826 -0.0654 0.063 0.000 1.000 +v -1.7129 2.1033 0.0390 0.063 0.000 1.000 +v -1.6109 2.1169 0.2079 0.063 0.000 1.000 +v -1.5940 2.2184 0.3768 0.063 0.000 1.000 +v -1.6686 2.3689 0.4812 0.063 0.000 1.000 +v -1.8061 2.5110 0.4812 0.063 0.000 1.000 +v -1.9542 2.5904 0.3768 0.063 0.000 1.000 +v -2.3670 2.1938 0.4067 0.129 0.000 1.000 +v -2.3569 2.0948 0.2359 0.129 0.000 1.000 +v -2.2472 1.9686 0.1303 0.129 0.000 1.000 +v -2.0796 1.8636 0.1303 0.129 0.000 1.000 +v -1.9182 1.8198 0.2359 0.129 0.000 1.000 +v -1.8247 1.8540 0.4067 0.129 0.000 1.000 +v -1.8347 1.9531 0.5776 0.129 0.000 1.000 +v -1.9445 2.0792 0.6832 0.129 0.000 1.000 +v -2.1121 2.1842 0.6832 0.129 0.000 1.000 +v -2.2735 2.2280 0.5776 0.129 0.000 1.000 +v -2.5760 1.7525 0.5878 0.196 0.000 1.000 +v -2.5408 1.6652 0.4139 0.196 0.000 1.000 +v -2.4031 1.5725 0.3064 0.196 0.000 1.000 +v -2.2155 1.5099 0.3064 0.196 0.000 1.000 +v -2.0497 1.5011 0.4139 0.196 0.000 1.000 +v -1.9690 1.5497 0.5878 0.196 0.000 1.000 +v -2.0043 1.6370 0.7617 0.196 0.000 1.000 +v -2.1420 1.7297 0.8692 0.196 0.000 1.000 +v -2.3296 1.7923 0.8692 0.196 0.000 1.000 +v -2.4954 1.8011 0.7617 0.196 0.000 1.000 +v -2.6754 1.2823 0.7431 0.263 0.000 1.000 +v -2.6201 1.2154 0.5654 0.263 0.000 1.000 +v -2.4643 1.1629 0.4556 0.263 0.000 1.000 +v -2.2673 1.1448 0.4556 0.263 0.000 1.000 +v -2.1045 1.1681 0.5654 0.263 0.000 1.000 +v -2.0380 1.2239 0.7431 0.263 0.000 1.000 +v -2.0933 1.2908 0.9209 0.263 0.000 1.000 +v -2.2491 1.3433 1.0307 0.263 0.000 1.000 +v -2.4461 1.3613 1.0307 0.263 0.000 1.000 +v -2.6089 1.3380 0.9209 0.263 0.000 1.000 +v -2.6665 0.8130 0.8660 0.329 0.000 1.000 +v -2.5995 0.7732 0.6842 0.329 0.000 1.000 +v -2.4370 0.7646 0.5719 0.329 0.000 1.000 +v -2.2409 0.7906 0.5719 0.329 0.000 1.000 +v -2.0862 0.8412 0.6842 0.329 0.000 1.000 +v -2.0320 0.8971 0.8660 0.329 0.000 1.000 +v -2.0989 0.9369 1.0478 0.329 0.000 1.000 +v -2.2615 0.9455 1.1602 0.329 0.000 1.000 +v -2.4575 0.9195 1.1602 0.329 0.000 1.000 +v -2.6122 0.8689 1.0478 0.329 0.000 1.000 +v -2.5597 0.3717 0.9511 0.396 0.000 1.000 +v -2.4915 0.3627 0.7656 0.396 0.000 1.000 +v -2.3343 0.3986 0.6510 0.396 0.000 1.000 +v -2.1482 0.4656 0.6510 0.396 0.000 1.000 +v -2.0043 0.5381 0.7656 0.396 0.000 1.000 +v -1.9575 0.5884 0.9511 0.396 0.000 1.000 +v -2.0256 0.5974 1.1365 0.396 0.000 1.000 +v -2.1828 0.5616 1.2511 0.396 0.000 1.000 +v -2.3689 0.4946 1.2511 0.396 0.000 1.000 +v -2.5128 0.4221 1.1365 0.396 0.000 1.000 +v -2.3725 -0.0200 0.9945 0.467 0.000 1.000 +v -2.3145 0.0023 0.8068 0.467 0.000 1.000 +v -2.1743 0.0797 0.6907 0.467 0.000 1.000 +v -2.0055 0.1828 0.6907 0.467 0.000 1.000 +v -1.8726 0.2721 0.8068 0.467 0.000 1.000 +v -1.8263 0.3136 0.9945 0.467 0.000 1.000 +v -1.8843 0.2913 1.1823 0.467 0.000 1.000 +v -2.0245 0.2139 1.2983 0.467 0.000 1.000 +v -2.1933 0.1108 1.2983 0.467 0.000 1.000 +v -2.3262 0.0215 1.1823 0.467 0.000 1.000 +v -2.1276 -0.3475 0.9945 0.529 0.000 1.000 +v -2.0907 -0.2972 0.8068 0.529 0.000 1.000 +v -1.9775 -0.1839 0.6908 0.529 0.000 1.000 +v -1.8312 -0.0509 0.6908 0.529 0.000 1.000 +v -1.7076 0.0511 0.8068 0.529 0.000 1.000 +v -1.6541 0.0831 0.9945 0.529 0.000 1.000 +v -1.6910 0.0328 1.1822 0.529 0.000 1.000 +v -1.8042 -0.0805 1.2982 0.529 0.000 1.000 +v -1.9505 -0.2136 1.2982 0.529 0.000 1.000 +v -2.0741 -0.3155 1.1822 0.529 0.000 1.000 +v -1.8501 -0.6045 0.9511 0.600 0.000 1.000 +v -1.8433 -0.5324 0.7670 0.600 0.000 1.000 +v -1.7642 -0.3913 0.6533 0.600 0.000 1.000 +v -1.6430 -0.2350 0.6533 0.600 0.000 1.000 +v -1.5261 -0.1232 0.7670 0.600 0.000 1.000 +v -1.4580 -0.0987 0.9511 0.600 0.000 1.000 +v -1.4648 -0.1707 1.1351 0.600 0.000 1.000 +v -1.5439 -0.3118 1.2489 0.600 0.000 1.000 +v -1.6650 -0.4682 1.2489 0.600 0.000 1.000 +v -1.7820 -0.5799 1.1351 0.600 0.000 1.000 +v -1.5649 -0.7928 0.8660 0.667 0.000 1.000 +v -1.5936 -0.7070 0.6902 0.667 0.000 1.000 +v -1.5519 -0.5471 0.5815 0.667 0.000 1.000 +v -1.4559 -0.3742 0.5815 0.667 0.000 1.000 +v -1.3421 -0.2543 0.6902 0.667 0.000 1.000 +v -1.2542 -0.2333 0.8660 0.667 0.000 1.000 +v -1.2255 -0.3191 1.0419 0.667 0.000 1.000 +v -1.2672 -0.4790 1.1506 0.667 0.000 1.000 +v -1.3632 -0.6519 1.1506 0.667 0.000 1.000 +v -1.4769 -0.7717 1.0419 0.667 0.000 1.000 +v -1.2950 -0.9215 0.7431 0.733 0.000 1.000 +v -1.3596 -0.8295 0.5804 0.733 0.000 1.000 +v -1.3537 -0.6593 0.4799 0.733 0.000 1.000 +v -1.2795 -0.4759 0.4799 0.733 0.000 1.000 +v -1.1655 -0.3494 0.5804 0.733 0.000 1.000 +v -1.0552 -0.3281 0.7431 0.733 0.000 1.000 +v -0.9906 -0.4201 0.9059 0.733 0.000 1.000 +v -0.9965 -0.5903 1.0064 0.733 0.000 1.000 +v -1.0706 -0.7737 1.0064 0.733 0.000 1.000 +v -1.1846 -0.9002 0.9059 0.733 0.000 1.000 +v -1.0596 -1.0053 0.5878 0.800 0.000 1.000 +v -1.1551 -0.9112 0.4424 0.800 0.000 1.000 +v -1.1774 -0.7364 0.3525 0.800 0.000 1.000 +v -1.1180 -0.5478 0.3525 0.800 0.000 1.000 +v -0.9997 -0.4173 0.4424 0.800 0.000 1.000 +v -0.8675 -0.3948 0.5878 0.800 0.000 1.000 +v -0.7720 -0.4889 0.7332 0.800 0.000 1.000 +v -0.7497 -0.6637 0.8230 0.800 0.000 1.000 +v -0.8090 -0.8523 0.8230 0.800 0.000 1.000 +v -0.9274 -0.9828 0.7332 0.800 0.000 1.000 +v -0.8735 -1.0612 0.4067 0.867 0.000 1.000 +v -0.9893 -0.9627 0.2803 0.867 0.000 1.000 +v -1.0258 -0.7847 0.2022 0.867 0.000 1.000 +v -0.9690 -0.5953 0.2022 0.867 0.000 1.000 +v -0.8406 -0.4667 0.2803 0.867 0.000 1.000 +v -0.6896 -0.4482 0.4067 0.867 0.000 1.000 +v -0.5737 -0.5468 0.5331 0.867 0.000 1.000 +v -0.5373 -0.7247 0.6113 0.867 0.000 1.000 +v -0.5941 -0.9142 0.6113 0.867 0.000 1.000 +v -0.7225 -1.0427 0.5331 0.867 0.000 1.000 +v -0.7442 -1.1038 0.2079 0.933 0.000 1.000 +v -0.8642 -0.9921 0.0973 0.933 0.000 1.000 +v -0.8943 -0.8090 0.0289 0.933 0.000 1.000 +v -0.8232 -0.6244 0.0289 0.933 0.000 1.000 +v -0.6779 -0.5090 0.0973 0.933 0.000 1.000 +v -0.5140 -0.5066 0.2079 0.933 0.000 1.000 +v -0.3941 -0.6184 0.3185 0.933 0.000 1.000 +v -0.3639 -0.8015 0.3869 0.933 0.000 1.000 +v -0.4350 -0.9860 0.3869 0.933 0.000 1.000 +v -0.5803 -1.1015 0.3185 0.933 0.000 1.000 +v -0.6603 -1.1430 0.0000 1.000 0.000 1.000 +v -0.7652 -1.0116 -0.1043 1.000 0.000 1.000 +v -0.7687 -0.8247 -0.1688 1.000 0.000 1.000 +v -0.6696 -0.6536 -0.1688 1.000 0.000 1.000 +v -0.5057 -0.5636 -0.1043 1.000 0.000 1.000 +v -0.3397 -0.5891 0.0000 1.000 0.000 1.000 +v -0.2348 -0.7204 0.1043 1.000 0.000 1.000 +v -0.2313 -0.9073 0.1688 1.000 0.000 1.000 +v -0.3304 -1.0785 0.1688 1.000 0.000 1.000 +v -0.4943 -1.1685 0.1043 1.000 0.000 1.000 +v -0.5843 -1.1961 -0.2079 1.000 0.000 0.933 +v -0.6639 -1.0529 -0.3187 1.000 0.000 0.933 +v -0.6361 -0.8694 -0.3872 1.000 0.000 0.933 +v -0.5116 -0.7158 -0.3872 1.000 0.000 0.933 +v -0.3379 -0.6506 -0.3187 1.000 0.000 0.933 +v -0.1813 -0.6988 -0.2079 1.000 0.000 0.933 +v -0.1017 -0.8420 -0.0971 1.000 0.000 0.933 +v -0.1295 -1.0255 -0.0286 1.000 0.000 0.933 +v -0.2540 -1.1791 -0.0286 1.000 0.000 0.933 +v -0.4277 -1.2443 -0.0971 1.000 0.000 0.933 +v -0.4824 -1.2870 -0.4067 1.000 0.000 0.867 +v -0.5416 -1.1471 -0.5334 1.000 0.000 0.867 +v -0.4943 -0.9717 -0.6117 1.000 0.000 0.867 +v -0.3586 -0.8279 -0.6117 1.000 0.000 0.867 +v -0.1863 -0.7705 -0.5334 1.000 0.000 0.867 +v -0.0433 -0.8214 -0.4067 1.000 0.000 0.867 +v 0.0159 -0.9613 -0.2801 1.000 0.000 0.867 +v -0.0313 -1.1366 -0.2018 1.000 0.000 0.867 +v -0.1670 -1.2805 -0.2018 1.000 0.000 0.867 +v -0.3393 -1.3379 -0.2801 1.000 0.000 0.867 +v -0.3406 -1.4204 -0.5878 1.000 0.000 0.796 +v -0.3871 -1.2950 -0.7334 1.000 0.000 0.796 +v -0.3333 -1.1273 -0.8235 1.000 0.000 0.796 +v -0.1997 -0.9815 -0.8235 1.000 0.000 0.796 +v -0.0374 -0.9132 -0.7334 1.000 0.000 0.796 +v 0.0917 -0.9485 -0.5878 1.000 0.000 0.796 +v 0.1381 -1.0739 -0.4421 1.000 0.000 0.796 +v 0.0843 -1.2416 -0.3521 1.000 0.000 0.796 +v -0.0493 -1.3874 -0.3521 1.000 0.000 0.796 +v -0.2116 -1.4557 -0.4421 1.000 0.000 0.796 +v -0.1502 -1.5825 -0.7431 1.000 0.000 0.733 +v -0.1867 -1.4766 -0.9061 1.000 0.000 0.733 +v -0.1343 -1.3147 -1.0068 1.000 0.000 0.733 +v -0.0127 -1.1586 -1.0068 1.000 0.000 0.733 +v 0.1314 -1.0681 -0.9061 1.000 0.000 0.733 +v 0.2430 -1.0776 -0.7431 1.000 0.000 0.733 +v 0.2796 -1.1835 -0.5802 1.000 0.000 0.733 +v 0.2271 -1.3454 -0.4795 1.000 0.000 0.733 +v 0.1056 -1.5015 -0.4795 1.000 0.000 0.733 +v -0.0385 -1.5920 -0.5802 1.000 0.000 0.733 +v 0.0964 -1.7520 -0.8660 1.000 0.000 0.667 +v 0.0708 -1.6655 -1.0420 1.000 0.000 0.667 +v 0.1177 -1.5071 -1.1508 1.000 0.000 0.667 +v 0.2191 -1.3373 -1.1508 1.000 0.000 0.667 +v 0.3362 -1.2209 -1.0420 1.000 0.000 0.667 +v 0.4245 -1.2024 -0.8660 1.000 0.000 0.667 +v 0.4501 -1.2889 -0.6900 1.000 0.000 0.667 +v 0.4033 -1.4473 -0.5812 1.000 0.000 0.667 +v 0.3019 -1.6171 -0.5812 1.000 0.000 0.667 +v 0.1847 -1.7335 -0.6900 1.000 0.000 0.667 +v 0.4022 -1.9047 -0.9511 1.000 0.000 0.596 +v 0.3896 -1.8337 -1.1352 1.000 0.000 0.596 +v 0.4278 -1.6765 -1.2490 1.000 0.000 0.596 +v 0.5022 -1.4932 -1.2490 1.000 0.000 0.596 +v 0.5843 -1.3539 -1.1352 1.000 0.000 0.596 +v 0.6429 -1.3117 -0.9511 1.000 0.000 0.596 +v 0.6554 -1.3828 -0.7669 1.000 0.000 0.596 +v 0.6173 -1.5399 -0.6531 1.000 0.000 0.596 +v 0.5429 -1.7232 -0.6531 1.000 0.000 0.596 +v 0.4608 -1.8625 -0.7669 1.000 0.000 0.596 +v 0.7637 -2.0165 -0.9945 1.000 0.000 0.529 +v 0.7648 -1.9542 -1.1822 1.000 0.000 0.529 +v 0.7911 -1.7962 -1.2982 1.000 0.000 0.529 +v 0.8327 -1.6029 -1.2982 1.000 0.000 0.529 +v 0.8736 -1.4480 -1.1822 1.000 0.000 0.529 +v 0.8982 -1.3908 -0.9945 1.000 0.000 0.529 +v 0.8971 -1.4531 -0.8068 1.000 0.000 0.529 +v 0.8707 -1.6110 -0.6908 1.000 0.000 0.529 +v 0.8292 -1.8044 -0.6908 1.000 0.000 0.529 +v 0.7883 -1.9593 -0.8068 1.000 0.000 0.529 +v 1.1699 -2.0647 -0.9945 1.000 0.000 0.467 +v 1.1828 -2.0038 -1.1823 1.000 0.000 0.467 +v 1.1934 -1.8440 -1.2983 1.000 0.000 0.467 +v 1.1977 -1.6463 -1.2983 1.000 0.000 0.467 +v 1.1941 -1.4862 -1.1823 1.000 0.000 0.467 +v 1.1838 -1.4248 -0.9945 1.000 0.000 0.467 +v 1.1709 -1.4857 -0.8068 1.000 0.000 0.467 +v 1.1603 -1.6455 -0.6908 1.000 0.000 0.467 +v 1.1560 -1.8432 -0.6908 1.000 0.000 0.467 +v 1.1596 -2.0033 -0.8068 1.000 0.000 0.467 +v 1.6027 -2.0307 -0.9511 1.000 0.000 0.400 +v 1.6229 -1.9649 -1.1364 1.000 0.000 0.400 +v 1.6135 -1.8039 -1.2510 1.000 0.000 0.400 +v 1.5778 -1.6094 -1.2510 1.000 0.000 0.400 +v 1.5297 -1.4556 -1.1364 1.000 0.000 0.400 +v 1.4874 -1.4012 -0.9511 1.000 0.000 0.400 +v 1.4671 -1.4670 -0.7657 1.000 0.000 0.400 +v 1.4766 -1.6279 -0.6511 1.000 0.000 0.400 +v 1.5122 -1.8225 -0.6511 1.000 0.000 0.400 +v 1.5604 -1.9763 -0.7657 1.000 0.000 0.400 +v 2.0383 -1.9023 -0.8660 1.000 0.000 0.333 +v 2.0595 -1.8273 -1.0478 1.000 0.000 0.333 +v 2.0256 -1.6680 -1.1601 1.000 0.000 0.333 +v 1.9495 -1.4855 -1.1601 1.000 0.000 0.333 +v 1.8602 -1.3494 -1.0478 1.000 0.000 0.333 +v 1.7920 -1.3116 -0.8660 1.000 0.000 0.333 +v 1.7707 -1.3867 -0.6843 1.000 0.000 0.333 +v 1.8046 -1.5459 -0.5720 1.000 0.000 0.333 +v 1.8807 -1.7284 -0.5720 1.000 0.000 0.333 +v 1.9700 -1.8646 -0.6843 1.000 0.000 0.333 +v 2.4490 -1.6752 -0.7431 1.000 0.000 0.263 +v 2.4639 -1.5896 -0.9208 1.000 0.000 0.263 +v 2.4023 -1.4371 -1.0306 1.000 0.000 0.263 +v 2.2876 -1.2759 -1.0306 1.000 0.000 0.263 +v 2.1638 -1.1677 -0.9208 1.000 0.000 0.263 +v 2.0781 -1.1537 -0.7431 1.000 0.000 0.263 +v 2.0632 -1.2393 -0.5655 1.000 0.000 0.263 +v 2.1248 -1.3918 -0.4557 1.000 0.000 0.263 +v 2.2395 -1.5529 -0.4557 1.000 0.000 0.263 +v 2.3633 -1.6612 -0.5655 1.000 0.000 0.263 +v 2.8065 -1.3539 -0.5878 1.000 0.000 0.200 +v 2.8079 -1.2596 -0.7617 1.000 0.000 0.200 +v 2.7171 -1.1207 -0.8691 1.000 0.000 0.200 +v 2.5686 -0.9901 -0.8691 1.000 0.000 0.200 +v 2.4191 -0.9177 -0.7617 1.000 0.000 0.200 +v 2.3259 -0.9312 -0.5878 1.000 0.000 0.200 +v 2.3244 -1.0254 -0.4139 1.000 0.000 0.200 +v 2.4153 -1.1644 -0.3065 1.000 0.000 0.200 +v 2.5638 -1.2950 -0.3065 1.000 0.000 0.200 +v 2.7132 -1.3674 -0.4139 1.000 0.000 0.200 +v 3.0839 -0.9520 -0.4067 1.000 0.000 0.133 +v 3.0664 -0.8539 -0.5776 1.000 0.000 0.133 +v 2.9475 -0.7364 -0.6832 1.000 0.000 0.133 +v 2.7724 -0.6444 -0.6832 1.000 0.000 0.133 +v 2.6081 -0.6130 -0.5776 1.000 0.000 0.133 +v 2.5174 -0.6542 -0.4067 1.000 0.000 0.133 +v 2.5349 -0.7523 -0.2359 1.000 0.000 0.133 +v 2.6539 -0.8698 -0.1303 1.000 0.000 0.133 +v 2.8290 -0.9618 -0.1303 1.000 0.000 0.133 +v 2.9932 -0.9932 -0.2359 1.000 0.000 0.133 +v 3.2598 -0.4912 -0.2079 1.000 0.000 0.063 +v 3.2203 -0.3962 -0.3768 1.000 0.000 0.063 +v 3.0773 -0.3082 -0.4812 1.000 0.000 0.063 +v 2.8853 -0.2607 -0.4812 1.000 0.000 0.063 +v 2.7177 -0.2720 -0.3768 1.000 0.000 0.063 +v 2.6385 -0.3377 -0.2079 1.000 0.000 0.063 +v 2.6780 -0.4327 -0.0390 1.000 0.000 0.063 +v 2.8210 -0.5208 0.0654 1.000 0.000 0.063 +v 3.0130 -0.5682 0.0654 1.000 0.000 0.063 +v 3.1806 -0.5569 -0.0390 1.000 0.000 0.063 +vn 1.0000 0.0017 -0.0000 +vn 0.8086 0.2643 -0.5257 +vn 0.3083 0.4259 -0.8507 +vn -0.3098 0.4248 -0.8507 +vn -0.8095 0.2614 -0.5257 +vn -1.0000 -0.0017 -0.0000 +vn -0.8086 -0.2643 0.5257 +vn -0.3083 -0.4259 0.8507 +vn 0.3098 -0.4248 0.8507 +vn 0.8095 -0.2614 0.5257 +vn 0.9700 0.2432 -0.0000 +vn 0.7218 0.4476 -0.5279 +vn 0.1980 0.4810 -0.8541 +vn -0.4015 0.3306 -0.8541 +vn -0.8476 0.0540 -0.5279 +vn -0.9700 -0.2432 -0.0000 +vn -0.7218 -0.4476 0.5279 +vn -0.1980 -0.4810 0.8541 +vn 0.4015 -0.3306 0.8541 +vn 0.8476 -0.0540 0.5279 +vn 0.8836 0.4683 -0.0000 +vn 0.5998 0.5959 -0.5340 +vn 0.0869 0.4959 -0.8640 +vn -0.4592 0.2065 -0.8640 +vn -0.8299 -0.1618 -0.5340 +vn -0.8836 -0.4683 -0.0000 +vn -0.5998 -0.5959 0.5340 +vn -0.0869 -0.4959 0.8640 +vn 0.4592 -0.2065 0.8640 +vn 0.8299 0.1618 0.5340 +vn 0.7487 0.6629 -0.0000 +vn 0.4574 0.7039 -0.5435 +vn -0.0087 0.4760 -0.8794 +vn -0.4714 0.0663 -0.8794 +vn -0.7541 -0.3687 -0.5435 +vn -0.7487 -0.6629 -0.0000 +vn -0.4574 -0.7039 0.5435 +vn 0.0087 -0.4760 0.8794 +vn 0.4714 -0.0663 0.8794 +vn 0.7541 0.3687 0.5435 +vn 0.5770 0.8167 -0.0000 +vn 0.3096 0.7718 -0.5554 +vn -0.0760 0.4320 -0.8986 +vn -0.4326 -0.0727 -0.8986 +vn -0.6240 -0.5497 -0.5554 +vn -0.5770 -0.8167 -0.0000 +vn -0.3096 -0.7718 0.5554 +vn 0.0760 -0.4320 0.8986 +vn 0.4326 0.0727 0.8986 +vn 0.6240 0.5497 0.5554 +vn 0.3819 0.9242 -0.0000 +vn 0.1696 0.8053 -0.5681 +vn -0.1076 0.3788 -0.9192 +vn -0.3436 -0.1924 -0.9192 +vn -0.4484 -0.6901 -0.5681 +vn -0.3819 -0.9242 -0.0000 +vn -0.1696 -0.8053 0.5681 +vn 0.1076 -0.3788 0.9192 +vn 0.3436 0.1924 0.9192 +vn 0.4484 0.6901 0.5681 +vn 0.1772 0.9842 -0.0000 +vn 0.0464 0.8137 -0.5795 +vn -0.1022 0.3324 -0.9376 +vn -0.2117 -0.2759 -0.9376 +vn -0.2403 -0.7788 -0.5795 +vn -0.1772 -0.9842 -0.0000 +vn -0.0464 -0.8137 0.5795 +vn 0.1022 -0.3324 0.9376 +vn 0.2117 0.2759 0.9376 +vn 0.2403 0.7788 0.5795 +vn -0.0246 0.9997 0.0000 +vn -0.0551 0.8079 -0.5867 +vn -0.0645 0.3075 -0.9494 +vn -0.0493 -0.3103 -0.9494 +vn -0.0152 -0.8096 -0.5867 +vn 0.0246 -0.9997 -0.0000 +vn 0.0551 -0.8079 0.5867 +vn 0.0645 -0.3075 0.9494 +vn 0.0493 0.3103 0.9494 +vn 0.0152 0.8096 0.5867 +vn -0.2127 0.9771 0.0000 +vn -0.1342 0.7987 -0.5865 +vn -0.0045 0.3153 -0.9490 +vn 0.1269 -0.2886 -0.9490 +vn 0.2099 -0.7823 -0.5865 +vn 0.2127 -0.9771 -0.0000 +vn 0.1342 -0.7987 0.5865 +vn 0.0045 -0.3153 0.9490 +vn -0.1269 0.2886 0.9490 +vn -0.2099 0.7823 0.5865 +vn -0.3782 0.9257 0.0000 +vn -0.1938 0.7948 -0.5752 +vn 0.0646 0.3602 -0.9306 +vn 0.2983 -0.2119 -0.9306 +vn 0.4181 -0.7031 -0.5752 +vn 0.3782 -0.9257 -0.0000 +vn 0.1938 -0.7948 0.5752 +vn -0.0646 -0.3602 0.9306 +vn -0.2983 0.2119 0.9306 +vn -0.4181 0.7031 0.5752 +vn -0.5143 0.8576 0.0000 +vn -0.2373 0.8010 -0.5496 +vn 0.1303 0.4385 -0.8892 +vn 0.4482 -0.0916 -0.8892 +vn 0.5948 -0.5866 -0.5496 +vn 0.5143 -0.8576 -0.0000 +vn 0.2373 -0.8010 0.5496 +vn -0.1303 -0.4385 0.8892 +vn -0.4482 0.0916 0.8892 +vn -0.5948 0.5866 0.5496 +vn -0.6155 0.7881 0.0000 +vn -0.2657 0.8190 -0.5085 +vn 0.1857 0.5371 -0.8228 +vn 0.5661 0.0501 -0.8228 +vn 0.7303 -0.4561 -0.5085 +vn 0.6155 -0.7881 -0.0000 +vn 0.2657 -0.8190 0.5085 +vn -0.1857 -0.5371 0.8228 +vn -0.5661 -0.0501 0.8228 +vn -0.7303 0.4561 0.5085 +vn -0.6760 0.7369 0.0000 +vn -0.2721 0.8483 -0.4543 +vn 0.2357 0.6356 -0.7351 +vn 0.6535 0.1802 -0.7351 +vn 0.8217 -0.3440 -0.4543 +vn 0.6760 -0.7369 -0.0000 +vn 0.2721 -0.8483 0.4543 +vn -0.2357 -0.6356 0.7351 +vn -0.6535 -0.1802 0.7351 +vn -0.8217 0.3440 0.4543 +vn -0.6859 0.7277 0.0000 +vn -0.2382 0.8873 -0.3950 +vn 0.3005 0.7079 -0.6392 +vn 0.7244 0.2582 -0.6392 +vn 0.8716 -0.2902 -0.3950 +vn 0.6859 -0.7277 -0.0000 +vn 0.2382 -0.8873 0.3950 +vn -0.3005 -0.7079 0.6392 +vn -0.7244 -0.2582 0.6392 +vn -0.8716 0.2902 0.3950 +vn -0.6283 0.7780 0.0000 +vn -0.1384 0.9281 -0.3457 +vn 0.4043 0.7236 -0.5594 +vn 0.7925 0.2428 -0.5594 +vn 0.8781 -0.3308 -0.3457 +vn 0.6283 -0.7780 -0.0000 +vn 0.1384 -0.9281 0.3457 +vn -0.4043 -0.7236 0.5594 +vn -0.7925 -0.2428 0.5594 +vn -0.8781 0.3308 0.3457 +vn -0.4989 0.8666 0.0000 +vn 0.0202 0.9451 -0.3260 +vn 0.5316 0.6626 -0.5276 +vn 0.8400 0.1270 -0.5276 +vn 0.8275 -0.4571 -0.3260 +vn 0.4989 -0.8666 -0.0000 +vn -0.0202 -0.9451 0.3260 +vn -0.5316 -0.6626 0.5276 +vn -0.8400 -0.1270 0.5276 +vn -0.8275 0.4571 0.3260 +vn -0.3580 0.9337 0.0000 +vn 0.1539 0.9254 -0.3463 +vn 0.6069 0.5637 -0.5603 +vn 0.8282 -0.0134 -0.5603 +vn 0.7331 -0.5854 -0.3463 +vn 0.3580 -0.9337 -0.0000 +vn -0.1539 -0.9254 0.3463 +vn -0.6069 -0.5637 0.5603 +vn -0.8282 0.0134 0.5603 +vn -0.7331 0.5854 0.3463 +vn -0.2869 0.9580 0.0000 +vn 0.1841 0.8997 -0.3959 +vn 0.5848 0.4977 -0.6405 +vn 0.7621 -0.0943 -0.6405 +vn 0.6483 -0.6504 -0.3959 +vn 0.2869 -0.9580 -0.0000 +vn -0.1841 -0.8997 0.3959 +vn -0.5848 -0.4977 0.6405 +vn -0.7621 0.0943 0.6405 +vn -0.6483 0.6504 0.3959 +vn -0.3009 0.9537 0.0000 +vn 0.1113 0.8834 -0.4552 +vn 0.4809 0.4757 -0.7365 +vn 0.6668 -0.1137 -0.7365 +vn 0.5981 -0.6596 -0.4552 +vn 0.3009 -0.9537 -0.0000 +vn -0.1113 -0.8834 0.4552 +vn -0.4809 -0.4757 0.7365 +vn -0.6668 0.1137 0.7365 +vn -0.5981 0.6596 0.4552 +vn -0.3761 0.9266 0.0000 +vn -0.0323 0.8600 -0.5092 +vn 0.3239 0.4650 -0.8239 +vn 0.5564 -0.1076 -0.8239 +vn 0.5763 -0.6392 -0.5092 +vn 0.3761 -0.9266 -0.0000 +vn 0.0323 -0.8600 0.5092 +vn -0.3239 -0.4650 0.8239 +vn -0.5564 0.1076 0.8239 +vn -0.5763 0.6392 0.5092 +vn -0.4873 0.8732 0.0000 +vn -0.2133 0.8074 -0.5501 +vn 0.1421 0.4332 -0.8900 +vn 0.4433 -0.1065 -0.8900 +vn 0.5752 -0.6055 -0.5501 +vn 0.4873 -0.8732 -0.0000 +vn 0.2133 -0.8074 0.5501 +vn -0.1421 -0.4332 0.8900 +vn -0.4433 0.1065 0.8900 +vn -0.5752 0.6055 0.5501 +vn -0.6145 0.7889 0.0000 +vn -0.4025 0.7119 -0.5754 +vn -0.0368 0.3630 -0.9311 +vn 0.3430 -0.1246 -0.9311 +vn 0.5917 -0.5646 -0.5754 +vn 0.6145 -0.7889 -0.0000 +vn 0.4025 -0.7119 0.5754 +vn 0.0368 -0.3630 0.9311 +vn -0.3430 0.1246 0.9311 +vn -0.5917 0.5646 0.5754 +vn -0.7416 0.6708 0.0000 +vn -0.5748 0.5705 -0.5866 +vn -0.1884 0.2524 -0.9491 +vn 0.2700 -0.1622 -0.9491 +vn 0.6252 -0.5148 -0.5866 +vn 0.7416 -0.6708 -0.0000 +vn 0.5748 -0.5705 0.5866 +vn 0.1884 -0.2524 0.9491 +vn -0.2700 0.1622 0.9491 +vn -0.6252 0.5148 0.5866 +vn -0.8549 0.5188 0.0000 +vn -0.7104 0.3888 -0.5867 +vn -0.2945 0.1103 -0.9493 +vn 0.2338 -0.2103 -0.9493 +vn 0.6729 -0.4506 -0.5867 +vn 0.8549 -0.5188 -0.0000 +vn 0.7104 -0.3888 0.5867 +vn 0.2945 -0.1103 0.9493 +vn -0.2338 0.2103 0.9493 +vn -0.6729 0.4506 0.5867 +vn -0.9419 0.3358 0.0000 +vn -0.7954 0.1781 -0.5793 +vn -0.3451 -0.0477 -0.9374 +vn 0.2371 -0.2552 -0.9374 +vn 0.7287 -0.3653 -0.5793 +vn 0.9419 -0.3358 -0.0000 +vn 0.7954 -0.1781 0.5793 +vn 0.3451 0.0477 0.9374 +vn -0.2371 0.2552 0.9374 +vn -0.7287 0.3653 0.5793 +vn -0.9917 0.1282 0.0000 +vn -0.8218 -0.0466 -0.5679 +vn -0.3379 -0.2035 -0.9189 +vn 0.2750 -0.2828 -0.9189 +vn 0.7829 -0.2540 -0.5679 +vn 0.9917 -0.1282 -0.0000 +vn 0.8218 0.0466 0.5679 +vn 0.3379 0.2035 0.9189 +vn -0.2750 0.2828 0.9189 +vn -0.7829 0.2540 0.5679 +vn -0.9955 -0.0946 0.0000 +vn -0.7871 -0.2686 -0.5552 +vn -0.2781 -0.3400 -0.8984 +vn 0.3372 -0.2816 -0.8984 +vn 0.8236 -0.1156 -0.5552 +vn 0.9955 0.0946 -0.0000 +vn 0.7871 0.2686 0.5552 +vn 0.2781 0.3400 0.8984 +vn -0.3372 0.2816 0.8984 +vn -0.8236 0.1156 0.5552 +vn -0.9474 -0.3201 0.0000 +vn -0.6947 -0.4714 -0.5434 +vn -0.1766 -0.4426 -0.8792 +vn 0.4089 -0.2447 -0.8792 +vn 0.8382 0.0466 -0.5434 +vn 0.9474 0.3201 -0.0000 +vn 0.6947 0.4714 0.5434 +vn 0.1766 0.4426 0.8792 +vn -0.4089 0.2447 0.8792 +vn -0.8382 -0.0466 0.5434 +vn -0.8455 -0.5339 0.0000 +vn -0.5527 -0.6399 -0.5339 +vn -0.0488 -0.5014 -0.8638 +vn 0.4737 -0.1714 -0.8638 +vn 0.8153 0.2240 -0.5339 +vn 0.8455 0.5339 -0.0000 +vn 0.5527 0.6399 0.5339 +vn 0.0488 0.5014 0.8638 +vn -0.4737 0.1714 0.8638 +vn -0.8153 -0.2240 0.5339 +vn -0.6931 -0.7208 0.0000 +vn -0.3743 -0.7625 -0.5278 +vn 0.0875 -0.5129 -0.8540 +vn 0.5159 -0.0674 -0.8540 +vn 0.7472 0.4038 -0.5278 +vn 0.6931 0.7208 -0.0000 +vn 0.3743 0.7625 0.5278 +vn -0.0875 0.5129 0.8540 +vn -0.5159 0.0674 0.8540 +vn -0.7472 -0.4038 0.5278 +vn -0.4985 -0.8669 0.0000 +vn -0.1754 -0.8324 -0.5257 +vn 0.2147 -0.4799 -0.8507 +vn 0.5228 0.0559 -0.8507 +vn 0.6312 0.5703 -0.5257 +vn 0.4985 0.8669 -0.0000 +vn 0.1754 0.8324 0.5257 +vn -0.2147 0.4799 0.8507 +vn -0.5228 -0.0559 0.8507 +vn -0.6312 -0.5703 0.5257 +vn -0.2743 -0.9616 0.0000 +vn 0.0267 -0.8489 -0.5279 +vn 0.3175 -0.4119 -0.8541 +vn 0.4871 0.1824 -0.8541 +vn 0.4706 0.7070 -0.5279 +vn 0.2743 0.9616 -0.0000 +vn -0.0267 0.8489 0.5279 +vn -0.3175 0.4119 0.8541 +vn -0.4871 -0.1824 0.8541 +vn -0.4706 -0.7070 0.5279 +vn -0.0362 -0.9993 0.0000 +vn 0.2162 -0.8174 -0.5340 +vn 0.3860 -0.3232 -0.8640 +vn 0.4084 0.2944 -0.8640 +vn 0.2748 0.7996 -0.5340 +vn 0.0362 0.9993 -0.0000 +vn -0.2162 0.8174 0.5340 +vn -0.3860 0.3232 0.8640 +vn -0.4084 -0.2944 0.8640 +vn -0.2748 -0.7996 0.5340 +vn 0.1997 -0.9798 0.0000 +vn 0.3809 -0.7480 -0.5435 +vn 0.4165 -0.2305 -0.8794 +vn 0.2931 0.3751 -0.8794 +vn 0.0577 0.8374 -0.5435 +vn -0.1997 0.9798 -0.0000 +vn -0.3809 0.7480 0.5435 +vn -0.4165 0.2305 0.8794 +vn -0.2931 -0.3751 0.8794 +vn -0.0577 -0.8374 0.5435 +vn 0.4188 -0.9081 0.0000 +vn 0.5136 -0.6540 -0.5554 +vn 0.4122 -0.1502 -0.8986 +vn 0.1533 0.4110 -0.8986 +vn -0.1641 0.8152 -0.5554 +vn -0.4188 0.9081 -0.0000 +vn -0.5136 0.6540 0.5554 +vn -0.4122 0.1502 0.8986 +vn -0.1533 -0.4110 0.8986 +vn 0.1641 -0.8152 0.5554 +vn 0.6094 -0.7929 0.0000 +vn 0.6126 -0.5495 -0.5681 +vn 0.3819 -0.0962 -0.9192 +vn 0.0052 0.3938 -0.9192 +vn -0.3734 0.7334 -0.5681 +vn -0.6094 0.7929 -0.0000 +vn -0.6126 0.5495 0.5681 +vn -0.3819 0.0962 0.9192 +vn -0.0052 -0.3938 0.9192 +vn 0.3734 -0.7334 0.5681 +vn 0.7637 -0.6455 0.0000 +vn 0.6815 -0.4470 -0.5795 +vn 0.3389 -0.0777 -0.9376 +vn -0.1331 0.3212 -0.9376 +vn -0.5543 0.5975 -0.5795 +vn -0.7637 0.6455 -0.0000 +vn -0.6815 0.4470 0.5795 +vn -0.3389 0.0777 0.9376 +vn 0.1331 -0.3212 0.9376 +vn 0.5543 -0.5975 0.5795 +vn 0.8781 -0.4785 0.0000 +vn 0.7272 -0.3562 -0.5867 +vn 0.2986 -0.0979 -0.9494 +vn -0.2441 0.1978 -0.9494 +vn -0.6936 0.4180 -0.5867 +vn -0.8781 0.4785 -0.0000 +vn -0.7272 0.3562 0.5867 +vn -0.2986 0.0979 0.9494 +vn 0.2441 -0.1978 0.9494 +vn 0.6936 -0.4180 0.5867 +vn 0.9525 -0.3044 0.0000 +vn 0.7588 -0.2831 -0.5865 +vn 0.2753 -0.1537 -0.9490 +vn -0.3134 0.0344 -0.9490 +vn -0.7824 0.2094 -0.5865 +vn -0.9525 0.3044 -0.0000 +vn -0.7588 0.2831 0.5865 +vn -0.2753 0.1537 0.9490 +vn 0.3134 -0.0344 0.9490 +vn 0.7824 -0.2094 0.5865 +vn 0.9908 -0.1354 0.0000 +vn 0.7852 -0.2296 -0.5752 +vn 0.2796 -0.2360 -0.9306 +vn -0.3327 -0.1524 -0.9306 +vn -0.8180 -0.0105 -0.5752 +vn -0.9908 0.1354 -0.0000 +vn -0.7852 0.2296 0.5752 +vn -0.2796 0.2360 0.9306 +vn 0.3327 0.1524 0.9306 +vn 0.8180 0.0105 0.5752 +vn 0.9999 0.0166 -0.0000 +vn 0.8124 -0.1950 -0.5496 +vn 0.3146 -0.3321 -0.8892 +vn -0.3034 -0.3423 -0.8892 +vn -0.8054 -0.2218 -0.5496 +vn -0.9999 -0.0166 -0.0000 +vn -0.8124 0.1950 0.5496 +vn -0.3146 0.3321 0.8892 +vn 0.3034 0.3423 0.8892 +vn 0.8054 0.2218 0.5496 +vn 0.9903 0.1390 -0.0000 +vn 0.8421 -0.1795 -0.5085 +vn 0.3723 -0.4294 -0.8228 +vn -0.2397 -0.5153 -0.8228 +vn -0.7602 -0.4044 -0.5085 +vn -0.9903 -0.1390 -0.0000 +vn -0.8421 0.1795 0.5085 +vn -0.3723 0.4294 0.8228 +vn 0.2397 0.5153 0.8228 +vn 0.7602 0.4044 0.5085 +vn 0.9762 0.2170 -0.0000 +vn 0.8707 -0.1885 -0.4543 +vn 0.4326 -0.5220 -0.7351 +vn -0.1707 -0.6561 -0.7351 +vn -0.7088 -0.5396 -0.4543 +vn -0.9762 -0.2170 -0.0000 +vn -0.8707 0.1885 0.4543 +vn -0.4326 0.5220 0.7351 +vn 0.1707 0.6561 0.7351 +vn 0.7088 0.5396 0.4543 +vn 0.9732 0.2301 -0.0000 +vn 0.8875 -0.2374 -0.3950 +vn 0.4628 -0.6142 -0.6392 +vn -0.1386 -0.7565 -0.6392 +vn -0.6871 -0.6098 -0.3950 +vn -0.9732 -0.2301 -0.0000 +vn -0.8875 0.2374 0.3950 +vn -0.4628 0.6142 0.6392 +vn 0.1386 0.7565 0.6392 +vn 0.6871 0.6098 0.3950 +vn 0.9879 0.1551 -0.0000 +vn 0.8729 -0.3441 -0.3457 +vn 0.4246 -0.7119 -0.5594 +vn -0.1860 -0.8078 -0.5594 +vn -0.7255 -0.5951 -0.3457 +vn -0.9879 -0.1551 -0.0000 +vn -0.8729 0.3441 0.3457 +vn -0.4246 0.7119 0.5594 +vn 0.1860 0.8078 0.5594 +vn 0.7255 0.5951 0.3457 +vn 1.0000 -0.0012 0.0000 +vn 0.8084 -0.4901 -0.3260 +vn 0.3080 -0.7917 -0.5276 +vn -0.3100 -0.7909 -0.5276 +vn -0.8096 -0.4881 -0.3260 +vn -1.0000 0.0012 -0.0000 +vn -0.8084 0.4901 0.3260 +vn -0.3080 0.7917 0.5276 +vn 0.3100 0.7909 0.5276 +vn 0.8096 0.4881 0.3260 +vn 0.9876 -0.1568 0.0000 +vn 0.7245 -0.5960 -0.3463 +vn 0.1847 -0.8075 -0.5603 +vn -0.4257 -0.7105 -0.5603 +vn -0.8735 -0.3422 -0.3463 +vn -0.9876 0.1568 -0.0000 +vn -0.7245 0.5960 0.3463 +vn -0.1847 0.8075 0.5603 +vn 0.4257 0.7105 0.5603 +vn 0.8735 0.3422 0.3463 +vn 0.9731 -0.2305 0.0000 +vn 0.6871 -0.6093 -0.3959 +vn 0.1386 -0.7553 -0.6405 +vn -0.4628 -0.6129 -0.6405 +vn -0.8874 -0.2363 -0.3959 +vn -0.9731 0.2305 -0.0000 +vn -0.6871 0.6093 0.3959 +vn -0.1386 0.7553 0.6405 +vn 0.4628 0.6129 0.6405 +vn 0.8874 0.2363 0.3959 +vn 0.9763 -0.2163 0.0000 +vn 0.7094 -0.5381 -0.4552 +vn 0.1716 -0.6543 -0.7365 +vn -0.4319 -0.5207 -0.7365 +vn -0.8703 -0.1881 -0.4552 +vn -0.9763 0.2163 -0.0000 +vn -0.7094 0.5381 0.4552 +vn -0.1716 0.6543 0.7365 +vn 0.4319 0.5207 0.7365 +vn 0.8703 0.1881 0.4552 +vn 0.9905 -0.1376 0.0000 +vn 0.7609 -0.4021 -0.5092 +vn 0.2407 -0.5130 -0.8239 +vn -0.3714 -0.4280 -0.8239 +vn -0.8417 -0.1795 -0.5092 +vn -0.9905 0.1376 -0.0000 +vn -0.7609 0.4021 0.5092 +vn -0.2407 0.5130 0.8239 +vn 0.3714 0.4280 0.8239 +vn 0.8417 0.1795 0.5092 +vn 0.9999 -0.0146 0.0000 +vn 0.8059 -0.2190 -0.5501 +vn 0.3041 -0.3397 -0.8900 +vn -0.3139 -0.3307 -0.8900 +vn -0.8120 -0.1954 -0.5501 +vn -0.9999 0.0146 -0.0000 +vn -0.8059 0.2190 0.5501 +vn -0.3041 0.3397 0.8900 +vn 0.3139 0.3307 0.8900 +vn 0.8120 0.1954 0.5501 +vn 0.9905 0.1377 -0.0000 +vn 0.8178 -0.0074 -0.5754 +vn 0.3328 -0.1496 -0.9311 +vn -0.2794 -0.2347 -0.9311 +vn -0.7848 -0.2302 -0.5754 +vn -0.9905 -0.1377 -0.0000 +vn -0.8178 0.0074 0.5754 +vn -0.3328 0.1496 0.9311 +vn 0.2794 0.2347 0.9311 +vn 0.7848 0.2302 0.5754 +vn 0.9517 0.3069 -0.0000 +vn 0.7815 0.2125 -0.5866 +vn 0.3128 0.0370 -0.9491 +vn -0.2755 -0.1527 -0.9491 +vn -0.7585 -0.2840 -0.5866 +vn -0.9517 -0.3069 -0.0000 +vn -0.7815 -0.2125 0.5866 +vn -0.3128 -0.0370 0.9491 +vn 0.2755 0.1527 0.9491 +vn 0.7585 0.2840 0.5866 +vn 0.8767 0.4810 -0.0000 +vn 0.6919 0.4208 -0.5867 +vn 0.2428 0.1999 -0.9493 +vn -0.2991 -0.0973 -0.9493 +vn -0.7267 -0.3574 -0.5867 +vn -0.8767 -0.4810 -0.0000 +vn -0.6919 -0.4208 0.5867 +vn -0.2428 -0.1999 0.9493 +vn 0.2991 0.0973 0.9493 +vn 0.7267 0.3574 0.5867 +vn 0.7618 0.6478 -0.0000 +vn 0.5519 0.5998 -0.5793 +vn 0.1313 0.3227 -0.9374 +vn -0.3396 -0.0777 -0.9374 +vn -0.6807 -0.4484 -0.5793 +vn -0.7618 -0.6478 -0.0000 +vn -0.5519 -0.5998 0.5793 +vn -0.1313 -0.3227 0.9374 +vn 0.3396 0.0777 0.9374 +vn 0.6807 0.4484 0.5793 +vn 0.6069 0.7948 -0.0000 +vn 0.3706 0.7349 -0.5679 +vn -0.0073 0.3944 -0.9189 +vn -0.3824 -0.0968 -0.9189 +vn -0.6114 -0.5510 -0.5679 +vn -0.6069 -0.7948 -0.0000 +vn -0.3706 -0.7349 0.5679 +vn 0.0073 -0.3944 0.9189 +vn 0.3824 0.0968 0.9189 +vn 0.6114 0.5510 0.5679 +vn 0.4159 0.9094 -0.0000 +vn 0.1610 0.8160 -0.5552 +vn -0.1554 0.4109 -0.8984 +vn -0.4124 -0.1512 -0.8984 +vn -0.5119 -0.6555 -0.5552 +vn -0.4159 -0.9094 -0.0000 +vn -0.1610 -0.8160 0.5552 +vn 0.1554 -0.4109 0.8984 +vn 0.4124 0.1512 0.8984 +vn 0.5119 0.6555 0.5552 +vn 0.1965 0.9805 -0.0000 +vn -0.0609 0.8373 -0.5434 +vn -0.2950 0.3743 -0.8792 +vn -0.4164 -0.2317 -0.8792 +vn -0.3787 -0.7492 -0.5434 +vn -0.1965 -0.9805 -0.0000 +vn 0.0609 -0.8373 0.5434 +vn 0.2950 -0.3743 0.8792 +vn 0.4164 0.2317 0.8792 +vn 0.3787 0.7492 0.5434 +vn -0.0396 0.9992 0.0000 +vn -0.2778 0.7986 -0.5339 +vn -0.4098 0.2930 -0.8638 +vn -0.3853 -0.3245 -0.8638 +vn -0.2137 -0.8181 -0.5339 +vn 0.0396 -0.9992 -0.0000 +vn 0.2778 -0.7986 0.5339 +vn 0.4098 -0.2930 0.8638 +vn 0.3853 0.3245 0.8638 +vn 0.2137 0.8181 0.5339 +vn -0.2777 0.9607 0.0000 +vn -0.4732 0.7054 -0.5278 +vn -0.4879 0.1806 -0.8540 +vn -0.3163 -0.4131 -0.8540 +vn -0.0239 -0.8490 -0.5278 +vn 0.2777 -0.9607 -0.0000 +vn 0.4732 -0.7054 0.5278 +vn 0.4879 -0.1806 0.8540 +vn 0.3163 0.4131 0.8540 +vn 0.0239 0.8490 0.5278 +vn -0.5015 0.8651 0.0000 +vn -0.6332 0.5681 -0.5257 +vn -0.5229 0.0540 -0.8507 +vn -0.2130 -0.4807 -0.8507 +vn 0.1783 -0.8318 -0.5257 +vn 0.5015 -0.8651 -0.0000 +vn 0.6332 -0.5681 0.5257 +vn 0.5229 -0.0540 0.8507 +vn 0.2130 0.4807 0.8507 +vn -0.1783 0.8318 0.5257 +vn -0.6956 0.7184 0.0000 +vn -0.7485 0.4013 -0.5279 +vn -0.5155 -0.0690 -0.8541 +vn -0.0856 -0.5130 -0.8541 +vn 0.3770 -0.7611 -0.5279 +vn 0.6956 -0.7184 -0.0000 +vn 0.7485 -0.4013 0.5279 +vn 0.5155 0.0690 0.8541 +vn 0.0856 0.5130 0.8541 +vn -0.3770 0.7611 0.5279 +vn -0.8474 0.5310 0.0000 +vn -0.8160 0.2214 -0.5340 +vn -0.4729 -0.1727 -0.8640 +vn 0.0508 -0.5009 -0.8640 +vn 0.5551 -0.6378 -0.5340 +vn 0.8474 -0.5310 -0.0000 +vn 0.8160 -0.2214 0.5340 +vn 0.4729 0.1727 0.8640 +vn -0.0508 0.5009 0.8640 +vn -0.5551 0.6378 0.5340 +vn -0.9484 0.3169 0.0000 +vn -0.8382 0.0441 -0.5435 +vn -0.4079 -0.2455 -0.8794 +vn 0.1783 -0.4414 -0.8794 +vn 0.6964 -0.4687 -0.5435 +vn 0.9484 -0.3169 -0.0000 +vn 0.8382 -0.0441 0.5435 +vn 0.4079 0.2455 0.8794 +vn -0.1783 0.4414 0.8794 +vn -0.6964 0.4687 0.5435 +vn -0.9958 0.0913 0.0000 +vn -0.8232 -0.1177 -0.5554 +vn -0.3362 -0.2818 -0.8986 +vn 0.2793 -0.3383 -0.8986 +vn 0.7881 -0.2655 -0.5554 +vn 0.9958 -0.0913 -0.0000 +vn 0.8232 0.1177 0.5554 +vn 0.3362 0.2818 0.8986 +vn -0.2793 0.3383 0.8986 +vn -0.7881 0.2655 0.5554 +vn -0.9913 -0.1313 0.0000 +vn -0.7822 -0.2558 -0.5681 +vn -0.2743 -0.2826 -0.9192 +vn 0.3384 -0.2014 -0.9192 +vn 0.8218 -0.0433 -0.5681 +vn 0.9913 0.1313 -0.0000 +vn 0.7822 0.2558 0.5681 +vn 0.2743 0.2826 0.9192 +vn -0.3384 0.2014 0.9192 +vn -0.8218 0.0433 0.5681 +vn -0.9409 -0.3387 0.0000 +vn -0.7278 -0.3667 -0.5795 +vn -0.2368 -0.2547 -0.9376 +vn 0.3448 -0.0454 -0.9376 +vn 0.7946 0.1813 -0.5795 +vn 0.9409 0.3387 -0.0000 +vn 0.7278 0.3667 0.5795 +vn 0.2368 0.2547 0.9376 +vn -0.3448 0.0454 0.9376 +vn -0.7946 -0.1813 0.5795 +vn -0.8534 -0.5212 0.0000 +vn -0.6721 -0.4517 -0.5867 +vn -0.2341 -0.2096 -0.9494 +vn 0.2934 0.1125 -0.9494 +vn 0.7088 0.3916 -0.5867 +vn 0.8534 0.5212 -0.0000 +vn 0.6721 0.4517 0.5867 +vn 0.2341 0.2096 0.9494 +vn -0.2934 -0.1125 0.9494 +vn -0.7088 -0.3916 0.5867 +vn -0.7399 -0.6727 0.0000 +vn -0.6246 -0.5156 -0.5865 +vn -0.2708 -0.1616 -0.9490 +vn 0.1865 0.2542 -0.9490 +vn 0.5726 0.5729 -0.5865 +vn 0.7399 0.6727 -0.0000 +vn 0.6246 0.5156 0.5865 +vn 0.2708 0.1616 0.9490 +vn -0.1865 -0.2542 0.9490 +vn -0.5726 -0.5729 0.5865 +vn -0.6126 -0.7904 0.0000 +vn -0.5914 -0.5652 -0.5752 +vn -0.3442 -0.1241 -0.9306 +vn 0.0344 0.3643 -0.9306 +vn 0.3999 0.7136 -0.5752 +vn 0.6126 0.7904 -0.0000 +vn 0.5914 0.5652 0.5752 +vn 0.3442 0.1241 0.9306 +vn -0.0344 -0.3643 0.9306 +vn -0.3999 -0.7136 0.5752 +vn -0.4856 -0.8742 0.0000 +vn -0.5751 -0.6060 -0.5496 +vn -0.4449 -0.1064 -0.8892 +vn -0.1448 0.4339 -0.8892 +vn 0.2106 0.8085 -0.5496 +vn 0.4856 0.8742 -0.0000 +vn 0.5751 0.6060 0.5496 +vn 0.4449 0.1064 0.8892 +vn 0.1448 -0.4339 0.8892 +vn -0.2106 -0.8085 0.5496 +vn -0.3747 -0.9271 0.0000 +vn -0.5765 -0.6396 -0.5085 +vn -0.5580 -0.1078 -0.8228 +vn -0.3264 0.4652 -0.8228 +vn 0.0299 0.8605 -0.5085 +vn 0.3747 0.9271 -0.0000 +vn 0.5765 0.6396 0.5085 +vn 0.5580 0.1078 0.8228 +vn 0.3264 -0.4652 0.8228 +vn -0.0299 -0.8605 0.5085 +vn -0.3002 -0.9539 0.0000 +vn -0.5986 -0.6598 -0.4543 +vn -0.6683 -0.1137 -0.7351 +vn -0.4828 0.4759 -0.7351 +vn -0.1129 0.8836 -0.4543 +vn 0.3002 0.9539 -0.0000 +vn 0.5986 0.6598 0.4543 +vn 0.6683 0.1137 0.7351 +vn 0.4828 -0.4759 0.7351 +vn 0.1129 -0.8836 0.4543 +vn -0.2873 -0.9578 0.0000 +vn -0.6493 -0.6499 -0.3950 +vn -0.7633 -0.0937 -0.6392 +vn -0.5858 0.4983 -0.6392 +vn -0.1845 0.9000 -0.3950 +vn 0.2873 0.9578 -0.0000 +vn 0.6493 0.6499 0.3950 +vn 0.7633 0.0937 0.6392 +vn 0.5858 -0.4983 0.6392 +vn 0.1845 -0.9000 0.3950 +vn -0.3597 -0.9331 0.0000 +vn -0.7345 -0.5839 -0.3457 +vn -0.8288 -0.0117 -0.5594 +vn -0.6065 0.5650 -0.5594 +vn -0.1526 0.9258 -0.3457 +vn 0.3597 0.9331 -0.0000 +vn 0.7345 0.5839 0.3457 +vn 0.8288 0.0117 0.5594 +vn 0.6065 -0.5650 0.5594 +vn 0.1526 -0.9258 0.3457 +vn -0.5011 -0.8654 0.0000 +vn -0.8286 -0.4551 -0.3260 +vn -0.8397 0.1291 -0.5276 +vn -0.5300 0.6639 -0.5276 +vn -0.0179 0.9452 -0.3260 +vn 0.5011 0.8654 -0.0000 +vn 0.8286 0.4551 0.3260 +vn 0.8397 -0.1291 0.5276 +vn 0.5300 -0.6639 0.5276 +vn 0.0179 -0.9452 0.3260 +vn -0.6296 -0.7769 0.0000 +vn -0.8784 -0.3295 -0.3463 +vn -0.7916 0.2438 -0.5603 +vn -0.4025 0.7239 -0.5603 +vn 0.1404 0.9276 -0.3463 +vn 0.6296 0.7769 -0.0000 +vn 0.8784 0.3295 0.3463 +vn 0.7916 -0.2438 0.5603 +vn 0.4025 -0.7239 0.5603 +vn -0.1404 -0.9276 0.3463 +vn -0.6862 -0.7274 0.0000 +vn -0.8712 -0.2904 -0.3959 +vn -0.7235 0.2576 -0.6405 +vn -0.2994 0.7072 -0.6405 +vn 0.2390 0.8867 -0.3959 +vn 0.6862 0.7274 -0.0000 +vn 0.8712 0.2904 0.3959 +vn 0.7235 -0.2576 0.6405 +vn 0.2994 -0.7072 0.6405 +vn -0.2390 -0.8867 0.3959 +vn -0.6755 -0.7374 0.0000 +vn -0.8207 -0.3453 -0.4552 +vn -0.6525 0.1786 -0.7365 +vn -0.2350 0.6343 -0.7365 +vn 0.2722 0.8478 -0.4552 +vn 0.6755 0.7374 -0.0000 +vn 0.8207 0.3453 0.4552 +vn 0.6525 -0.1786 0.7365 +vn 0.2350 -0.6343 0.7365 +vn -0.2722 -0.8478 0.4552 +vn -0.6144 -0.7890 0.0000 +vn -0.7287 -0.4579 -0.5092 +vn -0.5647 0.0480 -0.8239 +vn -0.1850 0.5357 -0.8239 +vn 0.2654 0.8187 -0.5092 +vn 0.6144 0.7890 -0.0000 +vn 0.7287 0.4579 0.5092 +vn 0.5647 -0.0480 0.8239 +vn 0.1850 -0.5357 0.8239 +vn -0.2654 -0.8187 0.5092 +vn -0.5126 -0.8586 0.0000 +vn -0.5926 -0.5885 -0.5501 +vn -0.4462 -0.0935 -0.8900 +vn -0.1294 0.4372 -0.8900 +vn 0.2368 0.8009 -0.5501 +vn 0.5126 0.8586 -0.0000 +vn 0.5926 0.5885 0.5501 +vn 0.4462 0.0935 0.8900 +vn 0.1294 -0.4372 0.8900 +vn -0.2368 -0.8009 0.5501 +vn -0.3760 -0.9266 0.0000 +vn -0.4153 -0.7046 -0.5754 +vn -0.2960 -0.2134 -0.9311 +vn -0.0636 0.3593 -0.9311 +vn 0.1931 0.7947 -0.5754 +vn 0.3760 0.9266 -0.0000 +vn 0.4153 0.7046 0.5754 +vn 0.2960 0.2134 0.9311 +vn 0.0636 -0.3593 0.9311 +vn -0.1931 -0.7947 0.5754 +vn -0.2101 -0.9777 0.0000 +vn -0.2067 -0.7831 -0.5866 +vn -0.1244 -0.2893 -0.9491 +vn 0.0055 0.3149 -0.9491 +vn 0.1333 0.7989 -0.5866 +vn 0.2101 0.9777 -0.0000 +vn 0.2067 0.7831 0.5866 +vn 0.1244 0.2893 0.9491 +vn -0.0055 -0.3149 0.9491 +vn -0.1333 -0.7989 0.5866 +vn -0.0218 -0.9998 0.0000 +vn 0.0185 -0.8096 -0.5867 +vn 0.0517 -0.3102 -0.9493 +vn 0.0652 0.3077 -0.9493 +vn 0.0538 0.8080 -0.5867 +vn 0.0218 0.9998 -0.0000 +vn -0.0185 0.8096 0.5867 +vn -0.0517 0.3102 0.9493 +vn -0.0652 -0.3077 0.9493 +vn -0.0538 -0.8080 0.5867 +vn 0.1801 -0.9836 0.0000 +vn 0.2435 -0.7779 -0.5793 +vn 0.2138 -0.2750 -0.9374 +vn 0.1025 0.3329 -0.9374 +vn -0.0480 0.8137 -0.5793 +vn -0.1801 0.9836 -0.0000 +vn -0.2435 0.7779 0.5793 +vn -0.2138 0.2750 0.9374 +vn -0.1025 -0.3329 0.9374 +vn 0.0480 -0.8137 0.5793 +vn 0.3848 -0.9230 0.0000 +vn 0.4512 -0.6884 -0.5679 +vn 0.3452 -0.1909 -0.9189 +vn 0.1074 0.3796 -0.9189 +vn -0.1715 0.8050 -0.5679 +vn -0.3848 0.9230 -0.0000 +vn -0.4512 0.6884 0.5679 +vn -0.3452 0.1909 0.9189 +vn -0.1074 -0.3796 0.9189 +vn 0.1715 -0.8050 0.5679 +vn 0.5797 -0.8149 0.0000 +vn 0.6262 -0.5474 -0.5552 +vn 0.4335 -0.0708 -0.8984 +vn 0.0753 0.4328 -0.8984 +vn -0.3117 0.7711 -0.5552 +vn -0.5797 0.8149 -0.0000 +vn -0.6262 0.5474 0.5552 +vn -0.4335 0.0708 0.8984 +vn -0.0753 -0.4328 0.8984 +vn 0.3117 -0.7711 0.5552 +vn 0.7509 -0.6604 0.0000 +vn 0.7556 -0.3659 -0.5434 +vn 0.4716 0.0683 -0.8792 +vn 0.0075 0.4765 -0.8792 +vn -0.4595 0.7026 -0.5434 +vn -0.7509 0.6604 -0.0000 +vn -0.7556 0.3659 0.5434 +vn -0.4716 -0.0683 0.8792 +vn -0.0075 -0.4765 0.8792 +vn 0.4595 -0.7026 0.5434 +vn 0.8852 -0.4653 0.0000 +vn 0.8305 -0.1587 -0.5339 +vn 0.4587 0.2084 -0.8638 +vn -0.0884 0.4960 -0.8638 +vn -0.6017 0.5941 -0.5339 +vn -0.8852 0.4653 -0.0000 +vn -0.8305 0.1587 0.5339 +vn -0.4587 -0.2084 0.8638 +vn 0.0884 -0.4960 0.8638 +vn 0.6017 -0.5941 0.5339 +vn 0.9708 -0.2399 0.0000 +vn 0.8474 0.0571 -0.5278 +vn 0.4004 0.3322 -0.8540 +vn -0.1996 0.4805 -0.8540 +vn -0.7234 0.4452 -0.5278 +vn -0.9708 0.2399 -0.0000 +vn -0.8474 -0.0571 0.5278 +vn -0.4004 -0.3322 0.8540 +vn 0.1996 -0.4805 0.8540 +vn 0.7234 -0.4452 0.5278 +f 1//1 2//2 12//12 11//11 +f 2//2 3//3 13//13 12//12 +f 3//3 4//4 14//14 13//13 +f 4//4 5//5 15//15 14//14 +f 5//5 6//6 16//16 15//15 +f 6//6 7//7 17//17 16//16 +f 7//7 8//8 18//18 17//17 +f 8//8 9//9 19//19 18//18 +f 9//9 10//10 20//20 19//19 +f 10//10 1//1 11//11 20//20 +f 11//11 12//12 22//22 21//21 +f 12//12 13//13 23//23 22//22 +f 13//13 14//14 24//24 23//23 +f 14//14 15//15 25//25 24//24 +f 15//15 16//16 26//26 25//25 +f 16//16 17//17 27//27 26//26 +f 17//17 18//18 28//28 27//27 +f 18//18 19//19 29//29 28//28 +f 19//19 20//20 30//30 29//29 +f 20//20 11//11 21//21 30//30 +f 21//21 22//22 32//32 31//31 +f 22//22 23//23 33//33 32//32 +f 23//23 24//24 34//34 33//33 +f 24//24 25//25 35//35 34//34 +f 25//25 26//26 36//36 35//35 +f 26//26 27//27 37//37 36//36 +f 27//27 28//28 38//38 37//37 +f 28//28 29//29 39//39 38//38 +f 29//29 30//30 40//40 39//39 +f 30//30 21//21 31//31 40//40 +f 31//31 32//32 42//42 41//41 +f 32//32 33//33 43//43 42//42 +f 33//33 34//34 44//44 43//43 +f 34//34 35//35 45//45 44//44 +f 35//35 36//36 46//46 45//45 +f 36//36 37//37 47//47 46//46 +f 37//37 38//38 48//48 47//47 +f 38//38 39//39 49//49 48//48 +f 39//39 40//40 50//50 49//49 +f 40//40 31//31 41//41 50//50 +f 41//41 42//42 52//52 51//51 +f 42//42 43//43 53//53 52//52 +f 43//43 44//44 54//54 53//53 +f 44//44 45//45 55//55 54//54 +f 45//45 46//46 56//56 55//55 +f 46//46 47//47 57//57 56//56 +f 47//47 48//48 58//58 57//57 +f 48//48 49//49 59//59 58//58 +f 49//49 50//50 60//60 59//59 +f 50//50 41//41 51//51 60//60 +f 51//51 52//52 62//62 61//61 +f 52//52 53//53 63//63 62//62 +f 53//53 54//54 64//64 63//63 +f 54//54 55//55 65//65 64//64 +f 55//55 56//56 66//66 65//65 +f 56//56 57//57 67//67 66//66 +f 57//57 58//58 68//68 67//67 +f 58//58 59//59 69//69 68//68 +f 59//59 60//60 70//70 69//69 +f 60//60 51//51 61//61 70//70 +f 61//61 62//62 72//72 71//71 +f 62//62 63//63 73//73 72//72 +f 63//63 64//64 74//74 73//73 +f 64//64 65//65 75//75 74//74 +f 65//65 66//66 76//76 75//75 +f 66//66 67//67 77//77 76//76 +f 67//67 68//68 78//78 77//77 +f 68//68 69//69 79//79 78//78 +f 69//69 70//70 80//80 79//79 +f 70//70 61//61 71//71 80//80 +f 71//71 72//72 82//82 81//81 +f 72//72 73//73 83//83 82//82 +f 73//73 74//74 84//84 83//83 +f 74//74 75//75 85//85 84//84 +f 75//75 76//76 86//86 85//85 +f 76//76 77//77 87//87 86//86 +f 77//77 78//78 88//88 87//87 +f 78//78 79//79 89//89 88//88 +f 79//79 80//80 90//90 89//89 +f 80//80 71//71 81//81 90//90 +f 81//81 82//82 92//92 91//91 +f 82//82 83//83 93//93 92//92 +f 83//83 84//84 94//94 93//93 +f 84//84 85//85 95//95 94//94 +f 85//85 86//86 96//96 95//95 +f 86//86 87//87 97//97 96//96 +f 87//87 88//88 98//98 97//97 +f 88//88 89//89 99//99 98//98 +f 89//89 90//90 100//100 99//99 +f 90//90 81//81 91//91 100//100 +f 91//91 92//92 102//102 101//101 +f 92//92 93//93 103//103 102//102 +f 93//93 94//94 104//104 103//103 +f 94//94 95//95 105//105 104//104 +f 95//95 96//96 106//106 105//105 +f 96//96 97//97 107//107 106//106 +f 97//97 98//98 108//108 107//107 +f 98//98 99//99 109//109 108//108 +f 99//99 100//100 110//110 109//109 +f 100//100 91//91 101//101 110//110 +f 101//101 102//102 112//112 111//111 +f 102//102 103//103 113//113 112//112 +f 103//103 104//104 114//114 113//113 +f 104//104 105//105 115//115 114//114 +f 105//105 106//106 116//116 115//115 +f 106//106 107//107 117//117 116//116 +f 107//107 108//108 118//118 117//117 +f 108//108 109//109 119//119 118//118 +f 109//109 110//110 120//120 119//119 +f 110//110 101//101 111//111 120//120 +f 111//111 112//112 122//122 121//121 +f 112//112 113//113 123//123 122//122 +f 113//113 114//114 124//124 123//123 +f 114//114 115//115 125//125 124//124 +f 115//115 116//116 126//126 125//125 +f 116//116 117//117 127//127 126//126 +f 117//117 118//118 128//128 127//127 +f 118//118 119//119 129//129 128//128 +f 119//119 120//120 130//130 129//129 +f 120//120 111//111 121//121 130//130 +f 121//121 122//122 132//132 131//131 +f 122//122 123//123 133//133 132//132 +f 123//123 124//124 134//134 133//133 +f 124//124 125//125 135//135 134//134 +f 125//125 126//126 136//136 135//135 +f 126//126 127//127 137//137 136//136 +f 127//127 128//128 138//138 137//137 +f 128//128 129//129 139//139 138//138 +f 129//129 130//130 140//140 139//139 +f 130//130 121//121 131//131 140//140 +f 131//131 132//132 142//142 141//141 +f 132//132 133//133 143//143 142//142 +f 133//133 134//134 144//144 143//143 +f 134//134 135//135 145//145 144//144 +f 135//135 136//136 146//146 145//145 +f 136//136 137//137 147//147 146//146 +f 137//137 138//138 148//148 147//147 +f 138//138 139//139 149//149 148//148 +f 139//139 140//140 150//150 149//149 +f 140//140 131//131 141//141 150//150 +f 141//141 142//142 152//152 151//151 +f 142//142 143//143 153//153 152//152 +f 143//143 144//144 154//154 153//153 +f 144//144 145//145 155//155 154//154 +f 145//145 146//146 156//156 155//155 +f 146//146 147//147 157//157 156//156 +f 147//147 148//148 158//158 157//157 +f 148//148 149//149 159//159 158//158 +f 149//149 150//150 160//160 159//159 +f 150//150 141//141 151//151 160//160 +f 151//151 152//152 162//162 161//161 +f 152//152 153//153 163//163 162//162 +f 153//153 154//154 164//164 163//163 +f 154//154 155//155 165//165 164//164 +f 155//155 156//156 166//166 165//165 +f 156//156 157//157 167//167 166//166 +f 157//157 158//158 168//168 167//167 +f 158//158 159//159 169//169 168//168 +f 159//159 160//160 170//170 169//169 +f 160//160 151//151 161//161 170//170 +f 161//161 162//162 172//172 171//171 +f 162//162 163//163 173//173 172//172 +f 163//163 164//164 174//174 173//173 +f 164//164 165//165 175//175 174//174 +f 165//165 166//166 176//176 175//175 +f 166//166 167//167 177//177 176//176 +f 167//167 168//168 178//178 177//177 +f 168//168 169//169 179//179 178//178 +f 169//169 170//170 180//180 179//179 +f 170//170 161//161 171//171 180//180 +f 171//171 172//172 182//182 181//181 +f 172//172 173//173 183//183 182//182 +f 173//173 174//174 184//184 183//183 +f 174//174 175//175 185//185 184//184 +f 175//175 176//176 186//186 185//185 +f 176//176 177//177 187//187 186//186 +f 177//177 178//178 188//188 187//187 +f 178//178 179//179 189//189 188//188 +f 179//179 180//180 190//190 189//189 +f 180//180 171//171 181//181 190//190 +f 181//181 182//182 192//192 191//191 +f 182//182 183//183 193//193 192//192 +f 183//183 184//184 194//194 193//193 +f 184//184 185//185 195//195 194//194 +f 185//185 186//186 196//196 195//195 +f 186//186 187//187 197//197 196//196 +f 187//187 188//188 198//198 197//197 +f 188//188 189//189 199//199 198//198 +f 189//189 190//190 200//200 199//199 +f 190//190 181//181 191//191 200//200 +f 191//191 192//192 202//202 201//201 +f 192//192 193//193 203//203 202//202 +f 193//193 194//194 204//204 203//203 +f 194//194 195//195 205//205 204//204 +f 195//195 196//196 206//206 205//205 +f 196//196 197//197 207//207 206//206 +f 197//197 198//198 208//208 207//207 +f 198//198 199//199 209//209 208//208 +f 199//199 200//200 210//210 209//209 +f 200//200 191//191 201//201 210//210 +f 201//201 202//202 212//212 211//211 +f 202//202 203//203 213//213 212//212 +f 203//203 204//204 214//214 213//213 +f 204//204 205//205 215//215 214//214 +f 205//205 206//206 216//216 215//215 +f 206//206 207//207 217//217 216//216 +f 207//207 208//208 218//218 217//217 +f 208//208 209//209 219//219 218//218 +f 209//209 210//210 220//220 219//219 +f 210//210 201//201 211//211 220//220 +f 211//211 212//212 222//222 221//221 +f 212//212 213//213 223//223 222//222 +f 213//213 214//214 224//224 223//223 +f 214//214 215//215 225//225 224//224 +f 215//215 216//216 226//226 225//225 +f 216//216 217//217 227//227 226//226 +f 217//217 218//218 228//228 227//227 +f 218//218 219//219 229//229 228//228 +f 219//219 220//220 230//230 229//229 +f 220//220 211//211 221//221 230//230 +f 221//221 222//222 232//232 231//231 +f 222//222 223//223 233//233 232//232 +f 223//223 224//224 234//234 233//233 +f 224//224 225//225 235//235 234//234 +f 225//225 226//226 236//236 235//235 +f 226//226 227//227 237//237 236//236 +f 227//227 228//228 238//238 237//237 +f 228//228 229//229 239//239 238//238 +f 229//229 230//230 240//240 239//239 +f 230//230 221//221 231//231 240//240 +f 231//231 232//232 242//242 241//241 +f 232//232 233//233 243//243 242//242 +f 233//233 234//234 244//244 243//243 +f 234//234 235//235 245//245 244//244 +f 235//235 236//236 246//246 245//245 +f 236//236 237//237 247//247 246//246 +f 237//237 238//238 248//248 247//247 +f 238//238 239//239 249//249 248//248 +f 239//239 240//240 250//250 249//249 +f 240//240 231//231 241//241 250//250 +f 241//241 242//242 252//252 251//251 +f 242//242 243//243 253//253 252//252 +f 243//243 244//244 254//254 253//253 +f 244//244 245//245 255//255 254//254 +f 245//245 246//246 256//256 255//255 +f 246//246 247//247 257//257 256//256 +f 247//247 248//248 258//258 257//257 +f 248//248 249//249 259//259 258//258 +f 249//249 250//250 260//260 259//259 +f 250//250 241//241 251//251 260//260 +f 251//251 252//252 262//262 261//261 +f 252//252 253//253 263//263 262//262 +f 253//253 254//254 264//264 263//263 +f 254//254 255//255 265//265 264//264 +f 255//255 256//256 266//266 265//265 +f 256//256 257//257 267//267 266//266 +f 257//257 258//258 268//268 267//267 +f 258//258 259//259 269//269 268//268 +f 259//259 260//260 270//270 269//269 +f 260//260 251//251 261//261 270//270 +f 261//261 262//262 272//272 271//271 +f 262//262 263//263 273//273 272//272 +f 263//263 264//264 274//274 273//273 +f 264//264 265//265 275//275 274//274 +f 265//265 266//266 276//276 275//275 +f 266//266 267//267 277//277 276//276 +f 267//267 268//268 278//278 277//277 +f 268//268 269//269 279//279 278//278 +f 269//269 270//270 280//280 279//279 +f 270//270 261//261 271//271 280//280 +f 271//271 272//272 282//282 281//281 +f 272//272 273//273 283//283 282//282 +f 273//273 274//274 284//284 283//283 +f 274//274 275//275 285//285 284//284 +f 275//275 276//276 286//286 285//285 +f 276//276 277//277 287//287 286//286 +f 277//277 278//278 288//288 287//287 +f 278//278 279//279 289//289 288//288 +f 279//279 280//280 290//290 289//289 +f 280//280 271//271 281//281 290//290 +f 281//281 282//282 292//292 291//291 +f 282//282 283//283 293//293 292//292 +f 283//283 284//284 294//294 293//293 +f 284//284 285//285 295//295 294//294 +f 285//285 286//286 296//296 295//295 +f 286//286 287//287 297//297 296//296 +f 287//287 288//288 298//298 297//297 +f 288//288 289//289 299//299 298//298 +f 289//289 290//290 300//300 299//299 +f 290//290 281//281 291//291 300//300 +f 291//291 292//292 302//302 301//301 +f 292//292 293//293 303//303 302//302 +f 293//293 294//294 304//304 303//303 +f 294//294 295//295 305//305 304//304 +f 295//295 296//296 306//306 305//305 +f 296//296 297//297 307//307 306//306 +f 297//297 298//298 308//308 307//307 +f 298//298 299//299 309//309 308//308 +f 299//299 300//300 310//310 309//309 +f 300//300 291//291 301//301 310//310 +f 301//301 302//302 312//312 311//311 +f 302//302 303//303 313//313 312//312 +f 303//303 304//304 314//314 313//313 +f 304//304 305//305 315//315 314//314 +f 305//305 306//306 316//316 315//315 +f 306//306 307//307 317//317 316//316 +f 307//307 308//308 318//318 317//317 +f 308//308 309//309 319//319 318//318 +f 309//309 310//310 320//320 319//319 +f 310//310 301//301 311//311 320//320 +f 311//311 312//312 322//322 321//321 +f 312//312 313//313 323//323 322//322 +f 313//313 314//314 324//324 323//323 +f 314//314 315//315 325//325 324//324 +f 315//315 316//316 326//326 325//325 +f 316//316 317//317 327//327 326//326 +f 317//317 318//318 328//328 327//327 +f 318//318 319//319 329//329 328//328 +f 319//319 320//320 330//330 329//329 +f 320//320 311//311 321//321 330//330 +f 321//321 322//322 332//332 331//331 +f 322//322 323//323 333//333 332//332 +f 323//323 324//324 334//334 333//333 +f 324//324 325//325 335//335 334//334 +f 325//325 326//326 336//336 335//335 +f 326//326 327//327 337//337 336//336 +f 327//327 328//328 338//338 337//337 +f 328//328 329//329 339//339 338//338 +f 329//329 330//330 340//340 339//339 +f 330//330 321//321 331//331 340//340 +f 331//331 332//332 342//342 341//341 +f 332//332 333//333 343//343 342//342 +f 333//333 334//334 344//344 343//343 +f 334//334 335//335 345//345 344//344 +f 335//335 336//336 346//346 345//345 +f 336//336 337//337 347//347 346//346 +f 337//337 338//338 348//348 347//347 +f 338//338 339//339 349//349 348//348 +f 339//339 340//340 350//350 349//349 +f 340//340 331//331 341//341 350//350 +f 341//341 342//342 352//352 351//351 +f 342//342 343//343 353//353 352//352 +f 343//343 344//344 354//354 353//353 +f 344//344 345//345 355//355 354//354 +f 345//345 346//346 356//356 355//355 +f 346//346 347//347 357//357 356//356 +f 347//347 348//348 358//358 357//357 +f 348//348 349//349 359//359 358//358 +f 349//349 350//350 360//360 359//359 +f 350//350 341//341 351//351 360//360 +f 351//351 352//352 362//362 361//361 +f 352//352 353//353 363//363 362//362 +f 353//353 354//354 364//364 363//363 +f 354//354 355//355 365//365 364//364 +f 355//355 356//356 366//366 365//365 +f 356//356 357//357 367//367 366//366 +f 357//357 358//358 368//368 367//367 +f 358//358 359//359 369//369 368//368 +f 359//359 360//360 370//370 369//369 +f 360//360 351//351 361//361 370//370 +f 361//361 362//362 372//372 371//371 +f 362//362 363//363 373//373 372//372 +f 363//363 364//364 374//374 373//373 +f 364//364 365//365 375//375 374//374 +f 365//365 366//366 376//376 375//375 +f 366//366 367//367 377//377 376//376 +f 367//367 368//368 378//378 377//377 +f 368//368 369//369 379//379 378//378 +f 369//369 370//370 380//380 379//379 +f 370//370 361//361 371//371 380//380 +f 371//371 372//372 382//382 381//381 +f 372//372 373//373 383//383 382//382 +f 373//373 374//374 384//384 383//383 +f 374//374 375//375 385//385 384//384 +f 375//375 376//376 386//386 385//385 +f 376//376 377//377 387//387 386//386 +f 377//377 378//378 388//388 387//387 +f 378//378 379//379 389//389 388//388 +f 379//379 380//380 390//390 389//389 +f 380//380 371//371 381//381 390//390 +f 381//381 382//382 392//392 391//391 +f 382//382 383//383 393//393 392//392 +f 383//383 384//384 394//394 393//393 +f 384//384 385//385 395//395 394//394 +f 385//385 386//386 396//396 395//395 +f 386//386 387//387 397//397 396//396 +f 387//387 388//388 398//398 397//397 +f 388//388 389//389 399//399 398//398 +f 389//389 390//390 400//400 399//399 +f 390//390 381//381 391//391 400//400 +f 391//391 392//392 402//402 401//401 +f 392//392 393//393 403//403 402//402 +f 393//393 394//394 404//404 403//403 +f 394//394 395//395 405//405 404//404 +f 395//395 396//396 406//406 405//405 +f 396//396 397//397 407//407 406//406 +f 397//397 398//398 408//408 407//407 +f 398//398 399//399 409//409 408//408 +f 399//399 400//400 410//410 409//409 +f 400//400 391//391 401//401 410//410 +f 401//401 402//402 412//412 411//411 +f 402//402 403//403 413//413 412//412 +f 403//403 404//404 414//414 413//413 +f 404//404 405//405 415//415 414//414 +f 405//405 406//406 416//416 415//415 +f 406//406 407//407 417//417 416//416 +f 407//407 408//408 418//418 417//417 +f 408//408 409//409 419//419 418//418 +f 409//409 410//410 420//420 419//419 +f 410//410 401//401 411//411 420//420 +f 411//411 412//412 422//422 421//421 +f 412//412 413//413 423//423 422//422 +f 413//413 414//414 424//424 423//423 +f 414//414 415//415 425//425 424//424 +f 415//415 416//416 426//426 425//425 +f 416//416 417//417 427//427 426//426 +f 417//417 418//418 428//428 427//427 +f 418//418 419//419 429//429 428//428 +f 419//419 420//420 430//430 429//429 +f 420//420 411//411 421//421 430//430 +f 421//421 422//422 432//432 431//431 +f 422//422 423//423 433//433 432//432 +f 423//423 424//424 434//434 433//433 +f 424//424 425//425 435//435 434//434 +f 425//425 426//426 436//436 435//435 +f 426//426 427//427 437//437 436//436 +f 427//427 428//428 438//438 437//437 +f 428//428 429//429 439//439 438//438 +f 429//429 430//430 440//440 439//439 +f 430//430 421//421 431//431 440//440 +f 431//431 432//432 442//442 441//441 +f 432//432 433//433 443//443 442//442 +f 433//433 434//434 444//444 443//443 +f 434//434 435//435 445//445 444//444 +f 435//435 436//436 446//446 445//445 +f 436//436 437//437 447//447 446//446 +f 437//437 438//438 448//448 447//447 +f 438//438 439//439 449//449 448//448 +f 439//439 440//440 450//450 449//449 +f 440//440 431//431 441//441 450//450 +f 441//441 442//442 452//452 451//451 +f 442//442 443//443 453//453 452//452 +f 443//443 444//444 454//454 453//453 +f 444//444 445//445 455//455 454//454 +f 445//445 446//446 456//456 455//455 +f 446//446 447//447 457//457 456//456 +f 447//447 448//448 458//458 457//457 +f 448//448 449//449 459//459 458//458 +f 449//449 450//450 460//460 459//459 +f 450//450 441//441 451//451 460//460 +f 451//451 452//452 462//462 461//461 +f 452//452 453//453 463//463 462//462 +f 453//453 454//454 464//464 463//463 +f 454//454 455//455 465//465 464//464 +f 455//455 456//456 466//466 465//465 +f 456//456 457//457 467//467 466//466 +f 457//457 458//458 468//468 467//467 +f 458//458 459//459 469//469 468//468 +f 459//459 460//460 470//470 469//469 +f 460//460 451//451 461//461 470//470 +f 461//461 462//462 472//472 471//471 +f 462//462 463//463 473//473 472//472 +f 463//463 464//464 474//474 473//473 +f 464//464 465//465 475//475 474//474 +f 465//465 466//466 476//476 475//475 +f 466//466 467//467 477//477 476//476 +f 467//467 468//468 478//478 477//477 +f 468//468 469//469 479//479 478//478 +f 469//469 470//470 480//480 479//479 +f 470//470 461//461 471//471 480//480 +f 471//471 472//472 482//482 481//481 +f 472//472 473//473 483//483 482//482 +f 473//473 474//474 484//484 483//483 +f 474//474 475//475 485//485 484//484 +f 475//475 476//476 486//486 485//485 +f 476//476 477//477 487//487 486//486 +f 477//477 478//478 488//488 487//487 +f 478//478 479//479 489//489 488//488 +f 479//479 480//480 490//490 489//489 +f 480//480 471//471 481//481 490//490 +f 481//481 482//482 492//492 491//491 +f 482//482 483//483 493//493 492//492 +f 483//483 484//484 494//494 493//493 +f 484//484 485//485 495//495 494//494 +f 485//485 486//486 496//496 495//495 +f 486//486 487//487 497//497 496//496 +f 487//487 488//488 498//498 497//497 +f 488//488 489//489 499//499 498//498 +f 489//489 490//490 500//500 499//499 +f 490//490 481//481 491//491 500//500 +f 491//491 492//492 502//502 501//501 +f 492//492 493//493 503//503 502//502 +f 493//493 494//494 504//504 503//503 +f 494//494 495//495 505//505 504//504 +f 495//495 496//496 506//506 505//505 +f 496//496 497//497 507//507 506//506 +f 497//497 498//498 508//508 507//507 +f 498//498 499//499 509//509 508//508 +f 499//499 500//500 510//510 509//509 +f 500//500 491//491 501//501 510//510 +f 501//501 502//502 512//512 511//511 +f 502//502 503//503 513//513 512//512 +f 503//503 504//504 514//514 513//513 +f 504//504 505//505 515//515 514//514 +f 505//505 506//506 516//516 515//515 +f 506//506 507//507 517//517 516//516 +f 507//507 508//508 518//518 517//517 +f 508//508 509//509 519//519 518//518 +f 509//509 510//510 520//520 519//519 +f 510//510 501//501 511//511 520//520 +f 511//511 512//512 522//522 521//521 +f 512//512 513//513 523//523 522//522 +f 513//513 514//514 524//524 523//523 +f 514//514 515//515 525//525 524//524 +f 515//515 516//516 526//526 525//525 +f 516//516 517//517 527//527 526//526 +f 517//517 518//518 528//528 527//527 +f 518//518 519//519 529//529 528//528 +f 519//519 520//520 530//530 529//529 +f 520//520 511//511 521//521 530//530 +f 521//521 522//522 532//532 531//531 +f 522//522 523//523 533//533 532//532 +f 523//523 524//524 534//534 533//533 +f 524//524 525//525 535//535 534//534 +f 525//525 526//526 536//536 535//535 +f 526//526 527//527 537//537 536//536 +f 527//527 528//528 538//538 537//537 +f 528//528 529//529 539//539 538//538 +f 529//529 530//530 540//540 539//539 +f 530//530 521//521 531//531 540//540 +f 531//531 532//532 542//542 541//541 +f 532//532 533//533 543//543 542//542 +f 533//533 534//534 544//544 543//543 +f 534//534 535//535 545//545 544//544 +f 535//535 536//536 546//546 545//545 +f 536//536 537//537 547//547 546//546 +f 537//537 538//538 548//548 547//547 +f 538//538 539//539 549//549 548//548 +f 539//539 540//540 550//550 549//549 +f 540//540 531//531 541//541 550//550 +f 541//541 542//542 552//552 551//551 +f 542//542 543//543 553//553 552//552 +f 543//543 544//544 554//554 553//553 +f 544//544 545//545 555//555 554//554 +f 545//545 546//546 556//556 555//555 +f 546//546 547//547 557//557 556//556 +f 547//547 548//548 558//558 557//557 +f 548//548 549//549 559//559 558//558 +f 549//549 550//550 560//560 559//559 +f 550//550 541//541 551//551 560//560 +f 551//551 552//552 562//562 561//561 +f 552//552 553//553 563//563 562//562 +f 553//553 554//554 564//564 563//563 +f 554//554 555//555 565//565 564//564 +f 555//555 556//556 566//566 565//565 +f 556//556 557//557 567//567 566//566 +f 557//557 558//558 568//568 567//567 +f 558//558 559//559 569//569 568//568 +f 559//559 560//560 570//570 569//569 +f 560//560 551//551 561//561 570//570 +f 561//561 562//562 572//572 571//571 +f 562//562 563//563 573//573 572//572 +f 563//563 564//564 574//574 573//573 +f 564//564 565//565 575//575 574//574 +f 565//565 566//566 576//576 575//575 +f 566//566 567//567 577//577 576//576 +f 567//567 568//568 578//578 577//577 +f 568//568 569//569 579//579 578//578 +f 569//569 570//570 580//580 579//579 +f 570//570 561//561 571//571 580//580 +f 571//571 572//572 582//582 581//581 +f 572//572 573//573 583//583 582//582 +f 573//573 574//574 584//584 583//583 +f 574//574 575//575 585//585 584//584 +f 575//575 576//576 586//586 585//585 +f 576//576 577//577 587//587 586//586 +f 577//577 578//578 588//588 587//587 +f 578//578 579//579 589//589 588//588 +f 579//579 580//580 590//590 589//589 +f 580//580 571//571 581//581 590//590 +f 581//581 582//582 592//592 591//591 +f 582//582 583//583 593//593 592//592 +f 583//583 584//584 594//594 593//593 +f 584//584 585//585 595//595 594//594 +f 585//585 586//586 596//596 595//595 +f 586//586 587//587 597//597 596//596 +f 587//587 588//588 598//598 597//597 +f 588//588 589//589 599//599 598//598 +f 589//589 590//590 600//600 599//599 +f 590//590 581//581 591//591 600//600 +f 591//591 592//592 602//602 601//601 +f 592//592 593//593 603//603 602//602 +f 593//593 594//594 604//604 603//603 +f 594//594 595//595 605//605 604//604 +f 595//595 596//596 606//606 605//605 +f 596//596 597//597 607//607 606//606 +f 597//597 598//598 608//608 607//607 +f 598//598 599//599 609//609 608//608 +f 599//599 600//600 610//610 609//609 +f 600//600 591//591 601//601 610//610 +f 601//601 602//602 612//612 611//611 +f 602//602 603//603 613//613 612//612 +f 603//603 604//604 614//614 613//613 +f 604//604 605//605 615//615 614//614 +f 605//605 606//606 616//616 615//615 +f 606//606 607//607 617//617 616//616 +f 607//607 608//608 618//618 617//617 +f 608//608 609//609 619//619 618//618 +f 609//609 610//610 620//620 619//619 +f 610//610 601//601 611//611 620//620 +f 611//611 612//612 622//622 621//621 +f 612//612 613//613 623//623 622//622 +f 613//613 614//614 624//624 623//623 +f 614//614 615//615 625//625 624//624 +f 615//615 616//616 626//626 625//625 +f 616//616 617//617 627//627 626//626 +f 617//617 618//618 628//628 627//627 +f 618//618 619//619 629//629 628//628 +f 619//619 620//620 630//630 629//629 +f 620//620 611//611 621//621 630//630 +f 621//621 622//622 632//632 631//631 +f 622//622 623//623 633//633 632//632 +f 623//623 624//624 634//634 633//633 +f 624//624 625//625 635//635 634//634 +f 625//625 626//626 636//636 635//635 +f 626//626 627//627 637//637 636//636 +f 627//627 628//628 638//638 637//637 +f 628//628 629//629 639//639 638//638 +f 629//629 630//630 640//640 639//639 +f 630//630 621//621 631//631 640//640 +f 631//631 632//632 642//642 641//641 +f 632//632 633//633 643//643 642//642 +f 633//633 634//634 644//644 643//643 +f 634//634 635//635 645//645 644//644 +f 635//635 636//636 646//646 645//645 +f 636//636 637//637 647//647 646//646 +f 637//637 638//638 648//648 647//647 +f 638//638 639//639 649//649 648//648 +f 639//639 640//640 650//650 649//649 +f 640//640 631//631 641//641 650//650 +f 641//641 642//642 652//652 651//651 +f 642//642 643//643 653//653 652//652 +f 643//643 644//644 654//654 653//653 +f 644//644 645//645 655//655 654//654 +f 645//645 646//646 656//656 655//655 +f 646//646 647//647 657//657 656//656 +f 647//647 648//648 658//658 657//657 +f 648//648 649//649 659//659 658//658 +f 649//649 650//650 660//660 659//659 +f 650//650 641//641 651//651 660//660 +f 651//651 652//652 662//662 661//661 +f 652//652 653//653 663//663 662//662 +f 653//653 654//654 664//664 663//663 +f 654//654 655//655 665//665 664//664 +f 655//655 656//656 666//666 665//665 +f 656//656 657//657 667//667 666//666 +f 657//657 658//658 668//668 667//667 +f 658//658 659//659 669//669 668//668 +f 659//659 660//660 670//670 669//669 +f 660//660 651//651 661//661 670//670 +f 661//661 662//662 672//672 671//671 +f 662//662 663//663 673//673 672//672 +f 663//663 664//664 674//674 673//673 +f 664//664 665//665 675//675 674//674 +f 665//665 666//666 676//676 675//675 +f 666//666 667//667 677//677 676//676 +f 667//667 668//668 678//678 677//677 +f 668//668 669//669 679//679 678//678 +f 669//669 670//670 680//680 679//679 +f 670//670 661//661 671//671 680//680 +f 671//671 672//672 682//682 681//681 +f 672//672 673//673 683//683 682//682 +f 673//673 674//674 684//684 683//683 +f 674//674 675//675 685//685 684//684 +f 675//675 676//676 686//686 685//685 +f 676//676 677//677 687//687 686//686 +f 677//677 678//678 688//688 687//687 +f 678//678 679//679 689//689 688//688 +f 679//679 680//680 690//690 689//689 +f 680//680 671//671 681//681 690//690 +f 681//681 682//682 692//692 691//691 +f 682//682 683//683 693//693 692//692 +f 683//683 684//684 694//694 693//693 +f 684//684 685//685 695//695 694//694 +f 685//685 686//686 696//696 695//695 +f 686//686 687//687 697//697 696//696 +f 687//687 688//688 698//698 697//697 +f 688//688 689//689 699//699 698//698 +f 689//689 690//690 700//700 699//699 +f 690//690 681//681 691//691 700//700 +f 691//691 692//692 702//702 701//701 +f 692//692 693//693 703//703 702//702 +f 693//693 694//694 704//704 703//703 +f 694//694 695//695 705//705 704//704 +f 695//695 696//696 706//706 705//705 +f 696//696 697//697 707//707 706//706 +f 697//697 698//698 708//708 707//707 +f 698//698 699//699 709//709 708//708 +f 699//699 700//700 710//710 709//709 +f 700//700 691//691 701//701 710//710 +f 701//701 702//702 712//712 711//711 +f 702//702 703//703 713//713 712//712 +f 703//703 704//704 714//714 713//713 +f 704//704 705//705 715//715 714//714 +f 705//705 706//706 716//716 715//715 +f 706//706 707//707 717//717 716//716 +f 707//707 708//708 718//718 717//717 +f 708//708 709//709 719//719 718//718 +f 709//709 710//710 720//720 719//719 +f 710//710 701//701 711//711 720//720 +f 711//711 712//712 722//722 721//721 +f 712//712 713//713 723//723 722//722 +f 713//713 714//714 724//724 723//723 +f 714//714 715//715 725//725 724//724 +f 715//715 716//716 726//726 725//725 +f 716//716 717//717 727//727 726//726 +f 717//717 718//718 728//728 727//727 +f 718//718 719//719 729//729 728//728 +f 719//719 720//720 730//730 729//729 +f 720//720 711//711 721//721 730//730 +f 721//721 722//722 732//732 731//731 +f 722//722 723//723 733//733 732//732 +f 723//723 724//724 734//734 733//733 +f 724//724 725//725 735//735 734//734 +f 725//725 726//726 736//736 735//735 +f 726//726 727//727 737//737 736//736 +f 727//727 728//728 738//738 737//737 +f 728//728 729//729 739//739 738//738 +f 729//729 730//730 740//740 739//739 +f 730//730 721//721 731//731 740//740 +f 731//731 732//732 742//742 741//741 +f 732//732 733//733 743//743 742//742 +f 733//733 734//734 744//744 743//743 +f 734//734 735//735 745//745 744//744 +f 735//735 736//736 746//746 745//745 +f 736//736 737//737 747//747 746//746 +f 737//737 738//738 748//748 747//747 +f 738//738 739//739 749//749 748//748 +f 739//739 740//740 750//750 749//749 +f 740//740 731//731 741//741 750//750 +f 741//741 742//742 752//752 751//751 +f 742//742 743//743 753//753 752//752 +f 743//743 744//744 754//754 753//753 +f 744//744 745//745 755//755 754//754 +f 745//745 746//746 756//756 755//755 +f 746//746 747//747 757//757 756//756 +f 747//747 748//748 758//758 757//757 +f 748//748 749//749 759//759 758//758 +f 749//749 750//750 760//760 759//759 +f 750//750 741//741 751//751 760//760 +f 751//751 752//752 762//762 761//761 +f 752//752 753//753 763//763 762//762 +f 753//753 754//754 764//764 763//763 +f 754//754 755//755 765//765 764//764 +f 755//755 756//756 766//766 765//765 +f 756//756 757//757 767//767 766//766 +f 757//757 758//758 768//768 767//767 +f 758//758 759//759 769//769 768//768 +f 759//759 760//760 770//770 769//769 +f 760//760 751//751 761//761 770//770 +f 761//761 762//762 772//772 771//771 +f 762//762 763//763 773//773 772//772 +f 763//763 764//764 774//774 773//773 +f 764//764 765//765 775//775 774//774 +f 765//765 766//766 776//776 775//775 +f 766//766 767//767 777//777 776//776 +f 767//767 768//768 778//778 777//777 +f 768//768 769//769 779//779 778//778 +f 769//769 770//770 780//780 779//779 +f 770//770 761//761 771//771 780//780 +f 771//771 772//772 782//782 781//781 +f 772//772 773//773 783//783 782//782 +f 773//773 774//774 784//784 783//783 +f 774//774 775//775 785//785 784//784 +f 775//775 776//776 786//786 785//785 +f 776//776 777//777 787//787 786//786 +f 777//777 778//778 788//788 787//787 +f 778//778 779//779 789//789 788//788 +f 779//779 780//780 790//790 789//789 +f 780//780 771//771 781//781 790//790 +f 781//781 782//782 792//792 791//791 +f 782//782 783//783 793//793 792//792 +f 783//783 784//784 794//794 793//793 +f 784//784 785//785 795//795 794//794 +f 785//785 786//786 796//796 795//795 +f 786//786 787//787 797//797 796//796 +f 787//787 788//788 798//798 797//797 +f 788//788 789//789 799//799 798//798 +f 789//789 790//790 800//800 799//799 +f 790//790 781//781 791//791 800//800 +f 791//791 792//792 802//802 801//801 +f 792//792 793//793 803//803 802//802 +f 793//793 794//794 804//804 803//803 +f 794//794 795//795 805//805 804//804 +f 795//795 796//796 806//806 805//805 +f 796//796 797//797 807//807 806//806 +f 797//797 798//798 808//808 807//807 +f 798//798 799//799 809//809 808//808 +f 799//799 800//800 810//810 809//809 +f 800//800 791//791 801//801 810//810 +f 801//801 802//802 812//812 811//811 +f 802//802 803//803 813//813 812//812 +f 803//803 804//804 814//814 813//813 +f 804//804 805//805 815//815 814//814 +f 805//805 806//806 816//816 815//815 +f 806//806 807//807 817//817 816//816 +f 807//807 808//808 818//818 817//817 +f 808//808 809//809 819//819 818//818 +f 809//809 810//810 820//820 819//819 +f 810//810 801//801 811//811 820//820 +f 811//811 812//812 822//822 821//821 +f 812//812 813//813 823//823 822//822 +f 813//813 814//814 824//824 823//823 +f 814//814 815//815 825//825 824//824 +f 815//815 816//816 826//826 825//825 +f 816//816 817//817 827//827 826//826 +f 817//817 818//818 828//828 827//827 +f 818//818 819//819 829//829 828//828 +f 819//819 820//820 830//830 829//829 +f 820//820 811//811 821//821 830//830 +f 821//821 822//822 832//832 831//831 +f 822//822 823//823 833//833 832//832 +f 823//823 824//824 834//834 833//833 +f 824//824 825//825 835//835 834//834 +f 825//825 826//826 836//836 835//835 +f 826//826 827//827 837//837 836//836 +f 827//827 828//828 838//838 837//837 +f 828//828 829//829 839//839 838//838 +f 829//829 830//830 840//840 839//839 +f 830//830 821//821 831//831 840//840 +f 831//831 832//832 842//842 841//841 +f 832//832 833//833 843//843 842//842 +f 833//833 834//834 844//844 843//843 +f 834//834 835//835 845//845 844//844 +f 835//835 836//836 846//846 845//845 +f 836//836 837//837 847//847 846//846 +f 837//837 838//838 848//848 847//847 +f 838//838 839//839 849//849 848//848 +f 839//839 840//840 850//850 849//849 +f 840//840 831//831 841//841 850//850 +f 841//841 842//842 852//852 851//851 +f 842//842 843//843 853//853 852//852 +f 843//843 844//844 854//854 853//853 +f 844//844 845//845 855//855 854//854 +f 845//845 846//846 856//856 855//855 +f 846//846 847//847 857//857 856//856 +f 847//847 848//848 858//858 857//857 +f 848//848 849//849 859//859 858//858 +f 849//849 850//850 860//860 859//859 +f 850//850 841//841 851//851 860//860 +f 851//851 852//852 862//862 861//861 +f 852//852 853//853 863//863 862//862 +f 853//853 854//854 864//864 863//863 +f 854//854 855//855 865//865 864//864 +f 855//855 856//856 866//866 865//865 +f 856//856 857//857 867//867 866//866 +f 857//857 858//858 868//868 867//867 +f 858//858 859//859 869//869 868//868 +f 859//859 860//860 870//870 869//869 +f 860//860 851//851 861//861 870//870 +f 861//861 862//862 872//872 871//871 +f 862//862 863//863 873//873 872//872 +f 863//863 864//864 874//874 873//873 +f 864//864 865//865 875//875 874//874 +f 865//865 866//866 876//876 875//875 +f 866//866 867//867 877//877 876//876 +f 867//867 868//868 878//878 877//877 +f 868//868 869//869 879//879 878//878 +f 869//869 870//870 880//880 879//879 +f 870//870 861//861 871//871 880//880 +f 871//871 872//872 882//882 881//881 +f 872//872 873//873 883//883 882//882 +f 873//873 874//874 884//884 883//883 +f 874//874 875//875 885//885 884//884 +f 875//875 876//876 886//886 885//885 +f 876//876 877//877 887//887 886//886 +f 877//877 878//878 888//888 887//887 +f 878//878 879//879 889//889 888//888 +f 879//879 880//880 890//890 889//889 +f 880//880 871//871 881//881 890//890 +f 881//881 882//882 892//892 891//891 +f 882//882 883//883 893//893 892//892 +f 883//883 884//884 894//894 893//893 +f 884//884 885//885 895//895 894//894 +f 885//885 886//886 896//896 895//895 +f 886//886 887//887 897//897 896//896 +f 887//887 888//888 898//898 897//897 +f 888//888 889//889 899//899 898//898 +f 889//889 890//890 900//900 899//899 +f 890//890 881//881 891//891 900//900 +f 891//891 892//892 2//2 1//1 +f 892//892 893//893 3//3 2//2 +f 893//893 894//894 4//4 3//3 +f 894//894 895//895 5//5 4//4 +f 895//895 896//896 6//6 5//5 +f 896//896 897//897 7//7 6//6 +f 897//897 898//898 8//8 7//7 +f 898//898 899//899 9//9 8//8 +f 899//899 900//900 10//10 9//9 +f 900//900 891//891 1//1 10//10 +o base +v 4.2000 0.0000 -1.6 0.35 0.35 0.4 +v 4.2000 0.0000 -1.2 0.6 0.6 0.65 +v 4.1641 0.5482 -1.6 0.35 0.35 0.4 +v 4.1641 0.5482 -1.2 0.6 0.6 0.65 +v 4.0569 1.0870 -1.6 0.35 0.35 0.4 +v 4.0569 1.0870 -1.2 0.6 0.6 0.65 +v 3.8803 1.6073 -1.6 0.35 0.35 0.4 +v 3.8803 1.6073 -1.2 0.6 0.6 0.65 +v 3.6373 2.1000 -1.6 0.35 0.35 0.4 +v 3.6373 2.1000 -1.2 0.6 0.6 0.65 +v 3.3321 2.5568 -1.6 0.35 0.35 0.4 +v 3.3321 2.5568 -1.2 0.6 0.6 0.65 +v 2.9698 2.9698 -1.6 0.35 0.35 0.4 +v 2.9698 2.9698 -1.2 0.6 0.6 0.65 +v 2.5568 3.3321 -1.6 0.35 0.35 0.4 +v 2.5568 3.3321 -1.2 0.6 0.6 0.65 +v 2.1000 3.6373 -1.6 0.35 0.35 0.4 +v 2.1000 3.6373 -1.2 0.6 0.6 0.65 +v 1.6073 3.8803 -1.6 0.35 0.35 0.4 +v 1.6073 3.8803 -1.2 0.6 0.6 0.65 +v 1.0870 4.0569 -1.6 0.35 0.35 0.4 +v 1.0870 4.0569 -1.2 0.6 0.6 0.65 +v 0.5482 4.1641 -1.6 0.35 0.35 0.4 +v 0.5482 4.1641 -1.2 0.6 0.6 0.65 +v 0.0000 4.2000 -1.6 0.35 0.35 0.4 +v 0.0000 4.2000 -1.2 0.6 0.6 0.65 +v -0.5482 4.1641 -1.6 0.35 0.35 0.4 +v -0.5482 4.1641 -1.2 0.6 0.6 0.65 +v -1.0870 4.0569 -1.6 0.35 0.35 0.4 +v -1.0870 4.0569 -1.2 0.6 0.6 0.65 +v -1.6073 3.8803 -1.6 0.35 0.35 0.4 +v -1.6073 3.8803 -1.2 0.6 0.6 0.65 +v -2.1000 3.6373 -1.6 0.35 0.35 0.4 +v -2.1000 3.6373 -1.2 0.6 0.6 0.65 +v -2.5568 3.3321 -1.6 0.35 0.35 0.4 +v -2.5568 3.3321 -1.2 0.6 0.6 0.65 +v -2.9698 2.9698 -1.6 0.35 0.35 0.4 +v -2.9698 2.9698 -1.2 0.6 0.6 0.65 +v -3.3321 2.5568 -1.6 0.35 0.35 0.4 +v -3.3321 2.5568 -1.2 0.6 0.6 0.65 +v -3.6373 2.1000 -1.6 0.35 0.35 0.4 +v -3.6373 2.1000 -1.2 0.6 0.6 0.65 +v -3.8803 1.6073 -1.6 0.35 0.35 0.4 +v -3.8803 1.6073 -1.2 0.6 0.6 0.65 +v -4.0569 1.0870 -1.6 0.35 0.35 0.4 +v -4.0569 1.0870 -1.2 0.6 0.6 0.65 +v -4.1641 0.5482 -1.6 0.35 0.35 0.4 +v -4.1641 0.5482 -1.2 0.6 0.6 0.65 +v -4.2000 0.0000 -1.6 0.35 0.35 0.4 +v -4.2000 0.0000 -1.2 0.6 0.6 0.65 +v -4.1641 -0.5482 -1.6 0.35 0.35 0.4 +v -4.1641 -0.5482 -1.2 0.6 0.6 0.65 +v -4.0569 -1.0870 -1.6 0.35 0.35 0.4 +v -4.0569 -1.0870 -1.2 0.6 0.6 0.65 +v -3.8803 -1.6073 -1.6 0.35 0.35 0.4 +v -3.8803 -1.6073 -1.2 0.6 0.6 0.65 +v -3.6373 -2.1000 -1.6 0.35 0.35 0.4 +v -3.6373 -2.1000 -1.2 0.6 0.6 0.65 +v -3.3321 -2.5568 -1.6 0.35 0.35 0.4 +v -3.3321 -2.5568 -1.2 0.6 0.6 0.65 +v -2.9698 -2.9698 -1.6 0.35 0.35 0.4 +v -2.9698 -2.9698 -1.2 0.6 0.6 0.65 +v -2.5568 -3.3321 -1.6 0.35 0.35 0.4 +v -2.5568 -3.3321 -1.2 0.6 0.6 0.65 +v -2.1000 -3.6373 -1.6 0.35 0.35 0.4 +v -2.1000 -3.6373 -1.2 0.6 0.6 0.65 +v -1.6073 -3.8803 -1.6 0.35 0.35 0.4 +v -1.6073 -3.8803 -1.2 0.6 0.6 0.65 +v -1.0870 -4.0569 -1.6 0.35 0.35 0.4 +v -1.0870 -4.0569 -1.2 0.6 0.6 0.65 +v -0.5482 -4.1641 -1.6 0.35 0.35 0.4 +v -0.5482 -4.1641 -1.2 0.6 0.6 0.65 +v -0.0000 -4.2000 -1.6 0.35 0.35 0.4 +v -0.0000 -4.2000 -1.2 0.6 0.6 0.65 +v 0.5482 -4.1641 -1.6 0.35 0.35 0.4 +v 0.5482 -4.1641 -1.2 0.6 0.6 0.65 +v 1.0870 -4.0569 -1.6 0.35 0.35 0.4 +v 1.0870 -4.0569 -1.2 0.6 0.6 0.65 +v 1.6073 -3.8803 -1.6 0.35 0.35 0.4 +v 1.6073 -3.8803 -1.2 0.6 0.6 0.65 +v 2.1000 -3.6373 -1.6 0.35 0.35 0.4 +v 2.1000 -3.6373 -1.2 0.6 0.6 0.65 +v 2.5568 -3.3321 -1.6 0.35 0.35 0.4 +v 2.5568 -3.3321 -1.2 0.6 0.6 0.65 +v 2.9698 -2.9698 -1.6 0.35 0.35 0.4 +v 2.9698 -2.9698 -1.2 0.6 0.6 0.65 +v 3.3321 -2.5568 -1.6 0.35 0.35 0.4 +v 3.3321 -2.5568 -1.2 0.6 0.6 0.65 +v 3.6373 -2.1000 -1.6 0.35 0.35 0.4 +v 3.6373 -2.1000 -1.2 0.6 0.6 0.65 +v 3.8803 -1.6073 -1.6 0.35 0.35 0.4 +v 3.8803 -1.6073 -1.2 0.6 0.6 0.65 +v 4.0569 -1.0870 -1.6 0.35 0.35 0.4 +v 4.0569 -1.0870 -1.2 0.6 0.6 0.65 +v 4.1641 -0.5482 -1.6 0.35 0.35 0.4 +v 4.1641 -0.5482 -1.2 0.6 0.6 0.65 +v 0 0 -1.2 0.6 0.6 0.65 +f 901 903 904 902 +f 902 904 997 +f 903 905 906 904 +f 904 906 997 +f 905 907 908 906 +f 906 908 997 +f 907 909 910 908 +f 908 910 997 +f 909 911 912 910 +f 910 912 997 +f 911 913 914 912 +f 912 914 997 +f 913 915 916 914 +f 914 916 997 +f 915 917 918 916 +f 916 918 997 +f 917 919 920 918 +f 918 920 997 +f 919 921 922 920 +f 920 922 997 +f 921 923 924 922 +f 922 924 997 +f 923 925 926 924 +f 924 926 997 +f 925 927 928 926 +f 926 928 997 +f 927 929 930 928 +f 928 930 997 +f 929 931 932 930 +f 930 932 997 +f 931 933 934 932 +f 932 934 997 +f 933 935 936 934 +f 934 936 997 +f 935 937 938 936 +f 936 938 997 +f 937 939 940 938 +f 938 940 997 +f 939 941 942 940 +f 940 942 997 +f 941 943 944 942 +f 942 944 997 +f 943 945 946 944 +f 944 946 997 +f 945 947 948 946 +f 946 948 997 +f 947 949 950 948 +f 948 950 997 +f 949 951 952 950 +f 950 952 997 +f 951 953 954 952 +f 952 954 997 +f 953 955 956 954 +f 954 956 997 +f 955 957 958 956 +f 956 958 997 +f 957 959 960 958 +f 958 960 997 +f 959 961 962 960 +f 960 962 997 +f 961 963 964 962 +f 962 964 997 +f 963 965 966 964 +f 964 966 997 +f 965 967 968 966 +f 966 968 997 +f 967 969 970 968 +f 968 970 997 +f 969 971 972 970 +f 970 972 997 +f 971 973 974 972 +f 972 974 997 +f 973 975 976 974 +f 974 976 997 +f 975 977 978 976 +f 976 978 997 +f 977 979 980 978 +f 978 980 997 +f 979 981 982 980 +f 980 982 997 +f 981 983 984 982 +f 982 984 997 +f 983 985 986 984 +f 984 986 997 +f 985 987 988 986 +f 986 988 997 +f 987 989 990 988 +f 988 990 997 +f 989 991 992 990 +f 990 992 997 +f 991 993 994 992 +f 992 994 997 +f 993 995 996 994 +f 994 996 997 +f 995 901 902 996 +f 996 902 997 +f 903 901 997 +f 905 903 997 +f 907 905 997 +f 909 907 997 +f 911 909 997 +f 913 911 997 +f 915 913 997 +f 917 915 997 +f 919 917 997 +f 921 919 997 +f 923 921 997 +f 925 923 997 +f 927 925 997 +f 929 927 997 +f 931 929 997 +f 933 931 997 +f 935 933 997 +f 937 935 997 +f 939 937 997 +f 941 939 997 +f 943 941 997 +f 945 943 997 +f 947 945 997 +f 949 947 997 +f 951 949 997 +f 953 951 997 +f 955 953 997 +f 957 955 997 +f 959 957 997 +f 961 959 997 +f 963 961 997 +f 965 963 997 +f 967 965 997 +f 969 967 997 +f 971 969 997 +f 973 971 997 +f 975 973 997 +f 977 975 997 +f 979 977 997 +f 981 979 997 +f 983 981 997 +f 985 983 997 +f 987 985 997 +f 989 987 997 +f 991 989 997 +f 993 991 997 +f 995 993 997 +f 901 995 997 diff --git a/crates/exav-viewer/demo/examples/files/models/table.gltf b/crates/exav-viewer/demo/examples/files/models/table.gltf new file mode 100644 index 0000000..76b667c --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/models/table.gltf @@ -0,0 +1 @@ +{"asset":{"version":"2.0","generator":"exav make-models.py","copyright":"CC0-1.0"},"scene":0,"scenes":[{"nodes":[4,11,18]}],"nodes":[{"mesh":1,"translation":[-0.74,-0.39,-0.38],"name":"leg 0"},{"mesh":1,"translation":[0.74,-0.39,-0.38],"name":"leg 1"},{"mesh":1,"translation":[-0.74,-0.39,0.38],"name":"leg 2"},{"mesh":1,"translation":[0.74,-0.39,0.38],"name":"leg 3"},{"mesh":0,"translation":[0,0.74,0],"name":"table","children":[0,1,2,3]},{"mesh":1,"scale":[0.8,0.6,0.8],"translation":[-0.19,-0.2,-0.19],"name":"chair leg 0"},{"mesh":1,"scale":[0.8,0.6,0.8],"translation":[0.19,-0.2,-0.19],"name":"chair leg 1"},{"mesh":1,"scale":[0.8,0.6,0.8],"translation":[-0.19,-0.2,0.19],"name":"chair leg 2"},{"mesh":1,"scale":[0.8,0.6,0.8],"translation":[0.19,-0.2,0.19],"name":"chair leg 3"},{"mesh":3,"translation":[0,0.28,-0.2],"name":"back"},{"mesh":2,"translation":[0,0.45,0],"name":"seat","children":[5,6,7,8,9]},{"name":"chair a","translation":[-0.4,0,0.85],"children":[10]},{"mesh":3,"translation":[0,0.28,-0.2],"name":"back b"},{"mesh":1,"scale":[0.8,0.6,0.8],"translation":[-0.19,-0.2,-0.19]},{"mesh":1,"scale":[0.8,0.6,0.8],"translation":[0.19,-0.2,-0.19]},{"mesh":1,"scale":[0.8,0.6,0.8],"translation":[-0.19,-0.2,0.19]},{"mesh":1,"scale":[0.8,0.6,0.8],"translation":[0.19,-0.2,0.19]},{"mesh":2,"translation":[0,0.45,0],"name":"seat b","children":[12,13,14,15,16]},{"name":"chair b","translation":[0.5,0,-0.85],"rotation":[0.0,1.0,0.0,6.123233995736766e-17],"children":[17]}],"meshes":[{"name":"top","primitives":[{"attributes":{"POSITION":0,"NORMAL":1},"indices":2,"material":0,"mode":4}]},{"name":"leg","primitives":[{"attributes":{"POSITION":3,"NORMAL":4},"indices":5,"material":0,"mode":4}]},{"name":"seat","primitives":[{"attributes":{"POSITION":6,"NORMAL":7},"indices":8,"material":1,"mode":4}]},{"name":"back","primitives":[{"attributes":{"POSITION":9,"NORMAL":10},"indices":11,"material":1,"mode":4}]}],"materials":[{"name":"wood","pbrMetallicRoughness":{"baseColorFactor":[0.55,0.35,0.18,1],"metallicFactor":0.0,"roughnessFactor":0.7}},{"name":"cloth","pbrMetallicRoughness":{"baseColorFactor":[0.8,0.15,0.15,1],"metallicFactor":0.0,"roughnessFactor":0.9}}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"type":"VEC3","min":[-0.800000011920929,-0.03999999910593033,-0.44999998807907104],"max":[0.800000011920929,0.03999999910593033,0.44999998807907104]},{"bufferView":1,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":2,"componentType":5123,"count":36,"type":"SCALAR"},{"bufferView":3,"componentType":5126,"count":24,"type":"VEC3","min":[-0.03999999910593033,-0.3499999940395355,-0.03999999910593033],"max":[0.03999999910593033,0.3499999940395355,0.03999999910593033]},{"bufferView":4,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":5,"componentType":5123,"count":36,"type":"SCALAR"},{"bufferView":6,"componentType":5126,"count":24,"type":"VEC3","min":[-0.22499999403953552,-0.029999999329447746,-0.22499999403953552],"max":[0.22499999403953552,0.029999999329447746,0.22499999403953552]},{"bufferView":7,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":8,"componentType":5123,"count":36,"type":"SCALAR"},{"bufferView":9,"componentType":5126,"count":24,"type":"VEC3","min":[-0.22499999403953552,-0.25,-0.02500000037252903],"max":[0.22499999403953552,0.25,0.02500000037252903]},{"bufferView":10,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":11,"componentType":5123,"count":36,"type":"SCALAR"}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":288,"target":34962},{"buffer":0,"byteOffset":288,"byteLength":288,"target":34962},{"buffer":0,"byteOffset":576,"byteLength":72,"target":34963},{"buffer":0,"byteOffset":648,"byteLength":288,"target":34962},{"buffer":0,"byteOffset":936,"byteLength":288,"target":34962},{"buffer":0,"byteOffset":1224,"byteLength":72,"target":34963},{"buffer":0,"byteOffset":1296,"byteLength":288,"target":34962},{"buffer":0,"byteOffset":1584,"byteLength":288,"target":34962},{"buffer":0,"byteOffset":1872,"byteLength":72,"target":34963},{"buffer":0,"byteOffset":1944,"byteLength":288,"target":34962},{"buffer":0,"byteOffset":2232,"byteLength":288,"target":34962},{"buffer":0,"byteOffset":2520,"byteLength":72,"target":34963}],"buffers":[{"byteLength":2592,"uri":"data:application/octet-stream;base64,zcxMvwrXI71mZua+zcxMvwrXIz1mZua+zcxMvwrXIz1mZuY+zcxMvwrXI71mZuY+zcxMPwrXI71mZua+zcxMPwrXIz1mZua+zcxMPwrXIz1mZuY+zcxMPwrXI71mZuY+zcxMvwrXI71mZua+zcxMvwrXI71mZuY+zcxMPwrXI71mZuY+zcxMPwrXI71mZua+zcxMvwrXIz1mZua+zcxMvwrXIz1mZuY+zcxMPwrXIz1mZuY+zcxMPwrXIz1mZua+zcxMvwrXI71mZua+zcxMPwrXI71mZua+zcxMPwrXIz1mZua+zcxMvwrXIz1mZua+zcxMvwrXI71mZuY+zcxMPwrXI71mZuY+zcxMPwrXIz1mZuY+zcxMvwrXIz1mZuY+AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcACtcjvTMzs74K1yO9CtcjvTMzsz4K1yO9CtcjvTMzsz4K1yM9CtcjvTMzs74K1yM9CtcjPTMzs74K1yO9CtcjPTMzsz4K1yO9CtcjPTMzsz4K1yM9CtcjPTMzs74K1yM9CtcjvTMzs74K1yO9CtcjvTMzs74K1yM9CtcjPTMzs74K1yM9CtcjPTMzs74K1yO9CtcjvTMzsz4K1yO9CtcjvTMzsz4K1yM9CtcjPTMzsz4K1yM9CtcjPTMzsz4K1yO9CtcjvTMzs74K1yO9CtcjPTMzs74K1yO9CtcjPTMzsz4K1yO9CtcjvTMzsz4K1yO9CtcjvTMzs74K1yM9CtcjPTMzs74K1yM9CtcjPTMzsz4K1yM9CtcjvTMzsz4K1yM9AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcAZmZmvo/C9bxmZma+ZmZmvo/C9TxmZma+ZmZmvo/C9TxmZmY+ZmZmvo/C9bxmZmY+ZmZmPo/C9bxmZma+ZmZmPo/C9TxmZma+ZmZmPo/C9TxmZmY+ZmZmPo/C9bxmZmY+ZmZmvo/C9bxmZma+ZmZmvo/C9bxmZmY+ZmZmPo/C9bxmZmY+ZmZmPo/C9bxmZma+ZmZmvo/C9TxmZma+ZmZmvo/C9TxmZmY+ZmZmPo/C9TxmZmY+ZmZmPo/C9TxmZma+ZmZmvo/C9bxmZma+ZmZmPo/C9bxmZma+ZmZmPo/C9TxmZma+ZmZmvo/C9TxmZma+ZmZmvo/C9bxmZmY+ZmZmPo/C9bxmZmY+ZmZmPo/C9TxmZmY+ZmZmvo/C9TxmZmY+AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcAZmZmvgAAgL7NzMy8ZmZmvgAAgD7NzMy8ZmZmvgAAgD7NzMw8ZmZmvgAAgL7NzMw8ZmZmPgAAgL7NzMy8ZmZmPgAAgD7NzMy8ZmZmPgAAgD7NzMw8ZmZmPgAAgL7NzMw8ZmZmvgAAgL7NzMy8ZmZmvgAAgL7NzMw8ZmZmPgAAgL7NzMw8ZmZmPgAAgL7NzMy8ZmZmvgAAgD7NzMy8ZmZmvgAAgD7NzMw8ZmZmPgAAgD7NzMw8ZmZmPgAAgD7NzMy8ZmZmvgAAgL7NzMy8ZmZmPgAAgL7NzMy8ZmZmPgAAgD7NzMy8ZmZmvgAAgD7NzMy8ZmZmvgAAgL7NzMw8ZmZmPgAAgL7NzMw8ZmZmPgAAgD7NzMw8ZmZmvgAAgD7NzMw8AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcA"}]} \ No newline at end of file diff --git a/crates/exav-viewer/demo/examples/files/models/terrain.ply b/crates/exav-viewer/demo/examples/files/models/terrain.ply new file mode 100644 index 0000000..0f93c57 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/models/terrain.ply differ diff --git a/crates/exav-viewer/demo/examples/files/office/deck.pptx b/crates/exav-viewer/demo/examples/files/office/deck.pptx new file mode 100644 index 0000000..257d3ec Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/office/deck.pptx differ diff --git a/crates/exav-viewer/demo/examples/files/office/handbook.docx b/crates/exav-viewer/demo/examples/files/office/handbook.docx new file mode 100644 index 0000000..931b4e2 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/office/handbook.docx differ diff --git a/crates/exav-viewer/demo/examples/files/office/workbook.xlsx b/crates/exav-viewer/demo/examples/files/office/workbook.xlsx new file mode 100644 index 0000000..75a5e28 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/office/workbook.xlsx differ diff --git a/crates/exav-viewer/demo/examples/files/pdf/annotations.pdf b/crates/exav-viewer/demo/examples/files/pdf/annotations.pdf new file mode 100644 index 0000000..a5b2819 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/pdf/annotations.pdf differ diff --git a/crates/exav-viewer/demo/examples/files/pdf/application-form.pdf b/crates/exav-viewer/demo/examples/files/pdf/application-form.pdf new file mode 100644 index 0000000..6adc530 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/pdf/application-form.pdf differ diff --git a/crates/exav-viewer/demo/examples/files/pdf/field-report.pdf b/crates/exav-viewer/demo/examples/files/pdf/field-report.pdf new file mode 100644 index 0000000..0aed9e7 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/pdf/field-report.pdf differ diff --git a/crates/exav-viewer/demo/examples/files/pdf/handbook-tagged.pdf b/crates/exav-viewer/demo/examples/files/pdf/handbook-tagged.pdf new file mode 100644 index 0000000..fd6c834 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/pdf/handbook-tagged.pdf differ diff --git a/crates/exav-viewer/demo/examples/files/pdf/scan-mixed.pdf b/crates/exav-viewer/demo/examples/files/pdf/scan-mixed.pdf new file mode 100644 index 0000000..02d8a9e Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/pdf/scan-mixed.pdf differ diff --git a/crates/exav-viewer/demo/examples/files/pdf/vector-art.pdf b/crates/exav-viewer/demo/examples/files/pdf/vector-art.pdf new file mode 100644 index 0000000..4a51e54 Binary files /dev/null and b/crates/exav-viewer/demo/examples/files/pdf/vector-art.pdf differ diff --git a/crates/exav-viewer/demo/examples/files/text/bits.c b/crates/exav-viewer/demo/examples/files/text/bits.c new file mode 100644 index 0000000..0170396 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/bits.c @@ -0,0 +1,51 @@ +/* Bit tricks on 32-bit words. CC0-1.0, exav project. */ +#include +#include + +/* The number of set bits, by the parallel sum. */ +static unsigned popcount32(uint32_t x) { + x = x - ((x >> 1) & 0x55555555u); + x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u); + x = (x + (x >> 4)) & 0x0f0f0f0fu; + return (x * 0x01010101u) >> 24; +} + +/* The index of the highest set bit, or -1 for zero. */ +static int high_bit(uint32_t x) { + int n = -1; + while (x) { + n++; + x >>= 1; + } + return n; +} + +/* The next power of two that is not below x. */ +static uint32_t next_pow2(uint32_t x) { + if (x <= 1) return 1; + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x + 1; +} + +/* The bits of x in reverse order. */ +static uint32_t reverse32(uint32_t x) { + x = ((x >> 1) & 0x55555555u) | ((x & 0x55555555u) << 1); + x = ((x >> 2) & 0x33333333u) | ((x & 0x33333333u) << 2); + x = ((x >> 4) & 0x0f0f0f0fu) | ((x & 0x0f0f0f0fu) << 4); + x = ((x >> 8) & 0x00ff00ffu) | ((x & 0x00ff00ffu) << 8); + return (x >> 16) | (x << 16); +} + +int main(void) { + const uint32_t samples[] = {0u, 1u, 255u, 1000u, 0xdeadbeefu}; + for (size_t i = 0; i < sizeof samples / sizeof samples[0]; i++) { + uint32_t v = samples[i]; + printf("%10u: bits %2u, high %2d, pow2 %10u, reversed %08x\n", v, popcount32(v), high_bit(v), next_pow2(v), reverse32(v)); + } + return 0; +} diff --git a/crates/exav-viewer/demo/examples/files/text/changes.diff b/crates/exav-viewer/demo/examples/files/text/changes.diff new file mode 100644 index 0000000..9098ae3 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/changes.diff @@ -0,0 +1,31 @@ +diff --git a/src/berths.py b/src/berths.py +index 3f2a1c4..9b7d0e8 100644 +--- a/src/berths.py ++++ b/src/berths.py +@@ -10,12 +10,16 @@ class Berth: + number: int + length_m: float ++ max_draught_m: float = 1.5 + + def fits(self, boat): +- return boat.length_m <= self.length_m ++ return boat.length_m <= self.length_m and boat.draught_m <= self.max_draught_m + + def label(self): +- return "Berth %d" % self.number ++ return f"Berth {self.number} ({self.length_m:.1f} m)" +@@ -40,7 +44,7 @@ def free_berths(register, boat): + for berth in register: + if berth.fits(boat): + yield berth +- return ++ return None +diff --git a/README.md b/README.md +index 1e2d3f4..5a6b7c8 100644 +--- a/README.md ++++ b/README.md +@@ -1,4 +1,5 @@ + # Harbour register + + The mooring register of the east quay. ++Berths now have a maximum draught. diff --git a/crates/exav-viewer/demo/examples/files/text/config.yaml b/crates/exav-viewer/demo/examples/files/text/config.yaml new file mode 100644 index 0000000..cee2b1d --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/config.yaml @@ -0,0 +1,28 @@ +# A configuration file, to show YAML as text. +service: + name: harbour-register + port: 8080 + debug: false + tags: [boats, berths, "quay east"] + limits: + requests_per_minute: 600 + body_bytes: 1048576 +database: + url: postgres://register@localhost:5432/harbour + pool: {min: 2, max: 10} +berths: + - number: 1 + length_m: 6.5 + vessel: Aurora + - number: 2 + length_m: 8.2 + vessel: Brise +notes: | + A block of text that keeps + its line breaks. +folded: > + A block of text that is + folded into one line. +anchors: + base: &base {retries: 3, timeout_s: 30} + copy: *base diff --git a/crates/exav-viewer/demo/examples/files/text/deploy.sh b/crates/exav-viewer/demo/examples/files/text/deploy.sh new file mode 100644 index 0000000..bf71a01 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/deploy.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Build, check and copy a static site. CC0-1.0, exav project. +set -euo pipefail + +SITE_DIR="${SITE_DIR:-./public}" +REMOTE="${REMOTE:-deploy@example.invalid:/var/www/site}" +LOG="$(mktemp)" + +cleanup() { + local status=$? + rm -f "$LOG" + if [ "$status" -ne 0 ]; then + echo "deploy failed with status $status" >&2 + fi +} +trap cleanup EXIT + +log() { printf '[%s] %s\n' "$(date +%H:%M:%S)" "$*"; } + +build() { + log "building" + npm ci --silent >"$LOG" 2>&1 || { cat "$LOG" >&2; return 1; } + npm run build --silent +} + +check() { + local broken=0 + while IFS= read -r -d '' file; do + if ! grep -q '' "$file"; then + log "incomplete page: $file" + broken=$((broken + 1)) + fi + done < <(find "$SITE_DIR" -name '*.html' -print0) + return "$broken" +} + +case "${1:-all}" in + build) build ;; + check) check ;; + all) build && check && rsync -az --delete "$SITE_DIR/" "$REMOTE" && log "done" ;; + *) echo "usage: $0 [build|check|all]" >&2; exit 2 ;; +esac diff --git a/crates/exav-viewer/demo/examples/files/text/feed.xml b/crates/exav-viewer/demo/examples/files/text/feed.xml new file mode 100644 index 0000000..b931bb9 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/feed.xml @@ -0,0 +1,27 @@ + + + + Notes from the east quay + Moorings, tides & weather + + + urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 + 2000-01-03T12:00:00Z + The harbour officeoffice@example.invalid + + New berths on the east quay + + urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a + 2000-01-03T12:00:00Z + Twelve berths for visiting boats open on 1 March. +

The east quay is longer by 40 metres.

+ +
+ + Tide tables for the year + + urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6b + 2000-01-01T08:00:00Z + + +
diff --git a/crates/exav-viewer/demo/examples/files/text/field-guide.md b/crates/exav-viewer/demo/examples/files/text/field-guide.md new file mode 100644 index 0000000..4488dfa --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/field-guide.md @@ -0,0 +1,124 @@ +# Field guide to Markdown + +A short document that uses most of what Markdown can say. It is written for the +exav demo and is in the public domain (CC0-1.0). + +## Emphasis and spans + +Text can be **bold**, *italic*, ***both***, ~~struck through~~ or `code`. A line +that ends with two spaces +breaks without starting a paragraph. A [link with a title](https://exav.org/ "exav.org"), +an autolink , and a reference link: [the demo][demo]. + +[demo]: https://exav.org/viewer/demo/ + +Escapes: \*not italic\*, 2 \< 3, a literal backtick \`, and entities: © & é. +Unicode goes through unchanged: café, naïve, Ωmega, Жук, 日本語, مرحبا, ☃. + +## Headings + +### Third level +#### Fourth level +##### Fifth level +###### Sixth level + +Setext heading +============== + +Another one +----------- + +## Lists + +- A bullet +- Another, with a nested list: + - second level + - third level + - back to the second +- And a last one + +1. Numbered +2. Items + 1. Nested numbers + 2. Continue +3. Done + +7. A list that starts at seven +8. and goes on + +- [x] A finished task +- [ ] An open task +- [ ] Another open task, with `code` in it + +Loose list: + +- First paragraph. + + A second paragraph inside the same item. + +- Next item. + +## Quotes + +> A quotation, which can wrap over several lines and holds +> *other* **formatting**. +> +> > A quotation inside it. +> +> - and a list + +## Tables + +| Left | Centre | Right | +| :--- | :----: | ----: | +| a | b | c | +| `code` | **bold** | 1,234.50 | +| A longer cell that holds more words | x | 7 | + +## Code + +Inline `let x = 1;` and a fenced block with a language: + +```rust +fn fib(n: u32) -> u64 { + let (mut a, mut b) = (0u64, 1u64); + for _ in 0..n { + (a, b) = (b, a + b); + } + a +} +``` + +```python +def fib(n): + a, b = 0, 1 + for _ in range(n): + a, b = b, a + b + return a +``` + +```diff +- old line ++ new line +``` + +An indented block: + + four spaces make this code + and it keeps its spacing + +## Rules, HTML and footnotes + +--- + +Inline HTML such as Ctrl + C and sub and sup is +shown as text or ignored, never run: does nothing. + +A sentence with a footnote.[^1] And another one.[^note] + +[^1]: The first footnote. +[^note]: A second, with *formatting*. + +![An image reference](https://example.invalid/not-fetched.png) + +The end. diff --git a/crates/exav-viewer/demo/examples/files/text/field-notes.txt b/crates/exav-viewer/demo/examples/files/text/field-notes.txt new file mode 100644 index 0000000..6c15e68 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/field-notes.txt @@ -0,0 +1,30 @@ +Field notes +=========== + +Plain text is shown as it is written: line breaks, indentation, tabs and +long lines are kept. + + A line that starts with a tab. + A line that starts with eight spaces. + +A very long line, to see how the viewer wraps or scrolls it: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + +Pangrams, one for each script: + + English The quick brown fox jumps over the lazy dog. + Français Portez ce vieux whisky au juge blond qui fume. + Deutsch Zwölf Boxkämpfer jagen Viktor quer über den großen Sylter Deich. + Español El pingüino Wenceslao hizo kilómetros bajo exhaustiva lluvia y frío. + Ελληνικά Ξεσκεπάζω την ψυχοφθόÏ�α βδελυγμία. + РуÑ�Ñ�кий Съешь же ещё Ñ�тих мÑ�гких французÑ�ких булок да выпей чаю. + 日本語 ã�„ã‚�ã�¯ã�«ã�»ã�¸ã�¨ ã�¡ã‚Šã�¬ã‚‹ã‚’ ã‚�ã�‹ã‚ˆã�Ÿã‚Œã�� ã�¤ã�­ã�ªã‚‰ã‚€ + العربية نص حكيم له سر قاطع وذو شأن عظيم مكتوب على ثوب أخضر ومزخرÙ� + עברית דג סקרן שט בי×� מ×�וכזב ולפתע מצ×� לו חברה ×�יך הקליטה + +Symbols and box drawing: + + ┌──────┬──────â”� â†� ↑ → ↓ ✓ ✗ ½ â…“ ¾ ± × ÷ ≠ ≤ ≥ ∞ + │ a │ b │ € £ Â¥ â‚¿ © ® â„¢ ☀ â˜� ☂ ☃ + └──────┴──────┘ + +The last line has no newline at the end. \ No newline at end of file diff --git a/crates/exav-viewer/demo/examples/files/text/harbour-log.csv b/crates/exav-viewer/demo/examples/files/text/harbour-log.csv new file mode 100644 index 0000000..d2845fb --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/harbour-log.csv @@ -0,0 +1,332 @@ +date,vessel,type,length_m,beam_m,berth,nights,fee_eur,notes +2000-01-01,Hirondelle,motor yacht,9.7,3.2,33,5,117.60,"Arrived late, ""quiet"" night" +2000-01-01,Hirondelle,dinghy,6.6,2.18,40,5,92.80, +2000-01-01,Calypso,sloop,5.6,1.85,35,3,50.88, +2000-01-01,Hirondelle,dinghy,11.3,3.73,48,4,104.32, +2000-01-01,Brise,sloop,11.7,3.86,3,5,133.60,"Arrived late, ""quiet"" night" +2000-01-01,Aurora,motor yacht,14.6,4.82,21,5,156.80,Café voucher given +2000-01-01,Iroise,ketch,11.3,3.73,41,2,52.16,Bill sent; paid by cheque +2000-01-01,Hirondelle,dinghy,10.2,3.37,18,1,24.32,"Two nights, +left at dawn" +2000-01-01,La Mouette,trawler,16.0,5.28,21,1,33.60,"Arrived late, ""quiet"" night" +2000-01-01,Brise,catamaran,10.4,3.43,50,1,24.64, +2000-01-02,Goeland,sloop,9.1,3.0,2,3,67.68, +2000-01-02,Hirondelle,motor yacht,7.0,2.31,46,1,19.20,"Two nights, +left at dawn" +2000-01-02,Kerguelen,ketch,9.3,3.07,50,5,114.40,Bill sent; paid by cheque +2000-01-02,Fauvette,sloop,8.4,2.77,27,3,64.32, +2000-01-02,Aurora,sloop,6.0,1.98,30,1,17.60,Café voucher given +2000-01-02,Dorade,motor yacht,6.5,2.15,33,5,92.00,"Arrived late, ""quiet"" night" +2000-01-02,Goeland,dinghy,15.8,5.21,25,2,66.56, +2000-01-02,Aurora,trawler,9.0,2.97,56,2,44.80,Bill sent; paid by cheque +2000-01-02,Dorade,ketch,16.0,5.28,26,1,33.60, +2000-01-02,Dorade,motor yacht,5.0,1.65,17,2,32.00, +2000-01-03,Etoile,motor yacht,13.4,4.42,5,3,88.32, +2000-01-03,Kerguelen,ketch,5.5,1.82,1,5,84.00,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-03,Calypso,catamaran,8.8,2.9,31,4,88.32, +2000-01-03,Kerguelen,ketch,14.5,4.79,20,2,62.40,"Arrived late, ""quiet"" night" +2000-01-03,La Mouette,ketch,13.9,4.59,11,2,60.48, +2000-01-03,Hirondelle,catamaran,6.8,2.24,6,4,75.52,"Two nights, +left at dawn" +2000-01-03,Aurora,catamaran,5.0,1.65,17,1,16.00,"Arrived late, ""quiet"" night" +2000-01-03,Etoile,motor yacht,13.0,4.29,53,4,115.20,Café voucher given +2000-01-03,La Mouette,sloop,7.9,2.61,9,2,41.28,"Arrived late, ""quiet"" night" +2000-01-03,Jolie Brise,sloop,10.0,3.3,18,5,120.00,"Arrived late, ""quiet"" night" +2000-01-04,La Mouette,sloop,15.0,4.95,5,2,64.00,Bill sent; paid by cheque +2000-01-04,Aurora,sloop,9.2,3.04,12,2,45.44,Bill sent; paid by cheque +2000-01-04,Calypso,sloop,8.7,2.87,24,5,109.60, +2000-01-04,Kerguelen,dinghy,14.7,4.85,45,3,94.56, +2000-01-04,Jolie Brise,sloop,11.2,3.7,60,2,51.84, +2000-01-04,La Mouette,trawler,10.0,3.3,3,3,72.00, +2000-01-04,Hirondelle,sloop,11.4,3.76,47,1,26.24,Bill sent; paid by cheque +2000-01-04,Brise,motor yacht,8.2,2.71,35,1,21.12,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-04,Fauvette,trawler,13.0,4.29,6,2,57.60,Café voucher given +2000-01-04,Aurora,motor yacht,14.9,4.92,37,4,127.36, +2000-01-05,Goeland,catamaran,11.7,3.86,1,4,106.88, +2000-01-05,Etoile 3,motor yacht,5.4,1.78,47,1,16.64,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-05,Hirondelle 3,motor yacht,9.0,2.97,30,5,112.00, +2000-01-05,Aurora 3,trawler,5.5,1.82,39,5,84.00, +2000-01-05,La Mouette 3,sloop,10.0,3.3,32,2,48.00,Café voucher given +2000-01-05,Fauvette 3,trawler,7.4,2.44,10,1,19.84,"Arrived late, ""quiet"" night" +2000-01-05,Kerguelen 3,motor yacht,10.5,3.47,32,3,74.40,"Arrived late, ""quiet"" night" +2000-01-05,Dorade 3,dinghy,8.3,2.74,28,3,63.84,"Arrived late, ""quiet"" night" +2000-01-05,Dorade 3,catamaran,14.6,4.82,59,4,125.44,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-05,Hirondelle 3,trawler,6.9,2.28,54,2,38.08, +2000-01-06,Calypso 3,sloop,12.7,4.19,29,3,84.96,Café voucher given +2000-01-06,Goeland 3,motor yacht,7.7,2.54,41,2,40.64, +2000-01-06,La Mouette 3,catamaran,10.2,3.37,29,3,72.96,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-06,Etoile 3,catamaran,5.4,1.78,3,1,16.64,Bill sent; paid by cheque +2000-01-06,Kerguelen 3,catamaran,11.1,3.66,2,3,77.28, +2000-01-06,Aurora 3,trawler,9.2,3.04,16,2,45.44, +2000-01-06,Hirondelle 3,sloop,13.7,4.52,41,1,29.92, +2000-01-06,Brise 3,dinghy,12.0,3.96,13,3,81.60,"Arrived late, ""quiet"" night" +2000-01-06,Calypso 3,dinghy,14.0,4.62,1,3,91.20,Café voucher given +2000-01-06,Calypso 3,ketch,10.7,3.53,18,1,25.12,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-07,Iroise 3,catamaran,10.7,3.53,49,5,125.60, +2000-01-07,Brise 3,motor yacht,9.0,2.97,60,2,44.80,"Two nights, +left at dawn" +2000-01-07,Dorade 3,dinghy,6.0,1.98,57,4,70.40, +2000-01-07,Kerguelen 3,catamaran,8.8,2.9,51,5,110.40,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-07,Brise 3,dinghy,9.8,3.23,56,2,47.36, +2000-01-07,Brise 3,trawler,7.0,2.31,35,4,76.80,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-07,Fauvette 3,catamaran,7.5,2.48,6,1,20.00, +2000-01-07,Goeland 3,trawler,9.6,3.17,32,5,116.80, +2000-01-07,Goeland 3,sloop,7.0,2.31,12,1,19.20, +2000-01-07,Hirondelle 3,ketch,8.4,2.77,34,2,42.88, +2000-01-08,Hirondelle 3,catamaran,14.2,4.69,45,4,122.88, +2000-01-08,Iroise 3,catamaran,13.2,4.36,19,4,116.48, +2000-01-08,Iroise 3,catamaran,11.8,3.89,17,5,134.40,Bill sent; paid by cheque +2000-01-08,Dorade 3,trawler,12.2,4.03,55,5,137.60, +2000-01-08,Etoile 3,catamaran,15.6,5.15,32,5,164.80,"Arrived late, ""quiet"" night" +2000-01-08,Iroise 3,sloop,9.2,3.04,39,1,22.72,"Two nights, +left at dawn" +2000-01-08,Iroise 3,motor yacht,4.8,1.58,35,1,15.68, +2000-01-08,Brise 3,catamaran,10.1,3.33,30,2,48.32,"Two nights, +left at dawn" +2000-01-08,Etoile 3,ketch,15.1,4.98,31,4,128.64,Café voucher given +2000-01-08,Hirondelle 3,catamaran,6.0,1.98,21,4,70.40, +2000-01-09,Aurora 4,trawler,6.7,2.21,9,5,93.60, +2000-01-09,Dorade 4,sloop,4.9,1.62,44,2,31.68,Bill sent; paid by cheque +2000-01-09,Dorade 4,catamaran,8.2,2.71,32,3,63.36, +2000-01-09,Brise 4,catamaran,10.2,3.37,40,5,121.60,Bill sent; paid by cheque +2000-01-09,Goeland 4,sloop,12.8,4.22,25,5,142.40,"Two nights, +left at dawn" +2000-01-09,Calypso 4,catamaran,14.0,4.62,14,5,152.00, +2000-01-09,Dorade 4,catamaran,11.8,3.89,40,5,134.40, +2000-01-09,Calypso 4,trawler,7.2,2.38,39,3,58.56,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-09,Dorade 4,ketch,14.7,4.85,57,2,63.04, +2000-01-09,Calypso 4,dinghy,6.0,1.98,6,2,35.20,Bill sent; paid by cheque +2000-01-10,Goeland 4,catamaran,9.0,2.97,51,4,89.60, +2000-01-10,Brise 4,ketch,6.8,2.24,37,1,18.88,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-10,Brise 4,dinghy,15.0,4.95,33,3,96.00,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-10,Brise 4,motor yacht,10.3,3.4,7,2,48.96, +2000-01-10,Jolie Brise 4,catamaran,4.9,1.62,58,5,79.20,Café voucher given +2000-01-10,Brise 4,ketch,6.2,2.05,12,2,35.84, +2000-01-10,Jolie Brise 4,sloop,15.9,5.25,9,1,33.44,Café voucher given +2000-01-10,Fauvette 4,motor yacht,5.4,1.78,30,1,16.64,"Two nights, +left at dawn" +2000-01-10,Dorade 4,catamaran,10.4,3.43,24,4,98.56, +2000-01-10,Dorade 4,ketch,11.8,3.89,27,1,26.88,Café voucher given +2000-01-11,Goeland 4,ketch,8.6,2.84,39,3,65.28, +2000-01-11,Fauvette 4,sloop,5.6,1.85,52,1,16.96,"Two nights, +left at dawn" +2000-01-11,Iroise 4,catamaran,11.1,3.66,22,2,51.52,Bill sent; paid by cheque +2000-01-11,La Mouette 4,dinghy,7.7,2.54,50,1,20.32, +2000-01-11,Calypso 4,trawler,13.9,4.59,57,4,120.96, +2000-01-11,Calypso 4,motor yacht,12.5,4.12,14,4,112.00, +2000-01-11,Etoile 4,motor yacht,5.3,1.75,7,3,49.44, +2000-01-11,Aurora 4,ketch,14.7,4.85,18,5,157.60,Bill sent; paid by cheque +2000-01-11,Jolie Brise 4,ketch,8.4,2.77,35,4,85.76, +2000-01-11,Kerguelen 4,ketch,9.0,2.97,45,4,89.60, +2000-01-12,Aurora 4,sloop,13.3,4.39,40,5,146.40, +2000-01-12,Hirondelle 4,motor yacht,13.0,4.29,33,3,86.40, +2000-01-12,Aurora 4,sloop,13.3,4.39,17,4,117.12,Bill sent; paid by cheque +2000-01-12,Iroise 4,catamaran,7.7,2.54,33,3,60.96,"Two nights, +left at dawn" +2000-01-12,Brise 4,dinghy,15.6,5.15,29,5,164.80, +2000-01-12,Goeland 4,ketch,10.8,3.56,25,1,25.28,Café voucher given +2000-01-12,Iroise 4,catamaran,15.7,5.18,39,4,132.48, +2000-01-12,Goeland 4,trawler,9.4,3.1,34,4,92.16,"Two nights, +left at dawn" +2000-01-12,Iroise 4,trawler,11.4,3.76,31,3,78.72,Bill sent; paid by cheque +2000-01-12,Kerguelen 4,dinghy,10.9,3.6,48,3,76.32,Bill sent; paid by cheque +2000-01-13,Jolie Brise 5,sloop,4.8,1.58,41,2,31.36, +2000-01-13,Aurora 5,trawler,9.2,3.04,48,4,90.88,"Two nights, +left at dawn" +2000-01-13,Brise 5,ketch,5.1,1.68,28,3,48.48,Café voucher given +2000-01-13,Aurora 5,catamaran,7.4,2.44,7,2,39.68,Café voucher given +2000-01-13,Jolie Brise 5,dinghy,6.2,2.05,8,2,35.84, +2000-01-13,Brise 5,ketch,11.7,3.86,56,4,106.88, +2000-01-13,Brise 5,trawler,8.6,2.84,29,2,43.52, +2000-01-13,Jolie Brise 5,trawler,12.2,4.03,41,4,110.08,"Two nights, +left at dawn" +2000-01-13,Calypso 5,trawler,8.7,2.87,47,5,109.60, +2000-01-13,Iroise 5,trawler,7.2,2.38,51,1,19.52, +2000-01-14,Etoile 5,trawler,11.7,3.86,40,3,80.16,"Arrived late, ""quiet"" night" +2000-01-14,Dorade 5,ketch,11.8,3.89,33,2,53.76,"Arrived late, ""quiet"" night" +2000-01-14,Kerguelen 5,sloop,14.6,4.82,1,1,31.36,Bill sent; paid by cheque +2000-01-14,Jolie Brise 5,sloop,7.5,2.48,7,1,20.00,"Arrived late, ""quiet"" night" +2000-01-14,Brise 5,dinghy,10.7,3.53,11,1,25.12, +2000-01-14,Hirondelle 5,motor yacht,7.2,2.38,23,3,58.56,"Arrived late, ""quiet"" night" +2000-01-14,La Mouette 5,ketch,8.4,2.77,54,4,85.76, +2000-01-14,Jolie Brise 5,ketch,13.7,4.52,29,4,119.68,"Two nights, +left at dawn" +2000-01-14,Calypso 5,trawler,13.1,4.32,10,4,115.84,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-14,Goeland 5,dinghy,7.8,2.57,24,2,40.96, +2000-01-15,Brise 5,catamaran,9.8,3.23,6,3,71.04,"Two nights, +left at dawn" +2000-01-15,Kerguelen 5,motor yacht,11.0,3.63,20,4,102.40, +2000-01-15,Kerguelen 5,catamaran,5.4,1.78,6,2,33.28,Bill sent; paid by cheque +2000-01-15,Etoile 5,ketch,10.2,3.37,15,3,72.96,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-15,Fauvette 5,sloop,12.1,3.99,21,3,82.08,Café voucher given +2000-01-15,Hirondelle 5,catamaran,11.0,3.63,52,3,76.80,Bill sent; paid by cheque +2000-01-15,Goeland 5,dinghy,9.8,3.23,58,2,47.36, +2000-01-15,Fauvette 5,sloop,7.4,2.44,24,3,59.52,"Two nights, +left at dawn" +2000-01-15,La Mouette 5,catamaran,11.2,3.7,24,2,51.84,"Two nights, +left at dawn" +2000-01-15,Jolie Brise 5,ketch,10.7,3.53,12,5,125.60, +2000-01-16,Aurora 5,ketch,13.2,4.36,34,3,87.36, +2000-01-16,Etoile 5,sloop,10.8,3.56,42,5,126.40,"Two nights, +left at dawn" +2000-01-16,Etoile 5,catamaran,5.2,1.72,6,5,81.60,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-16,Fauvette 5,sloop,5.4,1.78,2,1,16.64, +2000-01-16,Dorade 5,dinghy,5.6,1.85,15,4,67.84,Café voucher given +2000-01-16,Fauvette 5,motor yacht,13.3,4.39,26,5,146.40,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-16,Kerguelen 5,ketch,8.4,2.77,32,3,64.32,Café voucher given +2000-01-16,La Mouette 5,catamaran,10.7,3.53,59,1,25.12, +2000-01-16,Aurora 5,motor yacht,9.2,3.04,54,3,68.16, +2000-01-16,Kerguelen 5,sloop,14.7,4.85,34,5,157.60,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-17,Goeland 6,motor yacht,12.7,4.19,59,1,28.32, +2000-01-17,Kerguelen 6,motor yacht,7.3,2.41,44,2,39.36, +2000-01-17,Goeland 6,catamaran,8.2,2.71,19,4,84.48,Bill sent; paid by cheque +2000-01-17,Hirondelle 6,trawler,15.7,5.18,47,1,33.12, +2000-01-17,Calypso 6,sloop,8.0,2.64,49,2,41.60,Café voucher given +2000-01-17,Aurora 6,trawler,4.7,1.55,7,4,62.08,"Arrived late, ""quiet"" night" +2000-01-17,Jolie Brise 6,ketch,6.6,2.18,39,2,37.12,Café voucher given +2000-01-17,Hirondelle 6,ketch,11.3,3.73,58,2,52.16,Bill sent; paid by cheque +2000-01-17,Kerguelen 6,catamaran,9.1,3.0,53,3,67.68, +2000-01-17,Hirondelle 6,motor yacht,10.0,3.3,59,3,72.00,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-18,Hirondelle 6,ketch,12.1,3.99,26,1,27.36, +2000-01-18,Goeland 6,catamaran,7.0,2.31,51,2,38.40, +2000-01-18,Kerguelen 6,ketch,13.4,4.42,58,1,29.44, +2000-01-18,Hirondelle 6,ketch,14.6,4.82,46,3,94.08,"Two nights, +left at dawn" +2000-01-18,Goeland 6,ketch,11.5,3.8,50,2,52.80,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-18,Calypso 6,dinghy,6.2,2.05,48,5,89.60,Bill sent; paid by cheque +2000-01-18,Calypso 6,catamaran,10.4,3.43,50,1,24.64, +2000-01-18,Calypso 6,sloop,4.5,1.49,23,2,30.40,Bill sent; paid by cheque +2000-01-18,Brise 6,motor yacht,11.6,3.83,45,5,132.80,Café voucher given +2000-01-18,Iroise 6,catamaran,5.5,1.82,20,5,84.00, +2000-01-19,Dorade 6,dinghy,13.6,4.49,6,4,119.04,Café voucher given +2000-01-19,Goeland 6,catamaran,6.9,2.28,32,5,95.20, +2000-01-19,Fauvette 6,trawler,15.4,5.08,26,3,97.92, +2000-01-19,Kerguelen 6,dinghy,10.9,3.6,5,4,101.76,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-19,Brise 6,dinghy,5.4,1.78,26,2,33.28,Café voucher given +2000-01-19,Kerguelen 6,motor yacht,13.1,4.32,1,1,28.96,"Two nights, +left at dawn" +2000-01-19,Dorade 6,trawler,12.7,4.19,37,4,113.28, +2000-01-19,La Mouette 6,ketch,9.8,3.23,58,1,23.68, +2000-01-19,Iroise 6,dinghy,7.8,2.57,20,4,81.92,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-19,Kerguelen 6,sloop,13.2,4.36,17,5,145.60,"Arrived late, ""quiet"" night" +2000-01-20,Fauvette 6,trawler,6.8,2.24,18,1,18.88,Café voucher given +2000-01-20,Hirondelle 6,motor yacht,12.8,4.22,6,3,85.44, +2000-01-20,Calypso 6,dinghy,6.1,2.01,41,1,17.76, +2000-01-20,Aurora 6,motor yacht,6.6,2.18,38,4,74.24, +2000-01-20,Calypso 6,sloop,5.7,1.88,28,1,17.12,"Two nights, +left at dawn" +2000-01-20,Goeland 6,catamaran,13.4,4.42,9,3,88.32,"Arrived late, ""quiet"" night" +2000-01-20,Hirondelle 6,trawler,13.3,4.39,59,4,117.12,"Two nights, +left at dawn" +2000-01-20,Jolie Brise 6,dinghy,11.7,3.86,21,4,106.88,"Arrived late, ""quiet"" night" +2000-01-20,Iroise 6,sloop,12.1,3.99,17,5,136.80,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-20,Kerguelen 6,motor yacht,6.7,2.21,7,3,56.16, +2000-01-21,Fauvette 7,trawler,8.8,2.9,53,5,110.40, +2000-01-21,Etoile 7,catamaran,11.5,3.8,58,2,52.80,Bill sent; paid by cheque +2000-01-21,Jolie Brise 7,catamaran,10.8,3.56,33,3,75.84, +2000-01-21,Iroise 7,dinghy,11.1,3.66,46,2,51.52,"Arrived late, ""quiet"" night" +2000-01-21,Kerguelen 7,dinghy,11.0,3.63,13,1,25.60, +2000-01-21,Jolie Brise 7,motor yacht,6.1,2.01,45,4,71.04,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-21,Etoile 7,motor yacht,8.3,2.74,57,3,63.84, +2000-01-21,Dorade 7,catamaran,9.7,3.2,35,2,47.04, +2000-01-21,Etoile 7,ketch,10.9,3.6,59,5,127.20,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-21,Aurora 7,trawler,11.4,3.76,44,1,26.24,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-22,Fauvette 7,ketch,7.3,2.41,12,5,98.40, +2000-01-22,Aurora 7,motor yacht,13.8,4.55,12,4,120.32, +2000-01-22,Jolie Brise 7,catamaran,8.0,2.64,41,4,83.20, +2000-01-22,Hirondelle 7,sloop,6.3,2.08,10,4,72.32, +2000-01-22,Goeland 7,ketch,8.9,2.94,22,5,111.20, +2000-01-22,Jolie Brise 7,trawler,6.0,1.98,4,2,35.20, +2000-01-22,Goeland 7,motor yacht,12.8,4.22,39,2,56.96, +2000-01-22,Jolie Brise 7,dinghy,9.9,3.27,37,4,95.36,"Two nights, +left at dawn" +2000-01-22,Hirondelle 7,dinghy,13.1,4.32,27,4,115.84,"Two nights, +left at dawn" +2000-01-22,Iroise 7,trawler,5.8,1.91,34,1,17.28, +2000-01-23,Fauvette 7,sloop,9.5,3.14,19,1,23.20,"Two nights, +left at dawn" +2000-01-23,Fauvette 7,trawler,12.9,4.26,57,5,143.20, +2000-01-23,Dorade 7,catamaran,7.3,2.41,56,4,78.72,"Two nights, +left at dawn" +2000-01-23,La Mouette 7,sloop,15.7,5.18,34,4,132.48,"Arrived late, ""quiet"" night" +2000-01-23,Dorade 7,sloop,10.8,3.56,59,4,101.12,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-23,Jolie Brise 7,ketch,14.5,4.79,15,4,124.80,"Two nights, +left at dawn" +2000-01-23,Brise 7,catamaran,11.0,3.63,51,1,25.60, +2000-01-23,Jolie Brise 7,motor yacht,5.9,1.95,1,5,87.20,Bill sent; paid by cheque +2000-01-23,Aurora 7,trawler,7.3,2.41,12,3,59.04, +2000-01-23,Iroise 7,motor yacht,9.6,3.17,10,4,93.44,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-24,Aurora 7,trawler,12.5,4.12,2,2,56.00,Café voucher given +2000-01-24,Fauvette 7,motor yacht,14.8,4.88,10,3,95.04,Café voucher given +2000-01-24,Etoile 7,dinghy,14.6,4.82,58,2,62.72, +2000-01-24,Hirondelle 7,sloop,6.7,2.21,12,3,56.16, +2000-01-24,Dorade 7,sloop,6.8,2.24,42,2,37.76, +2000-01-24,Etoile 7,motor yacht,8.0,2.64,46,3,62.40, +2000-01-24,Goeland 7,sloop,8.4,2.77,11,4,85.76,"Arrived late, ""quiet"" night" +2000-01-24,La Mouette 7,dinghy,14.4,4.75,13,1,31.04,Bill sent; paid by cheque +2000-01-24,Iroise 7,dinghy,6.6,2.18,19,2,37.12,Bill sent; paid by cheque +2000-01-24,Brise 7,catamaran,8.8,2.9,34,5,110.40,"Arrived late, ""quiet"" night" +2000-01-25,Kerguelen 8,ketch,15.7,5.18,18,2,66.24, +2000-01-25,Hirondelle 8,sloop,11.9,3.93,29,1,27.04, +2000-01-25,Aurora 8,catamaran,5.3,1.75,38,1,16.48,Bill sent; paid by cheque +2000-01-25,Jolie Brise 8,sloop,10.7,3.53,11,4,100.48,Bill sent; paid by cheque +2000-01-25,Dorade 8,ketch,15.9,5.25,18,2,66.88, +2000-01-25,Aurora 8,catamaran,4.8,1.58,30,2,31.36,"Two nights, +left at dawn" +2000-01-25,Aurora 8,ketch,4.5,1.49,5,4,60.80, +2000-01-25,Fauvette 8,dinghy,13.4,4.42,31,3,88.32, +2000-01-25,Kerguelen 8,dinghy,10.4,3.43,34,5,123.20, +2000-01-25,Brise 8,catamaran,6.5,2.15,28,2,36.80,"Arrived late, ""quiet"" night" +2000-01-26,Etoile 8,dinghy,12.2,4.03,51,5,137.60,"Arrived late, ""quiet"" night" +2000-01-26,Dorade 8,catamaran,7.5,2.48,39,5,100.00,Café voucher given +2000-01-26,Jolie Brise 8,dinghy,7.5,2.48,4,2,40.00,Café voucher given +2000-01-26,Fauvette 8,ketch,14.5,4.79,39,2,62.40, +2000-01-26,Iroise 8,motor yacht,11.5,3.8,47,4,105.60,Bill sent; paid by cheque +2000-01-26,Brise 8,sloop,14.4,4.75,59,1,31.04, +2000-01-26,Jolie Brise 8,dinghy,11.0,3.63,16,5,128.00, +2000-01-26,Aurora 8,dinghy,5.1,1.68,21,4,64.64, +2000-01-26,Hirondelle 8,sloop,13.5,4.46,42,5,148.00, +2000-01-26,Dorade 8,ketch,6.5,2.15,32,3,55.20,Café voucher given +2000-01-27,Hirondelle 8,trawler,5.2,1.72,45,4,65.28,"Arrived late, ""quiet"" night" +2000-01-27,Calypso 8,motor yacht,12.6,4.16,49,1,28.16, +2000-01-27,Iroise 8,dinghy,6.2,2.05,3,4,71.68, +2000-01-27,Calypso 8,sloop,7.3,2.41,26,5,98.40, +2000-01-27,Brise 8,sloop,7.9,2.61,44,4,82.56,"Arrived late, ""quiet"" night" +2000-01-27,Iroise 8,ketch,7.9,2.61,27,1,20.64,Café voucher given +2000-01-27,Fauvette 8,trawler,5.5,1.82,22,2,33.60,"Arrived late, ""quiet"" night" +2000-01-27,Jolie Brise 8,dinghy,5.0,1.65,4,4,64.00,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-27,Calypso 8,motor yacht,11.0,3.63,56,5,128.00,"Two nights, +left at dawn" +2000-01-27,Goeland 8,motor yacht,15.3,5.05,51,2,64.96, +2000-01-28,Dorade 8,ketch,7.0,2.31,51,3,57.60, +2000-01-28,Dorade 8,motor yacht,13.7,4.52,14,4,119.68,Café voucher given +2000-01-28,Hirondelle 8,motor yacht,13.2,4.36,41,4,116.48, +2000-01-28,Iroise 8,motor yacht,14.4,4.75,27,2,62.08, +2000-01-28,Fauvette 8,trawler,5.0,1.65,40,3,48.00, +2000-01-28,Iroise 8,motor yacht,10.5,3.47,37,3,74.40,"Arrived late, ""quiet"" night" +2000-01-28,Aurora 8,ketch,7.6,2.51,47,3,60.48,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-28,La Mouette 8,sloop,6.1,2.01,2,2,35.52,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-01-28,Brise 8,motor yacht,14.1,4.65,21,4,122.24,Bill sent; paid by cheque +2000-01-28,Kerguelen 8,sloop,13.4,4.42,20,5,147.20,"Two nights, +left at dawn" +2000-02-01,Aurora 9,ketch,11.5,3.8,10,4,105.60, +2000-02-01,Dorade 9,trawler,11.3,3.73,27,1,26.08,"Two nights, +left at dawn" +2000-02-01,Iroise 9,dinghy,10.0,3.3,36,2,48.00,Bill sent; paid by cheque +2000-02-01,Kerguelen 9,motor yacht,8.1,2.67,10,4,83.84,"Arrived late, ""quiet"" night" +2000-02-01,La Mouette 9,motor yacht,14.1,4.65,26,5,152.80, +2000-02-01,Dorade 9,sloop,8.9,2.94,19,3,66.72,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-02-01,Calypso 9,sloop,8.5,2.81,55,2,43.20, +2000-02-01,Jolie Brise 9,sloop,13.1,4.32,52,4,115.84,Bill sent; paid by cheque +2000-02-01,Dorade 9,catamaran,12.1,3.99,45,1,27.36,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-02-01,Dorade 9,dinghy,12.2,4.03,17,3,82.56, +2000-02-02,Goeland 9,motor yacht,13.7,4.52,4,1,29.92,Café voucher given +2000-02-02,Etoile 9,motor yacht,8.9,2.94,46,3,66.72,Bill sent; paid by cheque +2000-02-02,Dorade 9,motor yacht,7.0,2.31,50,4,76.80, +2000-02-02,Iroise 9,sloop,8.5,2.81,48,2,43.20,"Owner: M. Le Gall, tel. 02 98 00 00 00" +2000-02-02,Hirondelle 9,catamaran,14.9,4.92,17,2,63.68, +2000-02-02,Goeland 9,sloop,8.0,2.64,24,1,20.80, +2000-02-02,Aurora 9,motor yacht,15.0,4.95,32,3,96.00,Bill sent; paid by cheque +2000-02-02,Etoile 9,sloop,9.9,3.27,2,3,71.52, +2000-02-02,Jolie Brise 9,trawler,8.5,2.81,17,3,64.80, +2000-02-02,Jolie Brise 9,trawler,11.9,3.93,58,4,108.16,"Owner: M. Le Gall, tel. 02 98 00 00 00" diff --git a/crates/exav-viewer/demo/examples/files/text/life.py b/crates/exav-viewer/demo/examples/files/text/life.py new file mode 100644 index 0000000..b5942ab --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/life.py @@ -0,0 +1,34 @@ +"""Conway's Game of Life on a torus, printed as text. CC0-1.0, exav project.""" +import random +import sys + +WIDTH, HEIGHT = 40, 16 + + +def step(cells): + """The next generation of a set of (x, y) cells on a WIDTH by HEIGHT torus.""" + counts = {} + for (x, y) in cells: + for dx in (-1, 0, 1): + for dy in (-1, 0, 1): + if dx or dy: + key = ((x + dx) % WIDTH, (y + dy) % HEIGHT) + counts[key] = counts.get(key, 0) + 1 + return {cell for cell, n in counts.items() if n == 3 or (n == 2 and cell in cells)} + + +def show(cells): + return "\n".join("".join("#" if (x, y) in cells else "." for x in range(WIDTH)) for y in range(HEIGHT)) + + +def main(generations=20, seed=7): + rng = random.Random(seed) + cells = {(x, y) for x in range(WIDTH) for y in range(HEIGHT) if rng.random() < 0.25} + for g in range(generations): + print(f"generation {g}: {len(cells)} cells") + print(show(cells)) + cells = step(cells) + + +if __name__ == "__main__": + main(*(int(a) for a in sys.argv[1:3])) diff --git a/crates/exav-viewer/demo/examples/files/text/lru.rs b/crates/exav-viewer/demo/examples/files/text/lru.rs new file mode 100644 index 0000000..da9bfd9 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/lru.rs @@ -0,0 +1,57 @@ +//! A small least-recently-used cache. CC0-1.0, exav project. +use std::collections::HashMap; +use std::hash::Hash; + +/// A cache that keeps at most `capacity` entries and drops the one used longest ago. +pub struct Lru { + capacity: usize, + tick: u64, + entries: HashMap, +} + +impl Lru { + pub fn new(capacity: usize) -> Self { + assert!(capacity > 0, "a cache holds at least one entry"); + Lru { capacity, tick: 0, entries: HashMap::with_capacity(capacity) } + } + + pub fn get(&mut self, key: &K) -> Option<&V> { + self.tick += 1; + let tick = self.tick; + self.entries.get_mut(key).map(|(v, used)| { + *used = tick; + &*v + }) + } + + pub fn put(&mut self, key: K, value: V) -> Option { + self.tick += 1; + if !self.entries.contains_key(&key) && self.entries.len() == self.capacity { + let oldest = self.entries.iter().min_by_key(|(_, (_, used))| *used).map(|(k, _)| k.clone()); + if let Some(k) = oldest { + self.entries.remove(&k); + } + } + self.entries.insert(key, (value, self.tick)).map(|(v, _)| v) + } + + pub fn len(&self) -> usize { + self.entries.len() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn drops_the_least_recently_used() { + let mut c = Lru::new(2); + c.put("a", 1); + c.put("b", 2); + assert_eq!(c.get(&"a"), Some(&1)); + c.put("c", 3); + assert_eq!(c.get(&"b"), None); + assert_eq!(c.len(), 2); + } +} diff --git a/crates/exav-viewer/demo/examples/files/text/page.html b/crates/exav-viewer/demo/examples/files/text/page.html new file mode 100644 index 0000000..566f240 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/page.html @@ -0,0 +1,28 @@ + + + + + A page, shown as its source + + + + + + +

Harbour office

+
+
+

Berths

+ + + +
BerthLength
16.5 m
28.2 m
+

Lengths are over all, in metres.

+
+
+
+ + + diff --git a/crates/exav-viewer/demo/examples/files/text/places.kml b/crates/exav-viewer/demo/examples/files/text/places.kml new file mode 100644 index 0000000..503b038 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/places.kml @@ -0,0 +1,22 @@ + + + + Places (made up) + + + East quay + Moorings
for 60 boats.]]> + #harbour + -4.4860,48.3830,0 + + + Breakwater + 1-4.4900,48.3790,0 -4.4850,48.3820,0 -4.4800,48.3835,0 + + + Anchorage + #harbour + -4.4950,48.3850,0 -4.4900,48.3850,0 -4.4900,48.3900,0 -4.4950,48.3900,0 -4.4950,48.3850,0 + + + diff --git a/crates/exav-viewer/demo/examples/files/text/prix.csv b/crates/exav-viewer/demo/examples/files/text/prix.csv new file mode 100644 index 0000000..1ceb0b0 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/prix.csv @@ -0,0 +1,7 @@ +Région;Produit;Quantité;Prix unitaire (€);Total (€) +Bretagne;Cidre;120;3,50;420,00 +Bretagne;Galettes;300;1,20;360,00 +Normandie;Cidre;90;3,80;342,00 +Normandie;Camembert;200;4,10;820,00 +Alsace;Riesling;150;7,90;1185,00 +Alsace;Bretzels;500;0,60;300,00 diff --git a/crates/exav-viewer/demo/examples/files/text/pyproject.toml b/crates/exav-viewer/demo/examples/files/text/pyproject.toml new file mode 100644 index 0000000..54ae757 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/pyproject.toml @@ -0,0 +1,22 @@ +# A project file, to show TOML as text. +[project] +name = "harbour-register" +version = "1.4.0" +description = "The mooring register of the east quay" +requires-python = ">=3.11" +dependencies = ["httpx>=0.27", "pydantic>=2"] + +[project.optional-dependencies] +test = ["pytest", "pytest-cov"] + +[tool.ruff] +line-length = 100 +select = ["E", "F", "I"] + +[[tool.harbour.berths]] +number = 1 +length = 6.5 + +[[tool.harbour.berths]] +number = 2 +length = 8.2 diff --git a/crates/exav-viewer/demo/examples/files/text/recipes.json b/crates/exav-viewer/demo/examples/files/text/recipes.json new file mode 100644 index 0000000..72c9a84 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/recipes.json @@ -0,0 +1,133 @@ +{ + "title": "A small recipe book", + "version": 3, + "published": true, + "updated": null, + "tags": [ + "cooking", + "demo", + "café", + "日本語" + ], + "numbers": { + "integer": 42, + "negative": -7, + "float": 3.14159, + "exponent": 6.02e+23, + "tiny": 1e-09, + "zero": 0 + }, + "recipes": [ + { + "name": "Crepes", + "serves": 4, + "time": { + "prep_min": 10, + "rest_min": 30, + "cook_min": 20 + }, + "ingredients": [ + { + "item": "flour", + "amount": 250, + "unit": "g" + }, + { + "item": "milk", + "amount": 0.5, + "unit": "l" + }, + { + "item": "eggs", + "amount": 3, + "unit": null + }, + { + "item": "salt", + "amount": "a pinch" + } + ], + "steps": [ + "Whisk the flour and eggs.", + "Add the milk slowly.", + "Rest for 30 minutes.", + "Cook in a hot pan, a minute a side." + ], + "nutrition": { + "kcal": 210, + "protein_g": 8.5, + "vegetarian": true + } + }, + { + "name": "Ratatouille", + "serves": 6, + "time": { + "prep_min": 25, + "cook_min": 60 + }, + "ingredients": [ + { + "item": "aubergine", + "amount": 2 + }, + { + "item": "courgette", + "amount": 3 + }, + { + "item": "tomatoes", + "amount": 500, + "unit": "g" + }, + { + "item": "olive oil", + "amount": 4, + "unit": "tbsp" + } + ], + "steps": [ + "Dice the vegetables.", + "Fry each in turn.", + "Stew together for an hour." + ], + "nutrition": { + "kcal": 160, + "protein_g": 3.1, + "vegetarian": true, + "vegan": true + } + } + ], + "nested": { + "a": { + "b": { + "c": { + "d": { + "e": [ + 1, + [ + 2, + [ + 3, + [ + 4, + [ + 5 + ] + ] + ] + ] + ] + } + } + } + } + }, + "escapes": "quote \" backslash \\ slash / newline \n tab \t unicode é 中 😀", + "empty": { + "object": {}, + "array": [], + "string": "" + } +} diff --git a/crates/exav-viewer/demo/examples/files/text/report.sql b/crates/exav-viewer/demo/examples/files/text/report.sql new file mode 100644 index 0000000..8bc1a09 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/report.sql @@ -0,0 +1,43 @@ +-- Moorings by month, with window functions. CC0-1.0, exav project. +CREATE TABLE vessel ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL UNIQUE, + length_m REAL NOT NULL CHECK (length_m > 0), + kind TEXT NOT NULL DEFAULT 'sloop' +); + +CREATE TABLE stay ( + id INTEGER PRIMARY KEY, + vessel_id INTEGER NOT NULL REFERENCES vessel (id), + berth INTEGER NOT NULL, + arrived DATE NOT NULL, + nights INTEGER NOT NULL, + fee_eur NUMERIC(8, 2) +); + +CREATE INDEX stay_by_arrival ON stay (arrived); + +WITH monthly AS ( + SELECT strftime('%Y-%m', arrived) AS month, + count(*) AS stays, + sum(nights) AS nights, + sum(fee_eur) AS income + FROM stay + GROUP BY 1 +) +SELECT month, + stays, + income, + income - lag(income) OVER (ORDER BY month) AS change, + round(100.0 * income / sum(income) OVER (), 1) AS share_pct, + rank() OVER (ORDER BY income DESC) AS income_rank +FROM monthly +ORDER BY month; + +-- The ten longest boats that stayed more than three nights. +SELECT v.name, v.length_m, s.nights +FROM vessel AS v +JOIN stay AS s ON s.vessel_id = v.id +WHERE s.nights > 3 AND v.kind IN ('ketch', 'trawler') +ORDER BY v.length_m DESC +LIMIT 10; diff --git a/crates/exav-viewer/demo/examples/files/text/route.gpx b/crates/exav-viewer/demo/examples/files/text/route.gpx new file mode 100644 index 0000000..0daf632 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/route.gpx @@ -0,0 +1,71 @@ + + + Coastal walk (made up)A made-up track, 60 points. + StartFlag + ViewpointSeals on the rocks, in winter. + + Morning walk + + 20.0 + 22.4 + 24.8 + 27.1 + 29.3 + 31.2 + 32.9 + 34.3 + 35.4 + 36.2 + 36.7 + 36.8 + 36.5 + 35.9 + 35.0 + 33.8 + 32.4 + 30.7 + 28.8 + 26.8 + 24.7 + 22.6 + 20.5 + 18.5 + 16.6 + 14.9 + 13.4 + 12.1 + 11.2 + 10.5 + 10.2 + 10.3 + 10.6 + 11.4 + 12.4 + 13.8 + 15.4 + 17.3 + 19.4 + 21.7 + 24.1 + 26.5 + 29.0 + 31.4 + 33.7 + 35.9 + 37.8 + 39.6 + 41.1 + 42.2 + 43.1 + 43.6 + 43.8 + 43.6 + 43.1 + 42.2 + 41.1 + 39.7 + 38.0 + 36.2 + + + diff --git a/crates/exav-viewer/demo/examples/files/text/server.log b/crates/exav-viewer/demo/examples/files/text/server.log new file mode 100644 index 0000000..8584946 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/server.log @@ -0,0 +1,120 @@ +2000-01-01T08:00:00Z INFO request id=1000 path=/berths/1 status=200 ms=12 +2000-01-01T08:01:07Z INFO request id=1001 path=/berths/2 status=200 ms=49 +2000-01-01T08:02:14Z INFO request id=1002 path=/berths/3 status=304 ms=86 +2000-01-01T08:03:21Z WARN request id=1003 path=/berths/4 status=404 ms=123 +2000-01-01T08:04:28Z ERROR request id=1004 path=/berths/5 status=500 ms=160 +2000-01-01T08:05:35Z INFO request id=1005 path=/berths/6 status=200 ms=197 +2000-01-01T08:06:42Z INFO request id=1006 path=/berths/7 status=200 ms=234 +2000-01-01T08:07:49Z INFO request id=1007 path=/berths/8 status=304 ms=21 +2000-01-01T08:08:56Z WARN request id=1008 path=/berths/9 status=404 ms=58 +2000-01-01T08:09:03Z ERROR request id=1009 path=/berths/10 status=500 ms=95 +2000-01-01T08:10:10Z INFO request id=1010 path=/berths/11 status=200 ms=132 +2000-01-01T08:11:17Z INFO request id=1011 path=/berths/12 status=200 ms=169 +2000-01-01T08:12:24Z INFO request id=1012 path=/berths/13 status=304 ms=206 +2000-01-01T08:13:31Z WARN request id=1013 path=/berths/14 status=404 ms=243 +2000-01-01T08:14:38Z ERROR request id=1014 path=/berths/15 status=500 ms=30 +2000-01-01T08:15:45Z INFO request id=1015 path=/berths/16 status=200 ms=67 +2000-01-01T08:16:52Z INFO request id=1016 path=/berths/17 status=200 ms=104 +2000-01-01T08:17:59Z INFO request id=1017 path=/berths/18 status=304 ms=141 +2000-01-01T08:18:06Z WARN request id=1018 path=/berths/19 status=404 ms=178 +2000-01-01T08:19:13Z ERROR request id=1019 path=/berths/20 status=500 ms=215 +2000-01-01T08:20:20Z INFO request id=1020 path=/berths/21 status=200 ms=252 +2000-01-01T08:21:27Z INFO request id=1021 path=/berths/22 status=200 ms=39 +2000-01-01T08:22:34Z INFO request id=1022 path=/berths/23 status=304 ms=76 +2000-01-01T08:23:41Z WARN request id=1023 path=/berths/24 status=404 ms=113 +2000-01-01T08:24:48Z ERROR request id=1024 path=/berths/25 status=500 ms=150 +2000-01-01T08:25:55Z INFO request id=1025 path=/berths/26 status=200 ms=187 +2000-01-01T08:26:02Z INFO request id=1026 path=/berths/27 status=200 ms=224 +2000-01-01T08:27:09Z INFO request id=1027 path=/berths/28 status=304 ms=261 +2000-01-01T08:28:16Z WARN request id=1028 path=/berths/29 status=404 ms=48 +2000-01-01T08:29:23Z ERROR request id=1029 path=/berths/30 status=500 ms=85 +2000-01-01T08:30:30Z INFO request id=1030 path=/berths/31 status=200 ms=122 +2000-01-01T08:31:37Z INFO request id=1031 path=/berths/32 status=200 ms=159 +2000-01-01T08:32:44Z INFO request id=1032 path=/berths/33 status=304 ms=196 +2000-01-01T08:33:51Z WARN request id=1033 path=/berths/34 status=404 ms=233 +2000-01-01T08:34:58Z ERROR request id=1034 path=/berths/35 status=500 ms=20 +2000-01-01T08:35:05Z INFO request id=1035 path=/berths/36 status=200 ms=57 +2000-01-01T08:36:12Z INFO request id=1036 path=/berths/37 status=200 ms=94 +2000-01-01T08:37:19Z INFO request id=1037 path=/berths/38 status=304 ms=131 +2000-01-01T08:38:26Z WARN request id=1038 path=/berths/39 status=404 ms=168 +2000-01-01T08:39:33Z ERROR request id=1039 path=/berths/40 status=500 ms=205 +2000-01-01T08:40:40Z INFO request id=1040 path=/berths/41 status=200 ms=242 +2000-01-01T08:41:47Z INFO request id=1041 path=/berths/42 status=200 ms=29 +2000-01-01T08:42:54Z INFO request id=1042 path=/berths/43 status=304 ms=66 +2000-01-01T08:43:01Z WARN request id=1043 path=/berths/44 status=404 ms=103 +2000-01-01T08:44:08Z ERROR request id=1044 path=/berths/45 status=500 ms=140 +2000-01-01T08:45:15Z INFO request id=1045 path=/berths/46 status=200 ms=177 +2000-01-01T08:46:22Z INFO request id=1046 path=/berths/47 status=200 ms=214 +2000-01-01T08:47:29Z INFO request id=1047 path=/berths/48 status=304 ms=251 +2000-01-01T08:48:36Z WARN request id=1048 path=/berths/49 status=404 ms=38 +2000-01-01T08:49:43Z ERROR request id=1049 path=/berths/50 status=500 ms=75 +2000-01-01T08:50:50Z INFO request id=1050 path=/berths/51 status=200 ms=112 +2000-01-01T08:51:57Z INFO request id=1051 path=/berths/52 status=200 ms=149 +2000-01-01T08:52:04Z INFO request id=1052 path=/berths/53 status=304 ms=186 +2000-01-01T08:53:11Z WARN request id=1053 path=/berths/54 status=404 ms=223 +2000-01-01T08:54:18Z ERROR request id=1054 path=/berths/55 status=500 ms=260 +2000-01-01T08:55:25Z INFO request id=1055 path=/berths/56 status=200 ms=47 +2000-01-01T08:56:32Z INFO request id=1056 path=/berths/57 status=200 ms=84 +2000-01-01T08:57:39Z INFO request id=1057 path=/berths/58 status=304 ms=121 +2000-01-01T08:58:46Z WARN request id=1058 path=/berths/59 status=404 ms=158 +2000-01-01T08:59:53Z ERROR request id=1059 path=/berths/60 status=500 ms=195 +2000-01-01T09:00:00Z INFO request id=1060 path=/berths/1 status=200 ms=232 +2000-01-01T09:01:07Z INFO request id=1061 path=/berths/2 status=200 ms=19 +2000-01-01T09:02:14Z INFO request id=1062 path=/berths/3 status=304 ms=56 +2000-01-01T09:03:21Z WARN request id=1063 path=/berths/4 status=404 ms=93 +2000-01-01T09:04:28Z ERROR request id=1064 path=/berths/5 status=500 ms=130 +2000-01-01T09:05:35Z INFO request id=1065 path=/berths/6 status=200 ms=167 +2000-01-01T09:06:42Z INFO request id=1066 path=/berths/7 status=200 ms=204 +2000-01-01T09:07:49Z INFO request id=1067 path=/berths/8 status=304 ms=241 +2000-01-01T09:08:56Z WARN request id=1068 path=/berths/9 status=404 ms=28 +2000-01-01T09:09:03Z ERROR request id=1069 path=/berths/10 status=500 ms=65 +2000-01-01T09:10:10Z INFO request id=1070 path=/berths/11 status=200 ms=102 +2000-01-01T09:11:17Z INFO request id=1071 path=/berths/12 status=200 ms=139 +2000-01-01T09:12:24Z INFO request id=1072 path=/berths/13 status=304 ms=176 +2000-01-01T09:13:31Z WARN request id=1073 path=/berths/14 status=404 ms=213 +2000-01-01T09:14:38Z ERROR request id=1074 path=/berths/15 status=500 ms=250 +2000-01-01T09:15:45Z INFO request id=1075 path=/berths/16 status=200 ms=37 +2000-01-01T09:16:52Z INFO request id=1076 path=/berths/17 status=200 ms=74 +2000-01-01T09:17:59Z INFO request id=1077 path=/berths/18 status=304 ms=111 +2000-01-01T09:18:06Z WARN request id=1078 path=/berths/19 status=404 ms=148 +2000-01-01T09:19:13Z ERROR request id=1079 path=/berths/20 status=500 ms=185 +2000-01-01T09:20:20Z INFO request id=1080 path=/berths/21 status=200 ms=222 +2000-01-01T09:21:27Z INFO request id=1081 path=/berths/22 status=200 ms=259 +2000-01-01T09:22:34Z INFO request id=1082 path=/berths/23 status=304 ms=46 +2000-01-01T09:23:41Z WARN request id=1083 path=/berths/24 status=404 ms=83 +2000-01-01T09:24:48Z ERROR request id=1084 path=/berths/25 status=500 ms=120 +2000-01-01T09:25:55Z INFO request id=1085 path=/berths/26 status=200 ms=157 +2000-01-01T09:26:02Z INFO request id=1086 path=/berths/27 status=200 ms=194 +2000-01-01T09:27:09Z INFO request id=1087 path=/berths/28 status=304 ms=231 +2000-01-01T09:28:16Z WARN request id=1088 path=/berths/29 status=404 ms=18 +2000-01-01T09:29:23Z ERROR request id=1089 path=/berths/30 status=500 ms=55 +2000-01-01T09:30:30Z INFO request id=1090 path=/berths/31 status=200 ms=92 +2000-01-01T09:31:37Z INFO request id=1091 path=/berths/32 status=200 ms=129 +2000-01-01T09:32:44Z INFO request id=1092 path=/berths/33 status=304 ms=166 +2000-01-01T09:33:51Z WARN request id=1093 path=/berths/34 status=404 ms=203 +2000-01-01T09:34:58Z ERROR request id=1094 path=/berths/35 status=500 ms=240 +2000-01-01T09:35:05Z INFO request id=1095 path=/berths/36 status=200 ms=27 +2000-01-01T09:36:12Z INFO request id=1096 path=/berths/37 status=200 ms=64 +2000-01-01T09:37:19Z INFO request id=1097 path=/berths/38 status=304 ms=101 +2000-01-01T09:38:26Z WARN request id=1098 path=/berths/39 status=404 ms=138 +2000-01-01T09:39:33Z ERROR request id=1099 path=/berths/40 status=500 ms=175 +2000-01-01T09:40:40Z INFO request id=1100 path=/berths/41 status=200 ms=212 +2000-01-01T09:41:47Z INFO request id=1101 path=/berths/42 status=200 ms=249 +2000-01-01T09:42:54Z INFO request id=1102 path=/berths/43 status=304 ms=36 +2000-01-01T09:43:01Z WARN request id=1103 path=/berths/44 status=404 ms=73 +2000-01-01T09:44:08Z ERROR request id=1104 path=/berths/45 status=500 ms=110 +2000-01-01T09:45:15Z INFO request id=1105 path=/berths/46 status=200 ms=147 +2000-01-01T09:46:22Z INFO request id=1106 path=/berths/47 status=200 ms=184 +2000-01-01T09:47:29Z INFO request id=1107 path=/berths/48 status=304 ms=221 +2000-01-01T09:48:36Z WARN request id=1108 path=/berths/49 status=404 ms=258 +2000-01-01T09:49:43Z ERROR request id=1109 path=/berths/50 status=500 ms=45 +2000-01-01T09:50:50Z INFO request id=1110 path=/berths/51 status=200 ms=82 +2000-01-01T09:51:57Z INFO request id=1111 path=/berths/52 status=200 ms=119 +2000-01-01T09:52:04Z INFO request id=1112 path=/berths/53 status=304 ms=156 +2000-01-01T09:53:11Z WARN request id=1113 path=/berths/54 status=404 ms=193 +2000-01-01T09:54:18Z ERROR request id=1114 path=/berths/55 status=500 ms=230 +2000-01-01T09:55:25Z INFO request id=1115 path=/berths/56 status=200 ms=17 +2000-01-01T09:56:32Z INFO request id=1116 path=/berths/57 status=200 ms=54 +2000-01-01T09:57:39Z INFO request id=1117 path=/berths/58 status=304 ms=91 +2000-01-01T09:58:46Z WARN request id=1118 path=/berths/59 status=404 ms=128 +2000-01-01T09:59:53Z ERROR request id=1119 path=/berths/60 status=500 ms=165 diff --git a/crates/exav-viewer/demo/examples/files/text/style.css b/crates/exav-viewer/demo/examples/files/text/style.css new file mode 100644 index 0000000..013affe --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/style.css @@ -0,0 +1,50 @@ +/* A small stylesheet with custom properties, grid and a media query. CC0-1.0, exav project. */ +:root { + --ink: #1b2430; + --paper: #fbfaf7; + --accent: #0b7285; + --radius: 0.5rem; + --gap: clamp(0.75rem, 2vw, 1.5rem); + color-scheme: light dark; +} + +@media (prefers-color-scheme: dark) { + :root { --ink: #e7edf3; --paper: #12171d; --accent: #66d9e8; } +} + +*, *::before, *::after { box-sizing: border-box; } + +body { + margin: 0; + background: var(--paper); + color: var(--ink); + font: 1rem/1.55 system-ui, sans-serif; +} + +.cards { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); + gap: var(--gap); + padding: var(--gap); +} + +.card { + padding: 1rem; + border: 1px solid color-mix(in srgb, var(--ink) 20%, transparent); + border-radius: var(--radius); + transition: transform 120ms ease, box-shadow 120ms ease; +} + +.card:hover, +.card:focus-within { + transform: translateY(-2px); + box-shadow: 0 6px 18px rgb(0 0 0 / 0.12); +} + +.card > h2::after { content: " \2192"; color: var(--accent); } + +a:not([class]) { color: var(--accent); text-underline-offset: 0.2em; } + +@media (max-width: 40rem) { + .cards { grid-template-columns: 1fr; } +} diff --git a/crates/exav-viewer/demo/examples/files/text/subtitles.srt b/crates/exav-viewer/demo/examples/files/text/subtitles.srt new file mode 100644 index 0000000..6630bd3 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/subtitles.srt @@ -0,0 +1,23 @@ +1 +00:00:02,000 --> 00:00:03,800 +The tide is coming in. + +2 +00:00:04,000 --> 00:00:05,800 +Berth fourteen is free. + +3 +00:00:06,000 --> 00:00:07,800 +A gull laughs. + +4 +00:00:08,000 --> 00:00:09,800 +Take the line, please. + +5 +00:00:10,000 --> 00:00:11,800 +Engine off, thank you. + +6 +00:00:12,000 --> 00:00:13,800 +Welcome to the east quay. diff --git a/crates/exav-viewer/demo/examples/files/text/tides.tsv b/crates/exav-viewer/demo/examples/files/text/tides.tsv new file mode 100644 index 0000000..989f038 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/tides.tsv @@ -0,0 +1,29 @@ +day high_1 height_1_m low_1 height_2_m coefficient +1 05.80 5.01 11.80 1.98 78 +2 06.60 5.49 12.60 1.93 86 +3 07.40 5.93 13.40 1.84 93 +4 08.20 6.30 14.20 1.73 100 +5 09.00 6.60 15.00 1.59 104 +6 09.80 6.80 15.80 1.43 108 +7 10.60 6.89 16.60 1.27 109 +8 11.40 6.88 17.40 1.10 109 +9 12.20 6.76 18.20 0.93 107 +10 13.00 6.54 19.00 0.78 103 +11 13.80 6.22 19.80 0.64 98 +12 14.60 5.83 20.60 0.53 92 +13 15.40 5.38 21.40 0.46 84 +14 16.20 4.89 22.20 0.41 76 +15 17.00 4.38 23.00 0.40 68 +16 17.80 3.88 23.80 0.43 59 +17 18.60 3.40 00.60 0.49 51 +18 19.40 2.98 01.40 0.58 44 +19 20.20 2.62 02.20 0.70 38 +20 21.00 2.35 03.00 0.85 34 +21 21.80 2.17 03.80 1.01 31 +22 22.60 2.10 04.60 1.17 30 +23 23.40 2.14 05.40 1.34 30 +24 00.20 2.28 06.20 1.51 33 +25 01.00 2.53 07.00 1.66 37 +26 01.80 2.86 07.80 1.78 42 +27 02.60 3.27 08.60 1.89 49 +28 03.40 3.73 09.40 1.96 57 diff --git a/crates/exav-viewer/demo/examples/files/text/tokens.ts b/crates/exav-viewer/demo/examples/files/text/tokens.ts new file mode 100644 index 0000000..3756dc2 --- /dev/null +++ b/crates/exav-viewer/demo/examples/files/text/tokens.ts @@ -0,0 +1,54 @@ +// An arithmetic tokenizer and evaluator. CC0-1.0, exav project. +type Token = { kind: "num"; value: number } | { kind: "op"; value: "+" | "-" | "*" | "/" | "^" } | { kind: "paren"; value: "(" | ")" }; + +export function tokenize(source: string): Token[] { + const tokens: Token[] = []; + const re = /\s*(?:(\d+(?:\.\d+)?)|([-+*/^])|([()]))/y; + let match: RegExpExecArray | null; + while (re.lastIndex < source.length && (match = re.exec(source))) { + if (match[1] !== undefined) tokens.push({ kind: "num", value: Number(match[1]) }); + else if (match[2]) tokens.push({ kind: "op", value: match[2] as "+" }); + else tokens.push({ kind: "paren", value: match[3] as "(" }); + } + if (re.lastIndex < source.trimEnd().length) throw new SyntaxError(`unexpected character at ${re.lastIndex}`); + return tokens; +} + +const PRECEDENCE: Record = { "+": [1, "left"], "-": [1, "left"], "*": [2, "left"], "/": [2, "left"], "^": [3, "right"] }; + +/** Evaluates with the shunting-yard algorithm. */ +export function evaluate(source: string): number { + const out: number[] = []; + const ops: string[] = []; + const apply = (op: string) => { + const b = out.pop(); + const a = out.pop(); + if (a === undefined || b === undefined) throw new SyntaxError("missing operand"); + out.push(op === "+" ? a + b : op === "-" ? a - b : op === "*" ? a * b : op === "/" ? a / b : a ** b); + }; + for (const t of tokenize(source)) { + if (t.kind === "num") out.push(t.value); + else if (t.kind === "op") { + const [p, assoc] = PRECEDENCE[t.value]!; + while (ops.length) { + const top = ops[ops.length - 1]!; + const [tp] = PRECEDENCE[top] ?? [-1]; + if (top !== "(" && (tp > p || (tp === p && assoc === "left"))) apply(ops.pop()!); + else break; + } + ops.push(t.value); + } else if (t.value === "(") ops.push("("); + else { + while (ops.length && ops[ops.length - 1] !== "(") apply(ops.pop()!); + if (ops.pop() !== "(") throw new SyntaxError("unbalanced parenthesis"); + } + } + while (ops.length) { + const op = ops.pop()!; + if (op === "(") throw new SyntaxError("unbalanced parenthesis"); + apply(op); + } + return out[0] ?? NaN; +} + +console.log(evaluate("2 + 3 * (4 - 1) ^ 2")); diff --git a/crates/exav-viewer/demo/examples/generate/catalog.json b/crates/exav-viewer/demo/examples/generate/catalog.json new file mode 100644 index 0000000..92d354f --- /dev/null +++ b/crates/exav-viewer/demo/examples/generate/catalog.json @@ -0,0 +1,376 @@ +{ + "refs": { + "pixls": { "author": "Uploader to raw.pixls.us (the site gives no name)", "source": "https://raw.pixls.us/#repo", "evidence": "https://raw.pixls.us/json/getrepository.php?set=all", "evidence_quote": "Creative Commons 0 - Public Domain", "evidence_row": "sha256", "licence": "CC0-1.0", "attribution": "" }, + "bsi": { "author": "buildingSMART International Ltd.", "source": "https://github.com/buildingSMART/Sample-Test-Files", "evidence": "https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/LICENSE", "evidence_quote": "This work is licensed under the Creative Commons Attribution 4.0 International License.", "licence": "CC-BY-4.0", "attribution": "buildingSMART International, Sample-Test-Files, https://github.com/buildingSMART/Sample-Test-Files, licensed CC BY 4.0. No changes." }, + "barraca": { "author": "Ã’scar Selfa", "source": "https://zenodo.org/records/14293897", "evidence": "https://zenodo.org/records/14293897", "evidence_quote": "Creative Commons Attribution 4.0 International", "licence": "CC-BY-4.0", "attribution": "Ã’scar Selfa, Barraca Valenciana de Llauradors: Model BIM i Estudi de la Tipologia Arquitectònica, Zenodo, doi:10.5281/zenodo.14293897, CC BY 4.0. No changes." }, + "ezdxf": { "author": "Manfred Moitzi (ezdxf)", "source": "https://github.com/mozman/ezdxf", "evidence": "https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/LICENSE", "evidence_quote": "Copyright (c) 2020 Manfred Moitzi", "licence": "MIT", "attribution": "Copyright (c) 2020 Manfred Moitzi, ezdxf, MIT License. No changes." }, + "khronos": { "author": "Khronos glTF Sample Assets (the model's own README names the author)", "source": "https://github.com/KhronosGroup/glTF-Sample-Assets", "licence": "CC-BY-4.0" }, + "poi": { "author": "Apache POI committers", "source": "https://github.com/apache/poi/tree/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data", "evidence": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/legal/LICENSE", "evidence_quote": "Version 2.0, January 2004", "licence": "Apache-2.0", "attribution": "Apache POI test data, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/poi. No changes." }, + "tika": { "author": "Apache Tika committers", "source": "https://github.com/apache/tika/tree/f58e44c022a9952252f3e094dcc40abd931f7ecd", "evidence": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/LICENSE.txt", "evidence_quote": "Version 2.0, January 2004", "licence": "Apache-2.0", "attribution": "Apache Tika test document, Copyright The Apache Software Foundation, Apache-2.0, https://github.com/apache/tika. No changes." }, + "docx4j": { "author": "Jason Harrop and the docx4j contributors", "source": "https://github.com/plutext/docx4j", "evidence": "https://raw.githubusercontent.com/plutext/docx4j/c95b55be6832ff716131ffdbd7006755db92f696/legals/LICENSE", "evidence_quote": "Version 2.0, January 2004", "licence": "Apache-2.0", "attribution": "docx4j, Jason Harrop / Plutext, https://github.com/plutext/docx4j, Apache-2.0. No changes." }, + "odfdo": { "author": "Jérôme Dumonteil (odfdo)", "source": "https://github.com/jdum/odfdo", "evidence": "https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/LICENSE", "evidence_quote": "Version 2.0, January 2004", "licence": "Apache-2.0", "attribution": "Copyright Jérôme Dumonteil, odfdo, Apache-2.0, https://github.com/jdum/odfdo. No changes." }, + "gsa508": { "author": "U.S. General Services Administration and the agencies that wrote the documents (Section508.gov)", "source": "https://github.com/GSA/Assets.Section508.gov", "evidence": "https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/LICENSE.md", "evidence_quote": "this project is in the public domain within the United States of America. Additionally, we waive copyright and", "licence": "CC0-1.0", "attribution": "" }, + "cleveland": { "author": "Cleveland Museum of Art", "licence": "CC0-1.0", "evidence_quote": "\"share_license_status\":\"CC0\"", "attribution": "" }, + "zenodo": { "licence": "CC-BY-4.0", "evidence_quote": "Creative Commons Attribution 4.0 International" } + }, + "blocks": [ + { + "group": "images", + "source": "generated", + "gen": "make-images.py", + "dir": "images", + "files": [ + { "file": "scene.png", "family": "png", "title": "Dusk landscape, PNG", "features": "8-bit RGB, optimised" }, + { "file": "scene-alpha.png", "family": "png", "title": "Landscape fading to transparent, PNG", "features": "RGBA: the viewer shows its chequerboard through the alpha" }, + { "file": "scene-indexed.png", "family": "png", "title": "Landscape in 32 colours, PNG", "features": "palette (indexed) PNG" }, + { "file": "gradient-grey16.png", "family": "png", "title": "Grey ramp, 16-bit PNG", "features": "16-bit greyscale" }, + { "file": "bounce.png", "family": "apng", "title": "Bouncing ball, animated PNG", "features": "24 frames, APNG" }, + { "file": "scene.jpg", "family": "jpeg", "title": "Dusk landscape, JPEG", "features": "baseline 4:2:0 with EXIF description and copyright" }, + { "file": "scene-progressive.jpg", "family": "jpeg", "title": "Dusk landscape, progressive JPEG", "features": "progressive scans, optimised Huffman tables" }, + { "file": "scene-orientation6.jpg", "family": "jpeg", "title": "JPEG stored on its side with EXIF orientation 6", "features": "shown upright through the EXIF orientation" }, + { "file": "scene-grey.jpg", "family": "jpeg", "title": "Landscape in grey, JPEG", "features": "single-component JPEG" }, + { "file": "scene-cmyk.jpg", "family": "jpeg", "title": "Landscape as a CMYK JPEG", "features": "four components (Adobe inverted CMYK)" }, + { "file": "bounce.gif", "family": "gif", "title": "Bouncing ball, animated GIF", "features": "24 frames with a palette each" }, + { "file": "scene.gif", "family": "gif", "title": "Dusk landscape, dithered GIF", "features": "256 colours, Floyd-Steinberg dithering" }, + { "file": "scene.webp", "family": "webp", "title": "Dusk landscape, lossy WebP", "features": "VP8" }, + { "file": "scene-lossless.webp", "family": "webp", "title": "Dusk landscape, lossless WebP", "features": "VP8L" }, + { "file": "scene-alpha.webp", "family": "webp", "title": "Landscape fading to transparent, WebP", "features": "lossy colour with an alpha plane (VP8X, ALPH)" }, + { "file": "bounce.webp", "family": "webp", "title": "Bouncing ball, animated WebP", "features": "24 frames" }, + { "file": "scene-lzw.tif", "family": "tiff", "title": "Dusk landscape, TIFF with LZW", "features": "RGB, LZW, 300 dpi" }, + { "file": "scene-jpeg.tif", "family": "tiff", "title": "Dusk landscape, TIFF with JPEG compression", "features": "JPEG in TIFF (compression 7)" }, + { "file": "scene-cmyk-packbits.tif", "family": "tiff", "title": "Landscape as a CMYK TIFF", "features": "four inks, PackBits" }, + { "file": "gradient-grey16.tif", "family": "tiff", "title": "Grey ramp, 16-bit TIFF", "features": "16-bit greyscale, Deflate" }, + { "file": "scene-pages.tif", "family": "tiff", "title": "Three-page TIFF", "features": "pages of 512, 256 and 128 pixels, the last in grey, Deflate" }, + { "file": "fax-g4.tif", "family": "tiff-fax", "title": "Fax cover sheet and register, CCITT Group 4 TIFF", "features": "1-bit, 1728 by 2200 at 204 by 196 dpi, T.6" }, + { "file": "fax-g4-3pages.tif", "family": "tiff-fax", "title": "Three-page fax, CCITT Group 4 TIFF", "features": "three pages, T.6" }, + { "file": "fax-g3-1d.tif", "group": "unsupported", "family": "tiff-fax", "title": "Fax page, CCITT Group 3 (T.4, one-dimensional) TIFF", "features": "kept to show the error: the TIFF decoder reads Group 4 only" }, + { "file": "scene-24.bmp", "family": "bmp", "title": "Dusk landscape, 24-bit BMP", "features": "BI_RGB, bottom-up" }, + { "file": "scene-8.bmp", "family": "bmp", "title": "Dusk landscape, 8-bit BMP", "features": "256-colour palette" }, + { "file": "scene-32.bmp", "family": "bmp", "title": "Dusk landscape, 32-bit BMP", "features": "four channels" }, + { "file": "scene-1bit.bmp", "family": "bmp", "title": "Dusk landscape, 1-bit BMP", "features": "two-colour palette" }, + { "file": "scene-rle8.bmp", "family": "bmp", "title": "Dusk landscape, 8-bit BMP with RLE compression", "features": "BI_RLE8 with encoded and absolute runs" }, + { "file": "icon.ico", "family": "ico", "title": "Icon with seven sizes", "features": "16 to 256 pixels, PNG-coded images" }, + { "file": "icon-legacy.ico", "family": "ico", "title": "Icon in the legacy bitmap coding", "features": "32-bit and 8-bit DIBs with AND masks, and one PNG image" }, + { "file": "scene.ppm", "family": "pnm", "title": "Dusk landscape, PPM (P6)", "features": "binary pixmap with a comment" }, + { "file": "scene-ascii.ppm", "family": "pnm", "title": "Dusk landscape, ASCII PPM (P3)", "features": "text pixmap, 48 by 36" }, + { "file": "scene-grey16.pgm", "family": "pnm", "title": "Landscape in grey, 16-bit PGM (P5)", "features": "maxval 65535" }, + { "file": "scene.pbm", "family": "pnm", "title": "Landscape as a bitmap, PBM (P4)", "features": "1 bit a pixel" }, + { "file": "scene-alpha.pam", "family": "pnm", "title": "Landscape with alpha, PAM (P7)", "features": "RGB_ALPHA tuples" }, + { "file": "scene.qoi", "family": "qoi", "title": "Dusk landscape, QOI", "features": "three channels" }, + { "file": "scene-alpha.qoi", "family": "qoi", "title": "Landscape with alpha, QOI", "features": "four channels" }, + { "file": "scene.ff", "family": "farbfeld", "title": "Landscape with alpha, farbfeld", "features": "16-bit RGBA, big-endian" }, + { "file": "sunset.hdr", "family": "hdr", "title": "Sunset with a sun far brighter than the sky, Radiance HDR", "features": "RGBE with run-length scanlines; the sun is 60 times white" }, + { "file": "sunset-flat.hdr", "family": "hdr", "title": "Sunset, uncompressed Radiance HDR", "features": "flat RGBE scanlines" }, + { "file": "scene-bc1.dds", "family": "dds", "title": "Dusk landscape, DDS with BC1 (DXT1)", "features": "full mipmap chain" }, + { "file": "scene-bc3.dds", "family": "dds", "title": "Landscape with alpha, DDS with BC3 (DXT5)", "features": "full mipmap chain, alpha blocks" }, + { "file": "scene.jp2", "family": "jpeg2000", "title": "Dusk landscape, JPEG 2000 (JP2)", "features": "lossy, 3 quality layers, 5 resolutions, 256-pixel tiles, RPCL progression" }, + { "file": "scene.j2k", "family": "jpeg2000", "title": "Dusk landscape, bare JPEG 2000 codestream", "features": "no JP2 boxes" }, + { "file": "scene-grey.jp2", "family": "jpeg2000", "title": "Landscape in grey, JPEG 2000", "features": "one component" }, + { "file": "scene-alpha.jp2", "family": "jpeg2000", "title": "Landscape with alpha, JPEG 2000", "features": "four components with an alpha channel" }, + { "file": "page-generic.jb2", "family": "jbig2", "title": "Fax page as a JBIG2 file, generic region", "features": "1-bit page of 1240 by 1579, arithmetic coding" }, + { "file": "page-symbol.jb2", "family": "jbig2", "title": "Fax page as a JBIG2 file, symbol coding", "features": "text region over a symbol dictionary" }, + { "file": "scene-lossy.jxl", "family": "jpeg-xl", "title": "Dusk landscape, JPEG XL, lossy", "features": "VarDCT at distance 1" }, + { "file": "scene-lossless.jxl", "family": "jpeg-xl", "title": "Dusk landscape, JPEG XL, lossless", "features": "modular mode" }, + { "file": "scene-alpha.jxl", "family": "jpeg-xl", "title": "Landscape with alpha, JPEG XL", "features": "lossless with an extra alpha channel" }, + { "file": "bounce.jxl", "family": "jpeg-xl", "title": "Bouncing ball, animated JPEG XL", "features": "24 frames" } + ] + }, + { + "group": "cad", + "source": "generated", + "gen": "make-cad.py", + "dir": "cad", + "files": [ + { "file": "house-plan.dxf", "family": "dxf", "title": "House, ground floor plan (DXF 2018)", "features": "walls cut at openings with pattern hatches, door blocks with attributes, window and furniture blocks, axes with bubbles, room labels, linear, aligned, radius and angular dimensions, stair, north arrow, 17 layers, paper-space sheet with a viewport and a title block" }, + { "file": "house-plan-r2000.dxf", "family": "dxf", "title": "House, ground floor plan (DXF 2000)", "features": "the same plan written as an AutoCAD 2000 file" }, + { "file": "house-elevations.dxf", "family": "dxf", "title": "House, four elevations and a section in 2D", "features": "gabled roofs with roof-tile hatches, plaster hatches, ground hatching, windows with transparent glass, steps, level marks, height dimensions, a hatched section with a stair" }, + { "file": "hatch-gallery.dxf", "family": "dxf", "title": "Hatch gallery", "features": "about a hundred predefined patterns, nine gradient types, islands in the three hatch styles, boundaries of lines, arcs, ellipses and splines, pattern angle and scale" }, + { "file": "dimensions.dxf", "family": "dxf", "title": "Dimension types", "features": "linear, aligned, diameter, radius, arc length, angular (two lines and three points), ordinate, leaders, a multileader, tolerances, text override, three dimension styles" }, + { "file": "linetypes.dxf", "family": "dxf", "title": "Linetypes, line weights and polylines", "features": "the standard linetypes, custom ones with text inside, 12 line weights, per-entity scale, linetype generation, polylines with widths, circles, arcs, ellipses and splines in dashed styles" }, + { "file": "text-styles.dxf", "family": "dxf", "title": "Text styles and MTEXT", "features": "ten text styles (width and oblique factors, mirrored, upside down), justifications, rotation, special codes, Unicode, MTEXT colours, fonts, stacked fractions, underline, columns, background, nine attachment points" }, + { "file": "blocks.dxf", "family": "dxf", "title": "Blocks, nested inserts and arrays", "features": "a block inside a block inside a block with attributes, mirrored, scaled and rotated inserts, a 3 by 8 array, BYBLOCK colours" }, + { "file": "bracket.dxf", "family": "dxf", "title": "Mechanical part: an L bracket in three views", "features": "centre and hidden lines, a section with hatching, dimensions with tolerances, diameter and radius dimensions, a leader, an A4 sheet with a title block" }, + { "file": "site-plan.dxf", "family": "dxf", "title": "Site plan with contour lines", "features": "closed spline contours, wide polyline roads, parcels with areas, hatched buildings, a gradient pond, spot heights, trees, scale bar, legend and north arrow" }, + { "file": "legacy-r12.dxf", "family": "dxf", "title": "Gear in the R12 format", "features": "POLYLINE, CIRCLE, ARC, TEXT, SOLID, 3DFACE and INSERT entities of the 1992 format" } + ] + }, + { + "group": "3d", + "source": "generated", + "gen": "make-models.py", + "dir": "models", + "files": [ + { "file": "gear.stl", "family": "stl", "title": "Spur gear, binary STL with facet colours", "features": "864 facets, orange teeth and blue hub through the VisCAM colour attribute" }, + { "file": "bracket-ascii.stl", "family": "stl", "title": "L bracket, ASCII STL", "features": "text STL, three overlapping boxes" }, + { "file": "knot.obj", "family": "obj", "title": "Trefoil knot and base, OBJ with vertex colours", "features": "two objects (knot, base), a colour and a normal per vertex, quads, a rainbow along the knot" }, + { "file": "terrain.ply", "family": "ply", "title": "Height field, binary PLY with colours", "features": "2304 vertices with normals and a hypsometric colour each, 4418 triangles" }, + { "file": "icosphere-ascii.ply", "family": "ply", "title": "Icosphere, ASCII PLY with colours", "features": "text PLY with normals and RGBA per vertex" }, + { "file": "arm.glb", "family": "glb", "title": "Articulated arm in a glass dome, GLB", "features": "node tree with rotations and scales, five materials, a metallic and a transparent one, vertex colours on the floor" }, + { "file": "table.gltf", "family": "gltf", "title": "Table and two chairs, glTF with an embedded buffer", "features": "17 nodes, a data URI buffer, shared meshes instanced under several nodes" } + ] + }, + { + "group": "pdf", + "source": "generated", + "gen": "make-pdf.py", + "dir": "pdf", + "files": [ + { "file": "field-report.pdf", "family": "pdf", "title": "Field report, six pages", "features": "a table of contents whose lines are links, a two-level outline, roman and arabic page labels, internal and external links, a table, bar, line and pie charts as vectors, a JPEG, standard and embedded fonts (Latin, Greek, Cyrillic), document information" }, + { "file": "application-form.pdf", "family": "pdf-form", "title": "Berth application form (AcroForm)", "features": "text fields (multiline, maximum length, password, read-only), check boxes, radio buttons, a drop-down list, a list box, some filled in" }, + { "file": "annotations.pdf", "family": "pdf-annotations", "title": "Annotations without appearance streams", "features": "links to a URL, a page and a named destination, highlight, underline, strike-out, squiggly, note, free text, square, circle, line with arrows, polygon, polyline, ink, stamp, file attachment, an outline and a named destination" }, + { "file": "scan-mixed.pdf", "family": "pdf-scan", "title": "Scanned letters, one page for each scanner image filter", "features": "four pages: DCTDecode (JPEG), CCITTFaxDecode (Group 4), JBIG2Decode and JPXDecode (JPEG 2000), each with an invisible OCR text layer; the viewer decodes the last three with its own decoders", "tools": ["opj_compress", "jbig2", "tiffcp"] }, + { "file": "vector-art.pdf", "family": "pdf", "title": "Vector art", "features": "axial and radial shadings, transparency, a clipping path, dashes, caps and joins, Bezier curves, an even-odd fill, text with render modes, rotated and scaled text" } + ] + }, + { + "group": "office", + "source": "generated", + "gen": "make-office.py", + "tools": ["soffice"], + "files": [ + { "file": "handbook.docx", "dir": "office", "family": "docx", "title": "Harbour handbook (Word)", "features": "title page, table of contents with links, outline numbering, character and paragraph styles, bulleted and numbered lists of three levels, tables with merged cells and a repeated header, two pictures (one floating with wrapped text), a shape, footnotes, hyperlinks, bookmarks, fields, a comment, tracked changes, a two-column section, a landscape section with a wide table, headers and footers with page numbers" }, + { "file": "workbook.xlsx", "dir": "office", "family": "xlsx", "title": "Harbour workbook (Excel)", "features": "three sheets: a budget with formulas (SUM, AVERAGE, INDEX, MATCH, COUNTIF, IF, VLOOKUP, ROUND), currency, percent and date formats, merged title, frozen header rows, a validation list, a comment, a hyperlink and named ranges; 120 rows of sales with an autofilter; a bar, a line and a pie chart" }, + { "file": "deck.pptx", "dir": "office", "family": "pptx", "title": "Harbour review (PowerPoint)", "features": "five slides: a gradient title slide, nested bullets, a native bar chart with a callout, a table, a picture with shapes, gradients and arrows; a master with footer and slide number; speaker notes (not shown) and transitions" }, + { "file": "handbook-tagged.pdf", "dir": "pdf", "group": "pdf", "family": "pdf", "title": "Harbour handbook as a tagged PDF/A-2", "features": "bookmarks from the headings, hyperlinks, tags, footnotes, a landscape section, embedded Liberation fonts" }, + { "file": "handbook.doc", "dir": "converted", "group": "converted", "family": "doc", "title": "Harbour handbook (Word 97 to 2003)", "features": "the handbook as a binary .doc" }, + { "file": "handbook.odt", "dir": "converted", "group": "converted", "family": "odt", "title": "Harbour handbook (OpenDocument text)", "features": "the handbook as .odt" }, + { "file": "handbook.fodt", "dir": "converted", "group": "converted", "family": "fodt", "title": "Harbour handbook (flat OpenDocument text)", "features": "one XML file, pictures in base64; written by hand, not converted", "tools": [] }, + { "file": "handbook.rtf", "dir": "converted", "group": "converted", "family": "rtf", "title": "Harbour handbook (Rich Text Format)", "features": "the handbook as .rtf" }, + { "file": "workbook.xls", "dir": "converted", "group": "converted", "family": "xls", "title": "Harbour workbook (Excel 97 to 2003)", "features": "the workbook as a binary .xls" }, + { "file": "workbook.ods", "dir": "converted", "group": "converted", "family": "ods", "title": "Harbour workbook (OpenDocument spreadsheet)", "features": "the workbook as .ods" }, + { "file": "workbook.fods", "dir": "converted", "group": "converted", "family": "fods", "title": "Harbour workbook (flat OpenDocument spreadsheet)", "features": "one XML file; written by hand, not converted", "tools": [] }, + { "file": "deck.ppt", "dir": "converted", "group": "converted", "family": "ppt", "title": "Harbour review (PowerPoint 97 to 2003)", "features": "the deck as a binary .ppt (its thumbnail makes it large)" }, + { "file": "deck.odp", "dir": "converted", "group": "converted", "family": "odp", "title": "Harbour review (OpenDocument presentation)", "features": "the deck as .odp" }, + { "file": "deck.fodp", "dir": "converted", "group": "converted", "family": "fodp", "title": "Harbour review (flat OpenDocument presentation)", "features": "one XML file; written by hand, not converted", "tools": [] }, + { "file": "diagram.odg", "dir": "converted", "group": "converted", "family": "odg", "title": "Flowchart (OpenDocument drawing)", "features": "two pages, layers (one hidden), connectors glued to shapes, groups, gradients, a curve and a polyline, shadows, dashes" }, + { "file": "diagram.fodg", "dir": "converted", "group": "converted", "family": "fodg", "title": "Flowchart (flat OpenDocument drawing)", "features": "one XML file; written by hand, not converted", "tools": [] } + ] + }, + { + "group": "text", + "source": "generated", + "gen": "make-text.py", + "dir": "text", + "files": [ + { "file": "field-guide.md", "family": "markdown", "title": "Field guide to Markdown", "features": "headings of six levels, nested and task lists, quotes, an aligned table, fenced code with languages, footnotes, links and references, inline HTML, Unicode" }, + { "file": "field-notes.txt", "family": "text", "title": "Plain text with tabs, a long line and pangrams in nine scripts", "features": "Latin, Greek, Cyrillic, Japanese, Arabic and Hebrew text, box drawing, symbols, no final newline" }, + { "file": "recipes.json", "family": "json", "title": "A small recipe book as JSON", "features": "nested objects and arrays, numbers of every kind, null, booleans, escapes, empty values" }, + { "file": "config.yaml", "family": "yaml", "title": "Configuration file, YAML", "features": "mappings, lists, block scalars, anchors and aliases, comments" }, + { "file": "pyproject.toml", "family": "toml", "title": "Project file, TOML", "features": "tables, arrays of tables, inline values" }, + { "file": "feed.xml", "family": "xml", "title": "Atom feed", "features": "namespaces, CDATA, an XHTML content element, entities, comments" }, + { "file": "route.gpx", "family": "xml", "title": "Coastal walk, GPX track", "features": "60 track points with elevation and time, two waypoints" }, + { "file": "places.kml", "family": "xml", "title": "Places, KML", "features": "a point, a line and a polygon, a shared style, HTML in CDATA" }, + { "file": "harbour-log.csv", "family": "csv", "title": "Harbour log, 300 rows of CSV", "features": "nine columns, quoted fields with commas, quotes and line breaks, accents" }, + { "file": "tides.tsv", "family": "csv", "title": "Tide table, tab-separated values", "features": "28 rows, six columns" }, + { "file": "prix.csv", "family": "csv", "title": "Price list in the European style", "features": "semicolon separator, decimal commas, accented headers" }, + { "file": "life.py", "family": "source", "title": "Conway's Game of Life, Python", "features": "docstrings, comprehensions, f-strings, a main guard" }, + { "file": "lru.rs", "family": "source", "title": "A least-recently-used cache, Rust", "features": "generics, trait bounds, closures, a test module" }, + { "file": "tokens.ts", "family": "source", "title": "Arithmetic tokenizer and evaluator, TypeScript", "features": "union types, a sticky regular expression, the shunting-yard algorithm" }, + { "file": "bits.c", "family": "source", "title": "Bit tricks on 32-bit words, C", "features": "static functions, hexadecimal literals, printf formats" }, + { "file": "report.sql", "family": "source", "title": "Monthly report with window functions, SQL", "features": "DDL, a CTE, lag, rank and sum over windows, joins" }, + { "file": "deploy.sh", "family": "source", "title": "Build and deploy script, Bash", "features": "strict mode, traps, functions, process substitution, a case statement" }, + { "file": "style.css", "family": "source", "title": "A small stylesheet, CSS", "features": "custom properties, grid, clamp, color-mix, a dark mode and a media query" }, + { "file": "page.html", "family": "html", "title": "A page, shown as its source, HTML", "features": "semantic elements, a table, a form, a style and a script that do not run" }, + { "file": "changes.diff", "family": "diff", "title": "A unified diff of two files", "features": "two files, three hunks, added and removed lines" }, + { "file": "subtitles.srt", "family": "text", "title": "Subtitles, SubRip", "features": "six cues with a tag" }, + { "file": "server.log", "family": "text", "title": "A server log of 120 lines", "features": "INFO, WARN and ERROR lines" } + ] + }, + { + "group": "archives", + "source": "generated", + "gen": "make-archives.py", + "dir": "archives", + "tools": ["7z", "genisoimage", "zstd", "gcab", "dpkg-deb", "cpio", "ar"], + "files": [ + { "file": "sample.zip", "family": "zip", "title": "Zip with folders, stored and deflated members, Unicode names and a comment", "features": "9 files in 5 folders, an empty folder", "tools": [] }, + { "file": "sample.tar", "family": "tar", "title": "Tar (ustar) with folders and a symbolic link", "features": "16 entries", "tools": [] }, + { "file": "sample.tar.gz", "family": "tar.gz", "title": "Tar compressed with gzip", "features": "the tar opens inside the gzip", "tools": [] }, + { "file": "sample.tar.bz2", "family": "tar.bz2", "title": "Tar compressed with bzip2", "features": "the tar opens inside the bzip2 stream", "tools": [] }, + { "file": "sample.tar.xz", "family": "tar.xz", "title": "Tar compressed with xz", "features": "the tar opens inside the xz stream", "tools": [] }, + { "file": "sample.tar.zst", "family": "tar.zst", "title": "Tar compressed with Zstandard", "features": "level 19", "tools": ["zstd"] }, + { "file": "server.log.gz", "family": "gz", "title": "A log compressed with gzip", "features": "one member, no tar", "tools": [] }, + { "file": "server.log.bz2", "family": "bz2", "title": "A log compressed with bzip2", "features": "one member, no tar", "tools": [] }, + { "file": "server.log.xz", "family": "xz", "title": "A log compressed with xz", "features": "one member, no tar", "tools": [] }, + { "file": "sample.7z", "family": "7z", "title": "7z with LZMA2", "features": "a solid archive of 9 files", "tools": ["7z"] }, + { "file": "sample.rar", "family": "rar", "title": "RAR 5 with stored members", "features": "folders, CRC32 and Unix modes, written by the script from the format's documentation (no RAR program)", "tools": [] }, + { "file": "sample.iso", "family": "iso", "title": "ISO 9660 image with Joliet and Rock Ridge", "features": "volume EXAV_EXAMPLE, long and Unicode names", "tools": ["genisoimage"] }, + { "file": "matryoshka.zip", "family": "zip", "title": "Nested archives: a zip holding a tar.gz holding a 7z holding a zip", "features": "four levels, opened in place one after the other", "tools": ["7z"] }, + { "file": "encrypted-aes.zip", "family": "zip", "title": "Zip encrypted with AES-256, password: exav", "features": "names are listed, each member says it is encrypted", "tools": ["7z"] }, + { "file": "encrypted-zipcrypto.zip", "family": "zip", "title": "Zip encrypted with the traditional ZipCrypto, password: exav", "features": "names are listed, each member says it is encrypted", "tools": ["7z"] }, + { "file": "encrypted.7z", "family": "7z", "title": "7z encrypted with AES-256, password: exav", "features": "file names visible, contents encrypted", "tools": ["7z"] }, + { "file": "example.jar", "family": "jar", "title": "A jar (a zip with a manifest)", "features": "META-INF/MANIFEST.MF, a source file, a properties file", "tools": [] }, + { "file": "pages.cbz", "family": "cbz", "title": "Comic book archive (zip of pages)", "features": "two page images and ComicInfo.xml", "tools": [] }, + { "file": "sample.cab", "family": "cab", "title": "Microsoft cabinet", "features": "four files, MSZIP", "tools": ["gcab"] }, + { "file": "exav-example.deb", "family": "deb", "title": "Debian package", "features": "an ar archive of debian-binary, control.tar.xz and data.tar.xz", "tools": ["dpkg-deb"] }, + { "file": "libexample.a", "family": "ar", "title": "Unix ar archive", "features": "two members", "tools": ["ar"] }, + { "file": "sample.cpio", "family": "cpio", "title": "cpio archive (newc)", "features": "four files", "tools": ["cpio"] } + ] + }, + { + "group": "media", + "source": "generated", + "gen": "make-media.py", + "dir": "media", + "tools": ["ffmpeg"], + "files": [ + { "file": "canon.wav", "family": "wav", "title": "A four-voice canon, WAV", "features": "8 kHz mono 16-bit, 8.4 seconds, synthesised" }, + { "file": "canon.mp3", "family": "mp3", "title": "The canon as MP3", "features": "24 kbit/s" }, + { "file": "canon.flac", "family": "flac", "title": "The canon as FLAC", "features": "lossless, level 8" }, + { "file": "canon.ogg", "family": "ogg", "title": "The canon as Ogg Vorbis", "features": "quality 2" }, + { "file": "canon.opus", "family": "opus", "title": "The canon as Opus", "features": "16 kbit/s" }, + { "file": "canon.m4a", "family": "m4a", "title": "The canon as AAC in MP4", "features": "24 kbit/s" }, + { "file": "testcard.mp4", "family": "mp4", "title": "Test card with a clock, H.264 and AAC in MP4", "features": "256 by 192, 12 frames a second, 4 seconds, with the canon as sound" }, + { "file": "testcard.webm", "family": "webm", "title": "Test card with a clock, VP9 and Opus in WebM", "features": "256 by 192, 12 frames a second, 4 seconds, with the canon as sound" } + ] + }, + { + "group": "3d", + "source": "generated", + "gen": "make-ifc.py", + "dir": "ifc", + "files": [ + { "file": "house.ifc", "family": "ifc", "title": "Two-storey house (IFC4)", "features": "walls with openings filled by windows and doors, slabs, a gable roof, porch columns, a stair of eleven steps, a table and chairs sharing a mapped representation, spaces, a property set, a material and colours" } + ] + }, + { + "group": "raw", + "source": "fetched", + "ref": "pixls", + "files": [ + { "file": "canon-eos-40d-sraw.cr2", "family": "raw-cr2", "title": "Canon EOS 40D, sRAW (CR2)", "features": "TIFF-based CR2 with a 1936 by 1288 JPEG preview", "fetched": "https://raw.pixls.us/getfile.php/2102/nice/Canon%20-%20EOS%2040D%20-%20sRAW2%20%28sRAW%29%20%283%3A2%29.CR2", "bytes": 5805950, "sha256": "ba644e7dd2abe74eca260e67f0206ff113bf0f62e710f8130611e964d6be5bf1" }, + { "file": "canon-eos-r6.cr3", "family": "raw-cr3", "title": "Canon EOS R6, C-RAW (CR3)", "features": "ISO base media CR3 with a 3408 by 2272 JPEG in its second track; its EXIF names Johannes Kimmel as artist and states CC0", "author": "Uploader to raw.pixls.us; EXIF artist Johannes Kimmel", "fetched": "https://raw.pixls.us/getfile.php/4659/nice/Canon%20-%20EOS%20R6%20-%203%3A2.CR3", "bytes": 5273174, "sha256": "74abb0a113d075ad9887a058082f40dd2a938c4813a08474d82356f11a027778" }, + { "file": "canon-powershot-g1.crw", "family": "raw-crw", "title": "Canon PowerShot G1 (CRW)", "features": "the 2000 CIFF/HEAP container with a 640 by 480 JPEG", "fetched": "https://raw.pixls.us/getfile.php/2073/nice/Canon%20-%20PowerShot%20G1%20-%20RAW%20%284%3A3%29.crw", "bytes": 2300702, "sha256": "f39be5acf14057ce04527fd8d0574e57ec8ed5fed082d7bfaff763075a44ee8a" }, + { "file": "nikon-d70s.nef", "family": "raw-nef", "title": "Nikon D70s (NEF)", "features": "TIFF-based NEF with a 3008 by 2000 JPEG in a SubIFD", "fetched": "https://raw.pixls.us/getfile.php/1117/nice/Nikon%20-%20D70s%20-%2012bit%2012bit%20compressed%20%28Lossy%20%28type%201%29%29%20%283%3A2%29.NEF", "bytes": 5193213, "sha256": "6c46f9854033e7623ebbb5de8c951df6762ca44f05d45035ccc5cb7e9f4e5692" }, + { "file": "sony-ilce-7s.arw", "family": "raw-arw", "title": "Sony A7S (ARW)", "features": "TIFF-based ARW with a 1616 by 1080 JPEG preview", "fetched": "https://raw.pixls.us/getfile.php/1582/nice/Sony%20-%20ILCE-7S%20-%2014bit%2014bit%20compressed%20%283%3A2%29.ARW", "bytes": 6160384, "sha256": "a35ebb2fbec929daa5beb20d1ce5c15a8aac7b1a7a231455387f3df8a7442e07" }, + { "file": "olympus-c5060wz.orf", "family": "raw-orf", "title": "Olympus C5060WZ (ORF)", "features": "the only picture inside is a 160 by 120 thumbnail", "fetched": "https://raw.pixls.us/getfile.php/1799/nice/Olympus%20-%20C5060WZ%20-%2012bit%20%284%3A3%29.ORF", "bytes": 7646208, "sha256": "3fc12bc3f6320cfab456111d7805b446e329fdd1907680be55e2e163e5e084bd" }, + { "file": "panasonic-dmc-lx7.rw2", "family": "raw-rw2", "title": "Panasonic Lumix DMC-LX7 (RW2)", "features": "RW2 with a 1920 by 1280 JPEG", "fetched": "https://raw.pixls.us/getfile.php/7010/nice/Panasonic%20-%20DMC-LX7%20-%203%3A2.RW2", "bytes": 3394560, "sha256": "18dfc3877e944020299635a8c2fad61fca2485b1c9b67645a495ee870a86e599" }, + { "file": "fujifilm-finepix-s5000.raf", "family": "raw-raf", "title": "Fujifilm FinePix S5000 (RAF)", "features": "RAF container with a 1280 by 960 JPEG", "fetched": "https://raw.pixls.us/getfile.php/2726/nice/Fujifilm%20-%20FinePix%20S5000%20-%204%3A3.RAF", "bytes": 6851240, "sha256": "dabd5e74521a6980156be9fd4b88d0c37b0fe4d0e0e6f5c12db8cffff1b76297" }, + { "file": "minolta-dimage-5.mrw", "group": "unsupported", "family": "raw-mrw", "title": "Minolta DiMAGE 5 (MRW)", "features": "MRW with a 640 by 480 preview whose first byte is stored as zero: the viewer finds no preview in it (kept to show the message)", "fetched": "https://raw.pixls.us/getfile.php/7795/nice/Minolta%20-%20DiMAGE%205%20-%204%3A3.MRW", "bytes": 6422144, "sha256": "d60bfd80bcb1f7b9c88b14a5e46ea27885bbf92d990ab30b3939288678fea0d9" }, + { "file": "adobe-dng-canon-5d3.dng", "family": "raw-dng", "title": "Canon EOS 5D Mark III converted to DNG (lossy JPEG)", "features": "DNG with previews of 256, 1024 and 3960 pixels; converted by Adobe DNG Converter, not straight from a camera", "author": "Uploader to raw.pixls.us; EXIF artist Simon Harhues", "fetched": "https://raw.pixls.us/getfile.php/1033/nice/Adobe%20DNG%20Converter%20-%20Canon%20EOS%205D%20Mark%20III%20-%20Lossy%20JPEG%20compression%2C%20rgb%20%283%3A2%29.DNG", "bytes": 2484836, "sha256": "b22f1e36331f679abb8b13e433b9bbde3988723adf10fee7aa0dda6381016a98" } + ] + }, + { + "group": "cad", + "source": "fetched", + "files": [ + { "file": "barraca-valenciana-0100-r2010.dwg", "ref": "barraca", "family": "dwg", "title": "Barraca Valenciana, ground floor plan (DWG 2010, Revit export)", "features": "walls, doors, glazing, stairs, furniture, hatches, areas, 24 layers, 56 blocks, extra layouts with title block and viewports", "fetched": "https://zenodo.org/records/14293897/files/BRC-OSP-XXX-P00-PLA-ARQ-0100-tipologiaGen%C3%A8rica-A1-P2.dwg?download=1", "bytes": 284266, "sha256": "fcd3eef78cbd568e3f8a8262378670495a3ea6b8e091cb162fe8ef9c3c9add13" }, + { "file": "barraca-valenciana-0300-r2010.dwg", "ref": "barraca", "family": "dwg", "title": "Barraca Valenciana, elevations (DWG 2010, Revit export)", "features": "elevations drawn as 2D linework with hatches, topography and planting, no 3D", "fetched": "https://zenodo.org/records/14293897/files/BRC-OSP-XXX-ZZZ-PLA-ARQ-0300-tipologiaGen%C3%A8rica-A1-P2.dwg?download=1", "bytes": 1069565, "sha256": "93a211cfb797525a94b5b41aeae3ecf33e61442eea07cadae056463cc400a3e5" }, + { "file": "barraca-valenciana-0400-r2010.dwg", "ref": "barraca", "family": "dwg", "title": "Barraca Valenciana, sections and details (DWG 2010, Revit export)", "features": "42 layers, hatches, arcs, splines, ellipses, 61 blocks", "fetched": "https://zenodo.org/records/14293897/files/BRC-OSP-XXX-ZZZ-PLA-ARQ-0400-tipologiaGen%C3%A8rica-A1-P2.dwg?download=1", "bytes": 511114, "sha256": "a09c492dc34ead8df619d6d618049298afffb050a8436c470055923a90f4b61c" }, + { "file": "building-survey-plans-r2000.dwg", "ref": "zenodo", "family": "dwg", "title": "Survey of a small building: plans, elevations and details (DWG 2000)", "features": "Italian drawing with room names and areas, over 120 layers, 890 blocks, 567 dimensions, 492 hatches", "author": "Giovanni De Gasperis, Sante Dino Facchini, Asif Saeed", "source": "https://zenodo.org/records/15076037", "evidence": "https://zenodo.org/records/15076037", "attribution": "De Gasperis, G., Facchini, S. D., Saeed, A., Building Ledger Dossier: Seismic Prevention and Building Documentation Tracking through a Digital Twin Approach (4_Architectural_Building_Survey.dwg), Zenodo, doi:10.5281/zenodo.15076037, CC BY 4.0. No changes.", "fetched": "https://zenodo.org/records/15076037/files/4_Architectural_Building_Survey.dwg?download=1", "bytes": 2097350, "sha256": "2f096b44cd5b60ded2ad8b12c2f46116db8b1fda1c980f7bb02660a85782ab1d" }, + { "file": "golden-tile-palace-r2004.dwg", "family": "dwg", "title": "Golden Tile Palace: front elevation and section (DWG 2004)", "features": "elevation and section with level marks and Chinese titles, 4393 polylines, 841 arcs, 328 splines, 26 dimensions, 24 hatches", "author": "Jing Zhang, Yunying Ren, Xiaofan An", "source": "https://figshare.com/articles/dataset/Figure_of_surveying_and_mapping_of_Golden_Tile_Palace_/21374221", "evidence": "https://api.figshare.com/v2/articles/21374221", "evidence_quote": "\"name\": \"CC BY 4.0\"", "licence": "CC-BY-4.0", "attribution": "Jing Zhang, Yunying Ren, Xiaofan An, Figure of surveying and mapping of Golden Tile Palace, supplementary file S1 of PLOS ONE doi:10.1371/journal.pone.0262155, figshare, CC BY 4.0. No changes.", "fetched": "https://ndownloader.figshare.com/files/37930432", "bytes": 763903, "sha256": "14d128397f89c1af652b2cd3c9d523db98ae539b1bc061d4f06fba6d21501ae9" }, + { "file": "residential-site-plan-r2007.dwg", "family": "dwg", "title": "Site plan of an old residential community in Beijing (DWG 2007)", "features": "58 layers, 79 blocks, buildings, roads, 2865 polylines, 656 texts, 125 hatches, 39 dimensions", "author": "Yijun Fan", "source": "https://figshare.com/articles/dataset/Drainage_System_Layout_of_Old_Urban_Residential_Communities_In_Beijing/28188725", "evidence": "https://api.figshare.com/v2/articles/28188725", "evidence_quote": "\"name\": \"CC BY 4.0\"", "licence": "CC-BY-4.0", "attribution": "Yijun Fan, Drainage System Layout of Old Urban Residential Communities In Beijing (Site Plan.dwg), figshare, doi:10.6084/m9.figshare.28188725.v1, CC BY 4.0. No changes.", "fetched": "https://ndownloader.figshare.com/files/51611078", "bytes": 948192, "sha256": "37b03757172e5360a03cc26da473cde84e85dbd61914b67741c94a40f7f0db2f" }, + { "file": "hospital-floor-plan-r2013.dwg", "ref": "zenodo", "family": "dwg", "title": "Furnished hospital floor plan (DWG 2013)", "features": "section and level marks, 109 dimensions, 429 block definitions of furniture and plants, 19 layers", "author": "Toka Ehab", "source": "https://zenodo.org/records/10520508", "evidence": "https://zenodo.org/records/10520508", "attribution": "Toka Ehab, Nanotechnology Applications in Interior Design of hospitals to enhance thermal comfort and decrease the infection spread for the occupants (Elite hospital plan.dwg), Zenodo, doi:10.5281/zenodo.10520508, CC BY 4.0. No changes.", "fetched": "https://zenodo.org/records/10520508/files/Elite%20hospital%20plan.dwg?download=1", "bytes": 1249695, "sha256": "b618207b01a1759142e038e1edf762ab8efbe11804bb2e84fc6f472e7e040fb9" }, + { "file": "commercial-building-hvac-plans-r2018.dwg", "ref": "zenodo", "family": "dwg", "title": "Air-conditioning plans of a commercial building (DWG 2018)", "features": "48 layers, 320 blocks, 316 dimensions, 125 hatches, 112 wipeouts", "author": "Kevin Anthony do Bem", "source": "https://zenodo.org/records/10407941", "evidence": "https://zenodo.org/records/10407941", "attribution": "Kevin Anthony do Bem, Projeto de Climatização de um Edifício de Comércio e Serviços (F04 Plantas- Rede aerolica.dwg), Zenodo, doi:10.5281/zenodo.10407941, CC BY 4.0. No changes.", "fetched": "https://zenodo.org/records/10407941/files/F04%20Plantas-%20Rede%20aerolica.dwg?download=1", "bytes": 506884, "sha256": "bcf3b92e0afdf29bb75e7632e8193f881918ddabb4de67a1331b5eda34ee9be2" }, + { "file": "ezdxf-dim-linear-tutorial-r2013.dwg", "ref": "ezdxf", "family": "dwg", "title": "ezdxf documentation: linear dimension tutorial (DWG 2013)", "features": "16 dimensions, 16 multileaders, 13 dimension styles, 27 text styles", "source": "https://github.com/mozman/ezdxf/blob/748e211c9a0b977b9e15845a6bcad8e1b9743e26/docs/graphics/dim_linear_tutorial.dwg", "fetched": "https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/docs/graphics/dim_linear_tutorial.dwg", "bytes": 36391, "sha256": "88037b595bd46d81c5c98ce7aa428ce6b8506d1aa4602e976811cfb154005155" }, + { "file": "hospital-ward-wing-plan-section.dxf", "family": "dxf", "title": "Hospital ward wing, plan and section (DXF 2010)", "features": "542 polylines, 17 layers of the A-* scheme, 3 blocks, a paper-space viewport", "author": "Innerscene (original model)", "source": "https://www.innerscene.com/tools/library/drawings/hospital-ward-wing-1200-square-metres-plan-and-section-73a3f4dd", "evidence": "https://www.innerscene.com/tools/library/drawings/hospital-ward-wing-1200-square-metres-plan-and-section-73a3f4dd", "evidence_quote": "Original Innerscene model, released CC0.", "licence": "CC0-1.0", "attribution": "", "fetched": "https://www.innerscene.com/api/library/hospital-ward-wing-1200-square-metres-plan-and-section-73a3f4dd/download", "bytes": 307408, "sha256": "4fabf62d6d7bbc7c8bdc5f3c9d292d4980c3ec504281b0bd77f487d3c6bb9ba3" }, + { "file": "grocery-store-plan-section.dxf", "family": "dxf", "title": "Grocery store, plan and section (DXF 2010)", "features": "234 lines, 150 polylines, 17 layers, 3 blocks, a viewport", "author": "Innerscene (original model)", "source": "https://www.innerscene.com/tools/library/drawings/grocery-store-600-square-metres-plan-and-section-2a67d041", "evidence": "https://www.innerscene.com/tools/library/drawings/grocery-store-600-square-metres-plan-and-section-2a67d041", "evidence_quote": "Original Innerscene model, released CC0.", "licence": "CC0-1.0", "attribution": "", "fetched": "https://www.innerscene.com/api/library/grocery-store-600-square-metres-plan-and-section-2a67d041/download", "bytes": 130840, "sha256": "0b875304e1769e0f7c9377abf270f1fb4d103547cc27a3795a57c34fb4619d30" }, + { "file": "ezdxf-uncommon-entities.dxf", "ref": "ezdxf", "family": "dxf", "title": "ezdxf example: uncommon entities (DXF 2018)", "features": "13 dimensions, 2 multileaders, large radial dimensions, rays, construction lines, splines, 33 blocks, 2 extra layouts", "source": "https://github.com/mozman/ezdxf/blob/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/uncommon.dxf", "fetched": "https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/uncommon.dxf", "bytes": 343110, "sha256": "5efdd671e3b6d8c45bd0688b1d6479d523f2290f0b390f1584348bf46e34c965" }, + { "file": "ezdxf-hatches-1.dxf", "ref": "ezdxf", "family": "dxf", "title": "ezdxf example: solid hatches (DXF 2018)", "features": "ten solid hatches over polylines and arcs", "source": "https://github.com/mozman/ezdxf/blob/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/hatches_1.dxf", "fetched": "https://raw.githubusercontent.com/mozman/ezdxf/748e211c9a0b977b9e15845a6bcad8e1b9743e26/examples_dxf/hatches_1.dxf", "bytes": 130334, "sha256": "2dc2930b4f7d5fb16698437e4f6972986e580a81b2b5d36a780b4311f85fb326" } + ] + }, + { + "group": "3d", + "source": "fetched", + "files": [ + { "file": "bsi-building-architecture-ifc2x3.ifc", "ref": "bsi", "family": "ifc", "title": "buildingSMART Simple-Scene Building-Architecture (IFC2X3)", "features": "a small SketchUp house: walls, slabs, a roof, spaces, materials with colours, quantity and property sets; faceted breps", "fetched": "https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/IFC%202.3.0.1%20%28IFC%202x3%20TC1%29/Simple-Scene/Building-Architecture.ifc", "bytes": 92542, "sha256": "c4db65ba847f6b369a95d6c54fa11f4750cbe6d59f021934e8923d8d578e5885" }, + { "file": "bsi-building-architecture-ifc4x3.ifc", "ref": "bsi", "family": "ifc", "title": "buildingSMART Simple-Scene Building-Architecture (IFC4X3_ADD2)", "features": "the same house in IFC 4.3, with triangulated faces", "fetched": "https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/IFC%204.3.2.0%20%28IFC%204.3%20ADD2%29/Simple-Scene/Building-Architecture.ifc", "bytes": 141965, "sha256": "96e7103812b15b65eb1fd7802d36b9962833485dce5ead4f440bbf529530881d" }, + { "file": "bsi-wall-with-opening-and-window-ifc4.ifc", "ref": "bsi", "family": "ifc", "title": "buildingSMART reference view: a wall with an opening and a window (IFC4)", "features": "a wall with a material layer set, an opening element and a window with its type", "author": "Peter Bonsma, RDF Ltd. (file header), distributed by buildingSMART International Ltd.", "fetched": "https://raw.githubusercontent.com/buildingSMART/Sample-Test-Files/80d976a9b193a26a8e928c3e79bff67af1de68a8/IFC%204.0.2.1%20%28IFC%204%20ADD2%20TC1%29/ISO%20Spec%20-%20ReferenceView_V1.2/wall-with-opening-and-window.ifc", "bytes": 12492, "sha256": "73b0e45d931d5dc13bfee5fdc7bd80f796526445458b2de74c4168d209097832" }, + { "file": "duplex-apartment-ifc2x3.ifc", "family": "ifc", "title": "Duplex Apartment (IFC2X3, Revit export)", "features": "four storeys: 57 walls, 24 windows, 14 doors, 2 stairs, 21 spaces, furniture, 18 materials", "author": "Provided to the US Army Construction Engineering Research Laboratory, republished by buildingSMART International", "source": "https://github.com/buildingsmart-community/Community-Sample-Test-Files/tree/7ddf57a201f88a0c213d5322b02ed15e94a60a40/IFC%202.3.0.1%20(IFC%202x3)/Duplex%20Apartment", "evidence": "https://raw.githubusercontent.com/buildingsmart-community/Community-Sample-Test-Files/7ddf57a201f88a0c213d5322b02ed15e94a60a40/IFC%202.3.0.1%20%28IFC%202x3%29/Duplex%20Apartment/README.md", "evidence_quote": "Creative Commons (CC BY 4.0). You are free (1) to copy and resitribute this material any way you like", "licence": "CC-BY-4.0", "attribution": "BSI (2020) Duplex Apartment Test Files, buildingSMART International, https://github.com/buildingsmart-community/Community-Sample-Test-Files, CC BY 4.0. No changes.", "fetched": "https://media.githubusercontent.com/media/buildingsmart-community/Community-Sample-Test-Files/7ddf57a201f88a0c213d5322b02ed15e94a60a40/IFC%202.3.0.1%20%28IFC%202x3%29/Duplex%20Apartment/Duplex_A_20110907.ifc", "bytes": 2380763, "sha256": "b347a2c8aa8fff6db896a4417a9c50c22ac0ccd7c5cfc22b99b8d29336c606ed" }, + { "file": "barraca-valenciana-ifc4.ifc", "ref": "barraca", "family": "ifc", "title": "Barraca Valenciana de Llauradors, BIM model (IFC4, Revit export)", "features": "a traditional farmhouse: 2 storeys, 16 walls, 5 slabs, 2 roofs, a stair, 27 beams, 28 materials", "fetched": "https://zenodo.org/records/14293897/files/BRC-OSP-XXX-ZZZ-M3D-ARQ-0001-tipologiaGen%C3%A8rica-S3-0001.ifc?download=1", "bytes": 1584183, "sha256": "b6f8828e9bd2491dc452b2ab78f9f9e28f39bd81a5f2f4e2cdb2d81668287193" }, + { "file": "office-archetype-1970-ifc4x3.ifc", "ref": "zenodo", "family": "ifc", "title": "Office archetype of 1970 (IFC4X3_ADD2)", "features": "four storeys: 88 walls, 167 windows, 49 doors, 16 curtain walls, 48 spaces", "author": "Verena Dannapfel, Moritz Müller, Rita Streblow, Dirk Müller et al., RWTH Aachen University", "source": "https://zenodo.org/records/21820756", "evidence": "https://zenodo.org/records/21820756", "attribution": "Dannapfel, V., Müller, M., Streblow, R., Müller, D. et al., Archetypes for German Office Buildings of Construction Years 1970, 1998 and 2026, Zenodo, doi:10.5281/zenodo.21820756, CC BY 4.0. No changes.", "fetched": "https://zenodo.org/records/21820756/files/2026-07_Klassiqua_Office_Archetype_Construction_Year_1970.ifc?download=1", "bytes": 1471699, "sha256": "a5f12304d33fe5da9174c8ea9827d2f322706646b3da2766dff0ab278c65df3c" }, + { "file": "fox.glb", "ref": "khronos", "family": "glb", "title": "Fox, skinned and animated (GLB)", "features": "a low-poly fox with a skin, three animations and a texture", "author": "PixelMannen (model, CC0), tomkranis (rigging and animation, CC BY 4.0), glTF conversion by Asobo Studio and the Khronos Group", "source": "https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/Fox", "evidence": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/Fox/README.md", "evidence_quote": "© 2014, tomkranis. [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/legalcode)", "attribution": "Fox: model by PixelMannen (CC0, https://opengameart.org/content/fox-and-shiba), rigging and animation by tomkranis (CC BY 4.0, https://sketchfab.com/3d-models/low-poly-fox-by-pixelmannen-animated-371dea88d7e04a76af5763f2a36866bc), glTF conversion by Asobo Studio and the Khronos Group. Unmodified.", "fetched": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/Fox/glTF-Binary/Fox.glb", "bytes": 162852, "sha256": "d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7" }, + { "file": "riggedfigure.gltf", "ref": "khronos", "family": "gltf", "title": "Rigged Figure (glTF with an embedded buffer)", "features": "a skinned figure, a data URI buffer", "author": "Cesium", "source": "https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/RiggedFigure", "evidence": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/RiggedFigure/README.md", "evidence_quote": "© 2017, Cesium. [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/legalcode)", "attribution": "Rigged Figure by Cesium, CC BY 4.0, https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main/Models/RiggedFigure. Unmodified.", "fetched": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/RiggedFigure/glTF-Embedded/RiggedFigure.gltf", "bytes": 99902, "sha256": "354572cfef17b136b437ac9749da0fa316fd6e42ee7d62fe50a696b25f5047e9" }, + { "file": "vertexcolortest.glb", "ref": "khronos", "family": "glb", "title": "Vertex Color Test (GLB)", "features": "COLOR_0 vertex colours, tangents, two textures", "author": "Ed Mackey, Analytical Graphics, Inc. (Cesium)", "source": "https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/VertexColorTest", "evidence": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/VertexColorTest/README.md", "evidence_quote": "© 2018, Analytical Graphics, Inc.. [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/legalcode)", "attribution": "Vertex Color Test by Ed Mackey, Copyright 2018 Analytical Graphics, Inc., CC BY 4.0, https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main/Models/VertexColorTest. Unmodified.", "fetched": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/VertexColorTest/glTF-Binary/VertexColorTest.glb", "bytes": 26220, "sha256": "58006bdcff8084339da0f6e24400160890638c16dbcb83c362ccaf150e8c6e10" }, + { "file": "metalroughspheres.glb", "ref": "khronos", "family": "glb", "title": "Metal-Rough spheres (GLB)", "features": "119 nodes and 98 materials of growing metalness and roughness", "author": "Krill Gavrilov / Draw Harness script (Open CASCADE Technology)", "licence": "CC0-1.0", "source": "https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/MetalRoughSpheresNoTextures", "evidence": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/MetalRoughSpheresNoTextures/README.md", "evidence_quote": "© 2019, Public. [Creative Commons Zero v1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/legalcode)", "attribution": "", "fetched": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/MetalRoughSpheresNoTextures/glTF-Binary/MetalRoughSpheresNoTextures.glb", "bytes": 291316, "sha256": "5e677f260ec0f366967a6e9545de2f3dab2a160e307b9bcb9d050cd2028f63f8" }, + { "file": "iridescencesuzanne.glb", "ref": "khronos", "family": "glb", "title": "Iridescence Suzanne (GLB)", "features": "Suzanne with the iridescence, transmission and volume extensions", "author": "Mathias Kanzler (UX3D), Pascal Schoen", "licence": "CC0-1.0", "source": "https://github.com/KhronosGroup/glTF-Sample-Assets/tree/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/IridescenceSuzanne", "evidence": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/IridescenceSuzanne/README.md", "evidence_quote": "© 2022, UX3D. [Creative Commons Zero v1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/legalcode)", "attribution": "", "fetched": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/edc7c9e67c639d230715049ee31f9a96a6babbbe/Models/IridescenceSuzanne/glTF-Binary/IridescenceSuzanne.glb", "bytes": 507608, "sha256": "866762602d60a0942b7608bfabf4e8686a29033636224f4b55c5e56abe8abf8f" }, + { "file": "ratchet-cam.stl", "family": "stl", "title": "Apollo 11 hatch, stationary ratchet cam (binary STL)", "features": "1536 triangles, a mechanical part", "author": "NASA Johnson Space Center, transferred to the Smithsonian Institution; model published on Wikimedia Commons", "source": "https://commons.wikimedia.org/wiki/File:Stationary_Ratchet_Cam_v11_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl", "evidence": "https://commons.wikimedia.org/wiki/File:Stationary_Ratchet_Cam_v11_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl", "evidence_quote": "CC0 1.0 Universal Public Domain Dedication", "licence": "CC0-1.0", "attribution": "", "fetched": "https://upload.wikimedia.org/wikipedia/commons/e/e0/Stationary_Ratchet_Cam_v11_%28Hatch%2C_Crew%2C_Apollo_11_by_NASA_and_Smithsonian_Institution%29.stl", "bytes": 76884, "sha256": "b42d79fb357413b118b973f3fa40b76ae2999451537cd991bebce18b486c581f" }, + { "file": "ratchet-spur-gear.stl", "family": "stl", "title": "Apollo 11 hatch, stationary ratchet spur gear (binary STL)", "features": "3026 triangles, a gear with 19 teeth", "author": "NASA Johnson Space Center, transferred to the Smithsonian Institution; model published on Wikimedia Commons", "source": "https://commons.wikimedia.org/wiki/File:N=19,_P=28_-_Stat._Ratchet_Spur_Gear_v13_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl", "evidence": "https://commons.wikimedia.org/wiki/File:N=19,_P=28_-_Stat._Ratchet_Spur_Gear_v13_(Hatch,_Crew,_Apollo_11_by_NASA_and_Smithsonian_Institution).stl", "evidence_quote": "CC0 1.0 Universal Public Domain Dedication", "licence": "CC0-1.0", "attribution": "", "fetched": "https://upload.wikimedia.org/wikipedia/commons/c/cb/N%3D19%2C_P%3D28_-_Stat._Ratchet_Spur_Gear_v13_%28Hatch%2C_Crew%2C_Apollo_11_by_NASA_and_Smithsonian_Institution%29.stl", "bytes": 151384, "sha256": "c99eca56ab40ed6b2e9dfc49b88c23c6fbef982ff18813ba593d3e138ef1f51d" }, + { "file": "petri-dish-holder-base.stl", "ref": "zenodo", "family": "stl", "title": "Petri dish holder base of a spore capture device (ASCII STL)", "features": "566 facets as text", "author": "Kevin A. Adkins, Kaiyu Li, M. N. Blasko, J. L. Cabrera, B. H. Neal, James et al.", "source": "https://zenodo.org/records/12193898", "evidence": "https://zenodo.org/api/records/12193898", "evidence_quote": "\"license\": {\"id\": \"cc-by-4.0\"}", "attribution": "Components of the spore capture device in A simple mechanism for uncrewed aircraft bioaerosol sampling in the lower atmosphere (Inspire1Petri_Dish_Holder_Base.stl), Kevin A. Adkins et al., Zenodo 2024, doi:10.5281/zenodo.12193898, CC BY 4.0. No changes.", "fetched": "https://zenodo.org/api/records/12193898/files/Inspire1Petri_Dish_Holder_Base.stl/content", "bytes": 151270, "sha256": "d654bf60064e79675acd9694726282c70251905d77391ad45c29d3ba3ecaf93e" }, + { "file": "chickpea-mesh.ply", "ref": "zenodo", "family": "ply", "title": "Photogrammetric mesh of a chickpea plant (binary PLY with colours)", "features": "8788 triangles, RGBA per vertex", "author": "William T. Salter, Arjina Shrestha, Margaret M. Barbour", "source": "https://zenodo.org/records/4018242", "evidence": "https://zenodo.org/api/records/4018242", "evidence_quote": "\"license\": {\"id\": \"cc-by-4.0\"}", "attribution": "3D photogrammetric reconstructions of individual chickpea plants (PBASlasher_S3s_Wk1_meshed.ply), William T. Salter, Arjina Shrestha and Margaret M. Barbour, Zenodo 2020, doi:10.5281/zenodo.4018242, CC BY 4.0. No changes.", "fetched": "https://zenodo.org/api/records/4018242/files/PBASlasher_S3s_Wk1_meshed.ply/content", "bytes": 202701, "sha256": "ef9cd2141897781c8e3e6a72ac316056b991d4d0fae99e053c4695fceea8cb75" }, + { "file": "ruthwell-lamb-of-god.ply", "ref": "zenodo", "family": "ply", "title": "Lamb of God panel of the Ruthwell Cross (binary PLY with normals and colours)", "features": "33020 triangles, a scanned stone carving", "author": "Gurpreet Singh", "source": "https://zenodo.org/records/3348342", "evidence": "https://zenodo.org/api/records/3348342", "evidence_quote": "\"license\": {\"id\": \"cc-by-4.0\"}", "attribution": "Small Panel PLY (Lamb of God panel from the Ruthwell Cross), Gurpreet Singh, Zenodo 2019, doi:10.5281/zenodo.3348342, CC BY 4.0. No changes.", "fetched": "https://zenodo.org/api/records/3348342/files/Small_Lamb_Of_God_North_Ruthwell_Cross.ply/content", "bytes": 893893, "sha256": "0d40a4305885932596afce091891a8f4b212b0c012b742db10d4487351c2457a" }, + { "file": "chickpea-pointcloud-ascii.ply", "group": "unsupported", "ref": "zenodo", "family": "ply", "title": "Point cloud of a chickpea plant (ASCII PLY without faces)", "features": "53195 coloured points and no faces: kept to show what the viewer says about a point cloud", "author": "William T. Salter, Arjina Shrestha, Margaret M. Barbour", "source": "https://zenodo.org/records/4018242", "evidence": "https://zenodo.org/api/records/4018242", "evidence_quote": "\"license\": {\"id\": \"cc-by-4.0\"}", "attribution": "3D photogrammetric reconstructions of individual chickpea plants (SonSla_3_groundtruth_pointcloud.ply), William T. Salter, Arjina Shrestha and Margaret M. Barbour, Zenodo 2020, doi:10.5281/zenodo.4018242, CC BY 4.0. No changes.", "fetched": "https://zenodo.org/api/records/4018242/files/SonSla_3_groundtruth_pointcloud.ply/content", "bytes": 3455582, "sha256": "53a08f6e1c831ac58c42342ee257c97730bcf6997e246c88198478f9aeba4fe0" } + ] + }, + { + "group": "pdf", + "source": "fetched", + "files": [ + { "file": "arxiv-rational-cherednik-torus-knots.pdf", "family": "pdf", "title": "Rational Cherednik Algebras and Torus Knot Invariants (arXiv:2402.18770)", "features": "28 pages of mathematics, 24 outline entries, 256 links, set in LaTeX", "author": "Xinchun Ma", "source": "https://arxiv.org/abs/2402.18770v1", "evidence": "https://arxiv.org/abs/2402.18770v1", "evidence_quote": "href=\"http://creativecommons.org/licenses/by/4.0/\" title=\"Rights to this article\"", "licence": "CC-BY-4.0", "attribution": "Xinchun Ma, Rational Cherednik Algebras and Torus Knot Invariants, arXiv:2402.18770v1, CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Not modified.", "fetched": "https://arxiv.org/pdf/2402.18770v1", "bytes": 430745, "sha256": "2b22841d8a64b271d7def6fa15aa0b5b98f533ae259e4108eb7104320f07cf10" }, + { "file": "nist-sp-800-63-4-digital-identity.pdf", "family": "pdf", "title": "NIST SP 800-63-4, Digital Identity Guidelines", "features": "96 tagged pages, 54 outline entries, 227 links", "author": "David Temoshok, Diana Proud-Madruga, Yee-Yin Choong et al., NIST", "source": "https://csrc.nist.gov/pubs/sp/800/63/4/final", "evidence": "https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-63-4.pdf", "evidence_quote": "is not subject to copyright in the United States.", "licence": "public-domain (US federal government work, 17 U.S.C. 105; the PDF says so itself)", "attribution": "", "fetched": "https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-63-4.pdf", "bytes": 858054, "sha256": "2f5b107de218a0fc3fe7f7e91b2ece5babb001eda5745b7c568a3cc876002f2d" }, + { "file": "scan-cfa-minutes-1971.pdf", "family": "pdf-scan", "title": "Minutes of the U.S. Commission of Fine Arts, 1970 to 1972 (scan)", "features": "40 scanned pages: JPEG 2000 pictures and JBIG2 masks, an OCR text layer, PDF/A-2B", "author": "U.S. Commission of Fine Arts; scanned by the Internet Archive", "source": "https://archive.org/details/cfaminutes21april1971", "evidence": "https://commons.wikimedia.org/wiki/File:July_8_1970_to_May_19_1972_(IA_cfaminutes21april1971).pdf", "evidence_quote": "This work is in the public domain in the United States because it is a work prepared by an officer o", "licence": "public-domain (US federal government work, 17 U.S.C. 105)", "attribution": "", "fetched": "https://archive.org/download/cfaminutes21april1971/cfaminutes21april1971.pdf", "bytes": 1104628, "sha256": "2fc5edb8a4f303b89449443dcb5a32249c79b2a8d67253348025d0e7eea5f94b" }, + { "file": "scan-blm-land-survey-records.pdf", "family": "pdf-scan", "title": "Land and survey records, Bureau of Land Management (scan)", "features": "40 pages scanned at about 500 ppi: JPEG 2000 and JBIG2 images, an OCR text layer, PDF/A-2B", "author": "United States Bureau of Land Management; scanned by the Internet Archive", "source": "https://archive.org/details/landsurveyrecord00unit", "evidence": "https://commons.wikimedia.org/wiki/File:Land_%26_survey_records_-_record_preservation_%26_service_through_microfilm_(IA_landsurveyrecord00unit).pdf", "evidence_quote": "This work is in the public domain in the United States because it is a work prepared by an officer o", "licence": "public-domain (US federal government work, 17 U.S.C. 105)", "attribution": "", "fetched": "https://archive.org/download/landsurveyrecord00unit/landsurveyrecord00unit.pdf", "bytes": 2192413, "sha256": "d9a9e6583d0afb1688a043ef59a8d2e236e20c58d4ba76ff625d7c11a181c16c" }, + { "file": "form-uscis-i9.pdf", "family": "pdf-form", "title": "USCIS Form I-9, Employment Eligibility Verification", "features": "115 text fields, 5 drop-down lists, 8 check boxes, links; a tagged government form", "author": "U.S. Citizenship and Immigration Services (DHS)", "source": "https://www.uscis.gov/i-9", "evidence": "https://www.uscis.gov/website-policies", "evidence_quote": "Information presented on this WWW site is considered public information and may be distributed or co", "licence": "public-domain (US federal government work, 17 U.S.C. 105)", "attribution": "", "fetched": "https://www.uscis.gov/sites/default/files/document/forms/i-9.pdf", "bytes": 524095, "sha256": "780f348c34df694bb0b4dbbfaf9f22b99b9757b80d16a37ba89aadf069597281" }, + { "file": "map-nps-canyonlands.pdf", "family": "pdf-map", "title": "Canyonlands National Park, Island in the Sky: roads and trails", "features": "two tagged pages of vector map", "author": "National Park Service", "source": "https://home.nps.gov/cany/planyourvisit/maps.htm", "evidence": "https://www.nps.gov/aboutus/disclaimer.htm", "evidence_quote": "material created by the National Park Service and presented on this website, unless otherwise indica", "licence": "public-domain (US federal government work, 17 U.S.C. 105)", "attribution": "", "fetched": "https://home.nps.gov/cany/planyourvisit/upload/IslandRoadsandTrailsUpdated24-508forweb.pdf", "bytes": 349001, "sha256": "b29a639d9bc0d2e37ca41b68c21bcddba7637b1727dce86980c3373715610d55" }, + { "file": "slides-unige-open-access.pdf", "ref": "zenodo", "family": "pdf", "title": "Open Access publishing at no cost thanks to UNIGE agreements (slides)", "features": "ten slides with outline, links, tags and pictures", "author": "Floriane Muller, Anouk Santos (University of Geneva)", "source": "https://zenodo.org/records/23478694", "evidence": "https://zenodo.org/records/23478694", "attribution": "Floriane Muller and Anouk Santos, Open Access publishing at no cost thanks to UNIGE agreements, in 15 minutes, Zenodo, https://doi.org/10.5281/zenodo.23478694, CC BY 4.0. Not modified.", "fetched": "https://zenodo.org/api/records/23478694/files/2026-10-20_Read_and_publish_en15min_EN_zenodo.pdf/content", "bytes": 800339, "sha256": "03356ed569a80f7d7dc1d96fcbfd75a2fbc663c63f6d74f4e89eb2390bb5ee64" }, + { "file": "paper-ja-labor-law.pdf", "ref": "zenodo", "family": "pdf", "title": "A paper in Japanese on labour law and the constitution", "features": "25 pages with embedded MS Mincho fonts", "author": "Takashi Fujiki (藤木 è²´å�²)", "source": "https://zenodo.org/records/23469422", "evidence": "https://zenodo.org/records/23469422", "attribution": "藤木 è²´å�², アメリカ労åƒ�法ã�‹ã‚‰ã�¿ã�Ÿæ†²æ³•ã�®å½±éŸ¿, アメリカ憲法ã�®ç�†è«–ã�¨å®Ÿè·µ 創刊å�·, Zenodo, https://doi.org/10.5281/zenodo.23469422, CC BY 4.0. Not modified.", "fetched": "https://zenodo.org/api/records/23469422/files/%E3%82%A2%E3%83%A1%E3%83%AA%E3%82%AB%E5%8A%B4%E5%83%8D%E6%B3%95%E3%81%8B%E3%82%89%E3%81%BF%E3%81%9F%E6%86%B2%E6%B3%95%E3%81%AE%E5%BD%B1%E9%9F%BF.pdf/content", "bytes": 881101, "sha256": "08b2be3ebc781107f71003344ccf8b230229079e978687f1e0da2329bef1cbe9" } + ] + }, + { + "group": "images", + "source": "fetched", + "files": [ + { "file": "monet-gardeners-house-antibes.jpg", "ref": "cleveland", "family": "jpeg", "title": "Claude Monet, The Gardener's House at Antibes (1888)", "features": "a painting, JPEG from the museum's web size", "author": "Claude Monet, Cleveland Museum of Art (open access)", "source": "https://clevelandart.org/art/1916.1044", "evidence": "https://clevelandart.org/art/1916.1044", "fetched": "https://openaccess-cdn.clevelandart.org/1916.1044/1916.1044_web.jpg", "bytes": 404254, "sha256": "95142eba48d54f01352eb4ef6f04260cb3df3bcb1d9c86000c1284a7817674ca" }, + { "file": "queen-mab-cave.jpg", "ref": "cleveland", "family": "jpeg", "title": "Queen Mab's Cave, in the manner of Turner", "features": "a painting", "author": "Imitator of J. M. W. Turner, Cleveland Museum of Art (open access)", "source": "https://clevelandart.org/art/1916.1036", "evidence": "https://clevelandart.org/art/1916.1036", "fetched": "https://openaccess-cdn.clevelandart.org/1916.1036/1916.1036_web.jpg", "bytes": 218321, "sha256": "b84e005332288229d808172a7610b501d9977c0b4668e333faea5ff780157223" }, + { "file": "rembrandt-st-francis.jpg", "ref": "cleveland", "family": "jpeg", "title": "Rembrandt, Saint Francis Beneath a Tree Praying (etching)", "features": "an etching, fine line work", "author": "Rembrandt van Rijn, Cleveland Museum of Art (open access)", "source": "https://clevelandart.org/art/2024.64", "evidence": "https://clevelandart.org/art/2024.64", "fetched": "https://openaccess-cdn.clevelandart.org/2024.64/2024.64_web.jpg", "bytes": 370411, "sha256": "74b37aa3738914dd66c07533b3758f7694fefbaa918d2f23c263205cf987db7b" }, + { "file": "nolli-rome-plate.jpg", "ref": "cleveland", "family": "jpeg", "title": "Nolli's map of Rome (1748), a plate", "features": "an engraved city plan", "author": "Giovanni Battista Nolli et al., Cleveland Museum of Art (open access)", "source": "https://clevelandart.org/art/2020.276.3", "evidence": "https://clevelandart.org/art/2020.276.3", "fetched": "https://openaccess-cdn.clevelandart.org/2020.276.3/2020.276.3_web.jpg", "bytes": 322943, "sha256": "7643c9e59f7706ebe62518a51daf7d72129acc8092dde7afc65516d3d11b6c77" }, + { "file": "pallid-swift.jpg", "family": "jpeg", "title": "Pallid swift in flight (photograph)", "features": "a camera JPEG with EXIF data (Canon EOS R6 Mark II)", "author": "Hobbyfotowiki", "source": "https://commons.wikimedia.org/wiki/File:Pallid_swift_(in_flight).jpg", "evidence": "https://commons.wikimedia.org/wiki/File:Pallid_swift_(in_flight).jpg", "evidence_quote": "This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Dedication.", "licence": "CC0-1.0", "attribution": "", "fetched": "https://upload.wikimedia.org/wikipedia/commons/d/df/Pallid_swift_%28in_flight%29.jpg", "bytes": 356572, "sha256": "9d0f79f12dcc236f549cdefb66dc468f25335d444ebd26e98805efdd94afecbd" }, + { "file": "cyclotron-patent.png", "family": "png", "title": "Drawing from Lawrence's cyclotron patent", "features": "a black and white technical drawing", "author": "Ernest O. Lawrence (US Patent Office)", "source": "https://commons.wikimedia.org/wiki/File:Cyclotron_patent_p1.png", "evidence": "https://commons.wikimedia.org/wiki/File:Cyclotron_patent_p1.png", "evidence_quote": "The text and illustrations of US patents published before March 1, 1989 are in the public domain unl", "licence": "public-domain (US patent text and drawings published before 1989)", "attribution": "", "fetched": "https://upload.wikimedia.org/wikipedia/commons/4/42/Cyclotron_patent_p1.png", "bytes": 207304, "sha256": "0be9b59ae21bbadeb8a13fafde5e0bcfb6d470ba516244eab0ec1c74afd7394f" }, + { "file": "mature-flower-diagram.svg", "family": "svg", "title": "Diagram of a mature flower", "features": "85 texts, about 90 gradient references, many paths", "author": "Mariana Ruiz Villarreal (LadyofHats)", "source": "https://commons.wikimedia.org/wiki/File:Mature_flower_diagram.svg", "evidence": "https://commons.wikimedia.org/wiki/File:Mature_flower_diagram.svg", "evidence_quote": "This work has been released into the public domain by its author, LadyofHats.", "licence": "public-domain (released by its author)", "attribution": "", "fetched": "https://upload.wikimedia.org/wikipedia/commons/7/7f/Mature_flower_diagram.svg", "bytes": 123527, "sha256": "b40bd4e188c0a99e51e994b4f39f931d3fca28093ecb6454aa2bd93c575ea999" }, + { "file": "entamoeba-life-cycle.svg", "family": "svg", "title": "Life cycle of Entamoeba histolytica", "features": "547 paths, text and arrows", "author": "Mariana Ruiz Villarreal (LadyofHats)", "source": "https://commons.wikimedia.org/wiki/File:Entamoeba_histolytica_life_cycle-en.svg", "evidence": "https://commons.wikimedia.org/wiki/File:Entamoeba_histolytica_life_cycle-en.svg", "evidence_quote": "This work has been released into the public domain by its author, LadyofHats.", "licence": "public-domain (released by its author)", "attribution": "", "fetched": "https://upload.wikimedia.org/wikipedia/commons/a/a1/Entamoeba_histolytica_life_cycle-en.svg", "bytes": 273234, "sha256": "68a4a92289d81f0e7e9361abbba2da9a8c8b4e440e3ad9de5c420646eb133eaa" }, + { "file": "sieve-of-eratosthenes.svg", "family": "svg", "title": "Sieve of Eratosthenes, animated", "features": "SMIL animation with 179 animate elements", "author": "Ricordisamoa, with later edits by Jc86035, HereToHelp and Glrx", "source": "https://commons.wikimedia.org/wiki/File:Sieve_of_Eratosthenes_animation.svg", "evidence": "https://commons.wikimedia.org/wiki/File:Sieve_of_Eratosthenes_animation.svg", "evidence_quote": "This work is ineligible for copyright and therefore in the public domain because it consists entirel", "licence": "public-domain (ineligible for copyright, Wikimedia Commons PD-ineligible)", "attribution": "", "fetched": "https://upload.wikimedia.org/wikipedia/commons/0/0b/Sieve_of_Eratosthenes_animation.svg", "bytes": 22054, "sha256": "d8f1d6d0a4b5710ebe1e7766eab30b766b10dc9380c1058ccb39baccd7d51586" }, + { "file": "muybridge-horse.gif", "family": "gif", "title": "Muybridge's horse in motion, animated GIF", "features": "15 frames", "author": "Eadweard Muybridge (photographs, 1887); animation by Waugsberg", "source": "https://commons.wikimedia.org/wiki/File:Muybridge_race_horse_animated.gif", "evidence": "https://commons.wikimedia.org/wiki/File:Muybridge_race_horse_animated.gif", "evidence_quote": "The author died in 1904, so this work is in the public domain in its country of origin and other cou", "licence": "public-domain (the author died in 1904)", "attribution": "", "fetched": "https://upload.wikimedia.org/wikipedia/commons/d/dd/Muybridge_race_horse_animated.gif", "bytes": 568203, "sha256": "eb40bebc1f039e7c2a121673c3b55d4aa73582f858053dbbcca9ebce9e2b479d" }, + { "file": "geneva-mechanism.gif", "family": "gif", "title": "Geneva mechanism with six spokes, animated GIF", "features": "101 frames", "author": "Mike1024", "source": "https://commons.wikimedia.org/wiki/File:Geneva_mechanism_6spoke_animation.gif", "evidence": "https://commons.wikimedia.org/wiki/File:Geneva_mechanism_6spoke_animation.gif", "evidence_quote": "I, the copyright holder of this work, release this work into the public domain.", "licence": "public-domain (released by its author)", "attribution": "", "fetched": "https://upload.wikimedia.org/wikipedia/commons/9/9b/Geneva_mechanism_6spoke_animation.gif", "bytes": 229346, "sha256": "d7df5c9984109c2ca60f7aab1a51db1f0b578cddcdede5d43be9f67536e2a1ee" }, + { "file": "abundance-nemo-g4-6pages.tif", "family": "tiff-fax", "title": "Les grans et merveilleux faictz du seigneur Nemo (scan, six pages, CCITT Group 4)", "features": "a multi-page bilevel TIFF scanned from a 16th-century book", "author": "Jean d'Abundance (16th century); scanned by the Bibliothèque nationale de France", "source": "https://commons.wikimedia.org/wiki/File:Abundance_-_Les_grans_et_merveilleux_faictz_du_seigneur_Nemo%2C_avec_les_privil%C3%A8ges_qu%E2%80%99il_a.tif", "evidence": "https://commons.wikimedia.org/wiki/File:Abundance_-_Les_grans_et_merveilleux_faictz_du_seigneur_Nemo%2C_avec_les_privil%C3%A8ges_qu%E2%80%99il_a.tif", "evidence_quote": "This file is in the public domain because it is a mere mechanical scan or photocopy of a public doma", "licence": "public-domain (a mechanical scan of a public domain book, Wikimedia Commons PD-scan)", "attribution": "", "fetched": "https://upload.wikimedia.org/wikipedia/commons/b/b5/Abundance_-_Les_grans_et_merveilleux_faictz_du_seigneur_Nemo%2C_avec_les_privil%C3%A8ges_qu%E2%80%99il_a.tif", "bytes": 330420, "sha256": "38bab27c6d559e11468d6c7e4222f0bb1bee4ba0044540adcebfc012930e00d1" } + ] + }, + { + "group": "office", + "source": "fetched", + "files": [ + { "file": "docx4j-getting-started.docx", "ref": "docx4j", "family": "docx", "title": "docx4j Getting Started (Word)", "features": "a manual with styles, tables, pictures and links", "source": "https://github.com/plutext/docx4j/blob/c95b55be6832ff716131ffdbd7006755db92f696/docs/Docx4j_GettingStarted.docx", "fetched": "https://raw.githubusercontent.com/plutext/docx4j/c95b55be6832ff716131ffdbd7006755db92f696/docs/Docx4j_GettingStarted.docx", "bytes": 156287, "sha256": "a518cffcbef0b60cf5c95930acd9af9a56484e47376c5f0c4d6e3a15a0799941" }, + { "file": "docx4j-two-charts.docx", "ref": "docx4j", "family": "docx", "title": "docx4j chart test: two charts (Word)", "features": "two native charts in a document", "source": "https://github.com/plutext/docx4j/blob/c95b55be6832ff716131ffdbd7006755db92f696/docx4j-chart-render/src/test/resources/charts/render/office/p3-two-charts.docx", "fetched": "https://raw.githubusercontent.com/plutext/docx4j/c95b55be6832ff716131ffdbd7006755db92f696/docx4j-chart-render/src/test/resources/charts/render/office/p3-two-charts.docx", "bytes": 41590, "sha256": "e0bc29916de415c53c03dcee14817bbd1e3eeea8f54a2b76629fe6754e6c641e" }, + { "file": "gsa-policy-review-template.xlsx", "ref": "gsa508", "family": "xlsx", "title": "Section508.gov Policy Review Template (Excel)", "features": "a government workbook with formatted tables", "source": "https://github.com/GSA/Assets.Section508.gov/blob/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Policy%20Review%20Template.xlsx", "fetched": "https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Policy%20Review%20Template.xlsx", "bytes": 222164, "sha256": "840661eba4653879dca24f209bca1619f7b168ef1232b595df5713741b2465bd" }, + { "file": "closedxml-pivot-tables.xlsx", "family": "xlsx", "title": "ClosedXML example: pivot tables (Excel)", "features": "pivot tables over a data sheet", "author": "ClosedXML contributors", "source": "https://github.com/ClosedXML/ClosedXML/blob/09f2f21a60e821ce7fb18ca3576b272e5dd6d921/ClosedXML.Tests/Resource/Examples/PivotTables/PivotTables.xlsx", "evidence": "https://raw.githubusercontent.com/ClosedXML/ClosedXML/09f2f21a60e821ce7fb18ca3576b272e5dd6d921/LICENSE", "evidence_quote": "MIT License Copyright (c) 2016 ClosedXML", "licence": "MIT", "attribution": "Copyright (c) 2016 ClosedXML, MIT, https://github.com/ClosedXML/ClosedXML. No changes.", "fetched": "https://raw.githubusercontent.com/ClosedXML/ClosedXML/09f2f21a60e821ce7fb18ca3576b272e5dd6d921/ClosedXML.Tests/Resource/Examples/PivotTables/PivotTables.xlsx", "bytes": 30912, "sha256": "d13f149091c804cfe9b02c81301ea7ce13d20d1f3311cac799151541d0467d02" }, + { "file": "xlsxwriter-bar-chart.xlsx", "family": "xlsx", "title": "XlsxWriter test file: a bar chart (Excel)", "features": "a native bar chart saved in Excel", "author": "John McNamara (XlsxWriter)", "source": "https://github.com/jmcnamara/XlsxWriter/blob/5d4606d89a955226d2d0825a0f44309043ae7251/xlsxwriter/test/comparison/xlsx_files/chart_bar14.xlsx", "evidence": "https://raw.githubusercontent.com/jmcnamara/XlsxWriter/5d4606d89a955226d2d0825a0f44309043ae7251/LICENSE.txt", "evidence_quote": "BSD 2-Clause License Copyright (c) 2013-2025, John McNamara", "licence": "BSD-2-Clause", "attribution": "Copyright (c) 2013-2025, John McNamara, BSD-2-Clause, https://github.com/jmcnamara/XlsxWriter. No changes.", "fetched": "https://raw.githubusercontent.com/jmcnamara/XlsxWriter/5d4606d89a955226d2d0825a0f44309043ae7251/xlsxwriter/test/comparison/xlsx_files/chart_bar14.xlsx", "bytes": 13879, "sha256": "c4ed1e8117b4a0e014b95f42361c7e060728b398d4ea650395d902557429cdd2" }, + { "file": "python-pptx-chart-types.pptx", "family": "pptx", "title": "python-pptx test file: one slide for each chart type (PowerPoint)", "features": "many native chart types", "author": "Steve Canny (python-pptx)", "source": "https://github.com/scanny/python-pptx/blob/278b47b1dedd5b46ee84c286e77cdfb0bf4594be/features/steps/test_files/cht-chart-type.pptx", "evidence": "https://raw.githubusercontent.com/scanny/python-pptx/278b47b1dedd5b46ee84c286e77cdfb0bf4594be/LICENSE", "evidence_quote": "The MIT License (MIT) Copyright (c) 2013 Steve Canny", "licence": "MIT", "attribution": "Copyright (c) 2013 Steve Canny, MIT, https://github.com/scanny/python-pptx. No changes.", "fetched": "https://raw.githubusercontent.com/scanny/python-pptx/278b47b1dedd5b46ee84c286e77cdfb0bf4594be/features/steps/test_files/cht-chart-type.pptx", "bytes": 1393564, "sha256": "d0a7979d05970aa83fd8406f0829cd0019853a7bc4e16f8cda814586fc2eaccc" }, + { "file": "cdc-lifecycle-508.pptx", "ref": "gsa508", "family": "pptx", "title": "Integrating Section 508 Requirements in the Development Lifecycle (PowerPoint)", "features": "a government deck with pictures and diagrams", "author": "Mark D. Urban, CDC Section 508 Coordinator (US federal government)", "source": "https://github.com/GSA/Assets.Section508.gov/blob/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Integrating%20Section%20508%20Requirements%20in%20the%20Development%20Lifecycle.pptx", "fetched": "https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Integrating%20Section%20508%20Requirements%20in%20the%20Development%20Lifecycle.pptx", "bytes": 611924, "sha256": "51c7d6af2e6682e5ee66204b813a45488e62b0e6e13cecc9207a982fdeb1720a" } + ] + }, + { + "group": "converted", + "source": "fetched", + "files": [ + { "file": "poi-sample.doc", "ref": "poi", "family": "doc", "title": "Apache POI test document (Word 97)", "features": "a binary .doc", "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/SampleDoc.doc", "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/SampleDoc.doc", "bytes": 27136, "sha256": "717585c0a88f20862c86220163dd03da87cd743970354c6b29add32725f2e833" }, + { "file": "poi-word95.doc", "ref": "poi", "family": "doc", "title": "Apache POI test document (Word 6 and 95 format)", "features": "the pre-1997 Word format", "author": "Nick Burch (Apache POI)", "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/Word95.doc", "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/document/Word95.doc", "bytes": 102400, "sha256": "a7b9557e917daf29cfee6baaa90226fbfa7900ffa05cc35bdc03aafdefef5789" }, + { "file": "dhs-directive-139-02.doc", "ref": "gsa508", "family": "doc", "title": "DHS Directive 139-02 (Word 97)", "features": "a government directive in the binary .doc format", "author": "U.S. Department of Homeland Security", "source": "https://github.com/GSA/Assets.Section508.gov/blob/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Directive_139.2_Final_10-28-2008.doc", "fetched": "https://raw.githubusercontent.com/GSA/Assets.Section508.gov/c1d8f46b9cca483e744772229b91bbfcb8665381/assets/files/Directive_139.2_Final_10-28-2008.doc", "bytes": 82432, "sha256": "48d1c85456d6b515ce8e3db6b43024f90bac69be86a3e78c1ae08406d4cad493" }, + { "file": "poi-formula-eval.xls", "ref": "poi", "family": "xls", "title": "Apache POI test workbook of formulas (Excel 97)", "features": "hundreds of formula cases", "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/FormulaEvalTestData.xls", "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/FormulaEvalTestData.xls", "bytes": 178176, "sha256": "c2040c1fac1088f1e112abef197ae1f9bcb03547861783b89c1d4281a42049d1" }, + { "file": "poi-conditional-formats.xls", "ref": "poi", "family": "xls", "title": "Apache POI test workbook of conditional formats (Excel 97)", "features": "colour scales, icon sets and data bars", "author": "Nick Burch (Apache POI)", "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/NewStyleConditionalFormattings.xls", "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/NewStyleConditionalFormattings.xls", "bytes": 44544, "sha256": "899a29aa6ce35fee0268847ff8b5d9459e6ce34d5e2ff462fd42ee9b80837b87" }, + { "file": "poi-excel5.xls", "ref": "poi", "family": "xls", "title": "Apache POI test workbook (Excel 5 and 95 format)", "features": "the BIFF5 format of 1993 to 1995", "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/testEXCEL_5.xls", "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/spreadsheet/testEXCEL_5.xls", "bytes": 7680, "sha256": "ac0ce3a2eff43e32e56d6b789df6aaa1645ae846d22fa3a2fe3057391d0f1cae" }, + { "file": "poi-sample-show.ppt", "ref": "poi", "family": "ppt", "title": "Apache POI test presentation (PowerPoint 97)", "features": "a binary .ppt", "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/slideshow/SampleShow.ppt", "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/slideshow/SampleShow.ppt", "bytes": 125440, "sha256": "64275a6685b8f267827178037dcc59de927475e56385725916f4c6039c7ce7f6" }, + { "file": "tika-rtf-various.rtf", "ref": "tika", "family": "rtf", "title": "Apache Tika test document: various RTF features", "features": "fonts, colours, tables and lists in RTF", "author": "Michael McCandless (Apache Tika)", "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/resources/test-documents/testRTFVarious.rtf", "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/resources/test-documents/testRTFVarious.rtf", "bytes": 65517, "sha256": "cf00c56fe7099d14b820a0d751324e415f2c09af580f2c96f08614a2aec42c1e" }, + { "file": "tdf-thesis-template.odt", "family": "odt", "title": "Thesis template in Spanish (OpenDocument text)", "features": "styles, a table of contents, headers", "author": "Phorious (Document Foundation wiki user)", "source": "https://wiki.documentfoundation.org/File:Tesis-v1.0.4.odt", "evidence": "https://wiki.documentfoundation.org/File:Tesis-v1.0.4.odt", "evidence_quote": "This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Ded", "licence": "CC0-1.0", "attribution": "", "fetched": "https://wiki.documentfoundation.org/images/5/54/Tesis-v1.0.4.odt", "bytes": 67249, "sha256": "ec323e9fde67103a7f0039d8a59625bd7e2c5afa9e057563f5064c6b68d442a1" }, + { "file": "tika-odt-ooo3.odt", "ref": "tika", "family": "odt", "title": "Apache Tika test document written with OpenOffice 3 (OpenDocument text)", "features": "an .odt of 2009", "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/test/resources/test-documents/testODFwithOOo3.odt", "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/test/resources/test-documents/testODFwithOOo3.odt", "bytes": 24286, "sha256": "b6cd74b570a98fcb6d838dd85ab869604e0711812d9533d5ecde0000b24ba7ef" }, + { "file": "tdf-household-budget.ods", "family": "ods", "title": "Household budget book (OpenDocument spreadsheet)", "features": "formulas, charts and several sheets", "author": "Hrbrgr (Document Foundation wiki user)", "source": "https://wiki.documentfoundation.org/File:Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods", "evidence": "https://wiki.documentfoundation.org/File:Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods", "evidence_quote": "This work is licensed under the Attribution 3.0 Unported License", "licence": "CC-BY-3.0", "attribution": "Hrbrgr (Document Foundation wiki user), Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods, https://wiki.documentfoundation.org/File:Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods, CC BY 3.0. No changes.", "fetched": "https://wiki.documentfoundation.org/images/b/bc/Housekeeping_book_-_Haushaltsbuch_-_in_Calc_final.ods", "bytes": 21595, "sha256": "aacd76666860f7bf879e1518a07b90d535815ce92d076ea26c835061b8aff854" }, + { "file": "odfdo-flat.fods", "ref": "odfdo", "family": "fods", "title": "odfdo test sample (flat OpenDocument spreadsheet)", "features": "one XML file", "source": "https://github.com/jdum/odfdo/blob/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/test_flat_lo.fods", "fetched": "https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/test_flat_lo.fods", "bytes": 33177, "sha256": "4966023bf427dbc9c975dc9b11816b4a90158f7dab452c59104b8800fb27ec36" }, + { "file": "tdf-presentation-template.odp", "family": "odp", "title": "Presentation template (OpenDocument presentation)", "features": "master slides, pictures and layouts", "author": "Phorious (Document Foundation wiki user)", "source": "https://wiki.documentfoundation.org/File:Presenta.odp", "evidence": "https://wiki.documentfoundation.org/File:Presenta.odp", "evidence_quote": "This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Ded", "licence": "CC0-1.0", "attribution": "", "fetched": "https://wiki.documentfoundation.org/images/5/51/Presenta.odp", "bytes": 412768, "sha256": "147ca9c6dbcdd45470627b84c04824c7f3e07de57485a8190018eea5f23c64b3" }, + { "file": "odfdo-example.odp", "ref": "odfdo", "family": "odp", "title": "odfdo test sample (OpenDocument presentation)", "features": "slides with text and shapes", "source": "https://github.com/jdum/odfdo/blob/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/example.odp", "fetched": "https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/example.odp", "bytes": 55687, "sha256": "9075b87e36bb4618bdc9a8a6138bcaaf31b2b81e089e9006ac906e66a94f912b" }, + { "file": "tdf-diagram-gallery.odg", "family": "odg", "title": "A gallery of diagrams (OpenDocument drawing)", "features": "several diagram types", "author": "Hrbrgr (Document Foundation wiki user)", "source": "https://wiki.documentfoundation.org/File:Diagramme.odg", "evidence": "https://wiki.documentfoundation.org/File:Diagramme.odg", "evidence_quote": "This work is licensed under the Attribution 3.0 Unported License", "licence": "CC-BY-3.0", "attribution": "Hrbrgr (Document Foundation wiki user), Diagramme.odg, https://wiki.documentfoundation.org/File:Diagramme.odg, CC BY 3.0. No changes.", "fetched": "https://wiki.documentfoundation.org/images/0/07/Diagramme.odg", "bytes": 91383, "sha256": "2e5f43734db7c600256e0670f6ec9da9428eb6b7a074c4742fd506e32c833a5a" }, + { "file": "odfdo-shapes.odg", "ref": "odfdo", "family": "odg", "title": "odfdo test sample: basic shapes (OpenDocument drawing)", "features": "rectangles, ellipses, lines and polygons", "source": "https://github.com/jdum/odfdo/blob/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/base_shapes.odg", "fetched": "https://raw.githubusercontent.com/jdum/odfdo/39e89938bd9df704c5e3760f845f91db513fd3e5/tests/samples/base_shapes.odg", "bytes": 10351, "sha256": "dfe6a6c83ba5caec340889d6c77a899e420060d55f4b08fd9a1fb7b36e0b799f" }, + { "file": "tika-keynote09.key", "ref": "tika", "family": "keynote", "title": "Apache Tika test presentation (Keynote '09)", "features": "an XML Keynote document (index.apxl)", "author": "Jukka Zitting (Apache Tika)", "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote.key", "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote.key", "bytes": 221745, "sha256": "4a270c2427f11d77f82fae696e3fd6eda945bae0422ae87c5fac6cf2bd06015c" }, + { "file": "tika-keynote2013.key", "ref": "tika", "family": "keynote", "title": "Apache Tika test presentation (Keynote 2013, IWA format)", "features": "a Keynote document in the iWork archive format", "author": "Tim Allison (Apache Tika)", "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote2013.key", "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testKeynote2013.key", "bytes": 274397, "sha256": "8da93f6b566bc9eb22f4791bbfd5f2179162f39bf80968187b164c33d31824db" }, + { "file": "tika-numbers09-charts.numbers", "ref": "tika", "family": "numbers", "title": "Apache Tika test spreadsheet with charts (Numbers '09)", "features": "an XML Numbers document with charts", "author": "Michael McCandless (Apache Tika)", "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testNumbersCharts.numbers", "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testNumbersCharts.numbers", "bytes": 104547, "sha256": "f4430f2aa0ddab186e7e32f15552b58b7b03abada7a978dfbcd51e5548757789" }, + { "file": "numbers-formulas.numbers", "family": "numbers", "title": "numbers-parser test spreadsheet of formulas (Numbers)", "features": "formulas across tables", "author": "Jon Connell (numbers-parser)", "source": "https://github.com/masaccio/numbers-parser/blob/a6affe5599c8373f575192ac5777d0c6426da696/tests/data/create-formulas.numbers", "evidence": "https://raw.githubusercontent.com/masaccio/numbers-parser/a6affe5599c8373f575192ac5777d0c6426da696/LICENSE.rst", "evidence_quote": "Permission is hereby granted, free of charge, to any person obtaining a copy of this softw", "licence": "MIT", "attribution": "Copyright 2021 Jon Connell, numbers-parser, MIT, https://github.com/masaccio/numbers-parser. No changes.", "fetched": "https://raw.githubusercontent.com/masaccio/numbers-parser/a6affe5599c8373f575192ac5777d0c6426da696/tests/data/create-formulas.numbers", "bytes": 330282, "sha256": "9371c5b1d6ee4dfa17569097f064eba9c67f804d88b48638efbbeeb459d07dd4" } + ] + }, + { + "group": "unsupported", + "source": "fetched", + "files": [ + { "file": "poi-network.vsdx", "group": "converted", "ref": "poi", "family": "visio", "title": "Apache POI test diagram (Visio): a network", "features": "a use-case diagram: actors, ovals and connecting lines", "author": "A reporter of Apache POI bug 60489 (committed by Tim Allison)", "source": "https://github.com/apache/poi/blob/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/diagram/60489.vsdx", "fetched": "https://raw.githubusercontent.com/apache/poi/d91a76448f0963a93b6cd95fb97fbe1d8bad82c6/test-data/diagram/60489.vsdx", "bytes": 44426, "sha256": "15494702ecb5554c1dfaee2c09ac35e2ea656e2eed7ba4ba0cf1039e6125fbe1" }, + { "file": "vsdx-house.vsdx", "group": "converted", "family": "visio", "title": "vsdx library test drawing (Visio): a house", "features": "boxes and house shapes with text", "author": "Dave Howard (vsdx library)", "source": "https://github.com/dave-howard/vsdx/blob/6703e6c2c906bea4051f43525ec9af9dcf735c13/tests/test3_house.vsdx", "evidence": "https://raw.githubusercontent.com/dave-howard/vsdx/6703e6c2c906bea4051f43525ec9af9dcf735c13/LICENSE", "evidence_quote": "BSD 3-Clause License Copyright (c) 2020, Dave Howard", "licence": "BSD-3-Clause", "attribution": "Copyright (c) 2020, Dave Howard, BSD-3-Clause, https://github.com/dave-howard/vsdx. No changes.", "fetched": "https://raw.githubusercontent.com/dave-howard/vsdx/6703e6c2c906bea4051f43525ec9af9dcf735c13/tests/test3_house.vsdx", "bytes": 20914, "sha256": "e454217e49d1ec2aaa7c9b8f38b148ffc0d028ce44ba096fe3386e9894b1775f" }, + { "file": "tika-pages09-layout.pages", "ref": "tika", "family": "pages", "title": "Apache Tika test document (Pages '09)", "features": "kept to show what the viewer says about Pages files, which it does not list yet", "author": "Michael McCandless (Apache Tika)", "source": "https://github.com/apache/tika/blob/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testPagesLayout.pages", "fetched": "https://raw.githubusercontent.com/apache/tika/f58e44c022a9952252f3e094dcc40abd931f7ecd/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/resources/test-documents/testPagesLayout.pages", "bytes": 66480, "sha256": "6157fe7a95f7bc7d42251872f990d2f2d589f7f5e25a52b58e25c14cc447a4b2" } + ] + } + ] +} diff --git a/crates/exav-viewer/demo/examples/generate/make-archives.py b/crates/exav-viewer/demo/examples/generate/make-archives.py new file mode 100644 index 0000000..635e26f --- /dev/null +++ b/crates/exav-viewer/demo/examples/generate/make-archives.py @@ -0,0 +1,279 @@ +#!/usr/bin/env python3 +"""Writes the demo's archive examples into ../files/archives/. + + python3 -I make-archives.py [OUT_DIR] + +Output: CC0-1.0, a public domain dedication by the exav project. The members +are files of this demo (../files/text and ../files/images, so run make-text.py +and make-images.py first) and short texts written here. + +Needs: Python 3, and the programs 7z (p7zip-full), genisoimage, zstd, gcab, +dpkg-deb, cpio and ar. A file whose program is missing is skipped. + +Written by Python alone: the zip, the tar family (tar, gz, bz2, xz), the jar, +the comic book archive (cbz), and the RAR 5 file, which is built here from the +published format (stored members: no program writes RAR without the +proprietary rar). The encrypted ones use 7z; their password is in the file +name's credit: "exav". + +Same bytes on every run, except the ISO image (genisoimage stamps the time) and +the encrypted files (7z picks a random salt). +""" +import bz2 +import gzip +import io +import lzma +import os +import shutil +import struct +import subprocess +import sys +import tarfile +import tempfile +import time +import zipfile +import zlib + +HERE = os.path.dirname(os.path.abspath(__file__)) +FILES = os.path.join(HERE, "..", "files") +OUT = os.path.abspath(sys.argv[1]) if len(sys.argv) > 1 else os.path.join(FILES, "archives") +os.makedirs(OUT, exist_ok=True) +EPOCH = 946684800 # 2000-01-01 00:00:00 UTC +DATE = (2000, 1, 1, 0, 0, 0) +PASSWORD = "exav" + + +def have(tool): + return shutil.which(tool) is not None + + +def read(*parts): + with open(os.path.join(FILES, *parts), "rb") as f: + return f.read() + + +README = """Example archive +=============== + +This archive holds a few files of the exav demo. It is in the public domain +(CC0-1.0). Look at the folders: docs, data, images, src, an empty one, and a +folder with accented and Japanese names. +""".encode() + +MEMBERS = [ + ("README.txt", README, True), + ("docs/field-guide.md", read("text", "field-guide.md"), True), + ("docs/field-notes.txt", read("text", "field-notes.txt"), True), + ("data/harbour-log.csv", read("text", "harbour-log.csv"), True), + ("data/recipes.json", read("text", "recipes.json"), True), + ("images/scene-indexed.png", read("images", "scene-indexed.png"), False), + ("src/life.py", read("text", "life.py"), True), + ("src/lru.rs", read("text", "lru.rs"), True), + ("café/日本語.txt", "Names with accents and Japanese characters.\n".encode(), True), +] +DIRS = ["docs", "data", "images", "src", "src/empty", "café"] + + +def stage(root): + """The members as files on disk with fixed times, for the programs that read a folder.""" + for d in DIRS: + os.makedirs(os.path.join(root, d), exist_ok=True) + for name, data, _ in MEMBERS: + path = os.path.join(root, name) + with open(path, "wb") as f: + f.write(data) + os.chmod(path, 0o644) + for p, dirs, files in os.walk(root): + for n in dirs + files: + os.utime(os.path.join(p, n), (EPOCH, EPOCH)) + os.utime(p, (EPOCH, EPOCH)) + + +# ---------------------------------------------------------------------- zip + + +def make_zip(path, members=MEMBERS, dirs=DIRS, comment=b"exav example archive, CC0-1.0"): + with zipfile.ZipFile(path, "w") as z: + z.comment = comment + for d in dirs: + zi = zipfile.ZipInfo(d + "/", DATE) + zi.external_attr = (0o40755 << 16) | 0x10 + zi.create_system = 3 + z.writestr(zi, b"") + for name, data, deflate in members: + zi = zipfile.ZipInfo(name, DATE) + zi.external_attr = 0o100644 << 16 + zi.create_system = 3 + zi.compress_type = zipfile.ZIP_DEFLATED if deflate else zipfile.ZIP_STORED + z.writestr(zi, data, compresslevel=9) + + +def zip_bytes(members, dirs=()): + buf = io.BytesIO() + make_zip(buf, members, dirs, comment=b"") + return buf.getvalue() + + +# ---------------------------------------------------------------------- tar + + +def tar_bytes(): + buf = io.BytesIO() + with tarfile.open(fileobj=buf, mode="w", format=tarfile.USTAR_FORMAT) as t: + def info(name, kind=tarfile.REGTYPE, size=0, mode=0o644, link=""): + ti = tarfile.TarInfo(name) + ti.type, ti.size, ti.mode, ti.mtime, ti.uid, ti.gid, ti.uname, ti.gname, ti.linkname = kind, size, mode, EPOCH, 0, 0, "", "", link + return ti + + for d in DIRS: + t.addfile(info(d + "/", tarfile.DIRTYPE, mode=0o755)) + for name, data, _ in MEMBERS: + t.addfile(info(name, size=len(data)), io.BytesIO(data)) + t.addfile(info("link-to-readme", tarfile.SYMTYPE, link="README.txt", mode=0o777)) + return buf.getvalue() + + +def gz(data): + buf = io.BytesIO() + with gzip.GzipFile(fileobj=buf, mode="wb", mtime=0, compresslevel=9) as f: + f.write(data) + return buf.getvalue() + + +def write(name, data): + with open(os.path.join(OUT, name), "wb") as f: + f.write(data) + + +# ------------------------------------------------------------------ RAR 5 + + +def vint(n): + out = bytearray() + while True: + b = n & 0x7F + n >>= 7 + if n: + out.append(b | 0x80) + else: + out.append(b) + return bytes(out) + + +def rar_block(htype, fields, data=b"", flags=0): + """One RAR 5 block: CRC32, header size, type, flags, [data size], fields, then the data.""" + body = vint(htype) + vint(flags | (2 if data else 0)) + (vint(len(data)) if data else b"") + fields + size = vint(len(body)) + return struct.pack("\nTwo pagesexav examples2\n', True)] +make_zip(os.path.join(OUT, "pages.cbz"), comic, [], comment=b"") + +# The nested one: a zip holding a tar.gz holding a 7z holding a zip. +with tempfile.TemporaryDirectory() as tmp: + stage_dir = os.path.join(tmp, "stage") + stage(stage_dir) + inner_zip = zip_bytes([("deep.txt", b"Four archives down.\n", True), ("field-guide.md", read("text", "field-guide.md"), True), ("scene-indexed.png", read("images", "scene-indexed.png"), False)]) + if have("7z"): + work = os.path.join(tmp, "inner") + os.makedirs(work) + with open(os.path.join(work, "inner.zip"), "wb") as f: + f.write(inner_zip) + os.utime(os.path.join(work, "inner.zip"), (EPOCH, EPOCH)) + subprocess.run(["7z", "a", "-t7z", "-mx=9", "-bd", "-y", os.path.join(tmp, "inner.7z"), "inner.zip"], cwd=work, check=True, capture_output=True) + with open(os.path.join(tmp, "inner.7z"), "rb") as f: + inner_7z = f.read() + buf = io.BytesIO() + with tarfile.open(fileobj=buf, mode="w", format=tarfile.USTAR_FORMAT) as t: + ti = tarfile.TarInfo("inner.7z") + ti.size, ti.mtime, ti.mode = len(inner_7z), EPOCH, 0o644 + t.addfile(ti, io.BytesIO(inner_7z)) + ti = tarfile.TarInfo("note.txt") + note = b"This tar.gz holds a 7z that holds a zip.\n" + ti.size, ti.mtime, ti.mode = len(note), EPOCH, 0o644 + t.addfile(ti, io.BytesIO(note)) + outer = gz(buf.getvalue()) + make_zip(os.path.join(OUT, "matryoshka.zip"), [("README.txt", b"A zip, holding a tar.gz, holding a 7z, holding a zip. Open them in turn.\n", True), ("inner.tar.gz", outer, False)], [], comment=b"") + + # Programs that read a folder. + if have("7z"): + for name, args in [ + ("sample.7z", ["-t7z", "-mx=9"]), + ("encrypted-aes.zip", ["-tzip", f"-p{PASSWORD}", "-mem=AES256"]), + ("encrypted-zipcrypto.zip", ["-tzip", f"-p{PASSWORD}", "-mem=ZipCrypto"]), + ("encrypted.7z", ["-t7z", "-mx=5", f"-p{PASSWORD}", "-mhe=off"]), + ]: + target = os.path.join(OUT, name) + if os.path.exists(target): + os.remove(target) + subprocess.run(["7z", "a", *args, "-bd", "-y", target, "."], cwd=stage_dir, check=True, capture_output=True) + if have("genisoimage"): + subprocess.run(["genisoimage", "-quiet", "-no-pad", "-R", "-J", "-joliet-long", "-V", "EXAV_EXAMPLE", "-input-charset", "utf-8", "-o", os.path.join(OUT, "sample.iso"), stage_dir], check=True, capture_output=True) + if have("zstd"): + subprocess.run(["zstd", "-q", "-19", "-f", "-o", os.path.join(OUT, "sample.tar.zst"), "-"], input=tar, check=True, capture_output=True) + if have("gcab"): + target = os.path.join(OUT, "sample.cab") + if os.path.exists(target): + os.remove(target) + files = ["README.txt", "docs/field-guide.md", "data/recipes.json", "src/life.py"] + subprocess.run(["gcab", "-c", "-n", target, *files], cwd=stage_dir, check=True, capture_output=True) + if have("ar"): + target = os.path.join(OUT, "libexample.a") + if os.path.exists(target): + os.remove(target) + subprocess.run(["ar", "rcsD", target, "README.txt"], cwd=stage_dir, check=True, capture_output=True) + for name in ("docs/field-notes.txt",): + subprocess.run(["ar", "rD", target, name], cwd=stage_dir, check=True, capture_output=True) + if have("cpio"): + names = "\n".join(["README.txt", "docs/field-guide.md", "data/recipes.json", "src/life.py"]) + "\n" + data = subprocess.run(["cpio", "-o", "-H", "newc", "--quiet", "--reproducible"], input=names.encode(), cwd=stage_dir, check=True, capture_output=True).stdout + write("sample.cpio", data) + if have("dpkg-deb"): + pkg = os.path.join(tmp, "pkg") + os.makedirs(os.path.join(pkg, "DEBIAN")) + os.makedirs(os.path.join(pkg, "usr", "share", "doc", "exav-example")) + with open(os.path.join(pkg, "DEBIAN", "control"), "w") as f: + f.write("Package: exav-example\nVersion: 1.0\nSection: misc\nPriority: optional\nArchitecture: all\nMaintainer: exav project \nDescription: an example package\n A package that holds a README, for the exav demo (CC0-1.0).\n") + shutil.copy(os.path.join(stage_dir, "README.txt"), os.path.join(pkg, "usr", "share", "doc", "exav-example", "README")) + shutil.copy(os.path.join(stage_dir, "docs", "field-guide.md"), os.path.join(pkg, "usr", "share", "doc", "exav-example", "field-guide.md")) + for p, dirs, files in os.walk(pkg): + for n in dirs + files: + os.utime(os.path.join(p, n), (EPOCH, EPOCH)) + env = dict(os.environ, SOURCE_DATE_EPOCH=str(EPOCH)) + subprocess.run(["dpkg-deb", "--root-owner-group", "-Zxz", "-b", pkg, os.path.join(OUT, "exav-example.deb")], check=True, capture_output=True, env=env) diff --git a/crates/exav-viewer/demo/examples/generate/make-attributions.mjs b/crates/exav-viewer/demo/examples/generate/make-attributions.mjs new file mode 100644 index 0000000..bf6a3b6 --- /dev/null +++ b/crates/exav-viewer/demo/examples/generate/make-attributions.mjs @@ -0,0 +1,140 @@ +#!/usr/bin/env node +// Writes the credits of the demo's examples from examples.json: +// +// - ../NOTICE.md, the list with every fact of the manifest, and +// - www/src/content/docs/viewer/examples.md, the page of the site. +// +// node generate/make-attributions.mjs # write both +// node generate/make-attributions.mjs --check # fail if either is out of date +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const here = path.dirname(fileURLToPath(import.meta.url)); +const root = path.join(here, ".."); +const repo = path.join(root, "..", "..", "..", ".."); +const check = process.argv.includes("--check"); + +const { examples } = JSON.parse(fs.readFileSync(path.join(root, "examples.json"), "utf8")); +const showcase = fs.readFileSync(path.join(root, "..", "src", "showcase.ts"), "utf8"); +const groups = [...showcase.matchAll(/^\s+(?:"([\w-]+)"|(\w+)): \{ en: "([^"]+)"/gm)].map((m) => ({ id: m[1] ?? m[2], label: m[3] })); + +const kb = (n) => (n < 1024 ? `${n} B` : n < 1024 * 1024 ? `${(n / 1024).toFixed(n < 10240 ? 1 : 0)} KB` : `${(n / 1024 / 1024).toFixed(1)} MB`); +const cell = (s) => String(s).replace(/\|/g, "\\|").replace(/\n/g, " "); +const host = (u) => new URL(u).hostname.replace(/^www\./, ""); +const SPDX_URL = (id) => { + if (id === "CC0-1.0") return "https://creativecommons.org/publicdomain/zero/1.0/"; + const m = /^CC-BY(-SA)?-(\d\.\d)$/.exec(id); + if (m) return `https://creativecommons.org/licenses/by${m[1] ? "-sa" : ""}/${m[2]}/`; + if (/^(MIT|BSD-2-Clause|BSD-3-Clause|Apache-2\.0)$/.test(id)) return `https://spdx.org/licenses/${id}.html`; + return null; +}; +const origin = (e) => { + if (e.generated) return `generated by \`${e.generated.script}\`${e.generated.args.length ? ` ${e.generated.args.join(" ")}` : ""}${e.generated.tools ? ` (with ${e.generated.tools.join(", ")})` : ""}`; + if (e.fixture) return `a fixture of this repository, \`${e.fixture}\``; + return `downloaded from ${e.fetched}`; +}; + +const ordered = [...groups.map((g) => g.id), ...new Set(examples.map((e) => e.group))].filter((g, i, a) => a.indexOf(g) === i); +const byGroup = (id) => examples.filter((e) => e.group === id); +const label = (id) => groups.find((g) => g.id === id)?.label ?? id; + +const total = (list) => list.reduce((n, e) => n + e.bytes, 0); +const committed = examples.filter((e) => e.committed); + +// ----------------------------------------------------------------- NOTICE.md +const notice = [ + "# Notices of the example files", + "", + "The demo of `@exav/viewer` lists the files of this directory's `examples.json`. Each has a free licence", + "that was read at the page named under \"Evidence\", or is made by a script of this repository and", + "given to the public domain (CC0-1.0). This file is written by `generate/make-attributions.mjs`; do not edit it.", + "", + `${examples.length} files: ${committed.length} are committed under \`files/\` (${kb(total(committed))}); ${examples.length - committed.length} are downloaded by \`npm run demo:examples\` (${kb(total(examples.filter((e) => !e.committed)))}).`, + "", + "To rebuild: run the scripts of `generate/` (each lists what it needs; `python3 -I generate/make-images.py`, `make-cad.py`,", + "`make-models.py`, `make-ifc.py`, `make-text.py`, `make-archives.py`, `make-media.py`, `make-pdf.py`, `make-office.py`), then", + "`node generate/make-manifest.mjs` and `node generate/make-attributions.mjs`. `node check.mjs` checks the manifest and the", + "files, `node verify-open.mjs` opens every example with the viewer's own engines, and `node generate/verify-evidence.mjs`", + "reads the licence pages again. `catalog.json` is where each example is described by hand.", + "", + "Where the pictures made here hold text, it is set in Aileron, the font Pillow bundles, which its author gives to the", + "public domain (CC0-1.0, \"No Rights Reserved\": https://dotcolon.net/font/aileron/). Drawings name their fonts and", + "embed none; documents that embed fonts embed the Liberation fonts (SIL OFL 1.1, which lets documents embed them).", + "", +]; +for (const id of ordered) { + const list = byGroup(id); + if (!list.length) continue; + notice.push(`## ${label(id)}`, ""); + for (const e of list) { + notice.push(`### ${e.file}`, ""); + notice.push(`- What: ${e.title} (${e.family}, ${kb(e.bytes)})`); + if (e.features) notice.push(`- Shows: ${e.features}`); + notice.push(`- Author: ${e.author}`); + notice.push(`- Source: ${e.source}`); + notice.push(`- Licence: ${e.licence}`); + notice.push(`- Evidence: ${e.evidence}`); + notice.push(`- Words read there: "${e.evidence_quote}"`); + if (e.attribution) notice.push(`- Attribution: ${e.attribution}`); + if (e.derived) notice.push(`- Changes: ${e.derived}`); + notice.push(`- Origin: ${origin(e)}`); + notice.push(`- SHA-256: ${e.sha256}`, ""); + } +} + +// ------------------------------------------------------------------ the page +const page = [ + "---", + "title: Example files", + "description: \"The files of the @exav/viewer demo: what each is, who made it, where it comes from and its licence.\"", + "---", + "", + "", + "", + `The [demo](/viewer/demo/) lists ${examples.length} example files, one or more for each format the viewer reads. Each is public domain, CC0,`, + "CC-BY, or an MIT, BSD or Apache test file, and its licence was read at the source page named below.", + "Most are made for the demo by scripts of the repository and given to the public domain (CC0-1.0); the others", + "are credited here and in the demo's licence notice. A file is downloaded only when it is opened.", + "", + "The facts are in [`examples.json`](https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/examples.json)", + "and [`NOTICE.md`](https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples/NOTICE.md): the page", + "that states each licence, the words read there, the SHA-256 of the file, and how it was made or fetched.", + "", +]; +for (const id of ordered) { + const list = byGroup(id); + if (!list.length) continue; + page.push(`## ${label(id)}`, "", "| File | Format | Size | Author | Source | Licence |", "| --- | --- | ---: | --- | --- | --- |"); + for (const e of list) { + const lic = SPDX_URL(e.licence) ? `[${cell(e.licence)}](${SPDX_URL(e.licence)})` : cell(e.licence); + const what = e.generated ? "made for the demo" : `[${host(e.source)}](${e.source})`; + page.push(`| \`${e.file}\` | ${cell(e.family)} | ${kb(e.bytes)} | ${cell(e.author)} | ${what} | ${lic} |`); + } + page.push(""); +} +const credited = examples.filter((e) => e.attribution); +if (credited.length) { + page.push("## Attributions", "", "The lines the licences ask to keep:", ""); + for (const e of credited) page.push(`- \`${e.file}\`: ${e.attribution}`); + page.push(""); +} + +const targets = [ + [path.join(root, "NOTICE.md"), `${notice.join("\n")}\n`], + [path.join(repo, "www", "src", "content", "docs", "viewer", "examples.md"), `${page.join("\n")}\n`], +]; +let stale = false; +for (const [file, text] of targets) { + const now = fs.existsSync(file) ? fs.readFileSync(file, "utf8") : null; + if (check) { + if (now !== text) { + console.error(`${path.relative(repo, file)} is out of date: run node generate/make-attributions.mjs`); + stale = true; + } + } else if (now !== text) { + fs.writeFileSync(file, text); + console.log(`wrote ${path.relative(repo, file)}`); + } +} +if (stale) process.exit(1); diff --git a/crates/exav-viewer/demo/examples/generate/make-cad.py b/crates/exav-viewer/demo/examples/generate/make-cad.py new file mode 100644 index 0000000..88f9057 --- /dev/null +++ b/crates/exav-viewer/demo/examples/generate/make-cad.py @@ -0,0 +1,970 @@ +#!/usr/bin/env python3 +"""Writes the demo's DXF drawing examples into ../files/cad/. + + python3 -I make-cad.py [OUT_DIR] + +Output: CC0-1.0, a public domain dedication by the exav project. Every +drawing is made here from scratch with ezdxf (MIT licence; tested with +1.4.1), with no outside drawing or block library. Two runs draw the same +drawing; the bytes differ in the order of a few table objects (ezdxf's +dictionaries follow the hash seed). The dates and GUIDs are fixed. + +Needs: Python 3 and ezdxf 1.4. + +- house-plan.dxf (2018), house-plan-r2000.dxf: a two-room-wide house plan, + walls with openings, door and window blocks with attributes, furniture + blocks, axes with bubbles, room labels, linear, aligned, radius and angular + dimensions, hatches, a paper-space sheet with a title block and a viewport. +- house-elevations.dxf: four elevations and a section in 2D, with ground + hatching, roof, windows, levels and height dimensions. +- hatch-gallery.dxf: the predefined patterns, gradients, solid fills, islands + and boundaries made of arcs, ellipses and splines. +- dimensions.dxf: every dimension type, in two dimension styles. +- linetypes.dxf: the standard and custom linetypes (text and shapes inside), + line weights, line type scales, wide and generated polylines. +- text-styles.dxf: fonts, width and oblique factors, mirrored and rotated + text, MTEXT formatting, columns, background, special characters. +- blocks.dxf: nested blocks, attributes, arrays, mirrored and scaled inserts. +- bracket.dxf: a mechanical part with centre and hidden lines, a section, + dimensions with tolerances and a title block. +- site-plan.dxf: contour lines (splines and polylines), parcels, points with + heights, a legend and a north arrow. +- legacy-r12.dxf: a drawing in the R12 format. +""" +import math +import os +import sys + +import ezdxf +from ezdxf import colors, zoom +from ezdxf.enums import TextEntityAlignment +from ezdxf.math import Vec2 +from ezdxf.render.mleader import ConnectionSide +from ezdxf.tools import pattern + +HERE = os.path.dirname(os.path.abspath(__file__)) +OUT = os.path.abspath(sys.argv[1]) if len(sys.argv) > 1 else os.path.join(HERE, "..", "files", "cad") +os.makedirs(OUT, exist_ok=True) + +# Fixed dates, GUIDs and creator line in the files, so that two runs give the same bytes. +ezdxf.options.write_fixed_meta_data_for_testing = True + + +def new(version="R2018", units=4): + doc = ezdxf.new(version, setup=["linetypes"]) + doc.units = units + return doc + + +def save(doc, name, extents=True): + if extents: + zoom.extents(doc.modelspace(), factor=1.05) + doc.saveas(os.path.join(OUT, name)) + + +def layer(doc, name, color=7, linetype="Continuous", weight=25, **kw): + return doc.layers.add(name, color=color, linetype=linetype, lineweight=weight, **kw) + + +def text_style(doc, name, font, **kw): + style = doc.styles.add(name, font=font) + for key, value in kw.items(): + setattr(style.dxf, key, value) + return style + + +def dimstyle(doc, name, scale_text=125, **over): + ds = doc.dimstyles.new(name) + ds.dxf.dimtxt = scale_text + ds.dxf.dimasz = scale_text * 0.8 + ds.dxf.dimexe = scale_text * 0.6 + ds.dxf.dimexo = scale_text * 0.8 + ds.dxf.dimgap = scale_text * 0.3 + ds.dxf.dimdec = 0 + ds.dxf.dimtad = 1 + ds.dxf.dimclrd = 3 + ds.dxf.dimclre = 3 + ds.dxf.dimclrt = 2 + for k, v in over.items(): + setattr(ds.dxf, k, v) + return ds + + +def rect(msp, x0, y0, x1, y1, **attr): + return msp.add_lwpolyline([(x0, y0), (x1, y0), (x1, y1), (x0, y1)], close=True, dxfattribs=attr) + + +# ----------------------------------------------------------------- blocks + + +def make_blocks(doc): + door = doc.blocks.new("DOOR") + # A leaf 900 wide, open to 90 degrees, with its swing. + door.add_line((0, 0), (0, 900), dxfattribs={"layer": "A-DOOR"}) + door.add_arc((0, 0), 900, 0, 90, dxfattribs={"layer": "A-DOOR", "linetype": "DASHED"}) + door.add_lwpolyline([(0, 0), (900, 0), (900, 40), (0, 40)], close=True, dxfattribs={"layer": "A-DOOR"}) + door.add_attdef("TAG", (350, -330), text="D-000", height=110, dxfattribs={"layer": "A-ANNO"}) + win = doc.blocks.new("WINDOW") + # Unit width; the frame is scaled in x to the opening and in y to the wall. + for y in (0.0, 0.35, 0.65, 1.0): + win.add_line((0, y), (1, y), dxfattribs={"layer": "A-WIND"}) + win.add_line((0, 0), (0, 1), dxfattribs={"layer": "A-WIND"}) + win.add_line((1, 0), (1, 1), dxfattribs={"layer": "A-WIND"}) + bed = doc.blocks.new("BED") + rect(bed, 0, 0, 1600, 2000, layer="A-FURN") + rect(bed, 80, 1300, 760, 1920, layer="A-FURN") + rect(bed, 840, 1300, 1520, 1920, layer="A-FURN") + bed.add_line((0, 1200), (1600, 1200), dxfattribs={"layer": "A-FURN"}) + table = doc.blocks.new("TABLE") + rect(table, 0, 0, 1800, 900, layer="A-FURN") + for i in range(4): + x = 150 + i * 450 + rect(table, x, -450, x + 400, -50, layer="A-FURN") + rect(table, x, 950, x + 400, 1350, layer="A-FURN") + sofa = doc.blocks.new("SOFA") + rect(sofa, 0, 0, 2200, 950, layer="A-FURN") + rect(sofa, 0, 0, 2200, 250, layer="A-FURN") + for i in range(3): + rect(sofa, 120 + i * 650, 300, 120 + i * 650 + 600, 900, layer="A-FURN") + wc = doc.blocks.new("WC") + rect(wc, 0, 0, 400, 200, layer="A-FIXT") + wc.add_ellipse((200, -250), major_axis=(0, 230), ratio=0.8, dxfattribs={"layer": "A-FIXT"}) + sink = doc.blocks.new("SINK") + rect(sink, 0, 0, 600, 450, layer="A-FIXT") + sink.add_circle((300, 225), 160, dxfattribs={"layer": "A-FIXT"}) + sink.add_circle((300, 225), 25, dxfattribs={"layer": "A-FIXT"}) + bath = doc.blocks.new("BATH") + rect(bath, 0, 0, 1700, 750, layer="A-FIXT") + bath.add_lwpolyline([(100, 100), (1500, 100), (1600, 375), (1500, 650), (100, 650)], close=True, dxfattribs={"layer": "A-FIXT"}) + bubble = doc.blocks.new("AXIS") + bubble.add_circle((0, 0), 300, dxfattribs={"layer": "A-GRID"}) + bubble.add_attdef("ID", (0, 0), text="A", height=300, dxfattribs={"layer": "A-GRID", "halign": 4, "valign": 0, "align_point": (0, 0)}) + north = doc.blocks.new("NORTH") + north.add_circle((0, 0), 500, dxfattribs={"layer": "A-ANNO"}) + north.add_solid([(0, 650), (-170, -400), (0, -200), (170, -400)], dxfattribs={"layer": "A-ANNO", "color": 7}) + north.add_text("N", height=300, dxfattribs={"layer": "A-ANNO"}).set_placement((0, 800), align=TextEntityAlignment.BOTTOM_CENTER) + level = doc.blocks.new("LEVEL") + level.add_lwpolyline([(-250, 250), (0, 0), (250, 250)], close=True, dxfattribs={"layer": "A-ANNO"}) + level.add_line((-250, 250), (900, 250), dxfattribs={"layer": "A-ANNO"}) + level.add_attdef("H", (320, 290), text="+0.00", height=120, dxfattribs={"layer": "A-ANNO"}) + + +def wall(msp, p1, p2, t, openings=(), layer="A-WALL", hatch=True): + """A wall along p1 to p2 of thickness t (centre line), cut at the openings + [(offset, width)]. Each piece is a closed polyline with its hatch.""" + v = Vec2(p2) - Vec2(p1) + length = v.magnitude + d = v.normalize() + n = Vec2(-d.y, d.x) * (t / 2) + cuts = sorted(openings) + pos = 0.0 + pieces = [] + for off, width in cuts: + pieces.append((pos, off)) + pos = off + width + pieces.append((pos, length)) + for a, b in pieces: + if b - a < 1: + continue + pts = [Vec2(p1) + d * a + n, Vec2(p1) + d * b + n, Vec2(p1) + d * b - n, Vec2(p1) + d * a - n] + msp.add_lwpolyline(pts, close=True, dxfattribs={"layer": layer}) + if hatch: + h = msp.add_hatch(color=8, dxfattribs={"layer": "A-WALL-PAT"}) + h.set_pattern_fill("ANSI31", color=8, scale=40) + h.paths.add_polyline_path([(p.x, p.y) for p in pts], is_closed=True) + # Door and window jambs. + for off, width in cuts: + for o in (off, off + width): + msp.add_line(Vec2(p1) + d * o + n, Vec2(p1) + d * o - n, dxfattribs={"layer": layer}) + + +# ------------------------------------------------------------- the house + + +W, D = 10000, 8000 # outer size (centre lines of the outer walls) +EXT, INT = 300, 150 + + +def house_layers(doc): + layer(doc, "A-WALL", 7, weight=50) + layer(doc, "A-WALL-PAT", 8, weight=9) + layer(doc, "A-DOOR", 3, weight=25) + layer(doc, "A-WIND", 5, weight=25) + layer(doc, "A-FURN", 9, weight=13) + layer(doc, "A-FIXT", 4, weight=18) + layer(doc, "A-GRID", 1, linetype="CENTER", weight=9) + layer(doc, "A-ANNO", 2, weight=18) + layer(doc, "A-DIMS", 3, weight=13) + layer(doc, "A-AREA", 6, weight=9) + layer(doc, "A-FLOR", 252, weight=9) + layer(doc, "A-SLAB", 254, weight=9) + layer(doc, "A-STAIR", 30, weight=18) + layer(doc, "A-SHEET", 7, weight=35) + layer(doc, "A-VPORT", 7, weight=9, plot=False) + + +def house_plan(version, name): + doc = new(version) + house_layers(doc) + doc.ltscale = 50 + text_style(doc, "ARCH-TEXT", "arial.ttf") + text_style(doc, "ARCH-TITLE", "times.ttf", width=1.0) + text_style(doc, "ARCH-NOTE", "arial.ttf", oblique=15, width=0.9) + dimstyle(doc, "PLAN50", 220, dimtxsty="ARCH-TEXT") + make_blocks(doc) + msp = doc.modelspace() + + ow, od = W, D + # Floor slab, under the walls. + h = msp.add_hatch(color=254, dxfattribs={"layer": "A-SLAB"}) + h.set_solid_fill(color=254) + h.paths.add_polyline_path([(0, 0), (ow, 0), (ow, od), (0, od)], is_closed=True) + + # Outer walls with the front door and windows. + wall(msp, (0, 0), (ow, 0), EXT, [(1400, 1500), (3600, 900), (6200, 900), (8200, 1200)]) + wall(msp, (ow, 0), (ow, od), EXT, [(1500, 1300), (4800, 1300)]) + wall(msp, (ow, od), (0, od), EXT, [(1200, 1400), (3600, 1600), (6600, 1200)]) + wall(msp, (0, od), (0, 0), EXT, [(1600, 1400), (5000, 1400)]) + # Inner walls: a hall in the middle, a bathroom and two bedrooms. + wall(msp, (0, 4200), (6200, 4200), INT, [(600, 900), (2700, 900), (4800, 900)]) + wall(msp, (6200, 0), (6200, 4200), INT, [(1700, 900)]) + wall(msp, (6200, 4200), (6200, od), INT, [(6000 - 4200 + 300, 900)]) + wall(msp, (3500, 0), (3500, 4200), INT, [(2400, 900)]) + wall(msp, (6200, 4200), (ow, 4200), INT, []) + wall(msp, (8200, 4200), (8200, od), INT, [(1600, 900)]) + + # Doors: block, rotated and mirrored to swing the right way. + msp.add_blockref("DOOR", (1700, 150), dxfattribs={"layer": "A-DOOR", "rotation": 0}).add_auto_attribs({"TAG": "D-101"}) + msp.add_blockref("DOOR", (6275, 1700), dxfattribs={"layer": "A-DOOR", "rotation": 90}).add_auto_attribs({"TAG": "D-102"}) + msp.add_blockref("DOOR", (3575, 2400), dxfattribs={"layer": "A-DOOR", "rotation": 90}).add_auto_attribs({"TAG": "D-103"}) + msp.add_blockref("DOOR", (700, 4275), dxfattribs={"layer": "A-DOOR", "rotation": 0, "yscale": -1.0}).add_auto_attribs({"TAG": "D-104"}) + msp.add_blockref("DOOR", (2800, 4275), dxfattribs={"layer": "A-DOOR", "rotation": 0}).add_auto_attribs({"TAG": "D-105"}) + msp.add_blockref("DOOR", (4900, 4275), dxfattribs={"layer": "A-DOOR", "rotation": 0, "yscale": -1.0}).add_auto_attribs({"TAG": "D-106"}) + msp.add_blockref("DOOR", (8275, 5800), dxfattribs={"layer": "A-DOOR", "rotation": 90}).add_auto_attribs({"TAG": "D-107"}) + + # Windows: the unit block stretched over each opening and the wall's thickness. + def window(p, width, vertical, thick=EXT): + x, y = p + if vertical: + msp.add_blockref("WINDOW", (x + thick / 2, y), dxfattribs={"layer": "A-WIND", "xscale": width, "yscale": thick, "rotation": 90}) + else: + msp.add_blockref("WINDOW", (x, y - thick / 2), dxfattribs={"layer": "A-WIND", "xscale": width, "yscale": thick}) + + for x, w in [(3600, 900), (6200, 900), (8200, 1200)]: + window((x, 0), w, False) + for y, w in [(4800, 1300)]: + window((ow, y), w, True) + for x, w in [(1200, 1400), (3600, 1600), (6600, 1200)]: + window((x, od), w, False) + for y, w in [(5000, 1400)]: + window((0, y), w, True) + + # Furniture and fixtures. + msp.add_blockref("SOFA", (1200, 6900), dxfattribs={"layer": "A-FURN"}) + msp.add_blockref("TABLE", (3900, 5300), dxfattribs={"layer": "A-FURN", "rotation": 0}) + msp.add_blockref("BED", (4300, 400), dxfattribs={"layer": "A-FURN", "xscale": 1.0}) + msp.add_blockref("BED", (500, 600), dxfattribs={"layer": "A-FURN", "rotation": 0, "xscale": 0.8, "yscale": 0.9}) + msp.add_blockref("BATH", (7000 - 200, 300), dxfattribs={"layer": "A-FIXT"}) + msp.add_blockref("WC", (8300, 3200), dxfattribs={"layer": "A-FIXT", "rotation": 90}) + msp.add_blockref("SINK", (6500, 3350), dxfattribs={"layer": "A-FIXT"}) + + # A straight stair in the hall: treads, a walking line and the cut line. + sx, sy = 6400, 4400 + for i in range(12): + msp.add_line((sx, sy + i * 280), (sx + 1000, sy + i * 280), dxfattribs={"layer": "A-STAIR"}) + msp.add_lwpolyline([(sx, sy), (sx + 1000, sy), (sx + 1000, sy + 12 * 280), (sx, sy + 12 * 280)], close=True, dxfattribs={"layer": "A-STAIR"}) + msp.add_lwpolyline([(sx + 500, sy + 100), (sx + 500, sy + 3300)], dxfattribs={"layer": "A-STAIR"}) + msp.add_leader([(sx + 500, sy + 3300), (sx + 420, sy + 3000), (sx + 580, sy + 3000)], dxfattribs={"layer": "A-STAIR"}) + msp.add_text("UP", height=150, dxfattribs={"layer": "A-STAIR", "style": "ARCH-TEXT"}).set_placement((sx + 550, sy + 200)) + + # Axes and bubbles. + for i, x in enumerate((0, 3500, 6200, ow)): + msp.add_line((x, -1700), (x, od + 1200), dxfattribs={"layer": "A-GRID"}) + msp.add_blockref("AXIS", (x, -2000), dxfattribs={"layer": "A-GRID"}).add_auto_attribs({"ID": str(i + 1)}) + for i, y in enumerate((0, 4200, od)): + msp.add_line((-1700, y), (ow + 1200, y), dxfattribs={"layer": "A-GRID"}) + msp.add_blockref("AXIS", (-2000, y), dxfattribs={"layer": "A-GRID"}).add_auto_attribs({"ID": "ABC"[i]}) + + # Room names and areas. + rooms = [("Bedroom 1", (1750, 2100), 3.5 * 4.2), ("Bedroom 2", (4850, 2100), 2.7 * 4.2), ("Bath", (7500, 2100), 3.8 * 4.2), + ("Living room", (3100, 6100), 6.2 * 3.8), ("Kitchen", (7150, 6100), 3.8 * 3.8), ("Hall", (1500, 4650), 0.0)] + for label, (x, y), area in rooms: + t = r"\fArial|b1;" + label.upper() + (r"\P\fArial|b0;" + f"{area:.1f} m²" if area else "") + m = msp.add_mtext(t, dxfattribs={"layer": "A-AREA", "style": "ARCH-TEXT", "char_height": 260, "attachment_point": 5}) + m.set_location((x, y)) + m.dxf.width = 2600 + + # Dimensions. + msp.add_linear_dim(base=(0, -3100), p1=(0, 0), p2=(ow, 0), dimstyle="PLAN50", dxfattribs={"layer": "A-DIMS"}).render() + msp.add_linear_dim(base=(0, -2600), p1=(0, 0), p2=(3500, 0), dimstyle="PLAN50", dxfattribs={"layer": "A-DIMS"}).render() + msp.add_linear_dim(base=(0, -2600), p1=(3500, 0), p2=(6200, 0), dimstyle="PLAN50", dxfattribs={"layer": "A-DIMS"}).render() + msp.add_linear_dim(base=(0, -2600), p1=(6200, 0), p2=(ow, 0), dimstyle="PLAN50", dxfattribs={"layer": "A-DIMS"}).render() + msp.add_linear_dim(base=(-3100, 0), p1=(0, 0), p2=(0, od), angle=90, dimstyle="PLAN50", dxfattribs={"layer": "A-DIMS"}).render() + msp.add_linear_dim(base=(-2600, 0), p1=(0, 0), p2=(0, 4200), angle=90, dimstyle="PLAN50", dxfattribs={"layer": "A-DIMS"}).render() + msp.add_linear_dim(base=(-2600, 0), p1=(0, 4200), p2=(0, od), angle=90, dimstyle="PLAN50", dxfattribs={"layer": "A-DIMS"}).render() + # A boundary fence beside the house: an aligned dimension and an angle against the house's wall. + msp.add_lwpolyline([(ow + 1500, 500), (ow + 4500, 3500)], dxfattribs={"layer": "A-WALL", "linetype": "DASHED"}) + msp.add_aligned_dim(p1=(ow + 1500, 500), p2=(ow + 4500, 3500), distance=-700, dimstyle="PLAN50", dxfattribs={"layer": "A-DIMS"}).render() + msp.add_line((ow + 1500, 500), (ow + 4500, 500), dxfattribs={"layer": "A-GRID"}) + msp.add_angular_dim_2l(base=(ow + 2300, 700), line1=((ow + 1500, 500), (ow + 4500, 3500)), line2=((ow + 1500, 500), (ow + 4500, 500)), dimstyle="PLAN50", dxfattribs={"layer": "A-DIMS"}).render() + msp.add_radius_dim(center=(6275, 1700), radius=900, angle=45, dimstyle="PLAN50", dxfattribs={"layer": "A-DIMS"}).render() + + # North arrow, level marks, title text. + msp.add_blockref("NORTH", (ow + 2200, od + 700), dxfattribs={"layer": "A-ANNO", "xscale": 1.0}) + msp.add_blockref("LEVEL", (5000, 3400), dxfattribs={"layer": "A-ANNO"}).add_auto_attribs({"H": "±0.00"}) + t = msp.add_text("GROUND FLOOR PLAN 1:50", height=330, dxfattribs={"layer": "A-ANNO", "style": "ARCH-TITLE"}) + t.set_placement((0, -4700)) + msp.add_line((0, -4900), (4500, -4900), dxfattribs={"layer": "A-ANNO", "lineweight": 70}) + msp.add_text("Drawn for the exav demo. Dimensions in millimetres.", height=130, dxfattribs={"layer": "A-ANNO", "style": "ARCH-NOTE"}).set_placement((0, -5200)) + + # A sheet in paper space: title block, a viewport on the plan. + lay = doc.layouts.new("A3 Plan") + lay.page_setup(size=(420, 297), margins=(10, 10, 10, 10), units="mm") + rect(lay, 10, 10, 410, 287, layer="A-SHEET") + rect(lay, 5, 5, 415, 292, layer="A-SHEET") + rect(lay, 260, 10, 410, 60, layer="A-SHEET") + lay.add_line((260, 35), (410, 35), dxfattribs={"layer": "A-SHEET"}) + lay.add_line((335, 10), (335, 35), dxfattribs={"layer": "A-SHEET"}) + lay.add_text("HOUSE, GROUND FLOOR", height=7, dxfattribs={"layer": "A-SHEET", "style": "ARCH-TITLE"}).set_placement((265, 45)) + lay.add_text("Scale 1:50", height=4, dxfattribs={"layer": "A-SHEET", "style": "ARCH-TEXT"}).set_placement((265, 18)) + lay.add_text("Sheet A-101", height=4, dxfattribs={"layer": "A-SHEET", "style": "ARCH-TEXT"}).set_placement((340, 18)) + vp = lay.add_viewport(center=(135, 160), size=(250, 200), view_center_point=(ow / 2, od / 2 - 600), view_height=200 * 50, status=1) + vp.dxf.layer = "A-VPORT" + vp.dxf.flags |= 0 + save(doc, name) + + +# ------------------------------------------------------------ elevations + + +def window_elev(msp, x, y, w, h, layer="A-WIND"): + rect(msp, x, y, x + w, y + h, layer=layer) + rect(msp, x + 60, y + 60, x + w - 60, y + h - 60, layer=layer) + msp.add_line((x + w / 2, y + 60), (x + w / 2, y + h - 60), dxfattribs={"layer": layer}) + hh = msp.add_hatch(color=5, dxfattribs={"layer": layer, "transparency": colors.float2transparency(0.6)}) + hh.set_solid_fill(color=5) + hh.paths.add_polyline_path([(x + 60, y + 60), (x + w - 60, y + 60), (x + w - 60, y + h - 60), (x + 60, y + h - 60)], is_closed=True) + rect(msp, x - 80, y - 90, x + w + 80, y, layer=layer) + + +def elevation(msp, ox, oy, name, width, windows, door, label): + """A gabled house front: ground, walls, roof, windows, door, levels.""" + wall_h, ridge = 5400, 8300 + layer_ = "E-WALL" + # Ground and its hatch. + msp.add_lwpolyline([(ox - 1500, oy), (ox + width + 1500, oy)], dxfattribs={"layer": "E-GROUND", "lineweight": 70}) + hh = msp.add_hatch(color=3, dxfattribs={"layer": "E-GROUND"}) + hh.set_pattern_fill("EARTH", color=3, scale=60) + hh.paths.add_polyline_path([(ox - 1500, oy - 600), (ox + width + 1500, oy - 600), (ox + width + 1500, oy), (ox - 1500, oy)], is_closed=True) + # Walls with a render hatch, plinth, roof. + rect(msp, ox, oy, ox + width, oy + wall_h, layer=layer_) + hw = msp.add_hatch(color=252, dxfattribs={"layer": "E-RENDER"}) + hw.set_pattern_fill("AR-SAND", color=8, scale=15) + hw.paths.add_polyline_path([(ox, oy), (ox + width, oy), (ox + width, oy + wall_h), (ox, oy + wall_h)], is_closed=True) + rect(msp, ox, oy, ox + width, oy + 450, layer="E-PLINTH") + roof = [(ox - 450, oy + wall_h), (ox + width / 2, oy + ridge), (ox + width + 450, oy + wall_h)] + msp.add_lwpolyline(roof, close=True, dxfattribs={"layer": "E-ROOF", "lineweight": 50}) + hr = msp.add_hatch(color=1, dxfattribs={"layer": "E-ROOF"}) + hr.set_pattern_fill("AR-RROOF", color=1, scale=60) + hr.paths.add_polyline_path(roof, is_closed=True) + # A floor line at 2700. + msp.add_line((ox, oy + 2700), (ox + width, oy + 2700), dxfattribs={"layer": "E-FLOOR", "linetype": "DASHDOT"}) + for wx, wy, w, h in windows: + window_elev(msp, ox + wx, oy + wy, w, h) + if door: + dx, dw, dh = door + rect(msp, ox + dx, oy, ox + dx + dw, oy + dh, layer="E-DOOR") + rect(msp, ox + dx + 100, oy + 100, ox + dx + dw - 100, oy + dh - 100, layer="E-DOOR") + msp.add_circle((ox + dx + dw - 200, oy + 1000), 40, dxfattribs={"layer": "E-DOOR"}) + for i in range(3): + rect(msp, ox + dx - 150 - i * 120, oy + 450 - 150 * i - 150, ox + dx + dw + 150 + i * 120, oy + 450 - 150 * i, layer="E-STEP") + # Levels and heights. + for lv, txt in [(0, "+0.00"), (2700, "+2.70"), (wall_h, "+5.40"), (ridge, "+8.30")]: + b = msp.add_blockref("LEVEL", (ox + width + 1900, oy + lv), dxfattribs={"layer": "A-ANNO"}) + b.add_auto_attribs({"H": txt}) + msp.add_line((ox + width, oy + lv), (ox + width + 1900, oy + lv), dxfattribs={"layer": "A-ANNO", "linetype": "DASHED"}) + msp.add_linear_dim(base=(ox - 1900, oy), p1=(ox, oy), p2=(ox, oy + wall_h), angle=90, dimstyle="ELEV50", dxfattribs={"layer": "A-DIMS"}).render() + msp.add_linear_dim(base=(ox - 1900, oy), p1=(ox, oy + wall_h), p2=(ox, oy + ridge), angle=90, dimstyle="ELEV50", dxfattribs={"layer": "A-DIMS"}).render() + msp.add_linear_dim(base=(ox, oy - 1100), p1=(ox, oy), p2=(ox + width, oy), dimstyle="ELEV50", dxfattribs={"layer": "A-DIMS"}).render() + t = msp.add_text(label, height=300, dxfattribs={"layer": "A-ANNO", "style": "ARCH-TITLE"}) + t.set_placement((ox, oy - 2100)) + msp.add_line((ox, oy - 2250), (ox + 3600, oy - 2250), dxfattribs={"layer": "A-ANNO", "lineweight": 70}) + + +def house_elevations(): + doc = new("R2018") + for n, c, lt, w in [("E-GROUND", 3, "Continuous", 50), ("E-WALL", 7, "Continuous", 35), ("E-RENDER", 8, "Continuous", 9), + ("E-PLINTH", 8, "Continuous", 25), ("E-ROOF", 1, "Continuous", 35), ("E-FLOOR", 9, "DASHDOT", 9), + ("E-DOOR", 30, "Continuous", 25), ("E-STEP", 8, "Continuous", 18), ("A-WIND", 5, "Continuous", 25), + ("A-ANNO", 2, "Continuous", 18), ("A-DIMS", 3, "Continuous", 13), ("A-FIXT", 4, "Continuous", 18)]: + layer(doc, n, c, lt, w) + doc.ltscale = 80 + text_style(doc, "ARCH-TEXT", "arial.ttf") + text_style(doc, "ARCH-TITLE", "times.ttf") + dimstyle(doc, "ELEV50", 160, dimtxsty="ARCH-TEXT") + make_blocks(doc) + msp = doc.modelspace() + # South (the front, with the door), east, north, west; widths 10000, 8000, 10000, 8000. + south = ([(3600, 1100, 900, 1300), (6200, 1100, 900, 1300), (8200, 1100, 1200, 1300), (800, 3400, 1000, 1400), (3600, 3400, 900, 1400), (6200, 3400, 900, 1400)], (1400, 1500, 2300)) + east = ([(1500, 1100, 1300, 1300), (4800, 1100, 1300, 1300), (1500, 3400, 1300, 1400), (4800, 3400, 1300, 1400)], None) + north = ([(1200, 1100, 1400, 1300), (3600, 1100, 1600, 1300), (6600, 1100, 1200, 1300), (3600, 3400, 1600, 1400)], None) + west = ([(1600, 1100, 1400, 1300), (5000, 1100, 1400, 1300), (3000, 3400, 1200, 1400)], None) + elevation(msp, 0, 0, "south", 10000, *south, "SOUTH ELEVATION 1:50") + elevation(msp, 16000, 0, "east", 8000, *east, "EAST ELEVATION 1:50") + elevation(msp, 0, -17000, "north", 10000, *north, "NORTH ELEVATION 1:50") + elevation(msp, 16000, -17000, "west", 8000, *west, "WEST ELEVATION 1:50") + # A section: floors, walls, roof, stair opening, hatched cuts. + ox, oy = 32000, 0 + for (x0, x1) in [(ox, ox + 300), (ox + 9700, ox + 10000)]: + rect(msp, x0, oy, x1, oy + 5400, layer="E-WALL") + hh = msp.add_hatch(color=8, dxfattribs={"layer": "E-WALL"}) + hh.set_pattern_fill("ANSI31", color=8, scale=60) + hh.paths.add_polyline_path([(x0, oy), (x1, oy), (x1, oy + 5400), (x0, oy + 5400)], is_closed=True) + for y in (0, 2700, 5100): + rect(msp, ox, oy + y - 100 if y else oy - 300, ox + 10000, oy + y + (200 if y else 0), layer="E-WALL") + sec = [(ox - 450, oy + 5400), (ox + 5000, oy + 8300), (ox + 10450, oy + 5400), (ox + 10450, oy + 5250), (ox + 5000, oy + 8150), (ox - 450, oy + 5250)] + msp.add_lwpolyline(sec, close=True, dxfattribs={"layer": "E-ROOF", "lineweight": 50}) + hr = msp.add_hatch(color=1, dxfattribs={"layer": "E-ROOF"}) + hr.set_solid_fill(color=1) + hr.paths.add_polyline_path(sec, is_closed=True) + msp.add_lwpolyline([(ox - 1500, oy - 300), (ox + 11500, oy - 300)], dxfattribs={"layer": "E-GROUND", "lineweight": 70}) + for i in range(10): + msp.add_line((ox + 6300 + i * 300, oy + i * 270), (ox + 6600 + i * 300, oy + i * 270), dxfattribs={"layer": "E-STEP"}) + msp.add_line((ox + 6600 + i * 300, oy + i * 270), (ox + 6600 + i * 300, oy + (i + 1) * 270), dxfattribs={"layer": "E-STEP"}) + t = msp.add_text("SECTION A-A 1:50", height=300, dxfattribs={"layer": "A-ANNO", "style": "ARCH-TITLE"}) + t.set_placement((ox, oy - 2100)) + save(doc, "house-elevations.dxf") + + +# ---------------------------------------------------------- hatch gallery + + +def hatch_gallery(): + doc = new("R2018") + layer(doc, "PATTERNS", 7) + layer(doc, "GRADIENTS", 5) + layer(doc, "ISLANDS", 1) + layer(doc, "EDGES", 3) + layer(doc, "LABELS", 2) + text_style(doc, "LABEL", "arial.ttf") + msp = doc.modelspace() + names = [n for n in pattern.load() if n.startswith(("ANSI", "AR-", "BRICK", "CLAY", "CORK", "CROSS", "DOTS", "EARTH", "GRASS", "GRAVEL", "HEX", "HONEY", "LINE", "NET", "SQUARE", "STEEL", "STARS", "TRIANG", "ZIGZAG", "ESCHER", "DOLMIT", "SWAMP", "INSUL", "MUDST", "PLAST", "BOX", "BRASS", "CONCRETE"))] + cols = 8 + size, gap = 100, 40 + for i, name in enumerate(names): + cx, cy = (i % cols) * (size + gap), -(i // cols) * (size + gap + 25) + h = msp.add_hatch(color=7, dxfattribs={"layer": "PATTERNS"}) + h.set_pattern_fill(name, color=7, scale=1.0) + h.paths.add_polyline_path([(cx, cy), (cx + size, cy), (cx + size, cy + size), (cx, cy + size)], is_closed=True) + rect(msp, cx, cy, cx + size, cy + size, layer="PATTERNS", color=8) + msp.add_text(name, height=9, dxfattribs={"layer": "LABELS", "style": "LABEL"}).set_placement((cx, cy - 14)) + y0 = -(len(names) // cols + 1) * (size + gap + 25) - 100 + # Gradients. + kinds = ["LINEAR", "CYLINDER", "INVCYLINDER", "SPHERICAL", "INVSPHERICAL", "HEMISPHERICAL", "INVHEMISPHERICAL", "CURVED", "INVCURVED"] + for i, k in enumerate(kinds): + cx = (i % cols) * (size + gap) + cy = y0 - (i // cols) * (size + gap + 25) + h = msp.add_hatch(dxfattribs={"layer": "GRADIENTS"}) + h.set_gradient((255, 220, 80), (20, 60, 140), rotation=30 if i % 2 else 0, name=k) + h.paths.add_polyline_path([(cx, cy), (cx + size, cy), (cx + size, cy + size), (cx, cy + size)], is_closed=True) + msp.add_text(k.lower(), height=9, dxfattribs={"layer": "LABELS", "style": "LABEL"}).set_placement((cx, cy - 14)) + y1 = y0 - 2 * (size + gap + 25) - 100 + # Islands: an outer square with a circle and a triangle inside, the three hatch styles. + for i, (style, label) in enumerate([(0, "normal: nested islands"), (1, "outer only"), (2, "ignore: all filled")]): + cx, cy = i * (size * 2 + gap), y1 + h = msp.add_hatch(color=1, dxfattribs={"layer": "ISLANDS", "hatch_style": style}) + h.set_pattern_fill("ANSI31", color=1, scale=1.4) + h.paths.add_polyline_path([(cx, cy), (cx + 2 * size, cy), (cx + 2 * size, cy + 2 * size), (cx, cy + 2 * size)], is_closed=True, flags=1 | 16) + ep = h.paths.add_edge_path(flags=16) + ep.add_arc((cx + size, cy + size), 70, 0, 360, ccw=True) + h.paths.add_polyline_path([(cx + size - 25, cy + size - 20), (cx + size + 25, cy + size - 20), (cx + size, cy + size + 28)], is_closed=True, flags=16) + msp.add_text(label, height=9, dxfattribs={"layer": "LABELS", "style": "LABEL"}).set_placement((cx, cy - 14)) + # A boundary of line, arc, ellipse and spline edges. + cx, cy = 3 * (size * 2 + gap), y1 + h = msp.add_hatch(color=3, dxfattribs={"layer": "EDGES"}) + h.set_pattern_fill("HONEY", color=3, scale=1.0) + ep = h.paths.add_edge_path(flags=1) + ep.add_line((cx, cy), (cx + 160, cy)) + ep.add_arc((cx + 160, cy + 40), 40, 270, 90, ccw=True) + ep.add_line((cx + 160, cy + 80), (cx + 120, cy + 80)) + ep.add_spline([(cx + 120, cy + 80), (cx + 100, cy + 140), (cx + 60, cy + 40), (cx + 40, cy + 120), (cx, cy + 100)], degree=3) + ep.add_line((cx, cy + 100), (cx, cy)) + msp.add_text("edges: line, arc, spline", height=9, dxfattribs={"layer": "LABELS", "style": "LABEL"}).set_placement((cx, cy - 14)) + cx = 3 * (size * 2 + gap) + 220 + h = msp.add_hatch(color=6, dxfattribs={"layer": "EDGES"}) + h.set_solid_fill(color=6) + ep = h.paths.add_edge_path(flags=1) + ep.add_ellipse((cx + 70, cy + 70), major_axis=(70, 0), ratio=0.55, start_angle=0, end_angle=360, ccw=True) + msp.add_text("ellipse, solid", height=9, dxfattribs={"layer": "LABELS", "style": "LABEL"}).set_placement((cx, cy - 14)) + # A pattern with its own angle and scale, and one with a seed point and a user-defined pattern. + cx = 3 * (size * 2 + gap) + 400 + h = msp.add_hatch(color=2, dxfattribs={"layer": "EDGES"}) + h.set_pattern_fill("ANSI37", color=2, angle=15, scale=2.5) + h.paths.add_polyline_path([(cx, cy), (cx + 140, cy), (cx + 140, cy + 140), (cx, cy + 140)], is_closed=True) + msp.add_text("angle 15, scale 2.5", height=9, dxfattribs={"layer": "LABELS", "style": "LABEL"}).set_placement((cx, cy - 14)) + save(doc, "hatch-gallery.dxf") + + +# -------------------------------------------------------------- dimensions + + +def dimensions(): + doc = new("R2018") + layer(doc, "OBJECT", 7, weight=35) + layer(doc, "DIMS", 3, weight=13) + layer(doc, "NOTE", 2, weight=13) + text_style(doc, "DIM-TEXT", "arial.ttf") + dimstyle(doc, "METRIC", 3.5, dimtxsty="DIM-TEXT", dimdec=1) + dimstyle(doc, "TOL", 3.5, dimtxsty="DIM-TEXT", dimdec=2, dimtol=1, dimtp=0.05, dimtm=0.02, dimtfac=0.7, dimtolj=1) + dimstyle(doc, "ARCH", 3.5, dimtxsty="DIM-TEXT", dimdec=0, dimtad=0, dimtih=1, dimtix=0, dimscale=1.0) + msp = doc.modelspace() + A = {"layer": "DIMS"} + rect(msp, 0, 0, 80, 50, layer="OBJECT") + msp.add_linear_dim(base=(0, -12), p1=(0, 0), p2=(80, 0), dimstyle="METRIC", dxfattribs=A).render() + msp.add_linear_dim(base=(-14, 0), p1=(0, 0), p2=(0, 50), angle=90, dimstyle="METRIC", dxfattribs=A).render() + msp.add_linear_dim(base=(0, 62), p1=(0, 50), p2=(80, 50), dimstyle="TOL", dxfattribs=A, text="<>").render() + msp.add_linear_dim(base=(0, 70), p1=(0, 50), p2=(80, 50), dimstyle="METRIC", dxfattribs=A, text="80 overall (text override)").render() + msp.add_aligned_dim(p1=(80, 0), p2=(110, 50), distance=12, dimstyle="METRIC", dxfattribs=A).render() + # Circles and arcs. + msp.add_circle((150, 25), 25, dxfattribs={"layer": "OBJECT"}) + msp.add_diameter_dim(center=(150, 25), radius=25, angle=40, dimstyle="METRIC", dxfattribs=A).render() + msp.add_circle((220, 25), 18, dxfattribs={"layer": "OBJECT"}) + msp.add_radius_dim(center=(220, 25), radius=18, angle=-60, dimstyle="METRIC", dxfattribs=A).render() + msp.add_arc((290, 0), 40, 20, 140, dxfattribs={"layer": "OBJECT"}) + msp.add_arc_dim_3p(base=(290 + 48 * math.cos(math.radians(80)), 48 * math.sin(math.radians(80))), center=(290, 0), p1=(290 + 40 * math.cos(math.radians(20)), 40 * math.sin(math.radians(20))), p2=(290 + 40 * math.cos(math.radians(140)), 40 * math.sin(math.radians(140))), dimstyle="METRIC", dxfattribs=A).render() + # Angles. + msp.add_line((0, -60), (60, -60), dxfattribs={"layer": "OBJECT"}) + msp.add_line((0, -60), (45, -20), dxfattribs={"layer": "OBJECT"}) + msp.add_angular_dim_2l(base=(30, -56), line1=((0, -60), (60, -60)), line2=((0, -60), (45, -20)), dimstyle="METRIC", dxfattribs=A).render() + msp.add_angular_dim_3p(base=(140, -60), center=(130, -80), p1=(150, -45), p2=(170, -80), dimstyle="METRIC", dxfattribs=A).render() + msp.add_line((130, -80), (170, -80), dxfattribs={"layer": "OBJECT"}) + msp.add_line((130, -80), (150, -45), dxfattribs={"layer": "OBJECT"}) + # Ordinate dimensions from an origin. + msp.add_lwpolyline([(220, -90), (320, -90), (320, -40), (260, -40), (260, -60), (220, -60)], close=True, dxfattribs={"layer": "OBJECT"}) + for x in (220, 260, 320): + msp.add_ordinate_x_dim(feature_location=(x, -90), offset=(0, -12), origin=(220, -90), dimstyle="METRIC", dxfattribs=A).render() + for y in (-90, -60, -40): + msp.add_ordinate_y_dim(feature_location=(320, y), offset=(14, 0), origin=(220, -90), dimstyle="METRIC", dxfattribs=A).render() + # Leaders and multileaders. + ml = msp.add_multileader_mtext("Standard") + ml.set_content("Chamfer 2 x 45°", char_height=3.5) + ml.add_leader_line(ConnectionSide.left, [Vec2(75, 45)]) + ml.build(insert=Vec2(100, 85)) + msp.add_leader([(15, 15), (30, 30), (40, 30)], dimstyle="METRIC", dxfattribs={"layer": "NOTE"}) + msp.add_text("hole 5", height=3.5, dxfattribs={"layer": "NOTE", "style": "DIM-TEXT"}).set_placement((41, 29)) + # Styles shown side by side. + msp.add_text("METRIC style (left), TOL style with tolerances, ARCH (text horizontal)", height=4, dxfattribs={"layer": "NOTE", "style": "DIM-TEXT"}).set_placement((0, 110)) + rect(msp, 0, -160, 60, -130, layer="OBJECT") + msp.add_linear_dim(base=(0, -168), p1=(0, -160), p2=(60, -160), dimstyle="ARCH", dxfattribs=A).render() + msp.add_linear_dim(base=(0, -178), p1=(0, -160), p2=(60, -160), dimstyle="TOL", dxfattribs=A).render() + save(doc, "dimensions.dxf") + + +# --------------------------------------------------------------- linetypes + + +def linetypes(): + doc = new("R2018") + doc.ltscale = 1.0 + text_style(doc, "LT-TEXT", "arial.ttf") + # Custom linetypes: simple, with text and with a shape-like arrow. + doc.linetypes.add("EXAV_DASH3", pattern=[10.0, 6.0, -3.0, 0.0, -3.0, 0.0, -3.0], description="Dash and three dots") + doc.linetypes.add("GAS_LINE", pattern='A,5,-2,["GAS",LT-TEXT,S=1.5,U=0.0,X=-1.0,Y=-0.75],-4', description="Gas line ---- GAS ----") + doc.linetypes.add("HOT_WATER", pattern='A,6,-1.5,["HW",LT-TEXT,S=1.5,R=0.0,X=-1.0,Y=-0.75],-3', description="Hot water ---- HW ----") + doc.linetypes.add("FENCE", pattern='A,4,-2,["x",LT-TEXT,S=1.4,U=0.0,X=-0.5,Y=-0.7],-2', description="Fence ---- x ----") + msp = doc.modelspace() + names = ["Continuous", "DASHED", "DASHED2", "DASHEDX2", "HIDDEN" if "HIDDEN" in doc.linetypes else "DASHED", "CENTER", "CENTER2", "CENTERX2", "PHANTOM", "PHANTOM2", "DASHDOT", "DASHDOT2", "DOT", "DOT2", "DIVIDE", "DIVIDE2", "EXAV_DASH3", "GAS_LINE", "HOT_WATER", "FENCE"] + y = 0 + for i, n in enumerate(names): + layer(doc, f"LT-{i:02d}", (i % 7) + 1, linetype=n, weight=25) + msp.add_line((0, y), (220, y), dxfattribs={"layer": f"LT-{i:02d}", "linetype": "BYLAYER"}) + msp.add_text(n, height=3, dxfattribs={"style": "LT-TEXT", "color": 7}).set_placement((230, y - 1)) + y -= 8 + y -= 6 + # Line weights. + msp.add_text("Line weights (mm)", height=4, dxfattribs={"style": "LT-TEXT", "color": 7}).set_placement((0, y + 6)) + for i, w in enumerate([0, 5, 9, 13, 18, 25, 35, 50, 70, 100, 140, 200]): + msp.add_line((0, y), (220, y), dxfattribs={"lineweight": w, "color": 7}) + msp.add_text(f"{w / 100:.2f}", height=3, dxfattribs={"style": "LT-TEXT", "color": 7}).set_placement((230, y - 1)) + y -= 5 + y -= 10 + # Per-entity linetype scale and BYBLOCK. + for i, s in enumerate([0.25, 0.5, 1, 2, 4]): + msp.add_line((0, y), (220, y), dxfattribs={"linetype": "DASHED", "ltscale": s, "color": 4}) + msp.add_text(f"DASHED, ltscale {s}", height=3, dxfattribs={"style": "LT-TEXT", "color": 7}).set_placement((230, y - 1)) + y -= 6 + y -= 8 + # Polylines: linetype generation on and off, wide segments. + pts = [(0, y), (40, y - 12), (80, y), (120, y - 12), (160, y), (200, y - 12)] + for gen in (True, False): + p = msp.add_lwpolyline(pts, dxfattribs={"linetype": "PHANTOM", "color": 1 if gen else 3}) + p.dxf.flags = 128 if gen else 0 + msp.add_text(f"lwpolyline, linetype generation {'on' if gen else 'off'}", height=3, dxfattribs={"style": "LT-TEXT", "color": 7}).set_placement((230, y - 1)) + pts = [(a, b - 25) for a, b in pts] + y -= 25 + y -= 6 + msp.add_lwpolyline([(0, y, 0, 6, 0), (50, y, 6, 1, 0), (100, y - 15, 1, 6, 0), (150, y, 6, 6, 0), (200, y - 8, 0, 0, 0)], format="xyseb", dxfattribs={"color": 6}) + msp.add_text("lwpolyline with start and end widths per segment", height=3, dxfattribs={"style": "LT-TEXT", "color": 7}).set_placement((230, y - 1)) + y -= 30 + msp.add_circle((30, y), 15, dxfattribs={"linetype": "CENTER", "color": 1, "lineweight": 35}) + msp.add_arc((90, y), 15, 30, 300, dxfattribs={"linetype": "HIDDEN" if "HIDDEN" in doc.linetypes else "DASHED", "color": 3}) + msp.add_ellipse((150, y), major_axis=(25, 0), ratio=0.5, dxfattribs={"linetype": "PHANTOM", "color": 5}) + msp.add_spline([(190, y - 10), (200, y + 12), (215, y - 14), (225, y + 10)], dxfattribs={"linetype": "DASHDOT", "color": 6}) + save(doc, "linetypes.dxf") + + +# ------------------------------------------------------------- text styles + + +def text_styles(): + doc = new("R2018") + layer(doc, "TEXT", 7) + layer(doc, "NOTE", 8) + fonts = [("S-ARIAL", "arial.ttf", {}), ("S-TIMES", "times.ttf", {}), ("S-COURIER", "cour.ttf", {}), ("S-NARROW", "arial.ttf", {"width": 0.6}), + ("S-WIDE", "arial.ttf", {"width": 1.6}), ("S-SLANT", "times.ttf", {"oblique": 20}), ("S-ROMANS", "romans.shx", {}), ("S-SIMPLEX", "simplex.shx", {}), + ("S-BACKWARDS", "arial.ttf", {}), ("S-UPSIDE", "arial.ttf", {})] + for n, f, kw in fonts: + st = text_style(doc, n, f, **kw) + doc.styles.get("S-BACKWARDS").dxf.flags |= 2 + doc.styles.get("S-UPSIDE").dxf.flags |= 4 + msp = doc.modelspace() + y = 0 + sample = "Sphinx of black quartz, judge my vow 0123456789" + for n, f, kw in fonts: + msp.add_text(f"{n} ({f}): {sample}", height=6, dxfattribs={"style": n, "layer": "TEXT"}).set_placement((0, y)) + y -= 12 + y -= 6 + for i, (halign, name) in enumerate([(TextEntityAlignment.TOP_LEFT, "TOP_LEFT"), (TextEntityAlignment.MIDDLE_CENTER, "MIDDLE_CENTER"), (TextEntityAlignment.BOTTOM_RIGHT, "BOTTOM_RIGHT"), (TextEntityAlignment.ALIGNED, "ALIGNED"), (TextEntityAlignment.FIT, "FIT")]): + x = 20 + i * 130 + msp.add_line((x - 5, y), (x + 5, y), dxfattribs={"color": 1}) + msp.add_line((x, y - 5), (x, y + 5), dxfattribs={"color": 1}) + t = msp.add_text(name, height=6, dxfattribs={"style": "S-ARIAL", "layer": "TEXT"}) + if halign in (TextEntityAlignment.ALIGNED, TextEntityAlignment.FIT): + t.set_placement((x, y), (x + 70, y), align=halign) + else: + t.set_placement((x, y), align=halign) + y -= 24 + for angle in (0, 30, 60, 90): + msp.add_text(f"rotated {angle} degrees", height=6, rotation=angle, dxfattribs={"style": "S-TIMES", "layer": "TEXT"}).set_placement((20 + angle * 1.5, y)) + y -= 70 + msp.add_text("Special: %%d degree 45%%d, %%p plus/minus 0.5, %%c diameter 25, %%%% percent, %%u under%%u, %%o over%%o", height=5, dxfattribs={"style": "S-ARIAL", "layer": "TEXT"}).set_placement((0, y)) + y -= 10 + msp.add_text("Unicode: éèê üöä ß ñ ΔΩπ ЖÑ� € ½ ²³", height=5, dxfattribs={"style": "S-ARIAL", "layer": "TEXT"}).set_placement((0, y)) + y -= 20 + # MTEXT formatting. + def mt(text, x, yy, w=110, h=4, **kw): + m = msp.add_mtext(text, dxfattribs={"style": "S-ARIAL", "char_height": h, "layer": "TEXT", **kw}) + m.set_location((x, yy)) + m.dxf.width = w + return m + mt(r"{\C1;Red}, {\C3;green}, {\C5;blue} and {\c16744192;orange by RGB}.\P" + r"{\fTimes New Roman|b1;Bold serif}, {\fArial|i1;italic sans}, {\fCourier New|b1|i1;bold italic mono}.\P" + r"Underline \Lis on\l, overline \Ois on\o, \Kstrike-through\k.\P" + r"Height \H2x;doubles\H1x; and returns; width \W2;wide\W1; and back; slant \Q20;oblique\Q0;.\P" + r"Stacked: \S1/2; \S1#2; \S1^2; \S\U+00B1 0.1^ -0.1; and x\S2^;, H\S2^ ;.\P" + r"Tab\Pstops: A\tB\tC", 0, y, 120) + mt(r"{\L\C2;Paragraph 1}\PA justified-looking paragraph with a long text that wraps inside the box of the entity, " + r"set at width 90, to see how line breaks are made by the viewer.", 130, y, 90, 4.2) + m = mt("Background box, with a border in the text colour: the viewer fills the box behind the text.", 230, y, 70, 4.2) + m.set_bg_color((255, 235, 140), scale=1.5) + y -= 70 + cols = msp.add_mtext_static_columns(["Column one text, a short paragraph that sits at the left.", "Column two: more text, in the middle.", "Column three at the right."], width=40, gutter_width=6, height=40, dxfattribs={"style": "S-ARIAL", "char_height": 3.5, "layer": "TEXT"}) + cols.set_location((0, y)) + msp.add_text("MTEXT in three static columns", height=3, dxfattribs={"layer": "NOTE", "style": "S-ARIAL"}).set_placement((0, y - 44)) + for i, ap in enumerate(range(1, 10)): + m = msp.add_mtext(f"AP {ap}", dxfattribs={"style": "S-ARIAL", "char_height": 4, "layer": "TEXT", "attachment_point": ap}) + m.set_location((150 + (i % 3) * 40, y - (i // 3) * 14)) + m.dxf.width = 30 + msp.add_circle((150 + (i % 3) * 40, y - (i // 3) * 14), 0.8, dxfattribs={"color": 1}) + save(doc, "text-styles.dxf") + + +# ------------------------------------------------------------------ blocks + + +def blocks(): + doc = new("R2018") + layer(doc, "PARTS", 7) + layer(doc, "NOTE", 8) + layer(doc, "RED", 1) + text_style(doc, "BL-TEXT", "arial.ttf") + msp = doc.modelspace() + # A bolt: cap, shank and a thread hatch. + bolt = doc.blocks.new("BOLT") + bolt.add_lwpolyline([(-6, 0), (6, 0), (6, 4), (-6, 4)], close=True) + bolt.add_lwpolyline([(-3, 0), (3, 0), (3, -22), (-3, -22)], close=True) + for i in range(7): + bolt.add_line((-3, -4 - i * 2.5), (3, -6.5 - i * 2.5)) + bolt.add_attdef("SIZE", (8, 1), text="M6", height=2.5) + # A plate with four BOLT inserts in a nested block. + plate = doc.blocks.new("PLATE") + plate.add_lwpolyline([(0, 0), (100, 0), (100, 60), (0, 60)], close=True) + for x, y in [(15, 15), (85, 15), (15, 45), (85, 45)]: + plate.add_circle((x, y), 4) + plate.add_blockref("BOLT", (x, y), dxfattribs={"layer": "RED"}).add_auto_attribs({"SIZE": "M6"}) + plate.add_attdef("MARK", (50, 30), text="P-1", height=6, dxfattribs={"halign": 4, "valign": 0, "align_point": (50, 30)}) + # A frame that nests the plate twice at different scales. + frame = doc.blocks.new("FRAME") + frame.add_lwpolyline([(-10, -10), (330, -10), (330, 90), (-10, 90)], close=True) + frame.add_blockref("PLATE", (0, 0)).add_auto_attribs({"MARK": "A"}) + frame.add_blockref("PLATE", (120, 0), dxfattribs={"xscale": 0.7, "yscale": 0.7, "rotation": 0}).add_auto_attribs({"MARK": "B"}) + frame.add_blockref("PLATE", (230, 70), dxfattribs={"rotation": -90, "xscale": 0.6, "yscale": 0.6}).add_auto_attribs({"MARK": "C"}) + msp.add_blockref("FRAME", (0, 0), dxfattribs={"layer": "PARTS"}) + msp.add_text("FRAME: nested PLATE, BOLT blocks, attributes", height=4, dxfattribs={"layer": "NOTE", "style": "BL-TEXT"}).set_placement((0, -20)) + # Inserts: rotated, scaled, mirrored in x and y. + y = -80 + for i, (sx, sy, rot, label) in enumerate([(1, 1, 0, "scale 1"), (-1, 1, 0, "xscale -1"), (1, -1, 0, "yscale -1"), (1.5, 0.6, 0, "1.5 by 0.6"), (1, 1, 30, "rotated 30")]): + x = i * 130 + msp.add_blockref("PLATE", (x + (100 if sx < 0 else 0), y + (60 if sy < 0 else 0)), dxfattribs={"xscale": sx, "yscale": sy, "rotation": rot}).add_auto_attribs({"MARK": label}) + msp.add_text(label, height=4, dxfattribs={"layer": "NOTE", "style": "BL-TEXT"}).set_placement((x, y - 20)) + # Arrays: a MINSERT of bolts (rows and columns), spaced. + y -= 120 + arr = msp.add_blockref("BOLT", (0, y), dxfattribs={"layer": "PARTS"}) + arr.dxf.row_count = 3 + arr.dxf.column_count = 8 + arr.dxf.row_spacing = 35 + arr.dxf.column_spacing = 20 + arr.add_auto_attribs({"SIZE": "M6"}) + msp.add_text("MINSERT: 3 rows by 8 columns of BOLT", height=4, dxfattribs={"layer": "NOTE", "style": "BL-TEXT"}).set_placement((0, y - 110)) + # A block on a layer that is on, BYBLOCK colours. + sym = doc.blocks.new("SYMBOL") + sym.add_circle((0, 0), 10, dxfattribs={"color": 0}) + sym.add_line((-10, 0), (10, 0), dxfattribs={"color": 0}) + sym.add_line((0, -10), (0, 10), dxfattribs={"color": 256}) + for i, c in enumerate([1, 3, 5, 6]): + msp.add_blockref("SYMBOL", (200 + i * 30, y - 20), dxfattribs={"color": c}) + msp.add_text("BYBLOCK circle and cross, BYLAYER vertical line: insert colour 1, 3, 5, 6", height=3, dxfattribs={"layer": "NOTE", "style": "BL-TEXT"}).set_placement((200, y - 40)) + save(doc, "blocks.dxf") + + +# ----------------------------------------------------------------- bracket + + +def bracket(): + doc = new("R2018") + layer(doc, "OUTLINE", 7, weight=50) + layer(doc, "HIDDEN", 4, linetype="DASHED", weight=25) + layer(doc, "CENTER", 1, linetype="CENTER", weight=18) + layer(doc, "SECTION", 8, weight=9) + layer(doc, "DIMS", 3, weight=18) + layer(doc, "SHEET", 7, weight=35) + layer(doc, "TEXT", 2, weight=18) + doc.ltscale = 1.0 + text_style(doc, "MECH", "arial.ttf") + dimstyle(doc, "MECH", 3.5, dimtxsty="MECH", dimdec=1) + dimstyle(doc, "MECHTOL", 3.5, dimtxsty="MECH", dimdec=2, dimtol=1, dimtp=0.1, dimtm=0.0, dimtfac=0.7, dimtolj=1) + msp = doc.modelspace() + O, Hd, C = {"layer": "OUTLINE"}, {"layer": "HIDDEN"}, {"layer": "CENTER"} + # Front view: an L bracket with two holes in the base and a slot in the upright. + # Base 100 x 60, thickness 12; upright 60 high; fillet radius 8. + pts = [(0, 0), (100, 0), (100, 12), (20, 12), (12, 12), (12, 72), (0, 72)] + msp.add_lwpolyline(pts, close=True, dxfattribs=O) + msp.add_arc((20, 20), 8, 180, 270, dxfattribs=O) + msp.add_line((12, 12), (12, 20), dxfattribs={"layer": "OUTLINE", "color": 8}) + msp.add_line((0, 0), (100, 0), dxfattribs=O) + # The holes seen from the front: hidden. + for x in (35, 80): + msp.add_line((x - 4, 0), (x - 4, 12), dxfattribs=Hd) + msp.add_line((x + 4, 0), (x + 4, 12), dxfattribs=Hd) + msp.add_line((x, -6), (x, 18), dxfattribs=C) + msp.add_line((-6, 52), (18, 52), dxfattribs=C) + # The upright's slot, hidden. + msp.add_line((0, 45), (12, 45), dxfattribs=Hd) + msp.add_line((0, 59), (12, 59), dxfattribs=Hd) + # Top view: below the front view. + oy = -90 + msp.add_lwpolyline([(0, oy), (100, oy), (100, oy - 60), (0, oy - 60)], close=True, dxfattribs=O) + msp.add_line((12, oy), (12, oy - 60), dxfattribs=O) + for x in (35, 80): + msp.add_circle((x, oy - 30), 4, dxfattribs=O) + msp.add_line((x - 8, oy - 30), (x + 8, oy - 30), dxfattribs=C) + msp.add_line((x, oy - 22), (x, oy - 38), dxfattribs=C) + msp.add_lwpolyline([(0, oy - 20), (12, oy - 20)], dxfattribs=Hd) + msp.add_lwpolyline([(0, oy - 40), (12, oy - 40)], dxfattribs=Hd) + msp.add_lwpolyline([(0, oy - 20, 0, 0, 0), (0, oy - 40, 0, 0, 0)], format="xyseb", dxfattribs={"layer": "OUTLINE", "color": 8}) + # Section A-A through a hole, to the right: hatched cut. + sx = 150 + cut = [(sx, 0), (sx + 60, 0), (sx + 60, 12), (sx + 42, 12), (sx + 42, 0 + 12), (sx + 38, 12), (sx + 12, 12), (sx + 12, 72), (sx, 72)] + sec = [(sx, 0), (sx + 31, 0), (sx + 31, 12), (sx + 39, 12), (sx + 39, 0), (sx + 60, 0), (sx + 60, 12), (sx + 12, 12), (sx + 12, 72), (sx, 72)] + msp.add_lwpolyline([(sx, 0), (sx + 31, 0), (sx + 31, 12), (sx + 12, 12), (sx + 12, 72), (sx, 72)], close=True, dxfattribs=O) + msp.add_lwpolyline([(sx + 39, 0), (sx + 60, 0), (sx + 60, 12), (sx + 39, 12)], close=True, dxfattribs=O) + h = msp.add_hatch(color=8, dxfattribs={"layer": "SECTION"}) + h.set_pattern_fill("ANSI31", color=8, scale=2.0) + h.paths.add_polyline_path([(sx, 0), (sx + 31, 0), (sx + 31, 12), (sx + 12, 12), (sx + 12, 72), (sx, 72)], is_closed=True) + h2 = msp.add_hatch(color=8, dxfattribs={"layer": "SECTION"}) + h2.set_pattern_fill("ANSI31", color=8, scale=2.0) + h2.paths.add_polyline_path([(sx + 39, 0), (sx + 60, 0), (sx + 60, 12), (sx + 39, 12)], is_closed=True) + msp.add_line((sx + 35, -6), (sx + 35, 18), dxfattribs=C) + msp.add_text("SECTION A-A", height=5, dxfattribs={"layer": "TEXT", "style": "MECH"}).set_placement((sx, -14)) + # Cutting plane line in the top view. + msp.add_lwpolyline([(-8, oy - 30), (108, oy - 30)], dxfattribs={"layer": "CENTER", "lineweight": 50}) + msp.add_text("A", height=6, dxfattribs={"layer": "TEXT", "style": "MECH"}).set_placement((-14, oy - 33)) + msp.add_text("A", height=6, dxfattribs={"layer": "TEXT", "style": "MECH"}).set_placement((112, oy - 33)) + # Dimensions, two with tolerances. + D = {"layer": "DIMS"} + msp.add_linear_dim(base=(0, -12), p1=(0, 0), p2=(100, 0), dimstyle="MECH", dxfattribs=D).render() + msp.add_linear_dim(base=(-12, 0), p1=(0, 0), p2=(0, 72), angle=90, dimstyle="MECHTOL", dxfattribs=D).render() + msp.add_linear_dim(base=(0, -24), p1=(35, 0), p2=(80, 0), dimstyle="MECHTOL", dxfattribs=D).render() + msp.add_radius_dim(center=(20, 20), radius=8, angle=225, dimstyle="MECH", dxfattribs=D).render() + msp.add_linear_dim(base=(0, oy + 12), p1=(0, oy), p2=(100, oy), dimstyle="MECH", dxfattribs=D).render() + msp.add_diameter_dim(center=(80, oy - 30), radius=4, angle=35, dimstyle="MECH", dxfattribs=D, text="2x ⌀<>").render() + msp.add_linear_dim(base=(sx + 70, 0), p1=(sx + 60, 0), p2=(sx + 60, 12), angle=90, dimstyle="MECH", dxfattribs=D).render() + msp.add_leader([(sx + 5, 60), (sx - 12, 80), (sx - 40, 80)], dxfattribs={"layer": "DIMS"}) + msp.add_text("slot 14 x 12", height=3.5, dxfattribs={"layer": "TEXT", "style": "MECH"}).set_placement((sx - 40, 82)) + # A sheet: layout with a viewport and a title block. + lay = doc.layouts.new("A4 Sheet") + lay.page_setup(size=(297, 210), margins=(5, 5, 5, 5), units="mm") + rect(lay, 5, 5, 292, 205, layer="SHEET") + rect(lay, 137, 5, 292, 45, layer="SHEET") + lay.add_line((137, 25), (292, 25), dxfattribs={"layer": "SHEET"}) + lay.add_line((200, 5), (200, 25), dxfattribs={"layer": "SHEET"}) + lay.add_line((250, 5), (250, 25), dxfattribs={"layer": "SHEET"}) + for txt, x, y, hgt in [("L-BRACKET 100 x 72 x 60", 142, 33, 6), ("Material: steel S235", 142, 15, 3.5), ("Scale 1:1", 205, 15, 3.5), ("Sheet 1/1", 255, 15, 3.5), ("Drawn: exav demo", 142, 8, 3)]: + lay.add_text(txt, height=hgt, dxfattribs={"layer": "SHEET", "style": "MECH"}).set_placement((x, y)) + vp = lay.add_viewport(center=(130, 120), size=(250, 140), view_center_point=(90, -30), view_height=140, status=1) + save(doc, "bracket.dxf") + + +# --------------------------------------------------------------- site plan + + +def site_plan(): + doc = new("R2018", units=6) + layer(doc, "CONTOUR-MINOR", 8, weight=9) + layer(doc, "CONTOUR-MAJOR", 30, weight=25) + layer(doc, "PARCEL", 1, linetype="DASHDOT", weight=35) + layer(doc, "BUILDING", 7, weight=50) + layer(doc, "ROAD", 9, weight=18) + layer(doc, "WATER", 5, weight=18) + layer(doc, "TREES", 3, weight=9) + layer(doc, "SPOT", 2, weight=9) + layer(doc, "TEXT", 2, weight=13) + layer(doc, "LEGEND", 7, weight=13) + text_style(doc, "SITE", "arial.ttf") + doc.ltscale = 6 + make_blocks(doc) + msp = doc.modelspace() + + def height(x, y): + return 100 + 18 * math.sin(x / 38) * math.cos(y / 47) + 8 * math.sin((x + y) / 21) + (x - 160) * 0.05 + + # Contours: marching squares would be long; use closed hill rings as splines at several heights. + for k, hgt in enumerate(range(94, 134, 2)): + r = 12 + k * 7 + cx, cy = 150 + 3 * k, 110 - 2 * k + pts = [] + for i in range(24): + a = i * 2 * math.pi / 24 + rr = r * (1 + 0.12 * math.sin(3 * a + k * 0.3) + 0.06 * math.cos(5 * a)) + pts.append((cx + rr * math.cos(a), cy + rr * 0.75 * math.sin(a))) + major = hgt % 10 == 0 + lyr = "CONTOUR-MAJOR" if major else "CONTOUR-MINOR" + msp.add_spline(pts + pts[:1], degree=3, dxfattribs={"layer": lyr}) + if major: + msp.add_text(f"{hgt}", height=3, dxfattribs={"layer": "TEXT", "style": "SITE"}).set_placement((pts[0][0] + 1, pts[0][1]), align=TextEntityAlignment.MIDDLE_LEFT) + # Roads: two polylines with a width, a roundabout. + msp.add_lwpolyline([(-40, 40), (60, 50), (140, 20), (260, 30), (360, 70)], dxfattribs={"layer": "ROAD", "const_width": 9}) + msp.add_lwpolyline([(140, 20), (150, -40), (130, -90)], dxfattribs={"layer": "ROAD", "const_width": 6}) + msp.add_circle((140, 20), 12, dxfattribs={"layer": "ROAD"}) + # Parcels with their numbers and areas. + parcels = [[(20, 60), (120, 66), (116, 150), (14, 140)], [(120, 66), (230, 62), (240, 160), (116, 150)], [(230, 62), (330, 80), (320, 170), (240, 160)]] + for i, p in enumerate(parcels): + msp.add_lwpolyline(p, close=True, dxfattribs={"layer": "PARCEL"}) + cx = sum(a for a, _ in p) / 4 + cy = sum(b for _, b in p) / 4 + area = 0.5 * abs(sum(p[j][0] * p[(j + 1) % 4][1] - p[(j + 1) % 4][0] * p[j][1] for j in range(4))) + m = msp.add_mtext(rf"Parcel {101 + i}\P{area:.0f} m²", dxfattribs={"layer": "TEXT", "style": "SITE", "char_height": 5, "attachment_point": 5}) + m.set_location((cx, cy - 40)) + # Buildings with a hatch. + for x, y, w, d in [(40, 90, 40, 26), (150, 95, 34, 30), (262, 110, 44, 28)]: + msp.add_lwpolyline([(x, y), (x + w, y), (x + w, y + d), (x, y + d)], close=True, dxfattribs={"layer": "BUILDING"}) + h = msp.add_hatch(color=252, dxfattribs={"layer": "BUILDING"}) + h.set_pattern_fill("ANSI31", color=8, scale=3) + h.paths.add_polyline_path([(x, y), (x + w, y), (x + w, y + d), (x, y + d)], is_closed=True) + # A pond (hatched gradient), trees as circles and points with heights. + pond = [(280, -10), (310, -25), (340, -5), (325, 20), (295, 18)] + msp.add_lwpolyline(pond, close=True, dxfattribs={"layer": "WATER"}) + h = msp.add_hatch(dxfattribs={"layer": "WATER"}) + h.set_gradient((140, 200, 255), (30, 90, 170), rotation=90, name="LINEAR") + h.paths.add_polyline_path(pond, is_closed=True) + import random + rnd = random.Random(5) + for _ in range(60): + x, y = rnd.uniform(-20, 340), rnd.uniform(-110, 40) + if 270 < x < 350 and -30 < y < 25: + continue + msp.add_circle((x, y), rnd.uniform(1.5, 3.2), dxfattribs={"layer": "TREES"}) + for i in range(30): + x, y = rnd.uniform(0, 330), rnd.uniform(-90, 170) + msp.add_point((x, y), dxfattribs={"layer": "SPOT", "color": 2}) + msp.add_text(f"{height(x, y):.2f}", height=1.8, dxfattribs={"layer": "SPOT", "style": "SITE"}).set_placement((x + 1.5, y + 0.5)) + # North arrow, scale bar, legend. + msp.add_blockref("NORTH", (370, 180), dxfattribs={"layer": "LEGEND", "xscale": 0.02, "yscale": 0.02, "zscale": 0.02}) + for i in range(5): + msp.add_lwpolyline([(0 + i * 20, -130), (20 + i * 20, -130), (20 + i * 20, -125), (0 + i * 20, -125)], close=True, dxfattribs={"layer": "LEGEND", "color": 7 if i % 2 else 8}) + h = msp.add_hatch(color=7 if i % 2 else 252, dxfattribs={"layer": "LEGEND"}) + h.set_solid_fill(color=7 if i % 2 else 252) + h.paths.add_polyline_path([(0 + i * 20, -130), (20 + i * 20, -130), (20 + i * 20, -125), (0 + i * 20, -125)], is_closed=True) + for i, v in enumerate((0, 20, 40, 60, 80, 100)): + msp.add_text(f"{v}", height=3, dxfattribs={"layer": "LEGEND", "style": "SITE"}).set_placement((v, -138), align=TextEntityAlignment.TOP_CENTER) + msp.add_text("m", height=3, dxfattribs={"layer": "LEGEND", "style": "SITE"}).set_placement((108, -138)) + ly = 170 + for lyr, label in [("CONTOUR-MINOR", "Contour, 2 m"), ("CONTOUR-MAJOR", "Contour, 10 m"), ("PARCEL", "Parcel boundary"), ("BUILDING", "Building"), ("ROAD", "Road"), ("WATER", "Water"), ("TREES", "Tree")]: + msp.add_line((300 + 70, ly), (320 + 70, ly), dxfattribs={"layer": lyr}) + msp.add_text(label, height=3, dxfattribs={"layer": "LEGEND", "style": "SITE"}).set_placement((324 + 70, ly - 1)) + ly -= 8 + msp.add_text("SITE PLAN 1:1000", height=8, dxfattribs={"layer": "TEXT", "style": "SITE"}).set_placement((0, -160)) + save(doc, "site-plan.dxf") + + +# --------------------------------------------------------------- R12 drawing + + +def legacy_r12(): + doc = ezdxf.new("R12") + doc.layers.add("GEAR", color=7) + doc.layers.add("AXES", color=1, linetype="CENTER") if "CENTER" in doc.linetypes else doc.layers.add("AXES", color=1) + doc.layers.add("TEXT", color=2) + doc.layers.add("DIMS", color=3) + msp = doc.modelspace() + teeth, r_out, r_in = 20, 40.0, 33.0 + pts = [] + for i in range(teeth): + a0 = i * 2 * math.pi / teeth + step = 2 * math.pi / teeth + for da, r in [(0.0, r_in), (step * 0.2, r_out), (step * 0.55, r_out), (step * 0.75, r_in)]: + pts.append((r * math.cos(a0 + da), r * math.sin(a0 + da))) + msp.add_polyline2d(pts, close=True, dxfattribs={"layer": "GEAR"}) + msp.add_circle((0, 0), 10, dxfattribs={"layer": "GEAR"}) + msp.add_circle((0, 0), 4, dxfattribs={"layer": "GEAR"}) + for i in range(6): + a = i * math.pi / 3 + msp.add_circle((20 * math.cos(a), 20 * math.sin(a)), 4, dxfattribs={"layer": "GEAR"}) + msp.add_line((-50, 0), (50, 0), dxfattribs={"layer": "AXES"}) + msp.add_line((0, -50), (0, 50), dxfattribs={"layer": "AXES"}) + msp.add_arc((0, 0), r_in - 3, 30, 150, dxfattribs={"layer": "GEAR", "color": 4}) + msp.add_text("GEAR, 20 TEETH (R12 FILE)", height=4, dxfattribs={"layer": "TEXT"}).set_placement((-45, -58)) + msp.add_text("module 4, pitch diameter 80", height=3, dxfattribs={"layer": "TEXT"}).set_placement((-45, -64)) + msp.add_point((0, 0), dxfattribs={"layer": "AXES"}) + msp.add_solid([(55, 40), (65, 40), (55, 46), (65, 46)], dxfattribs={"layer": "DIMS"}) + msp.add_3dface([(55, -10, 0), (70, -10, 0), (70, 5, 0), (55, 5, 0)], dxfattribs={"layer": "DIMS", "color": 5}) + blk = doc.blocks.new("TAG") + blk.add_circle((0, 0), 5) + blk.add_text("1", dxfattribs={"height": 5}).set_placement((-1.5, -2)) + for i in range(3): + msp.add_blockref("TAG", (60, 20 - i * 15), dxfattribs={"layer": "DIMS", "xscale": 1 + i * 0.3, "yscale": 1 + i * 0.3}) + save(doc, "legacy-r12.dxf") + + +if __name__ == "__main__": + house_plan("R2018", "house-plan.dxf") + house_plan("R2000", "house-plan-r2000.dxf") + house_elevations() + hatch_gallery() + dimensions() + linetypes() + text_styles() + blocks() + bracket() + site_plan() + legacy_r12() diff --git a/crates/exav-viewer/demo/examples/generate/make-ifc.py b/crates/exav-viewer/demo/examples/generate/make-ifc.py new file mode 100644 index 0000000..0e0225f --- /dev/null +++ b/crates/exav-viewer/demo/examples/generate/make-ifc.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python3 +"""Writes the demo's IFC example into ../files/ifc/. + + python3 -I make-ifc.py [OUT_DIR] + +Output: CC0-1.0, a public domain dedication by the exav project. The model is +written here as STEP text, entity by entity, with no IFC library and no +outside model. + +Needs: Python 3. + +house.ifc (IFC4): a two-storey house, 10 by 8 metres. Per storey: outer and +inner walls (extruded rectangles), openings cut by IfcRelVoidsElement and +filled by windows and doors (IfcRelFillsElement) with separate frame and glass +colours, a floor slab; a gable roof (an extruded triangle), a porch with +columns, a straight stair (a step per solid), a table and four chairs that +share one mapped representation, spaces, a material and a property set, and +colours through IfcStyledItem. +""" +import hashlib +import math +import os +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +OUT = os.path.abspath(sys.argv[1]) if len(sys.argv) > 1 else os.path.join(HERE, "..", "files", "ifc") +os.makedirs(OUT, exist_ok=True) + +ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$" + + +def guid(n): + num = int.from_bytes(hashlib.md5(f"exav-house-{n}".encode()).digest(), "big") + chars = [ALPHABET[num >> 126]] + for i in range(21): + chars.append(ALPHABET[(num >> (120 - 6 * i)) & 63]) + return "".join(chars) + + +def f(x): + s = repr(float(x)) + return s if "e" in s or "." in s else s + "." + + +class Step: + def __init__(self): + self.lines = [] + self.n = 0 + self.g = 0 + + def add(self, text): + self.n += 1 + self.lines.append(f"#{self.n}={text};") + return f"#{self.n}" + + def gid(self): + self.g += 1 + return f"'{guid(self.g)}'" + + +S = Step() +pt_cache = {} + + +def point(x, y, z=None): + key = (round(x, 6), round(y, 6), None if z is None else round(z, 6)) + if key not in pt_cache: + pt_cache[key] = S.add(f"IFCCARTESIANPOINT(({f(x)},{f(y)}" + (f",{f(z)}))" if z is not None else "))")) + return pt_cache[key] + + +def direction(x, y, z=None): + return S.add(f"IFCDIRECTION(({f(x)},{f(y)}" + (f",{f(z)}))" if z is not None else "))")) + + +def axis3(origin=(0, 0, 0), z=None, x=None): + return S.add(f"IFCAXIS2PLACEMENT3D({point(*origin)}," + (direction(*z) if z else "$") + "," + (direction(*x) if x else "$") + ")") + + +def axis2(origin=(0, 0), x=None): + return S.add(f"IFCAXIS2PLACEMENT2D({point(*origin)}," + (direction(*x) if x else "$") + ")") + + +def placement(rel, origin=(0, 0, 0), z=None, x=None): + return S.add(f"IFCLOCALPLACEMENT({rel if rel else '$'},{axis3(origin, z, x)})") + + +def rect_profile(w, d, centre=(0, 0)): + return S.add(f"IFCRECTANGLEPROFILEDEF(.AREA.,$,{axis2(centre)},{f(w)},{f(d)})") + + +def circle_profile(r): + return S.add(f"IFCCIRCLEPROFILEDEF(.AREA.,$,{axis2()},{f(r)})") + + +def poly_profile(points): + pl = S.add("IFCPOLYLINE((" + ",".join(point(*p) for p in points + [points[0]]) + "))") + return S.add(f"IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,{pl})") + + +def extrude(profile, depth, origin=(0, 0, 0), z=None, x=None): + return S.add(f"IFCEXTRUDEDAREASOLID({profile},{axis3(origin, z, x)},{direction(0, 0, 1)},{f(depth)})") + + +# ------------------------------------------------------------------ styles + +style_cache = {} + + +def style(name, rgb, transparency=0.0): + if name not in style_cache: + col = S.add(f"IFCCOLOURRGB($,{f(rgb[0])},{f(rgb[1])},{f(rgb[2])})") + rend = S.add(f"IFCSURFACESTYLERENDERING({col},{f(transparency)},$,$,$,$,$,$,.FLAT.)") + style_cache[name] = S.add(f"IFCSURFACESTYLE('{name}',.BOTH.,({rend}))") + return style_cache[name] + + +def styled(item, name, rgb, transparency=0.0): + S.add(f"IFCSTYLEDITEM({item},({style(name, rgb, transparency)}),$)") + return item + + +# --------------------------------------------------------------- the model + +origin_axis = axis3() +ctx = S.add(f"IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,{origin_axis},$)") +body = S.add(f"IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,{ctx},$,.MODEL_VIEW.,$)") +length = S.add("IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.)") +area = S.add("IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.)") +volume = S.add("IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.)") +angle = S.add("IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.)") +units = S.add(f"IFCUNITASSIGNMENT(({length},{area},{volume},{angle}))") +project = S.add(f"IFCPROJECT({S.gid()},$,'Example house',$,$,$,$,({ctx}),{units})") + +site_pl = placement(None) +site = S.add(f"IFCSITE({S.gid()},$,'Site',$,$,{site_pl},$,$,.ELEMENT.,$,$,$,$,$)") +bld_pl = placement(site_pl) +building = S.add(f"IFCBUILDING({S.gid()},$,'House',$,$,{bld_pl},$,$,.ELEMENT.,$,$,$)") +STOREY_H = 3.0 +storeys = [] +for i, name in enumerate(["Ground floor", "First floor"]): + pl = placement(bld_pl, (0, 0, i * STOREY_H)) + storeys.append((S.add(f"IFCBUILDINGSTOREY({S.gid()},$,'{name}',$,$,{pl},$,$,.ELEMENT.,{f(i * STOREY_H)})"), pl)) +S.add(f"IFCRELAGGREGATES({S.gid()},$,$,$,{project},({site}))") +S.add(f"IFCRELAGGREGATES({S.gid()},$,$,$,{site},({building}))") +S.add(f"IFCRELAGGREGATES({S.gid()},$,$,$,{building},({storeys[0][0]},{storeys[1][0]}))") + +contained = {s[0]: [] for s in storeys} +walls_all = [] +brick = S.add("IFCMATERIAL('Brick, rendered')") +WALL_RGB, FRAME_RGB, GLASS_RGB, DOOR_RGB = (0.93, 0.9, 0.82), (0.95, 0.95, 0.95), (0.55, 0.78, 0.92), (0.45, 0.28, 0.14) + + +def shape(items, kind="SweptSolid"): + rep = S.add(f"IFCSHAPEREPRESENTATION({body},'Body','{kind}',({','.join(items)}))") + return S.add(f"IFCPRODUCTDEFINITIONSHAPE($,$,({rep}))") + + +def add_wall(storey, p1, p2, t, h, openings, name): + """openings: [(kind, offset along the wall, width, sill, height)].""" + sidx = storey + sto, sto_pl = storeys[sidx] + dx, dy = p2[0] - p1[0], p2[1] - p1[1] + L = math.hypot(dx, dy) + ux, uy = dx / L, dy / L + pl = placement(sto_pl, (p1[0], p1[1], 0), (0, 0, 1), (ux, uy, 0)) + solid = styled(extrude(rect_profile(L, t, (L / 2, 0)), h), "Render", WALL_RGB) + wall = S.add(f"IFCWALL({S.gid()},$,'{name}',$,$,{pl},{shape([solid])},$,.STANDARD.)") + contained[sto].append(wall) + walls_all.append(wall) + for k, (kind, off, w, sill, oh) in enumerate(openings): + opl = placement(pl, (off + w / 2, 0, sill)) + hole = extrude(rect_profile(w, t + 0.2), oh) + opening = S.add(f"IFCOPENINGELEMENT({S.gid()},$,'Opening {name} {k + 1}',$,$,{opl},{shape([hole])},$,.OPENING.)") + S.add(f"IFCRELVOIDSELEMENT({S.gid()},$,$,$,{wall},{opening})") + fpl = placement(pl, (off + w / 2, 0, sill)) + if kind == "window": + frame = styled(extrude(rect_profile(w, 0.1), oh), "Frame", FRAME_RGB) + glass = styled(extrude(rect_profile(w - 0.12, 0.04), oh - 0.12, (0, 0, 0.06)), "Glass", GLASS_RGB, 0.55) + bar = styled(extrude(rect_profile(0.05, 0.12), oh), "Frame", FRAME_RGB) + el = S.add(f"IFCWINDOW({S.gid()},$,'Window {name} {k + 1}',$,$,{fpl},{shape([frame, glass, bar])},$,{f(oh)},{f(w)},.WINDOW.,.NOTDEFINED.,$)") + else: + leaf = styled(extrude(rect_profile(w - 0.1, 0.06), oh - 0.05), "Door", DOOR_RGB) + knob = styled(extrude(rect_profile(0.08, 0.14), 0.08, (w / 2 - 0.2, 0, 1.0)), "Frame", FRAME_RGB) + el = S.add(f"IFCDOOR({S.gid()},$,'Door {name} {k + 1}',$,$,{fpl},{shape([leaf, knob])},$,{f(oh)},{f(w)},.DOOR.,.NOTDEFINED.,$)") + S.add(f"IFCRELFILLSELEMENT({S.gid()},$,$,$,{opening},{el})") + contained[sto].append(el) + return wall + + +H = 2.8 +for sidx in (0, 1): + tag = "G" if sidx == 0 else "F" + door_south = [("door", 6.7, 1.1, 0.0, 2.1)] if sidx == 0 else [("window", 6.9, 1.2, 0.9, 1.3)] + add_wall(sidx, (0, 0), (10, 0), 0.3, H, [("window", 1.0, 1.2, 0.9, 1.3), ("window", 3.6, 1.2, 0.9, 1.3)] + door_south, f"{tag}-South") + add_wall(sidx, (10, 0), (10, 8), 0.3, H, [("window", 1.4, 1.3, 0.9, 1.3), ("window", 5.0, 1.3, 0.9, 1.3)], f"{tag}-East") + add_wall(sidx, (10, 8), (0, 8), 0.3, H, [("window", 1.2, 1.4, 0.9, 1.3), ("window", 4.1, 1.6, 0.9, 1.3), ("window", 7.2, 1.2, 0.9, 1.3)], f"{tag}-North") + add_wall(sidx, (0, 8), (0, 0), 0.3, H, [("window", 1.6, 1.4, 0.9, 1.3), ("window", 5.0, 1.4, 0.9, 1.3)], f"{tag}-West") + add_wall(sidx, (6, 0.15), (6, 7.85), 0.15, H, [("door", 1.5, 0.9, 0.0, 2.05), ("door", 5.0, 0.9, 0.0, 2.05)], f"{tag}-Partition A") + add_wall(sidx, (0.15, 4), (6, 4), 0.15, H, [("door", 1.0, 0.9, 0.0, 2.05)], f"{tag}-Partition B") + +# Slabs: ground slab under the house, a floor slab between the storeys, a porch slab. +ground, ground_pl = storeys[0] +first, first_pl = storeys[1] +slab1 = styled(extrude(rect_profile(10.3, 8.3, (5, 4)), 0.2, (0, 0, -0.2)), "Concrete", (0.62, 0.62, 0.6)) +s1 = S.add(f"IFCSLAB({S.gid()},$,'Ground slab',$,$,{placement(ground_pl)},{shape([slab1])},$,.BASESLAB.)") +slab2 = styled(extrude(poly_profile([(-0.15, -0.15), (10.15, -0.15), (10.15, 8.15), (-0.15, 8.15)]), 0.2, (0, 0, H)), "Concrete", (0.7, 0.7, 0.68)) +s2 = S.add(f"IFCSLAB({S.gid()},$,'Floor slab',$,$,{placement(ground_pl)},{shape([slab2])},$,.FLOOR.)") +porch = styled(extrude(rect_profile(4.0, 1.4, (8.2, -0.8)), 0.15, (0, 0, H)), "Concrete", (0.7, 0.7, 0.68)) +s3 = S.add(f"IFCSLAB({S.gid()},$,'Porch roof',$,$,{placement(ground_pl)},{shape([porch])},$,.ROOF.)") +contained[ground] += [s1, s2, s3] +for k, (cx, cy) in enumerate([(6.4, -1.3), (10.0, -1.3)]): + col = styled(extrude(circle_profile(0.15), H, (0, 0, 0)), "Column", (0.9, 0.9, 0.9)) + contained[ground].append(S.add(f"IFCCOLUMN({S.gid()},$,'Porch column {k + 1}',$,$,{placement(ground_pl, (cx, cy, 0))},{shape([col])},$,.COLUMN.)")) + +# Roof: a triangle in the YZ plane, extruded along X. +tri = poly_profile([(-0.6, 0.0), (8.6, 0.0), (4.0, 2.7)]) +roof_solid = styled(extrude(tri, 11.2, (0, 0, 0), (1, 0, 0), (0, 1, 0)), "Tiles", (0.7, 0.28, 0.2)) +roof_pl = placement(first_pl, (-0.6, 0, 2.8 + 0.2)) +roof = S.add(f"IFCROOF({S.gid()},$,'Gable roof',$,$,{roof_pl},{shape([roof_solid])},$,.GABLE_ROOF.)") +contained[first].append(roof) + +# A straight stair in the hall: eleven steps, each a block up to its tread. +steps = [] +for k in range(11): + top = 0.25 * (k + 1) + steps.append(styled(extrude(rect_profile(1.0, 0.28, (0.0, 0.14 + 0.28 * k)), top), "Wood", (0.6, 0.42, 0.25))) +stair = S.add(f"IFCSTAIR({S.gid()},$,'Stair',$,$,{placement(ground_pl, (6.9, 4.3, 0))},{shape(steps)},$,.STRAIGHT_RUN_STAIR.)") +contained[ground].append(stair) + +# A table and four chairs sharing one mapped representation. +def furniture_map(parts, name): + rep = S.add(f"IFCSHAPEREPRESENTATION({body},'Body','SweptSolid',({','.join(parts)}))") + return S.add(f"IFCREPRESENTATIONMAP({axis3()},{rep})") + + +chair_parts = [styled(extrude(rect_profile(0.45, 0.45, (0, 0)), 0.05, (0, 0, 0.45)), "Chair", (0.75, 0.2, 0.2)), + styled(extrude(rect_profile(0.45, 0.05, (0, -0.2)), 0.5, (0, 0, 0.5)), "Chair", (0.75, 0.2, 0.2))] +for dx in (-0.19, 0.19): + for dy in (-0.19, 0.19): + chair_parts.append(styled(extrude(rect_profile(0.05, 0.05, (dx, dy)), 0.45), "Chair legs", (0.3, 0.2, 0.15))) +chair_map = furniture_map(chair_parts, "Chair") +table_parts = [styled(extrude(rect_profile(1.6, 0.9, (0, 0)), 0.06, (0, 0, 0.72)), "Wood", (0.6, 0.42, 0.25))] +for dx in (-0.72, 0.72): + for dy in (-0.36, 0.36): + table_parts.append(styled(extrude(rect_profile(0.07, 0.07, (dx, dy)), 0.72), "Wood", (0.5, 0.35, 0.2))) +table_map = furniture_map(table_parts, "Table") + + +def mapped(rep_map, scale=1.0): + op = S.add(f"IFCCARTESIANTRANSFORMATIONOPERATOR3D($,$,{point(0, 0, 0)},{f(scale)},$)") + item = S.add(f"IFCMAPPEDITEM({rep_map},{op})") + return shape([item], "MappedRepresentation") + + +contained[ground].append(S.add(f"IFCFURNISHINGELEMENT({S.gid()},$,'Table',$,$,{placement(ground_pl, (3.0, 6.0, 0))},{mapped(table_map)},$)")) +for k, (cx, cy, rot) in enumerate([(2.4, 6.0, 90), (3.6, 6.0, -90), (3.0, 5.2, 180), (3.0, 6.8, 0)]): + a = math.radians(rot) + contained[ground].append(S.add(f"IFCFURNISHINGELEMENT({S.gid()},$,'Chair {k + 1}',$,$,{placement(ground_pl, (cx, cy, 0), (0, 0, 1), (math.cos(a), math.sin(a), 0))},{mapped(chair_map)},$)")) + +# Spaces (no geometry), a property set and the material on the walls. +spaces = [] +for name, plc in [("Living room", ground_pl), ("Kitchen", ground_pl), ("Hall", ground_pl), ("Bedroom", first_pl), ("Bath", first_pl)]: + spaces.append(S.add(f"IFCSPACE({S.gid()},$,'{name}',$,$,{placement(plc)},$,$,.ELEMENT.,.INTERNAL.,$)")) +S.add(f"IFCRELAGGREGATES({S.gid()},$,$,$,{ground},({spaces[0]},{spaces[1]},{spaces[2]}))") +S.add(f"IFCRELAGGREGATES({S.gid()},$,$,$,{first},({spaces[3]},{spaces[4]}))") +prop_ext = S.add("IFCPROPERTYSINGLEVALUE('IsExternal',$,IFCBOOLEAN(.T.),$)") +prop_fire = S.add("IFCPROPERTYSINGLEVALUE('FireRating',$,IFCLABEL('REI 60'),$)") +pset = S.add(f"IFCPROPERTYSET({S.gid()},$,'Pset_WallCommon',$,({prop_ext},{prop_fire}))") +S.add(f"IFCRELDEFINESBYPROPERTIES({S.gid()},$,$,$,({','.join(walls_all[:4])}),{pset})") +S.add(f"IFCRELASSOCIATESMATERIAL({S.gid()},$,$,$,({','.join(walls_all)}),{brick})") +for sto, items in contained.items(): + S.add(f"IFCRELCONTAINEDINSPATIALSTRUCTURE({S.gid()},$,$,$,({','.join(items)}),{sto})") + +text = ( + "ISO-10303-21;\nHEADER;\n" + "FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');\n" + "FILE_NAME('house.ifc','2000-01-01T00:00:00',('exav'),('exav'),'exav make-ifc.py','exav make-ifc.py','');\n" + "FILE_SCHEMA(('IFC4'));\nENDSEC;\nDATA;\n" + "\n".join(S.lines) + "\nENDSEC;\nEND-ISO-10303-21;\n" +) +with open(os.path.join(OUT, "house.ifc"), "w", newline="\n") as fh: + fh.write(text) diff --git a/crates/exav-viewer/demo/examples/generate/make-images.py b/crates/exav-viewer/demo/examples/generate/make-images.py new file mode 100644 index 0000000..90e94cf --- /dev/null +++ b/crates/exav-viewer/demo/examples/generate/make-images.py @@ -0,0 +1,593 @@ +#!/usr/bin/env python3 +"""Writes the demo's raster image examples into ../files/images/. + + python3 -I make-images.py [OUT_DIR] + +Output: CC0-1.0, a public domain dedication by the exav project. Every +picture is drawn here from scratch with numpy and Pillow (text in Pillow's +bundled Aileron font, CC0): no outside image is used. + +Needs: Python 3, Pillow 10 or later (with libtiff, WebP and OpenJPEG), +numpy; the programs opj_compress (libopenjp2-tools), jbig2 (jbig2enc), +cjxl (libjxl-tools) and tiffcp (libtiff-tools) for the JPEG 2000, JBIG2, +JPEG XL and fax files. Without a program, the files it makes are skipped. + +The encoders for QOI, farbfeld, Radiance HDR, DDS (BC1 and BC3), BMP with +RLE8 and the legacy ICO are written here, so that no encoder under another +licence is involved. +""" +import io +import math +import os +import shutil +import struct +import subprocess +import sys +import tempfile + +import numpy as np +from PIL import Image, ImageDraw, ImageFont + +HERE = os.path.dirname(os.path.abspath(__file__)) +OUT = os.path.abspath(sys.argv[1]) if len(sys.argv) > 1 else os.path.join(HERE, "..", "files", "images") +WORK = tempfile.mkdtemp() +os.makedirs(OUT, exist_ok=True) + + +def font(size): + return ImageFont.load_default(size) + + +def out(name): + return os.path.join(OUT, name) + + +def tool(name): + return shutil.which(name) is not None + + +# ---------------------------------------------------------------- the picture + + +def ridge(w, seed, base, amp): + """A mountain line: heights in 0..1 from the top, one per column.""" + rng = np.random.default_rng(seed) + x = np.linspace(0, 1, w) + y = np.zeros(w) + for k in range(1, 9): + y += (amp / k**1.15) * np.sin(2 * math.pi * (k * 0.9 + rng.random()) * x + rng.random() * 6.28) + return base + y + + +def scene(w=512, h=384): + """A dusk landscape: sky, stars, sun, three ridges, a lake, pines, a caption. + Returns the 8-bit RGB image and the sun's glow (0..1 per pixel).""" + yy = np.linspace(0, 1, h)[:, None] * np.ones((1, w)) + xx = np.linspace(0, 1, w)[None, :] * np.ones((h, 1)) + horizon = 0.62 + t = np.clip(yy / horizon, 0, 1) + top, mid, low = np.array([24, 30, 92.0]), np.array([196, 84, 110.0]), np.array([255, 190, 110.0]) + sky = np.where((t < 0.6)[..., None], top + (mid - top) * (t / 0.6)[..., None], mid + (low - mid) * ((t - 0.6) / 0.4)[..., None]) + sx, sy, sr = 0.68, 0.5, 0.045 + d = np.hypot((xx - sx) * w / h, yy - sy) + glow = np.clip(1 - d / 0.35, 0, 1) ** 2 + sky += glow[..., None] * np.array([120, 70, 20.0]) + sky = np.where((d < sr)[..., None], np.array([255, 250, 225.0]), sky) + rng = np.random.default_rng(3) + for _ in range(90): + px, py = rng.integers(0, w), rng.integers(0, int(h * 0.3)) + sky[py, px] = np.minimum(255, sky[py, px] + rng.integers(90, 200)) + img = sky.copy() + haze = np.array([230, 150, 130.0]) + for i, (base, amp, col) in enumerate([(0.50, 0.05, (120, 80, 120)), (0.56, 0.05, (80, 55, 95)), (0.61, 0.035, (40, 32, 70))]): + line = ridge(w, 10 + i, base, amp) + mask = yy > line[None, :] + shade = np.array(col, float) * (0.9 - 0.15 * i) + haze * (0.3 - 0.1 * i) + img = np.where(mask[..., None] & (yy <= 0.7)[..., None], shade, img) + # The lake: the sky and ridges mirrored about the horizon, with ripples. + lake_top = int(h * 0.66) + for row in range(lake_top, h): + k = row - lake_top + src = max(0, lake_top - 1 - int(k * 0.9)) + shift = int(3 * math.sin(k * 0.8)) + line = np.roll(img[src], shift, axis=0) + img[row] = line * 0.7 + np.array([10, 30, 60.0]) * 0.3 + img = np.clip(img, 0, 255).astype(np.uint8) + im = Image.fromarray(img, "RGB") + dr = ImageDraw.Draw(im) + for cx, base_y, size in [(0.1, 0.75, 70), (0.18, 0.72, 50), (0.3, 0.74, 90), (0.9, 0.73, 80), (0.8, 0.71, 55)]: + bx, by = int(cx * w), int(base_y * h) + for tier in range(5): + half = int(size * (0.18 + 0.1 * (4 - tier) * 0.8)) + top_y = by - size + tier * int(size * 0.18) + dr.polygon([(bx, top_y), (bx - half, top_y + int(size * 0.3)), (bx + half, top_y + int(size * 0.3))], fill=(14, 22, 36)) + dr.rectangle((bx - 3, by - 6, bx + 3, by + 8), fill=(10, 14, 22)) + dr.text((16, h - 34), "exav example picture", font=font(20), fill=(250, 235, 210)) + return im, glow + + +def bounce_frames(n=24, w=192, h=144): + frames = [] + for i in range(n): + im = Image.new("RGB", (w, h)) + px = np.zeros((h, w, 3), np.uint8) + gy = np.linspace(0, 1, h)[:, None] + # Every pixel changes a little in every frame (the tint below), so + # that encoders keep full frames: cjxl reads no cropped ones. + pulse = 14 * math.sin(2 * math.pi * i / n) + px[..., 0] = 20 + 40 * gy + px[..., 1] = 40 + 60 * gy + px[..., 2] = 90 + 120 * gy + im = Image.fromarray(px, "RGB") + d = ImageDraw.Draw(im) + d.rectangle((0, h - 24, w, h), fill=(46, 120, 66)) + phase = i / n + x = 20 + phase * (w - 40) + y = h - 24 - 14 - abs(math.sin(math.pi * phase * 2)) * 80 + rx, ry = 14 * (1 + (0.3 if y > h - 42 else 0)), 14 * (1 - (0.3 if y > h - 42 else 0)) + d.ellipse((x - 12, h - 26, x + 12, h - 20), fill=(30, 80, 45)) + d.ellipse((x - rx, y - ry, x + rx, y + ry), fill=(240, 200, 40), outline=(160, 110, 10)) + d.text((6, 6), f"{i + 1}/{n}", font=font(14), fill=(255, 255, 255)) + tint = np.array(im).astype(int) + tint[..., 0] += int(pulse) + tint[..., 2] -= int(pulse) + frames.append(Image.fromarray(np.clip(tint, 0, 255).astype(np.uint8), "RGB")) + return frames + + +def png_path(im, name): + p = os.path.join(WORK, name) + im.save(p) + return p + + +# --------------------------------------------------------------- fax page + + +def fax_page(w=1728, h=2200, number=1): + """A fax cover sheet and a letter, black on white, at fax size.""" + im = Image.new("L", (w, h), 255) + d = ImageDraw.Draw(im) + d.rectangle((60, 60, w - 60, 200), outline=0, width=6) + d.text((100, 85), "FACSIMILE TRANSMISSION", font=font(72), fill=0) + rows = [("To:", "Records office, harbour authority"), ("From:", "exav example generator"), + ("Date:", "1 January 2000 (a fixed date)"), ("Pages:", "3 including this one"), ("Re:", "Mooring register, east quay")] + y = 260 + for k, v in rows: + d.text((100, y), k, font=font(44), fill=0) + d.text((330, y), v, font=font(44), fill=0) + d.line((330, y + 56, w - 100, y + 56), fill=0, width=2) + y += 96 + d.line((60, y + 20, w - 60, y + 20), fill=0, width=8) + body = [ + "Dear colleagues,", "", + "The register of moorings on the east quay is attached. Each berth has a", + "number, a length in metres and the name of the vessel that holds it. Please", + "check the entries against your own list and send back a corrected copy", + "before the end of the month.", "", + "Berths 1 to 12 are for visiting boats and are not let by the season.", + "Berths 13 to 40 are let by the season; the fee is the same for every length.", "", + "This page and the next are sent in the fine mode (204 by 196 dots to the", + "inch). If anything is unreadable, ask for the page to be sent again.", "", + "With thanks,", + ] + y += 70 + for line in body: + d.text((100, y), line, font=font(40), fill=0) + y += 62 + # A table of berths. + y += 40 + rows = 5 + cols = [100, 330, 700, 1100, w - 100] + for r in range(rows + 1): + top = y + r * 70 + d.line((cols[0], top, cols[-1], top), fill=0, width=3 if r else 6) + if r < rows: + vals = ["Berth", "Length (m)", "Vessel", "Let by"] if r == 0 else [str(12 + number * r), f"{6 + (r * 7 + number) % 9}.{(r * 3) % 10}", ["Aurora", "Brise", "Calypso", "Dorade", "Etoile", "Fauvette", "Goeland"][(r + number) % 7], ["season", "week", "year"][r % 3]] + for c, v in enumerate(vals): + d.text((cols[c] + 12, top + 10), v, font=font(40), fill=0) + for c in cols: + d.line((c, y, c, y + rows * 70), fill=0, width=3) + # A signature scribble, a stamp, and the page number. + base = y + rows * 70 + pts = [(120 + i * 6, base + 110 + int(40 * math.sin(i * 0.5) * math.cos(i * 0.13))) for i in range(70)] + d.line(pts, fill=0, width=5) + d.ellipse((1150, base + 40, 1450, base + 240), outline=0, width=8) + d.text((1190, base + 115), "RECEIVED", font=font(36), fill=0) + d.text((100, h - 100), f"Page {number} of 3", font=font(40), fill=0) + return im + + +# ------------------------------------------------------------------ encoders + + +def qoi_encode(arr): + """QOI (qoiformat.org/qoi-specification.pdf) from an HxWx3 or HxWx4 uint8 array.""" + h, w, ch = arr.shape + out_ = bytearray(b"qoif" + struct.pack(">IIBB", w, h, ch, 0)) + index = [(0, 0, 0, 0)] * 64 + prev = (0, 0, 0, 255) + run = 0 + flat = arr.reshape(-1, ch) + for i, px in enumerate(flat): + px = (int(px[0]), int(px[1]), int(px[2]), int(px[3]) if ch == 4 else 255) + if px == prev: + run += 1 + if run == 62 or i == len(flat) - 1: + out_.append(0xC0 | (run - 1)) + run = 0 + continue + if run: + out_.append(0xC0 | (run - 1)) + run = 0 + h_ = (px[0] * 3 + px[1] * 5 + px[2] * 7 + px[3] * 11) % 64 + if index[h_] == px: + out_.append(h_) + else: + index[h_] = px + if px[3] == prev[3]: + dr, dg, db = (px[0] - prev[0] + 256) % 256, (px[1] - prev[1] + 256) % 256, (px[2] - prev[2] + 256) % 256 + sr, sg, sb = dr - 256 if dr > 127 else dr, dg - 256 if dg > 127 else dg, db - 256 if db > 127 else db + if -2 <= sr <= 1 and -2 <= sg <= 1 and -2 <= sb <= 1: + out_.append(0x40 | (sr + 2) << 4 | (sg + 2) << 2 | (sb + 2)) + else: + drg, dbg = sr - sg, sb - sg + if -32 <= sg <= 31 and -8 <= drg <= 7 and -8 <= dbg <= 7: + out_.append(0x80 | (sg + 32)) + out_.append((drg + 8) << 4 | (dbg + 8)) + else: + out_ += bytes([0xFE, px[0], px[1], px[2]]) + else: + out_ += bytes([0xFF, px[0], px[1], px[2], px[3]]) + prev = px + out_ += b"\x00\x00\x00\x00\x00\x00\x00\x01" + return bytes(out_) + + +def farbfeld(rgba8): + h, w, _ = rgba8.shape + wide = rgba8.astype(np.uint16) * 257 + return b"farbfeld" + struct.pack(">II", w, h) + wide.astype(">u2").tobytes() + + +def rgbe(linear): + """Radiance RGBE bytes from an HxWx3 float array.""" + m = linear.max(axis=2) + mant, ex = np.frexp(m) + scale = np.where(m > 1e-32, mant * 256.0 / np.maximum(m, 1e-32), 0) + px = np.zeros(linear.shape[:2] + (4,), np.uint8) + px[..., :3] = np.clip(linear * scale[..., None], 0, 255).astype(np.uint8) + px[..., 3] = np.where(m > 1e-32, ex + 128, 0).astype(np.uint8) + return px + + +def hdr_file(px, rle): + h, w, _ = px.shape + data = bytearray(b"#?RADIANCE\n# written by exav's make-images.py\nFORMAT=32-bit_rle_rgbe\nEXPOSURE=1.0\n\n") + data += f"-Y {h} +X {w}\n".encode() + for row in px: + if not rle: + data += row.tobytes() + continue + data += bytes([2, 2, w >> 8, w & 255]) + for c in range(4): + ch = row[:, c].tolist() + i = 0 + while i < w: + j = i + while j < w and ch[j] == ch[i] and j - i < 127: + j += 1 + if j - i >= 4: + data += bytes([128 + j - i, ch[i]]) + i = j + else: + k = i + while k < w and k - i < 128 and not (k + 3 < w and ch[k] == ch[k + 1] == ch[k + 2] == ch[k + 3]): + k += 1 + k = max(k, i + 1) + data += bytes([k - i]) + bytes(ch[i:k]) + i = k + return bytes(data) + + +def bc_blocks(arr, fmt): + """Greatly simplified BC1 / BC3 encoder: endpoints are the block's + darkest and brightest colours; indices are the nearest of four.""" + h, w, _ = arr.shape + out_ = bytearray() + + def to565(c): + return ((int(c[0]) >> 3) << 11) | ((int(c[1]) >> 2) << 5) | (int(c[2]) >> 3) + + def from565(v): + return np.array([((v >> 11) & 31) * 255 // 31, ((v >> 5) & 63) * 255 // 63, (v & 31) * 255 // 31], float) + + for by in range(0, h, 4): + for bx in range(0, w, 4): + blk = arr[by:by + 4, bx:bx + 4].reshape(-1, arr.shape[2]) + rgb = blk[:, :3].astype(float) + lum = rgb @ np.array([0.3, 0.59, 0.11]) + c0, c1 = rgb[lum.argmax()], rgb[lum.argmin()] + e0, e1 = to565(c0), to565(c1) + if e0 < e1: + e0, e1 = e1, e0 + if fmt == "bc3": + a = blk[:, 3].astype(int) + a0, a1 = int(a.max()), int(a.min()) + if a0 == a1: + a_idx = [0] * 16 + else: + pal = [a0, a1] + [((6 - i) * a0 + i * a1) // 7 for i in range(1, 7)] + a_idx = [int(np.argmin([abs(v - p) for p in pal])) for v in a] + bits = 0 + for i, v in enumerate(a_idx): + bits |= v << (3 * i) + out_ += bytes([a0, a1]) + bits.to_bytes(6, "little") + if e0 == e1: + idx = [0] * 16 + else: + p0, p1 = from565(e0), from565(e1) + pal = [p0, p1, (2 * p0 + p1) / 3, (p0 + 2 * p1) / 3] + idx = [int(np.argmin([np.sum((px - p) ** 2) for p in pal])) for px in rgb] + bits = 0 + for i, v in enumerate(idx): + bits |= v << (2 * i) + out_ += struct.pack("= 2: + enc += bytes([n, row[i]]) + i = j + else: + k = i + 1 + while k < w and k - i < 255 and (k + 1 >= w or row[k] != row[k + 1]): + k += 1 + n = k - i + if n >= 3: + enc += bytes([0, n]) + bytes(row[i:k]) + (b"\0" if n % 2 else b"") + else: + for v in row[i:k]: + enc += bytes([1, v]) + i = k + enc += b"\x00\x00" + rows.append(bytes(enc)) + data = b"".join(rows)[:-2] + b"\x00\x01" + palette = b"".join(bytes([pal[i * 3 + 2], pal[i * 3 + 1], pal[i * 3], 0]) for i in range(64)) + off = 14 + 40 + len(palette) + info = struct.pack("> (x % 8) + mask_rows += bits_row + if bits == 32: + pix = a[::-1][..., [2, 1, 0, 3]].tobytes() + pal = b"" + else: + p = im.convert("RGB").convert("P", palette=Image.ADAPTIVE, colors=256) + pp = p.getpalette()[:768] + pal = b"".join(bytes([pp[i * 3 + 2], pp[i * 3 + 1], pp[i * 3], 0]) for i in range(256)) + pix = b"".join(bytes(np.array(p)[y].tolist()) for y in range(size - 1, -1, -1)) + head = struct.pack("u2") +with open(out("scene-grey16.pgm"), "wb") as f: + f.write(b"P5\n128 96\n65535\n" + g16.tobytes()) +bw = np.array(small.convert("1")) > 0 +rows = [] +for row in bw: + rows.append(np.packbits(~row).tobytes()) +with open(out("scene.pbm"), "wb") as f: + f.write(b"P4\n256 192\n" + b"".join(rows)) +al = np.array(img.resize((128, 96), Image.LANCZOS).convert("RGBA")) +al[..., 3] = np.clip(255 - np.hypot(np.arange(128)[None, :] - 64, np.arange(96)[:, None] - 48) * 3.6, 0, 255) +with open(out("scene-alpha.pam"), "wb") as f: + f.write(b"P7\nWIDTH 128\nHEIGHT 96\nDEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n" + al.tobytes()) + +# QOI, farbfeld, HDR, DDS +with open(out("scene.qoi"), "wb") as f: + f.write(qoi_encode(np.array(img))) +with open(out("scene-alpha.qoi"), "wb") as f: + f.write(qoi_encode(np.array(Image.fromarray(a, "RGBA").resize((192, 144), Image.LANCZOS)))) +with open(out("scene.ff"), "wb") as f: + f.write(farbfeld(np.array(Image.fromarray(a, "RGBA").resize((96, 72), Image.LANCZOS)))) +srgb = np.array(img, float) / 255 +lin = np.where(srgb <= 0.04045, srgb / 12.92, ((srgb + 0.055) / 1.055) ** 2.4) +lin = lin * (1 + 60 * glow[..., None] ** 2) +with open(out("sunset.hdr"), "wb") as f: + f.write(hdr_file(rgbe(lin[::2, ::2]), True)) +with open(out("sunset-flat.hdr"), "wb") as f: + f.write(hdr_file(rgbe(lin[::4, ::4]), False)) +with open(out("scene-bc1.dds"), "wb") as f: + f.write(dds_file(img.resize((256, 192), Image.LANCZOS), "bc1")) +with open(out("scene-bc3.dds"), "wb") as f: + f.write(dds_file(Image.fromarray(a, "RGBA").resize((256, 192), Image.LANCZOS), "bc3")) + +# JPEG 2000 +if tool("opj_compress"): + src = png_path(img, "scene.png") + srca = png_path(Image.fromarray(a, "RGBA"), "scene-alpha.png") + srcg = png_path(img.convert("L"), "scene-grey.png") + run("opj_compress", "-i", src, "-o", out("scene.jp2"), "-r", "16,8,4", "-n", "5", "-p", "RPCL", "-t", "256,256", "-SOP", "-EPH") + run("opj_compress", "-i", src, "-o", out("scene.j2k"), "-r", "12", "-n", "4") + run("opj_compress", "-i", srcg, "-o", out("scene-grey.jp2"), "-r", "10") + run("opj_compress", "-i", srca, "-o", out("scene-alpha.jp2"), "-r", "10") + +# JBIG2 +page = fax_page(1728, 2200, 1).resize((1240, 1579), Image.LANCZOS).point(lambda v: 255 if v > 140 else 0).convert("1") +if tool("jbig2"): + pb = os.path.join(WORK, "page.png") + page.save(pb) + for name, args in [("page-generic.jb2", []), ("page-symbol.jb2", ["-s"])]: + with open(out(name), "wb") as f: + subprocess.run(["jbig2", *args, pb], stdout=f, check=True, stderr=subprocess.DEVNULL) + +# Fax TIFF (CCITT): Pillow writes the uncompressed bilevel page, tiffcp codes it. +if tool("tiffcp"): + pages = [] + for n in (1, 2, 3): + p = os.path.join(WORK, f"fax{n}.tif") + fax_page(1728, 2200, n).convert("1").save(p, dpi=(204, 196)) + pages.append(p) + # Group 3 is written to show what the viewer says about it: its TIFF decoder reads Group 4 only. + for name, mode in [("fax-g4.tif", "g4"), ("fax-g3-1d.tif", "g3:1d")]: + run("tiffcp", "-c", mode, "-r", "2200", pages[0], out(name)) + run("tiffcp", "-c", "g4", "-r", "2200", *pages, out("fax-g4-3pages.tif")) + +# JPEG XL +if tool("cjxl"): + src = png_path(img, "jxl-scene.png") + srca = png_path(Image.fromarray(a, "RGBA"), "jxl-scene-alpha.png") + gif = os.path.join(WORK, "bounce.gif") + frames[0].save(gif, save_all=True, append_images=frames[1:], duration=60, loop=0) + run("cjxl", src, out("scene-lossy.jxl"), "-d", "1.0", "-e", "7") + run("cjxl", src, out("scene-lossless.jxl"), "-d", "0", "-e", "7") + run("cjxl", srca, out("scene-alpha.jxl"), "-d", "0", "-e", "7") + run("cjxl", gif, out("bounce.jxl"), "-d", "1.0", "-e", "6") + +shutil.rmtree(WORK) diff --git a/crates/exav-viewer/demo/examples/generate/make-manifest.mjs b/crates/exav-viewer/demo/examples/generate/make-manifest.mjs new file mode 100644 index 0000000..c628d12 --- /dev/null +++ b/crates/exav-viewer/demo/examples/generate/make-manifest.mjs @@ -0,0 +1,82 @@ +#!/usr/bin/env node +// Writes ../examples.json from catalog.json and the files in ../files/. +// +// node generate/make-manifest.mjs +// +// catalog.json lists what each example is (title, features, author, licence, +// where it came from); this script adds what the bytes say (size, SHA-256) and +// fills the facts that every generated file shares. A file that is fetched and +// not committed keeps the size and hash the catalog gives. +import crypto from "node:crypto"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const here = path.dirname(fileURLToPath(import.meta.url)); +const root = path.join(here, ".."); +const REPO = "https://github.com/sylvinus/exav/blob/main/crates/exav-viewer/demo/examples"; + +const catalog = JSON.parse(fs.readFileSync(path.join(here, "catalog.json"), "utf8")); +const examples = []; +const seen = new Set(); + +for (const block of catalog.blocks) { + for (const f of block.files) { + const e = { file: f.file, group: f.group ?? block.group, family: f.family ?? block.family, title: f.title }; + if (f.features) e.features = f.features; + const kind = f.source ?? block.source; + if (kind === "generated") { + const script = f.gen ?? block.gen; + const e0 = { script: `generate/${script}`, args: f.args ?? block.args ?? [] }; + const tools = f.tools ?? block.tools; + if (tools) e0.tools = tools; + Object.assign(e, { + path: `${f.dir ?? block.dir}/${f.file}`, + committed: true, + author: f.author ?? "exav project", + source: `${REPO}/generate/${script}`, + evidence: `${REPO}/generate/${script}`, + evidence_quote: "Output: CC0-1.0, a public domain dedication by the exav project.", + licence: "CC0-1.0", + attribution: "", + generated: e0, + }); + } else { + // A `ref` names facts that several files share (the author, the page that states the licence, ...). + const ref = f.ref ?? block.ref; + if (ref && !catalog.refs?.[ref]) throw new Error(`${f.file}: unknown ref ${ref}`); + const g = { ...(ref ? catalog.refs[ref] : {}), ...f }; + for (const k of ["author", "source", "evidence", "evidence_quote", "licence", "attribution"]) { + if (g[k] === undefined) throw new Error(`${f.file}: no ${k}`); + e[k] = g[k]; + } + for (const k of ["fetched", "fixture", "generated"]) if (g[k] !== undefined) e[k] = g[k]; + if (g.derived) e.derived = g.derived; + if (g.evidence_row) e.evidence_row = g.evidence_row; + if (f.path) { + e.path = f.path; + e.committed = true; + } else { + e.committed = false; + } + } + if (seen.has(e.file)) throw new Error(`${e.file}: listed twice`); + seen.add(e.file); + if (e.committed) { + const data = fs.readFileSync(path.join(root, "files", e.path)); + e.bytes = data.length; + e.sha256 = crypto.createHash("sha256").update(data).digest("hex"); + } else { + if (!f.bytes || !f.sha256) throw new Error(`${f.file}: a fetched file needs bytes and sha256 in the catalog`); + e.bytes = f.bytes; + e.sha256 = f.sha256; + } + examples.push(e); + } +} + +const out = { version: 1, examples }; +fs.writeFileSync(path.join(root, "examples.json"), `${JSON.stringify(out, null, 2)}\n`); +const committed = examples.filter((e) => e.committed); +const total = (list) => list.reduce((n, e) => n + e.bytes, 0); +console.log(`${examples.length} examples: ${committed.length} committed (${total(committed)} bytes), ${examples.length - committed.length} fetched (${total(examples.filter((e) => !e.committed))} bytes)`); diff --git a/crates/exav-viewer/demo/examples/generate/make-media.py b/crates/exav-viewer/demo/examples/generate/make-media.py new file mode 100644 index 0000000..9699daf --- /dev/null +++ b/crates/exav-viewer/demo/examples/generate/make-media.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +"""Writes the demo's audio and video examples into ../files/media/. + + python3 -I make-media.py [OUT_DIR] + +Output: CC0-1.0, a public domain dedication by the exav project. The tune is +composed and synthesised here (a four-voice canon on a pentatonic scale, sine +waves with a few harmonics and an envelope); the picture is ffmpeg's own +"testsrc2" pattern with a clock. + +Needs: Python 3, numpy, and ffmpeg (with libx264, libvpx-vp9, libopus, +libvorbis, libmp3lame and the native aac and flac encoders). The files that +use a missing encoder are skipped. +""" +import math +import os +import shutil +import struct +import subprocess +import sys +import tempfile +import wave + +import numpy as np + +HERE = os.path.dirname(os.path.abspath(__file__)) +OUT = os.path.abspath(sys.argv[1]) if len(sys.argv) > 1 else os.path.join(HERE, "..", "files", "media") +os.makedirs(OUT, exist_ok=True) +RATE = 8000 +SCALE = [0, 2, 4, 7, 9] # a major pentatonic scale +MELODY = [0, 2, 4, 2, 3, 4, 6, 4, 2, 0, 1, 2, 4, 3, 2, 1] # degrees; the scale repeats over octaves + + +def freq(degree, base=261.63): + octave, step = divmod(degree, len(SCALE)) + return base * 2 ** ((SCALE[step] + 12 * octave) / 12) + + +def voice(delay_beats, octave, beat=0.3, seconds=8.4): + t = np.arange(int(RATE * seconds)) / RATE + out = np.zeros_like(t) + for i, degree in enumerate(MELODY): + start = (delay_beats + i) * beat + if start >= seconds: + break + f = freq(degree + octave * len(SCALE)) + n = np.clip(t - start, 0, None) + env = (t >= start) * np.exp(-n * 5.0) * np.minimum(n / 0.01, 1.0) + out += env * (np.sin(2 * math.pi * f * t) + 0.35 * np.sin(4 * math.pi * f * t) + 0.12 * np.sin(6 * math.pi * f * t)) + return out + + +def tune(): + mix = voice(0, 0) + voice(4, 1) * 0.8 + voice(8, 0) * 0.7 + voice(12, -1) * 0.9 + mix /= np.abs(mix).max() * 1.1 + fade = np.minimum(1.0, (len(mix) - np.arange(len(mix))) / (RATE * 0.5)) + return (mix * fade * 32000).astype(" 1 else os.path.join(HERE, "..", "files", "models") +os.makedirs(OUT, exist_ok=True) + + +def out(name): + return os.path.join(OUT, name) + + +def normal(a, b, c): + n = np.cross(b - a, c - a) + length = np.linalg.norm(n) + return n / length if length else n + + +# ---------------------------------------------------------------- the gear + + +def gear_facets(teeth=18, r_root=14.0, r_tip=17.0, r_bore=5.0, thick=8.0, hub_r=8.0): + """Facets (a, b, c, colour) of a spur gear: z from 0 to thick.""" + outline = [] + step = 2 * math.pi / teeth + for i in range(teeth): + a0 = i * step + for da, r in [(0.0, r_root), (0.18 * step, r_tip), (0.5 * step, r_tip), (0.68 * step, r_root)]: + outline.append((a0 + da, r)) + n = len(outline) + bore = [(outline[i][0], r_bore) for i in range(n)] + hub = [(outline[i][0], hub_r) for i in range(n)] + + def p(ang_r, z): + return np.array([ang_r[1] * math.cos(ang_r[0]), ang_r[1] * math.sin(ang_r[0]), z]) + + ORANGE, BLUE, GREY = (255, 140, 30), (40, 100, 220), (170, 170, 175) + facets = [] + + def quad(a, b, c, d, colour): + facets.append((a, b, c, colour)) + facets.append((a, c, d, colour)) + + for i in range(n): + j = (i + 1) % n + # Top and bottom: the ring between the bore and the outline, the hub ring in blue. + for z, flip in ((thick, False), (0.0, True)): + ring = [(bore[i], bore[j], hub[j], hub[i], BLUE), (hub[i], hub[j], outline[j], outline[i], ORANGE if z else GREY)] + for a, b, c, d, col in ring: + pts = [p(a, z), p(b, z), p(c, z), p(d, z)] + if flip: + pts = pts[::-1] + quad(*pts, col) + # The tooth walls and the bore wall. + quad(p(outline[i], 0), p(outline[j], 0), p(outline[j], thick), p(outline[i], thick), ORANGE) + quad(p(bore[j], 0), p(bore[i], 0), p(bore[i], thick), p(bore[j], thick), GREY) + return facets + + +def stl_binary(path, facets, header): + out_ = bytearray(header.ljust(80, b" ")[:80]) + out_ += struct.pack("> 3) << 10) | ((colour[1] >> 3) << 5) | (colour[2] >> 3) if colour else 0 + out_ += struct.pack("<12fH", *nrm, *a, *b, *c, attr) + with open(path, "wb") as f: + f.write(out_) + + +def box_facets(lo, hi): + x0, y0, z0 = lo + x1, y1, z1 = hi + v = [np.array(c, float) for c in [(x0, y0, z0), (x1, y0, z0), (x1, y1, z0), (x0, y1, z0), (x0, y0, z1), (x1, y0, z1), (x1, y1, z1), (x0, y1, z1)]] + quads = [(0, 3, 2, 1), (4, 5, 6, 7), (0, 1, 5, 4), (1, 2, 6, 5), (2, 3, 7, 6), (3, 0, 4, 7)] + tris = [] + for a, b, c, d in quads: + tris.append((v[a], v[b], v[c])) + tris.append((v[a], v[c], v[d])) + return tris + + +def stl_ascii(path, tris, name): + lines = [f"solid {name}"] + for a, b, c in tris: + n = normal(a, b, c) + lines.append(f" facet normal {n[0]:.6e} {n[1]:.6e} {n[2]:.6e}") + lines.append(" outer loop") + for v in (a, b, c): + lines.append(f" vertex {v[0]:.6e} {v[1]:.6e} {v[2]:.6e}") + lines.append(" endloop") + lines.append(" endfacet") + lines.append(f"endsolid {name}") + with open(path, "w") as f: + f.write("\n".join(lines) + "\n") + + +stl_binary(out("gear.stl"), gear_facets(), b"exav example gear, colours as VisCAM attributes") +stl_ascii(out("bracket-ascii.stl"), box_facets((0, 0, 0), (40, 25, 4)) + box_facets((0, 0, 4), (4, 25, 30)) + box_facets((4, 0, 4), (6, 25, 12)), "bracket") + +# ------------------------------------------------------------------- the knot + + +def hsv(h): + h6 = (h % 1.0) * 6 + i = int(h6) + f = h6 - i + q, t = 1 - f, f + r, g, b = [(1, t, 0), (q, 1, 0), (0, 1, t), (0, q, 1), (t, 0, 1), (1, 0, q)][i % 6] + return int(r * 255), int(g * 255), int(b * 255) + + +def knot_obj(path, segs=90, ring=10): + def centre(t): + return np.array([(2 + math.cos(3 * t)) * math.cos(2 * t), (2 + math.cos(3 * t)) * math.sin(2 * t), math.sin(3 * t)]) + + verts, colours, normals, faces = [], [], [], [] + for i in range(segs): + t = 2 * math.pi * i / segs + c = centre(t) + tan = centre(t + 1e-3) - c + tan /= np.linalg.norm(tan) + up = np.array([0.0, 0.0, 1.0]) + nrm = np.cross(tan, up) + nrm /= np.linalg.norm(nrm) + bin_ = np.cross(tan, nrm) + for k in range(ring): + a = 2 * math.pi * k / ring + d = math.cos(a) * nrm + math.sin(a) * bin_ + verts.append(c + 0.32 * d) + normals.append(d) + colours.append(hsv(i / segs)) + for i in range(segs): + for k in range(ring): + a = i * ring + k + b = i * ring + (k + 1) % ring + c = ((i + 1) % segs) * ring + (k + 1) % ring + d = ((i + 1) % segs) * ring + k + faces.append((a, b, c, d)) + lines = ["# A trefoil knot with a colour per vertex, and a base: two objects.", "o knot"] + for v, col in zip(verts, colours): + lines.append(f"v {v[0]:.4f} {v[1]:.4f} {v[2]:.4f} {col[0] / 255:.3f} {col[1] / 255:.3f} {col[2] / 255:.3f}") + for n in normals: + lines.append(f"vn {n[0]:.4f} {n[1]:.4f} {n[2]:.4f}") + for f in faces: + lines.append("f " + " ".join(f"{i + 1}//{i + 1}" for i in f)) + base = len(verts) + lines.append("o base") + ring_n = 48 + for k in range(ring_n): + a = 2 * math.pi * k / ring_n + lines.append(f"v {4.2 * math.cos(a):.4f} {4.2 * math.sin(a):.4f} -1.6 0.35 0.35 0.4") + lines.append(f"v {4.2 * math.cos(a):.4f} {4.2 * math.sin(a):.4f} -1.2 0.6 0.6 0.65") + lines.append(f"v 0 0 -1.2 0.6 0.6 0.65") + centre_i = base + 2 * ring_n + 1 + for k in range(ring_n): + j = (k + 1) % ring_n + lo0, hi0, lo1, hi1 = base + 2 * k + 1, base + 2 * k + 2, base + 2 * j + 1, base + 2 * j + 2 + lines.append(f"f {lo0} {lo1} {hi1} {hi0}") + lines.append(f"f {hi0} {hi1} {centre_i}") + # Faces counted from the end, as OBJ allows: the base's bottom disc. + for k in range(ring_n): + j = (k + 1) % ring_n + lines.append(f"f {base + 2 * j + 1} {base + 2 * k + 1} {base + 2 * ring_n + 1}") + with open(path, "w") as f: + f.write("\n".join(lines) + "\n") + + +knot_obj(out("knot.obj")) + +# -------------------------------------------------------------------- terrain + + +def terrain_ply(path, n=48): + xs = np.linspace(-1, 1, n) + X, Y = np.meshgrid(xs, xs) + Z = 0.35 * np.exp(-((X - 0.3) ** 2 + (Y + 0.2) ** 2) * 6) + 0.25 * np.exp(-((X + 0.5) ** 2 + (Y - 0.4) ** 2) * 9) + 0.04 * np.sin(9 * X) * np.cos(7 * Y) - 0.1 + verts = np.stack([X * 50, Y * 50, Z * 50], axis=-1).reshape(-1, 3).astype(" 0 else [0, 2, 1, 0, 3, 2] + idx += [base + o for o in order] + return np.array(pos), np.array(nrm), np.array(idx) + + +def uv_sphere(r, rings=12, segs=20): + pos, nrm, idx = [], [], [] + for i in range(rings + 1): + phi = math.pi * i / rings + for j in range(segs + 1): + th = 2 * math.pi * j / segs + n = np.array([math.sin(phi) * math.cos(th), math.cos(phi), math.sin(phi) * math.sin(th)]) + pos.append(n * r) + nrm.append(n) + for i in range(rings): + for j in range(segs): + a = i * (segs + 1) + j + idx += [a, a + segs + 1, a + 1, a + 1, a + segs + 1, a + segs + 2] + return np.array(pos), np.array(nrm), np.array(idx) + + +def cylinder(r, h, segs=20): + pos, nrm, idx = [], [], [] + for j in range(segs + 1): + th = 2 * math.pi * j / segs + n = np.array([math.cos(th), 0, math.sin(th)]) + pos += [n * r + [0, 0, 0], n * r + [0, h, 0]] + nrm += [n, n] + for j in range(segs): + a = 2 * j + idx += [a, a + 2, a + 1, a + 1, a + 2, a + 3] + c0 = len(pos) + pos.append(np.array([0, h, 0.0])) + nrm.append(np.array([0, 1.0, 0])) + for j in range(segs + 1): + th = 2 * math.pi * j / segs + pos.append(np.array([math.cos(th) * r, h, math.sin(th) * r])) + nrm.append(np.array([0, 1.0, 0])) + for j in range(segs): + idx += [c0, c0 + 2 + j, c0 + 1 + j] + return np.array(pos), np.array(nrm), np.array(idx) + + +def quat(axis, deg): + a = np.array(axis, float) + a /= np.linalg.norm(a) + s = math.sin(math.radians(deg) / 2) + return [float(a[0] * s), float(a[1] * s), float(a[2] * s), math.cos(math.radians(deg) / 2)] + + +def arm_glb(path): + g = Gltf() + steel = g.material((0.7, 0.72, 0.78, 1), 0.9, 0.35, name="steel") + orange = g.material((0.95, 0.45, 0.1, 1), 0.2, 0.5, name="paint") + blue = g.material((0.1, 0.3, 0.8, 1), 0.1, 0.6, name="blue") + glass = g.material((0.4, 0.8, 1.0, 0.45), 0.0, 0.1, name="glass") + glow = g.material((0.1, 0.1, 0.1, 1), 0.0, 0.5, emissive=(1.0, 0.3, 0.1), name="lamp") + base_m = g.mesh(*cylinder(0.6, 0.25), steel, name="base") + link_m = g.mesh(*box_mesh(0.22, 1.0, 0.22), orange, name="link") + joint_m = g.mesh(*uv_sphere(0.17), blue, name="joint") + dome_m = g.mesh(*uv_sphere(0.9, 10, 16), glass, name="dome") + lamp_m = g.mesh(*uv_sphere(0.1, 8, 12), glow, name="lamp") + pos, nrm, idx = box_mesh(2.4, 0.05, 2.4) + colors = np.array([[0.9, 0.9, 0.9] if (int(p[0] * 2.5 + 100) + int(p[2] * 2.5 + 100)) % 2 else [0.3, 0.3, 0.35] for p in pos]) + floor_m = g.mesh(pos, nrm, idx, g.material((1, 1, 1, 1), 0.0, 0.9, name="floor"), colors=colors, name="floor") + # A tree: base > joint1 > link1 > joint2 > link2 > joint3 > link3 > lamp. + lamp = g.node(mesh=lamp_m, translation=[0, 0.55, 0], name="lamp") + link3 = g.node(mesh=link_m, scale=[0.7, 0.6, 0.7], translation=[0, 0.3, 0], name="link3", children=[lamp]) + joint3 = g.node(mesh=joint_m, translation=[0, 1.0, 0], rotation=quat([0, 0, 1], -50), name="joint3", children=[link3]) + link2 = g.node(mesh=link_m, translation=[0, 0.5, 0], name="link2", children=[joint3]) + joint2 = g.node(mesh=joint_m, translation=[0, 1.0, 0], rotation=quat([0, 0, 1], 65), name="joint2", children=[link2]) + link1 = g.node(mesh=link_m, translation=[0, 0.5, 0], name="link1", children=[joint2]) + joint1 = g.node(mesh=joint_m, translation=[0, 0.25, 0], rotation=quat([0, 1, 0], 40), name="joint1", children=[link1]) + base = g.node(mesh=base_m, name="base", children=[joint1]) + dome = g.node(mesh=dome_m, translation=[0, 0.0, 0], name="dome") + floor = g.node(mesh=floor_m, translation=[0, -0.03, 0], name="floor") + root = g.node(name="arm cell", children=[floor, base, dome], rotation=quat([0, 1, 0], -20)) + doc = g.document([root]) + js = json.dumps(doc, separators=(",", ":")).encode() + js += b" " * (-len(js) % 4) + binary = bytes(g.buf) + b"\0" * (-len(g.buf) % 4) + blob = struct.pack("<4sII", b"glTF", 2, 12 + 8 + len(js) + 8 + len(binary)) + struct.pack(" 1 else os.path.join(HERE, "..", "files") +for d in ("office", "converted", "pdf"): + os.makedirs(os.path.join(OUT, d), exist_ok=True) + +NS = ( + 'xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" ' + 'xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" ' + 'xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" ' + 'xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" ' + 'xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" ' + 'xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" ' + 'xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" ' + 'xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" ' + 'xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" ' + 'xmlns:ooo="http://openoffice.org/2004/office"' +) + + +def aileron(size): + return ImageFont.load_default(size) + + +def png_b64(im): + buf = io.BytesIO() + im.save(buf, "PNG", optimize=True) + return base64.b64encode(buf.getvalue()).decode() + + +def picture(w=640, h=360, seed=1, label="exav example picture"): + """A made-up picture: a lake at dusk, drawn with numpy and Pillow.""" + y = np.linspace(0, 1, h)[:, None] + x = np.linspace(0, 1, w)[None, :] + px = np.zeros((h, w, 3), float) + px[..., 0] = 30 + 200 * y ** 1.5 + px[..., 1] = 40 + 90 * y + px[..., 2] = 110 + 40 * y - 60 * y ** 2 + sun = np.hypot((x - 0.7) * w / h, y - 0.55) < 0.07 + px[sun] = (255, 245, 215) + im = Image.fromarray(np.clip(px, 0, 255).astype(np.uint8), "RGB") + d = ImageDraw.Draw(im) + rng = np.random.default_rng(seed) + pts = [(0, int(h * 0.64))] + [(i * w // 16, int(h * (0.5 + 0.1 * rng.random()))) for i in range(1, 16)] + [(w, int(h * 0.64)), (w, h), (0, h)] + d.polygon(pts, fill=(34, 40, 66)) + d.rectangle((0, int(h * 0.64), w, h), fill=(28, 56, 92)) + d.text((12, h - 30), label, font=aileron(18), fill=(245, 235, 215)) + return im + + +# ====================================================================== +# The handbook (text document) +# ====================================================================== + +LOREM = [ + "The east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell.", + "Every berth has a number, a length in metres and a holder. The register is kept on paper and in a table; the two are compared each spring, and the differences are explained in the notes of the harbour master.", + "Visitors are asked to call the harbour office on channel 9 before they come in, to give the length of their boat and its draught, and to say how many nights they plan to stay.", +] + + +def t(text): + return escape(text) + + +def span(style, text): + return f'{t(text)}' + + +def para(style, *content): + return f'{"".join(c if c.startswith("<") else t(c) for c in content)}' + + +def heading(level, text, bookmark=None): + b = f'' if bookmark else "" + return f'{b}{t(text)}' + + +def list_(style, items, level=1): + out = [f''] + for it in items: + if isinstance(it, list): + out.append("" + list_(style, it, level + 1) + "") + else: + out.append(f'{it if it.startswith("<") else t(it)}') + out.append("") + return "".join(out) + + +def table(name, style, widths, rows, header_rows=1): + cols = "".join(f'' for w in widths) + head, body = rows[:header_rows], rows[header_rows:] + out = [f'', cols] + if header_rows: + out.append("" + "".join(row for row in head) + "") + out.append("".join(body)) + out.append("") + return "".join(out) + + +def cell(text, style="Tc", pstyle="Table_20_Contents", span_=1, rowspan=1, value=None): + attrs = f' table:style-name="{style}" office:value-type="string"' + if span_ > 1: + attrs += f' table:number-columns-spanned="{span_}"' + if rowspan > 1: + attrs += f' table:number-rows-spanned="{rowspan}"' + if value is not None: + attrs = attrs.replace('office:value-type="string"', f'office:value-type="float" office:value="{value}"') + return f'{text if text.startswith("<") else t(text)}' + + +def covered(n=1): + return "" * n + + +def row(*cells): + return "" + "".join(cells) + "" + + +def handbook_fodt(): + pic = picture(640, 360) + pic2 = picture(480, 270, 4, "Second picture") + cites = " ".join([f"[{i}]" for i in range(1, 3)]) + headings = [("Introduction", 1, "intro"), ("Text and styles", 1, "text"), ("Lists", 1, "lists"), ("Tables", 1, "tables"), ("Pictures and shapes", 1, "pictures"), ("Links, fields and notes", 1, "links"), ("Wide table (landscape)", 1, "wide")] + toc_entries = "".join( + f'{i}. {t(h)}' + for i, (h, _, b) in enumerate(headings, 1) + ) + body = [] + # Title page. + body.append(para("Title", "Harbour handbook")) + body.append(para("Subtitle", "The east quay: rules, figures and notes")) + body.append(para("Author", "exav project, written for the demo (CC0-1.0)")) + body.append(para("Author", "1 January 2000")) + body.append( + '' + 'Contents' + f'Contents{toc_entries}' + ) + # 1 Introduction. + body.append(heading(1, "Introduction", "intro")) + body.append(para("Text_20_body", LOREM[0])) + body.append(para("Text_20_body", LOREM[1] + " ", f'1The register of 2000 lists sixty berths.')) + body.append(para("Quotations", "“A harbour is a promise that the sea will wait.â€� ")) + body.append(para("Text_20_body", LOREM[2])) + # 2 Text and styles. + body.append(heading(1, "Text and styles", "text")) + body.append(heading(2, "Character formatting")) + body.append( + para( + "Text_20_body", + span("Strong", "Bold"), ", ", span("Emphasis", "italic"), ", ", span("Underline", "underlined"), ", ", span("Strike", "struck through"), ", ", span("Red", "red"), ", ", span("Highlight", "highlighted"), + ", ", span("SmallCaps", "small capitals"), ", ", span("Big", "large"), " and ", span("Mono", "monospaced"), " text; H", span("Sub", "2"), "O and 10", span("Super", "3"), "; a ", span("Emphasis", "mixed"), " style.", + ) + ) + body.append(heading(2, "Paragraph formatting")) + body.append(para("Justified", LOREM[0] + " " + LOREM[1])) + body.append(para("Centered", "A centred line")) + body.append(para("Right", "A line aligned to the right")) + body.append(para("Indented", "An indented paragraph with a left border: " + LOREM[2])) + body.append(para("Code", "moor --boat Aurora --length 6.5")) + body.append(para("Code", "berth 14 free until 06:00")) + body.append(heading(2, "A section in two columns")) + body.append( + '' + + para("Text_20_body", LOREM[0] + " " + LOREM[1] + " " + LOREM[2] + " " + LOREM[0]) + + "" + ) + # 3 Lists. + body.append(heading(1, "Lists", "lists")) + body.append(list_("L1", ["Water at every berth", ["cold, from the quay", "hot, in the shower block"], "Electricity", ["16 A at berths 1 to 40", ["with a meter", "without a meter"], "32 A at the east pontoon"], "Wi-Fi on the quay"])) + body.append(para("Text_20_body", "Numbered, with other numbering styles at each level:")) + body.append(list_("L2", ["Call the office on channel 9", "Give the length and the draught", ["length over all, in metres", "draught, in metres"], "Take the berth you are given", ["tie up bow first", "tie up stern first"], "Pay at the office"])) + # 4 Tables. + body.append(heading(1, "Tables", "tables")) + body.append(para("Caption", "Table ", '1', ": berths by length, with merged cells and a repeated header row")) + rows = [row(cell("Length", "Th", "Table_20_Heading"), cell("Berths", "Th", "Table_20_Heading"), cell("Let by", "Th", "Table_20_Heading"), cell("Fee (EUR)", "Th", "Table_20_Heading"))] + for a, b, c, d in [("up to 6 m", 12, "week", 18.0), ("6 to 8 m", 18, "season", 24.5), ("8 to 10 m", 14, "season", 31.0), ("10 to 12 m", 9, "year", 42.0), ("over 12 m", 7, "year", 58.5)]: + rows.append(row(cell(a), cell(str(b), "TcR", "Table_20_Right", value=b), cell(c), cell(f"{d:.2f}", "TcR", "Table_20_Right", value=d))) + rows.append(row(cell("Total", "TcTotal", span_=1), cell("60", "TcTotalR", "Table_20_Right", value=60), cell("", "TcTotal", span_=2), covered())) + body.append(table("Table1", "Tbl1", ["TcolA", "TcolB", "TcolC", "TcolD"], rows)) + body.append(para("Text_20_body", "")) + rows = [ + row(cell("Merged across two columns", "Th", "Table_20_Heading", span_=2), covered(), cell("Merged down two rows", "Tc", rowspan=2), ), + row(cell("a"), cell("b"), covered()), + row(cell("c"), cell("d"), cell("e")), + ] + body.append(table("Table2", "Tbl1", ["TcolA", "TcolB", "TcolC"], rows, header_rows=0)) + # 5 Pictures and shapes. + body.append(heading(1, "Pictures and shapes", "pictures")) + body.append( + '' + f'{png_b64(pic)}A lake at duskA made-up picture of a lake and a hill at dusk.' + + t(LOREM[0] + " " + LOREM[1] + " " + LOREM[2] + " ") + + t(LOREM[0] + " ") + + "" + ) + body.append(para("Caption", "Figure ", '1', ": a picture that text flows around")) + body.append( + '' + f'{png_b64(pic2)}The second picture' + ) + body.append( + '' + 'A shape with text in it' + "A line of text beside a shape." + ) + # 6 Links, fields and notes. + body.append(heading(1, "Links, fields and notes", "links")) + body.append( + para( + "Text_20_body", + "An external link: ", 'exav.org', + ". An internal link: ", 'back to the introduction', + ". A reference to a bookmark: ", 'Tables', ".", + ) + ) + body.append( + para( + "Text_20_body", "Fields: this document is titled “", 'Harbour handbook', "â€�, and this line is on page ", + '1', ". A fixed date: ", '01/01/2000', ".", + ) + ) + body.append( + para( + "Text_20_body", "A comment is attached to this word", 'exav2000-01-01T00:00:00A comment: the viewer shows or ignores it.', + ". A change that was tracked: ", 'this text was inserted', ", ", '', "and some text was deleted before this one.", + ) + ) + body.append(para("Text_20_body", f"Citations {cites}. ", '2A second footnote, with emphasis.')) + # 7 A wide table in landscape. + body.append('Wide table (landscape)') + heads = ["Month"] + [f"Berth {i}" for i in range(1, 11)] + ["Total"] + rows = [row(*[cell(h, "Th", "Table_20_Heading") for h in heads])] + for m, name in enumerate(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]): + vals = [(m * 7 + i * 5) % 9 + 1 for i in range(10)] + rows.append(row(cell(name), *[cell(str(v), "TcR", "Table_20_Right", value=v) for v in vals], cell(str(sum(vals)), "TcTotalR", "Table_20_Right", value=sum(vals)))) + body.append(table("Table3", "TblWide", ["TcolW"] * 12, rows)) + body.append(para("Text_20_body", "Nights let at each berth, by month.")) + + return f""" + +exav projectHarbour handbookA document made for the exav demo (CC0-1.0)demoen-US2000-01-01T00:00:00 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// + + + + + + + + + + + + + + + + + + +Harbour handbookexav demoPage 1 of 1 +Harbour handbook (landscape section)Page 1 + + + +exav2000-01-01T00:00:00 +exav2000-01-01T00:00:00some deleted words + +{"".join(body)} + + +""" + + +# ====================================================================== +# The workbook (spreadsheet) +# ====================================================================== + + +def chart(kind, title, ranges, cats, series, width="15cm", height="8.5cm", legend=True): + """An embedded chart object. series: [(name cell, values range)]; ranges: the whole data range.""" + ser = "".join( + f'' + for i, (n, v) in enumerate(series) + ) + styles = "".join( + f'' + for i, c in enumerate(["#146c94", "#f6a01a", "#2c7a4b", "#c0392b"]) + ) + pie_styles = "" + if kind == "circle": + pie_styles = "".join(f'' for i, c in enumerate(["#146c94", "#f6a01a", "#2c7a4b", "#c0392b", "#8e44ad"])) + ser = ser.replace('', "".join(f'' for i in range(5))) + axes = ( + f'' + if kind != "circle" + else "" + ) + return f"""{styles}{pie_styles} +{t(title)}{'' if legend else ""} +{axes}{ser}""" + + +def workbook_fods(): + months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"] + cats = ["Berths let", "Visitors", "Shop", "Fuel", "Repairs"] + values = [[11200, 11800, 12100, 15400, 21800, 24900], [3100, 3300, 4800, 8200, 15600, 19200], [1200, 1100, 1500, 2600, 4100, 5200], [900, 800, 1100, 1900, 3300, 4400], [-2100, -900, -3300, -1500, -800, -1200]] + + def fcell(v, style=None): + return f'{v}' + + def scell(s, style=None, extra=""): + return f'{t(s)}' + + def fm(formula, style=None, value=None, vtype="float"): + key = "office:string-value" if vtype == "string" else "office:value" + v = f' office:value-type="{vtype}"' + (f' {key}="{value}"' if value is not None else "") + return f'{value if value is not None else ""}' + + # Sheet 1: Budget (rows 1 title, 2 note, 3 header, 4-8 data, 9 total, then a lookup block). + rows = [] + rows.append('' + scell("Harbour budget, first half", "title", ' table:number-columns-spanned="9" table:number-rows-spanned="1"') + "" * 8 + "") + rows.append("" + scell("Amounts in euros; the totals are formulas.", "note") + "" * 8 + "") + rows.append("" + scell("Category", "head") + "".join(scell(m, "head") for m in months) + scell("Total", "head") + scell("Share", "head") + "") + # Every formula carries the value it gives, as a spreadsheet saves it. + grand = sum(sum(v) for v in values) + nets = [sum(v[i] for v in values) for i in range(6)] + for i, (name, vals) in enumerate(zip(cats, values)): + r = 4 + i + total = sum(vals) + rows.append( + "" + scell(name, "label") + "".join(fcell(v, "eur") for v in vals) + + fm(f"of:=SUM([.B{r}:.G{r}])", "eurb", total) + fm(f"of:=[.H{r}]/[.H$9]", "pct", total / grand) + "" + ) + rows.append( + "" + scell("Net", "labelb") + "".join(fm(f"of:=SUM([.{c}4:.{c}8])", "eurtot", nets[i]) for i, c in enumerate("BCDEFG")) + fm("of:=SUM([.H4:.H8])", "eurtot", grand) + fm("of:=SUM([.I4:.I8])", "pcttot", 1) + "" + ) + rows.append("" + "" * 9 + "") + rows.append("" + scell("Averages and checks", "labelb") + "" * 8 + "") + rows.append("" + scell("Average a month", "label") + fm("of:=AVERAGE([.B9:.G9])", "eur", grand / 6) + scell("Best month", "label") + fm("of:=INDEX([.B3:.G3];MATCH(MAX([.B9:.G9]);[.B9:.G9];0))", None, months[nets.index(max(nets))], "string") + scell("Months in credit", "label") + fm("of:=COUNTIF([.B9:.G9];\">0\")", None, sum(1 for n in nets if n > 0)) + "" * 3 + "") + rows.append("" + scell("Largest item", "label") + fm("of:=MAX([.B4:.G8])", "eur", max(max(v) for v in values)) + scell("Rounded share of fuel", "label") + fm("of:=ROUND([.I7];3)", "pct", round(sum(values[3]) / grand, 3)) + scell("Status", "label") + fm('of:=IF([.H9]>0;"surplus";"deficit")', None, "surplus" if grand > 0 else "deficit", "string") + "" * 3 + "") + rows.append("" + scell("Lookup: category", "label") + scell("Shop", "input") + scell("its total", "label") + fm("of:=VLOOKUP([.B14];[.A4:.H8];8;0)", "eur", sum(values[2])) + "" * 5 + "") + rows.append("" + scell("Link", "label") + 'exav.org/viewer' + scell("Note on a cell", "label") + 'exavThis cell has a comment.hover me' + "" * 5 + "") + budget_cols = '' + budget = '' + budget_cols + "".join(rows) + "" + + # Sheet 2: Data, 120 rows, with an autofilter. + rng = np.random.default_rng(3) + regions, products = ["West", "East", "North", "South"], ["Mooring", "Fuel", "Water", "Power", "Shop"] + drows = ["" + "".join(scell(h, "head") for h in ["Date", "Region", "Product", "Units", "Unit price", "Amount"]) + ""] + units_sum, amount_sum = 0, 0.0 + for i in range(120): + day = 1 + i * 150 // 120 + month, dd = 1 + (day - 1) // 28, 1 + (day - 1) % 28 + units = int(rng.integers(1, 40)) + price = round(float(rng.uniform(2, 60)), 2) + units_sum += units + amount_sum += round(units * price, 2) + r = i + 2 + drows.append( + "" + f'{dd:02d}/{month:02d}/2000' + + scell(regions[i % 4]) + scell(products[(i * 3) % 5]) + fcell(units) + fcell(price, "eur2") + fm(f"of:=[.D{r}]*[.E{r}]", "eur2", round(units * price, 2)) + "" + ) + drows.append("" + scell("Total", "labelb") + "" * 2 + fm("of:=SUM([.D2:.D121])", "eurtot", units_sum) + "" + fm("of:=SUBTOTAL(9;[.F2:.F121])", "eurtot", round(amount_sum, 2)) + "") + data = ( + '' + + "".join(drows) + "" + ) + + # Sheet 3: Charts. + c1 = chart("bar", "Spending by category", "Budget.$A$3:.$G$7", "Budget.$A$4:.$A$7", [("Budget.$B$3", "Budget.$B$4:.$B$7"), ("Budget.$G$3", "Budget.$G$4:.$G$7")]) + c2 = chart("line", "Net income by month", "Budget.$A$3:.$G$3", "Budget.$B$3:.$G$3", [("Budget.$A$9", "Budget.$B$9:.$G$9")]) + c3 = chart("circle", "Share of the total", "Budget.$A$4:.$A$8", "Budget.$A$4:.$A$8", [("Budget.$I$3", "Budget.$I$4:.$I$8")]) + charts = ( + '' + f'{c1}' + f'{c2}' + f'{c3}' + '' + ) + + settings = """ +view1 + +02 +33 + +02 +11 +""" + + return f""" + +exav projectHarbour workbookA workbook made for the exav demo (CC0-1.0)2000-01-01T00:00:00 +{settings} + + + +€ +€ +% +// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Choose one of the five categories. +{budget.replace('Shop', 'Shop')} +{data} +{charts} + + + + +""" + + +# ====================================================================== +# The deck (presentation) +# ====================================================================== + + +def deck_fodp(): + pic = picture(800, 450, 2, "Slide picture") + c = chart("bar", "Berths let by month", "local-table.$A$1:.$C$7", "local-table.$A$2:.$A$7", [("local-table.$B$1", "local-table.$B$2:.$B$7"), ("local-table.$C$1", "local-table.$C$2:.$C$7")]) + months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"] + local = 'This yearLast year' + for i, m in enumerate(months): + local += f'{m}{20 + i * 6}{18 + i * 5}' + local += "" + c = c.replace("", local + "") + + def title(text, y="0.8cm"): + return f'{t(text)}' + + def bullets(items, y="3.8cm", w="24cm", h="10cm", x="2cm"): + def li(it, lv=1): + if isinstance(it, list): + return "" + "".join(li(i, lv + 1) for i in it) + "" + return f'{t(it)}' + + return f'' + "".join(li(i) for i in items) + "" + + def notes(text): + return f'{t(text)}' + + slides = [] + slides.append( + f'' + f'Harbour review' + f'The east quay, first half of the year' + f'exav' + f'{notes("Welcome. These notes are speaker notes: the viewer does not show them.")}' + ) + slides.append( + f'{title("Agenda")}' + + bullets(["Where we are", ["berths let", ["by length", "by season"], "visitors"], "What the figures say", "What we do next", ["order the new chain", "paint the numbers"]]) + + notes("Four items.") + "" + ) + slides.append( + f'{title("Berths let, month by month")}' + f'{c}' + 'Up 40% on last year' + '' + + notes("The chart is a native chart, with its data inside the slide.") + "" + ) + rows = "" + for r in [("Length", "Berths", "Fee"), ("up to 6 m", "12", "18.00"), ("6 to 8 m", "18", "24.50"), ("8 to 10 m", "14", "31.00"), ("over 10 m", "16", "48.00")]: + head = r[0] == "Length" + rows += "" + "".join(f'{t(v)}' for v in r) + "" + slides.append( + f'{title("Fees")}' + '' + f"{rows}" + + bullets(["Season fee includes water", "Power is metered", "Visitors pay by the night"], y="4cm", w="8cm", h="8cm", x="19cm") + "" + ) + slides.append( + f'{title("A picture and shapes")}' + f'{png_b64(pic)}A lake at dusk' + 'Start' + '' + 'Moor' + '' + 'Pay?' + 'Star' + + notes("Shapes with gradients, arrows and text.") + "" + ) + return f""" + +exav projectHarbour reviewA deck made for the exav demo (CC0-1.0)2000-01-01T00:00:00 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + + + +{"".join(slides)} + + + +""" + + +# ====================================================================== +# The diagram (drawing) +# ====================================================================== + + +def diagram_fodg(): + def node(i, x, y, w, h, text, style="st-box", shape="rect"): + tag = "draw:rect" if shape == "rect" else "draw:ellipse" + return f'<{tag} draw:id="n{i}" draw:style-name="{style}" draw:layer="Boxes" svg:width="{w}cm" svg:height="{h}cm" svg:x="{x}cm" svg:y="{y}cm" draw:corner-radius="0.2cm">{t(text)}' if shape == "rect" else f'<{tag} draw:id="n{i}" draw:style-name="{style}" draw:layer="Boxes" svg:width="{w}cm" svg:height="{h}cm" svg:x="{x}cm" svg:y="{y}cm">{t(text)}' + + def conn(a, b, sa=2, sb=0, kind="standard", style="st-line", label=None): + return f'' + + p1 = [ + node(1, 9, 1, 6, 1.6, "Boat calls the office", "st-start", "ell"), + node(2, 9, 4, 6, 1.6, "Is a berth free?", "st-decision"), + node(3, 2, 7.5, 6, 1.6, "Give berth number"), + node(4, 16, 7.5, 6, 1.6, "Offer the waiting list"), + node(5, 2, 11, 6, 1.6, "Boat moors"), + node(6, 9, 14.5, 6, 1.6, "Pay at the office", "st-end", "ell"), + node(7, 16, 11, 6, 1.6, "Boat waits at anchor"), + ] + links = [conn(1, 2), conn(2, 3, 3, 0, "standard"), conn(2, 4, 3, 0), conn(3, 5), conn(4, 7), conn(5, 6, 2, 1), conn(7, 2, 1, 3, "curve")] + labels = 'yes' + 'no' + legend = ( + '' + 'start or end' + 'step' + 'decision' + ) + curve = '' + page1 = f'{"".join(p1)}{"".join(links)}{labels}{legend}{curve}Flowchart for the exav demo (CC0-1.0). Connectors follow their shapes.' + # Page 2: a block diagram with groups and a hidden layer. + blocks = "" + for i, (x, label) in enumerate([(1.5, "Harbour office"), (9.5, "Berth register"), (17.5, "Billing")]): + blocks += f'{label}{i + 1}' + blocks += '' + stack = "".join(f'Layer {i + 1}' for i in range(4)) + hidden = 'On a hidden layer' + page2 = f'{blocks}{stack}{hidden}' + return f""" + +exav projectFlowchartA drawing made for the exav demo (CC0-1.0)2000-01-01T00:00:00 + + + + + + + + + + + + + + + + + + + + + + + +{page1}{page2} + +""" + + +# ====================================================================== +# Conversion +# ====================================================================== + +TARGETS = { + "handbook": [("fodt", "converted", None), ("odt", "converted", "odt:writer8"), ("docx", "office", 'docx:MS Word 2007 XML'), ("doc", "converted", "doc:MS Word 97"), ("rtf", "converted", "rtf:Rich Text Format")], + "workbook": [("fods", "converted", None), ("ods", "converted", "ods:calc8"), ("xlsx", "office", "xlsx:Calc MS Excel 2007 XML"), ("xls", "converted", "xls:MS Excel 97")], + "deck": [("fodp", "converted", None), ("odp", "converted", "odp:impress8"), ("pptx", "office", "pptx:Impress MS PowerPoint 2007 XML"), ("ppt", "converted", "ppt:MS PowerPoint 97")], + "diagram": [("fodg", "converted", None), ("odg", "converted", "odg:draw8")], +} + + +def convert(src, filt, outdir, profile): + ext, name = filt.split(":", 1) + subprocess.run( + ["soffice", f"-env:UserInstallation=file://{profile}", "--headless", "--norestore", "--convert-to", f"{ext}:{name}", "--outdir", outdir, src], + check=True, capture_output=True, timeout=300, + ) + + +def main(): + docs = {"handbook": ("fodt", handbook_fodt()), "workbook": ("fods", workbook_fods()), "deck": ("fodp", deck_fodp()), "diagram": ("fodg", diagram_fodg())} + if not shutil.which("soffice"): + print("soffice is missing: only the flat files are written", file=sys.stderr) + with tempfile.TemporaryDirectory() as tmp: + profile = os.path.join(tmp, "profile") + for base, (ext, xml) in docs.items(): + src_dir = os.path.join(tmp, base) + os.makedirs(src_dir) + src = os.path.join(src_dir, f"{base}.{ext}") + with open(src, "w", encoding="utf-8") as f: + f.write(xml) + for target, folder, filt in TARGETS[base]: + dest = os.path.join(OUT, folder, f"{base}.{target}") + if filt is None: + shutil.copy(src, dest) + elif shutil.which("soffice"): + out_dir = os.path.join(tmp, f"out-{base}-{target}") + os.makedirs(out_dir) + convert(src, filt, out_dir, profile) + shutil.copy(os.path.join(out_dir, f"{base}.{target}"), dest) + if base == "handbook" and shutil.which("soffice"): + out_dir = os.path.join(tmp, "out-pdf") + os.makedirs(out_dir) + opts = '{"UseTaggedPDF":{"type":"boolean","value":"true"},"ExportBookmarks":{"type":"boolean","value":"true"},"ExportNotes":{"type":"boolean","value":"false"},"SelectPdfVersion":{"type":"long","value":"2"}}' + subprocess.run(["soffice", f"-env:UserInstallation=file://{profile}", "--headless", "--norestore", "--convert-to", f"pdf:writer_pdf_Export:{opts}", "--outdir", out_dir, src], check=True, capture_output=True, timeout=300) + shutil.copy(os.path.join(out_dir, "handbook.pdf"), os.path.join(OUT, "pdf", "handbook-tagged.pdf")) + + +main() diff --git a/crates/exav-viewer/demo/examples/generate/make-pdf.py b/crates/exav-viewer/demo/examples/generate/make-pdf.py new file mode 100644 index 0000000..7cf9049 --- /dev/null +++ b/crates/exav-viewer/demo/examples/generate/make-pdf.py @@ -0,0 +1,643 @@ +#!/usr/bin/env python3 +"""Writes the demo's PDF examples into ../files/pdf/. + + python3 -I make-pdf.py [OUT_DIR] + +Output: CC0-1.0, a public domain dedication by the exav project. Every file +is made here from scratch. + +Needs: Python 3, reportlab 4 (BSD licence), Pillow, numpy; the programs +opj_compress (libopenjp2-tools) and jbig2 (jbig2enc) and tiffcp (libtiff-tools) +for the scan; the Liberation fonts (SIL OFL 1.1, which lets documents embed +them) for the embedded-font page. The pictures' text is set in Pillow's +bundled Aileron font (CC0). A part whose program is missing is skipped. + +- field-report.pdf: six pages of a report written for the demo: a table of + contents whose entries are links, an outline of two levels, roman and + arabic page labels, internal and external links, tables, bar, line and pie + charts drawn as vectors, a raster picture, text in the 14 standard fonts + and in embedded Liberation fonts (Latin, Greek, Cyrillic), footnote + references, running heads, document information. +- application-form.pdf: an AcroForm with text fields (one multiline, one + with a maximum length), check boxes, radio buttons, a drop-down list, a + list box and a push button, some filled in. +- annotations.pdf: link annotations (URI, page, named destination) and + markup annotations (note, highlight, underline, strike-out, squiggly, free + text, square, circle, line, polygon, ink, stamp) without appearance + streams, an outline and a named destination: written by the small PDF + writer below. +- scan-mixed.pdf: a four-page scanned letter, one page for each image filter + a scanner's PDF uses: DCTDecode (JPEG), CCITTFaxDecode (Group 4), + JBIG2Decode and JPXDecode (JPEG 2000), each with an invisible text layer + (an OCR result). +- vector-art.pdf: gradients (axial and radial shadings), transparency, + clipping, dashes, caps and joins, Bezier curves, rotated and scaled text. +""" +import io +import math +import os +import shutil +import struct +import subprocess +import sys +import tempfile +import zlib + +import numpy as np +from PIL import Image, ImageDraw, ImageFilter, ImageFont +from reportlab import rl_config + +rl_config.invariant = 1 + +from reportlab.graphics.charts.barcharts import VerticalBarChart +from reportlab.graphics.charts.legends import Legend +from reportlab.graphics.charts.lineplots import LinePlot +from reportlab.graphics.charts.piecharts import Pie +from reportlab.graphics.shapes import Drawing, String +from reportlab.lib import colors +from reportlab.lib.enums import TA_JUSTIFY +from reportlab.lib.pagesizes import A4 +from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet +from reportlab.lib.units import cm, mm +from reportlab.pdfbase import pdfmetrics +from reportlab.pdfbase.ttfonts import TTFont +from reportlab.pdfgen import canvas +from reportlab.platypus import BaseDocTemplate, Frame, Image as RLImage, KeepTogether, PageBreak, PageTemplate, Paragraph, Spacer, Table, TableStyle +from reportlab.platypus.tableofcontents import TableOfContents + +HERE = os.path.dirname(os.path.abspath(__file__)) +OUT = os.path.abspath(sys.argv[1]) if len(sys.argv) > 1 else os.path.join(HERE, "..", "files", "pdf") +os.makedirs(OUT, exist_ok=True) +FONTS = "/usr/share/fonts/truetype/liberation" +EMBED = os.path.exists(os.path.join(FONTS, "LiberationSans-Regular.ttf")) +if EMBED: + for name, f in [("LibSans", "LiberationSans-Regular"), ("LibSerif", "LiberationSerif-Regular"), ("LibSerif-Italic", "LiberationSerif-Italic"), ("LibMono", "LiberationMono-Regular")]: + pdfmetrics.registerFont(TTFont(name, os.path.join(FONTS, f + ".ttf"))) + # Names the font by itself so that and stay in the family. + pdfmetrics.registerFontFamily("LibSerif", normal="LibSerif", italic="LibSerif-Italic", bold="LibSerif", boldItalic="LibSerif-Italic") + + +def aileron(size): + return ImageFont.load_default(size) + + +# ------------------------------------------------------------ field report + + +def diagram_image(): + """A small raster picture: a gradient with circles, for the report.""" + w, h = 480, 260 + y = np.linspace(0, 1, h)[:, None] + x = np.linspace(0, 1, w)[None, :] + px = np.zeros((h, w, 3), np.uint8) + px[..., 0] = 40 + 160 * x + px[..., 1] = 80 + 100 * y + px[..., 2] = 200 - 120 * x + im = Image.fromarray(px, "RGB") + d = ImageDraw.Draw(im) + for i in range(7): + r = 14 + i * 7 + d.ellipse((60 + i * 60 - r, 130 - r, 60 + i * 60 + r, 130 + r), outline=(255, 255, 255), width=3) + d.text((16, 14), "A raster picture in the report", font=aileron(22), fill=(255, 255, 255)) + buf = io.BytesIO() + im.save(buf, "JPEG", quality=88) + buf.seek(0) + return buf + + +class Report(BaseDocTemplate): + def __init__(self, path): + super().__init__(path, pagesize=A4, leftMargin=2.2 * cm, rightMargin=2.2 * cm, topMargin=2.5 * cm, bottomMargin=2.2 * cm, + title="Field report: the east quay", author="exav project", subject="A report written for the exav demo (CC0-1.0)", + keywords="demo, report, links, outline, charts", creator="exav make-pdf.py", pageCompression=1) + frame = Frame(self.leftMargin, self.bottomMargin, self.width, self.height, id="body") + self.addPageTemplates([PageTemplate(id="all", frames=[frame], onPage=self.decorate)]) + + def decorate(self, c, doc): + c.saveState() + if doc.page == 1: + # The cover and the contents are i and ii; the body starts again at 1. + c.addPageLabel(0, "ROMAN_LOWER", 1) + c.addPageLabel(2, "ARABIC", 1) + c.setFont("Helvetica", 8) + c.setFillColor(colors.HexColor("#555555")) + if doc.page > 1: + c.drawString(self.leftMargin, A4[1] - 1.5 * cm, "Field report: the east quay") + c.drawRightString(A4[0] - self.rightMargin, A4[1] - 1.5 * cm, "exav demo, CC0-1.0") + c.setStrokeColor(colors.HexColor("#999999")) + c.line(self.leftMargin, A4[1] - 1.7 * cm, A4[0] - self.rightMargin, A4[1] - 1.7 * cm) + c.drawCentredString(A4[0] / 2, 1.2 * cm, f"page {doc.page}") + c.linkURL("https://exav.org/viewer/", (A4[0] - self.rightMargin - 3 * cm, A4[1] - 1.6 * cm, A4[0] - self.rightMargin, A4[1] - 1.3 * cm), relative=0) + c.restoreState() + + def afterFlowable(self, fl): + if isinstance(fl, Paragraph) and fl.style.name in ("H1", "H2"): + level = 0 if fl.style.name == "H1" else 1 + text = fl.getPlainText() + key = "h" + "".join(c if c.isalnum() else "-" for c in text) + self.canv.bookmarkPage(key) + self.canv.addOutlineEntry(text, key, level, closed=False) + self.notify("TOCEntry", (level, text, self.page, key)) + + +def field_report(path): + ss = getSampleStyleSheet() + body_font, serif_font = ("LibSans", "LibSerif") if EMBED else ("Helvetica", "Times-Roman") + body = ParagraphStyle("Body", parent=ss["BodyText"], fontName=serif_font, fontSize=10.5, leading=14.5, alignment=TA_JUSTIFY, spaceAfter=6) + h1 = ParagraphStyle("H1", parent=ss["Heading1"], fontName="Helvetica-Bold", fontSize=18, spaceBefore=14, spaceAfter=8, textColor=colors.HexColor("#0b4f6c")) + h2 = ParagraphStyle("H2", parent=ss["Heading2"], fontName="Helvetica-Bold", fontSize=13, spaceBefore=10, spaceAfter=5, textColor=colors.HexColor("#146c94")) + small = ParagraphStyle("Small", parent=body, fontSize=8.5, leading=11, alignment=0) + mono = ParagraphStyle("Mono", parent=body, fontName="Courier", fontSize=9, leading=11.5, alignment=0, backColor=colors.HexColor("#f2f2f2"), borderPadding=4, spaceBefore=4, spaceAfter=8) + + lorem = [ + "The east quay was built in three stages. The first stage, a timber jetty of twenty berths, dates from the start of the register; the second doubled it in stone, and the third, the long breakwater, shelters both from the south-west swell.", + "Every berth has a number, a length in metres and a holder. The register is kept on paper and in a table; the two are compared each spring, and the differences are explained in the notes of the harbour master.", + "Visitors are asked to call the harbour office on channel 9 before they come in, to give the length of their boat and the draught, and to say how many nights they plan to stay. The office will give a berth number and, when the tide is low, the best line of approach.", + "A note on the figures. Lengths are over all, in metres, to one decimal. Fees are in euros and include the tax. Where a table gives a total, it is the sum of the rows above it, rounded once, at the end.", + ] + + def paras(n, start=0): + return [Paragraph(lorem[(start + i) % len(lorem)], body) for i in range(n)] + + story = [] + # The cover page. + story += [Spacer(1, 5 * cm), Paragraph("Field report", ParagraphStyle("Title", parent=h1, fontSize=34, leading=40, textColor=colors.HexColor("#0b4f6c"))), + Paragraph("The east quay: berths, tides and visitors", ParagraphStyle("Sub", parent=body, fontName="Helvetica", fontSize=16, leading=20, alignment=0)), Spacer(1, 1.2 * cm), + Paragraph("A document made for the exav demo. It has a table of contents whose lines are links, an outline in the side panel, page labels, charts drawn as vectors, tables, a picture, and text in embedded fonts. It is in the public domain (CC0-1.0).", body), + Spacer(1, 1 * cm), Paragraph('Project page: https://exav.org/viewer/', body), PageBreak()] + toc = TableOfContents() + toc.levelStyles = [ParagraphStyle("t0", fontName="Helvetica-Bold", fontSize=11, leading=16, leftIndent=0, firstLineIndent=0), ParagraphStyle("t1", fontName="Helvetica", fontSize=10, leading=14, leftIndent=18, firstLineIndent=0)] + story += [Paragraph("Contents", ParagraphStyle("TocTitle", parent=h1)), toc, PageBreak()] + + story += [Paragraph("1. The quay", h1), Paragraph("1.1 History", h2)] + paras(3) + story += [Paragraph("1.2 Today", h2)] + paras(2, 1) + story += [Paragraph("Notes: see the picture and the first table in section 2.1", small)] + story += [Paragraph("2. Figures", h1), Paragraph("2.1 Berths by length", h2)] + data = [["Length (m)", "Berths", "Let by", "Fee (EUR)", "Income (EUR)"]] + rows = [("up to 6", 12, "week", 18.0), ("6 to 8", 18, "season", 24.5), ("8 to 10", 14, "season", 31.0), ("10 to 12", 9, "year", 42.0), ("over 12", 7, "year", 58.5)] + for a, b, c, d in rows: + data.append([a, b, c, f"{d:.2f}", f"{b * d:.2f}"]) + data.append(["Total", sum(r[1] for r in rows), "", "", f"{sum(r[1] * r[3] for r in rows):.2f}"]) + t = Table(data, colWidths=[3.2 * cm, 2.4 * cm, 2.6 * cm, 3 * cm, 3.4 * cm], repeatRows=1) + t.setStyle(TableStyle([("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#0b4f6c")), ("TEXTCOLOR", (0, 0), (-1, 0), colors.white), ("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"), + ("FONTNAME", (0, -1), (-1, -1), "Helvetica-Bold"), ("ROWBACKGROUNDS", (0, 1), (-1, -2), [colors.white, colors.HexColor("#e8f1f5")]), + ("ALIGN", (1, 0), (-1, -1), "RIGHT"), ("GRID", (0, 0), (-1, -1), 0.4, colors.HexColor("#8aa6b4")), ("LINEABOVE", (0, -1), (-1, -1), 1.2, colors.black)])) + story += [Paragraph('Table 1. Berths by length, with the season\'s fee.', small), t, Spacer(1, 0.4 * cm)] + story += [Paragraph("2.2 Charts", h2)] + bar = Drawing(420, 200) + chart = VerticalBarChart() + chart.x, chart.y, chart.width, chart.height = 40, 30, 360, 150 + chart.data = [[12, 18, 14, 9, 7], [10, 17, 15, 8, 5]] + chart.categoryAxis.categoryNames = [r[0] for r in rows] + chart.valueAxis.valueMin, chart.valueAxis.valueMax, chart.valueAxis.valueStep = 0, 20, 5 + chart.bars[0].fillColor = colors.HexColor("#146c94") + chart.bars[1].fillColor = colors.HexColor("#f6a01a") + chart.barLabelFormat = "%d" + chart.barLabels.nudge = 7 + bar.add(chart) + bar.add(String(40, 188, "Berths let, this year and last", fontName="Helvetica-Bold", fontSize=10)) + story += [bar] + line = Drawing(420, 190) + lp = LinePlot() + lp.x, lp.y, lp.width, lp.height = 40, 25, 360, 140 + months = list(range(1, 13)) + lp.data = [[(m, 40 + 35 * math.sin((m - 3) / 12 * 2 * math.pi) + 5 * m / 12) for m in months], [(m, 28 + 22 * math.sin((m - 3) / 12 * 2 * math.pi)) for m in months]] + lp.lines[0].strokeColor, lp.lines[1].strokeColor = colors.HexColor("#c0392b"), colors.HexColor("#2c7a4b") + lp.lines[0].strokeWidth = lp.lines[1].strokeWidth = 2 + lp.lines[0].symbol = lp.lines[1].symbol = None + lp.xValueAxis.valueMin, lp.xValueAxis.valueMax, lp.xValueAxis.valueStep = 1, 12, 1 + line.add(lp) + line.add(String(40, 175, "Boats a day, by month (visitors and holders)", fontName="Helvetica-Bold", fontSize=10)) + story += [line] + pie = Drawing(420, 180) + p = Pie() + p.x, p.y, p.width, p.height = 40, 15, 140, 140 + p.data = [41, 27, 18, 9, 5] + p.labels = ["sail", "motor", "fishing", "rowing", "other"] + for i, c in enumerate(["#146c94", "#f6a01a", "#2c7a4b", "#c0392b", "#8e44ad"]): + p.slices[i].fillColor = colors.HexColor(c) + p.slices[0].popout = 8 + pie.add(p) + leg = Legend() + leg.x, leg.y, leg.alignment = 230, 120, "right" + leg.colorNamePairs = [(colors.HexColor(c), f"{n} ({v}%)") for c, n, v in zip(["#146c94", "#f6a01a", "#2c7a4b", "#c0392b", "#8e44ad"], p.labels, p.data)] + pie.add(leg) + story += [pie] + story += [Paragraph("2.3 A picture", h2), Paragraph('Figure 1. A raster picture, embedded as a JPEG.', small), RLImage(diagram_image(), width=12 * cm, height=6.5 * cm)] + story += [Paragraph("3. Fonts and text", h1), Paragraph("3.1 The standard fonts", h2)] + for fam, label in [("Helvetica", "Helvetica"), ("Times-Roman", "Times Roman"), ("Courier", "Courier"), ("Helvetica-Oblique", "Helvetica Oblique"), ("Times-BoldItalic", "Times Bold Italic"), ("Symbol", "Symbol: abgd"), ("ZapfDingbats", "abcdef")]: + story.append(Paragraph(f"{label}: The quick brown fox jumps over the lazy dog 0123456789", ParagraphStyle("f", parent=body, fontName=fam, fontSize=10.5, alignment=0, spaceAfter=2))) + if EMBED: + story += [Paragraph("3.2 Embedded fonts (Liberation, SIL OFL 1.1)", h2), + Paragraph("Latin: café, naïve, Zürich, Å�ódź, Ã¥ngström, €12,50. Greek: Αθήνα, Ï€ ≈ 3,14159. Cyrillic: МоÑ�ква, живой Ñ�зык.", ParagraphStyle("u", parent=body, fontName="LibSerif", alignment=0)), + Paragraph("Sans: Portez ce vieux whisky au juge blond qui fume. 0123456789", ParagraphStyle("u2", parent=body, fontName="LibSans", alignment=0)), + Paragraph("def moor(boat): return berth_for(boat.length)", ParagraphStyle("u3", parent=body, fontName="LibMono", fontSize=9.5, alignment=0))] + story += [Paragraph("3.3 Preformatted text and a list", h2), Paragraph("moor --boat Aurora --length 6.5\nberth 14 free until 06:00\n (tide table on page 6)", mono)] + bullets = [Paragraph(f"• {t}", ParagraphStyle("b", parent=body, leftIndent=14, firstLineIndent=-10, spaceAfter=2, alignment=0)) for t in ["Call the office on channel 9.", "Give the length, the draught and the number of nights.", "Take the berth you are given."]] + story += bullets + story += [Paragraph("4. Links", h1), Paragraph("4.1 Where they go", h2), + Paragraph('An external link: exav.org. A link to another page of this file: back to section 1. A link on a picture, and one around a long phrase that wraps at the end of a line to the next, so that its box is two rectangles: the source of the demo is on GitHub, and this phrase is long enough to wrap.', body)] + paras(2, 2) + story += [Paragraph("Footnote 1: the table's totals are exact; the charts are rounded.", small)] + doc = Report(path) + doc.multiBuild(story) + + +# ------------------------------------------------------------------- forms + + +def application_form(path): + c = canvas.Canvas(path, pagesize=A4, pageCompression=1) + c.setTitle("Berth application form") + c.setAuthor("exav project") + form = c.acroForm + w, h = A4 + c.setFont("Helvetica-Bold", 20) + c.drawString(2 * cm, h - 2.5 * cm, "Berth application") + c.setFont("Helvetica", 9) + c.drawString(2 * cm, h - 3.1 * cm, "A form for the exav demo (CC0-1.0). Some fields are filled in.") + y = h - 4.5 * cm + + def label(text, yy): + c.setFont("Helvetica", 10) + c.setFillColor(colors.black) + c.drawString(2 * cm, yy + 3, text) + + label("Full name", y) + form.textfield(name="name", tooltip="Full name", value="Anne Le Gall", x=6 * cm, y=y - 3, width=9 * cm, height=0.7 * cm, borderStyle="inset", fillColor=colors.HexColor("#fffbe6"), fontSize=11) + y -= 1.2 * cm + label("Boat's name", y) + form.textfield(name="boat", tooltip="Boat's name", value="Hirondelle", x=6 * cm, y=y - 3, width=9 * cm, height=0.7 * cm, borderStyle="inset", fontSize=11) + y -= 1.2 * cm + label("Length (m), 5 characters", y) + form.textfield(name="length", tooltip="Length", value="9.4", maxlen=5, x=6.5 * cm, y=y - 3, width=2.2 * cm, height=0.7 * cm, borderStyle="inset", fontSize=11) + y -= 1.2 * cm + label("Type of boat", y) + form.choice(name="kind", tooltip="Type of boat", value="sloop", options=["sloop", "ketch", "trawler", "motor yacht", "catamaran"], x=6 * cm, y=y - 3, width=5 * cm, height=0.7 * cm, fieldFlags="combo", borderStyle="inset", fontSize=11) + y -= 1.2 * cm + label("Services", y) + for i, (n, t) in enumerate([("water", "Water"), ("power", "Shore power"), ("wifi", "Wi-Fi")]): + form.checkbox(name=n, tooltip=t, checked=(i != 2), x=6 * cm + i * 4 * cm, y=y - 2, size=14, buttonStyle="check", borderColor=colors.black, fillColor=colors.white, textColor=colors.black) + c.drawString(6 * cm + i * 4 * cm + 20, y + 1, t) + y -= 1.2 * cm + label("Stay", y) + for i, (v, t) in enumerate([("night", "One night"), ("week", "A week"), ("season", "The season")]): + form.radio(name="stay", tooltip=t, value=v, selected=(v == "week"), x=6 * cm + i * 4 * cm, y=y - 2, size=14, buttonStyle="circle", borderColor=colors.black, fillColor=colors.white, textColor=colors.black) + c.drawString(6 * cm + i * 4 * cm + 20, y + 1, t) + y -= 1.2 * cm + label("Arrival month", y) + form.listbox(name="month", tooltip="Arrival month", value="June", options=["April", "May", "June", "July", "August", "September"], x=6 * cm, y=y - 2.4 * cm, width=4 * cm, height=2.4 * cm + 0.5 * cm, borderStyle="inset", fontSize=10) + y -= 3.6 * cm + label("Remarks", y) + form.textfield(name="remarks", tooltip="Remarks", value="Arriving after sunset.\nDraught 1.4 m.", x=6 * cm, y=y - 2 * cm, width=10 * cm, height=2.4 * cm, borderStyle="inset", fieldFlags="multiline", fontSize=10) + y -= 3.4 * cm + label("Password (hidden)", y) + form.textfield(name="secret", tooltip="A password field shows dots", value="berth", x=6 * cm, y=y - 3, width=5 * cm, height=0.7 * cm, borderStyle="inset", fieldFlags="password", fontSize=11) + y -= 1.6 * cm + form.textfield(name="readonly", tooltip="Read only", value="Application no. 2000-0001 (read only)", x=2 * cm, y=y - 3, width=9 * cm, height=0.7 * cm, borderStyle="solid", fieldFlags="readOnly", fontSize=10, fillColor=colors.HexColor("#eeeeee")) + c.setFont("Helvetica-Oblique", 8) + c.drawString(2 * cm, 2 * cm, "Fill the fields in the viewer; nothing is sent anywhere.") + c.showPage() + c.save() + + +# --------------------------------------------------------- a tiny PDF writer + + +class Pdf: + def __init__(self): + self.objs = [] + + def reserve(self): + self.objs.append(None) + return len(self.objs) + + def set(self, n, body): + self.objs[n - 1] = body if isinstance(body, bytes) else body.encode("latin-1") + + def add(self, body): + n = self.reserve() + self.set(n, body) + return n + + def stream(self, entries, data, compress=False): + if compress: + data = zlib.compress(data, 9) + entries += " /Filter /FlateDecode" + return self.add(f"<< {entries} /Length {len(data)} >>\nstream\n".encode("latin-1") + data + b"\nendstream") + + def write(self, path, root, info=None): + out = bytearray(b"%PDF-1.7\n%\xe2\xe3\xcf\xd3\n") + offsets = [] + for i, body in enumerate(self.objs, 1): + offsets.append(len(out)) + out += f"{i} 0 obj\n".encode() + body + b"\nendobj\n" + xref = len(out) + out += f"xref\n0 {len(self.objs) + 1}\n0000000000 65535 f \n".encode() + for o in offsets: + out += f"{o:010d} 00000 n \n".encode() + out += f"trailer\n<< /Size {len(self.objs) + 1} /Root {root} 0 R {f'/Info {info} 0 R' if info else ''} /ID [<6578617620657861> <6578617620657861>] >>\nstartxref\n{xref}\n%%EOF\n".encode() + with open(path, "wb") as f: + f.write(out) + + +def pdf_str(s): + return "(" + s.replace("\\", "\\\\").replace("(", "\\(").replace(")", "\\)") + ")" + + +def annotations(path): + p = Pdf() + catalog, pages = p.reserve(), p.reserve() + page1, page2 = p.reserve(), p.reserve() + font = p.add("<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>") + bold = p.add("<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding >>") + attach = p.stream("/Type /EmbeddedFile /Subtype /text#2Fplain /Params << /Size 38 >>", b"An attached file, inside the annotation.\n", False) + spec = p.add(f"<< /Type /Filespec /F (note.txt) /UF (note.txt) /EF << /F {attach} 0 R >> /Desc (A file attached to the page) >>") + + lines = [] + annots = [] + + def text(x, y, s, f="F1", size=11): + lines.append(f"BT /{f} {size} Tf {x} {y} Td {pdf_str(s)} Tj ET") + + def annot(body): + annots.append(p.add(body)) + + text(50, 790, "Annotations", "F2", 22) + text(50, 770, "Every mark below is an annotation of the page, drawn from its own entry.", "F1", 10) + rows = [ + ("Link to a web address", "<< /Type /Annot /Subtype /Link /Rect [200 722 330 740] /Border [0 0 1] /C [0 0 1] /A << /S /URI /URI (https://exav.org/viewer/) >> >>"), + ("Link to page 2", f"<< /Type /Annot /Subtype /Link /Rect [200 692 330 710] /Border [0 0 1] /C [0 0.5 0] /Dest [{page2} 0 R /XYZ 50 760 0] >>"), + ("Link to a named place", "<< /Type /Annot /Subtype /Link /Rect [200 662 330 680] /Border [0 0 1] /C [0.6 0 0.6] /Dest (target) >>"), + ] + y = 730 + for label, body in rows: + text(50, y, label) + text(205, y, "click here") + annot(body) + y -= 30 + y = 630 + marks = [ + ("Highlight", "Highlight", "/C [1 1 0]"), + ("Underline", "Underline", "/C [0 0.6 0]"), + ("Strike-out", "StrikeOut", "/C [1 0 0]"), + ("Squiggly", "Squiggly", "/C [0.6 0 0.8]"), + ] + for label, sub, extra in marks: + text(50, y, f"{label}: marked text in a line") + x0, x1 = 50, 50 + 7.0 * len(f"{label}: marked text in a line") * 0.82 + annot(f"<< /Type /Annot /Subtype /{sub} /Rect [{x0} {y - 3} {x1} {y + 11}] /QuadPoints [{x0} {y + 11} {x1} {y + 11} {x0} {y - 3} {x1} {y - 3}] {extra} /T (exav) /Contents ({label} annotation) /F 4 >>") + y -= 24 + text(50, 520, "Text note (sticky note), free text, shapes:") + annot("<< /Type /Annot /Subtype /Text /Rect [60 470 80 490] /Name /Comment /Contents (A note. Its text is in the annotation.) /T (exav) /C [1 0.8 0] /Open false /F 28 >>") + annot("<< /Type /Annot /Subtype /FreeText /Rect [100 450 300 495] /Contents (Free text in a box) /DA (/Helv 12 Tf 0 0 1 rg) /DS (font: Helvetica 12pt) /C [1 1 0.8] /IC [1 1 0.8] /BS << /W 1 >> /F 4 >>") + annot("<< /Type /Annot /Subtype /Square /Rect [320 450 400 495] /C [1 0 0] /IC [1 0.9 0.9] /BS << /W 2 >> /F 4 >>") + annot("<< /Type /Annot /Subtype /Circle /Rect [420 450 500 495] /C [0 0 1] /IC [0.9 0.9 1] /BS << /W 2 /S /D /D [4 2] >> /F 4 >>") + annot("<< /Type /Annot /Subtype /Line /Rect [50 390 250 430] /L [60 400 240 420] /LE [/OpenArrow /ClosedArrow] /C [0 0.5 0] /BS << /W 2 >> /F 4 >>") + annot("<< /Type /Annot /Subtype /Polygon /Rect [280 380 380 430] /Vertices [290 390 370 390 380 420 300 425] /C [0.5 0 0.5] /IC [0.95 0.85 0.95] /BS << /W 1.5 >> /F 4 >>") + annot("<< /Type /Annot /Subtype /PolyLine /Rect [400 380 500 430] /Vertices [410 390 440 425 470 392 495 420] /C [0 0.4 0.4] /BS << /W 2 >> /F 4 >>") + annot("<< /Type /Annot /Subtype /Ink /Rect [50 310 250 370] /InkList [[60 320 90 360 120 320 150 360 180 320 210 360 240 330]] /C [0.8 0.3 0] /BS << /W 2.5 >> /F 4 >>") + annot("<< /Type /Annot /Subtype /Stamp /Rect [280 310 400 370] /Name /Approved /Contents (A stamp) /C [0 0.6 0] /F 4 >>") + annot(f"<< /Type /Annot /Subtype /FileAttachment /Rect [430 330 450 350] /FS {spec} 0 R /Name /Paperclip /Contents (An attached file) /C [0.3 0.3 0.3] /F 28 >>") + text(50, 280, "The page also holds a link under a rotated line of text, below.", "F1", 10) + lines.append("q 0.866 0.5 -0.5 0.866 80 150 cm BT /F1 12 Tf 0 0 Td (A rotated line with a link over it) Tj ET Q") + annot("<< /Type /Annot /Subtype /Link /Rect [80 150 330 230] /Border [0 0 0] /QuadPoints [80 150 80 150 80 150 80 150] /A << /S /URI /URI (https://exav.org/) >> >>") + content1 = p.stream("", "\n".join(lines).encode("latin-1"), True) + + lines2 = [] + lines2.append("BT /F2 22 Tf 50 790 Td (Page 2: the target) Tj ET") + lines2.append("BT /F1 11 Tf 50 760 Td (The named destination \"target\" points here, and so does the second line of the outline.) Tj ET") + lines2.append("0.9 0.95 1 rg 50 600 300 120 re f 0 0 0.6 RG 50 600 300 120 re S") + lines2.append("BT /F1 11 Tf 60 700 Td (A framed box.) Tj ET") + content2 = p.stream("", "\n".join(lines2).encode("latin-1"), True) + + res = f"<< /Font << /F1 {font} 0 R /F2 {bold} 0 R /Helv {font} 0 R >> >>" + p.set(page1, f"<< /Type /Page /Parent {pages} 0 R /MediaBox [0 0 595 842] /Resources {res} /Contents {content1} 0 R /Annots [{' '.join(f'{a} 0 R' for a in annots)}] >>") + p.set(page2, f"<< /Type /Page /Parent {pages} 0 R /MediaBox [0 0 595 842] /Resources {res} /Contents {content2} 0 R >>") + p.set(pages, f"<< /Type /Pages /Kids [{page1} 0 R {page2} 0 R] /Count 2 >>") + outlines, o1, o2, o3 = p.reserve(), p.reserve(), p.reserve(), p.reserve() + p.set(outlines, f"<< /Type /Outlines /First {o1} 0 R /Last {o2} 0 R /Count 3 >>") + p.set(o1, f"<< /Title (Annotations) /Parent {outlines} 0 R /Next {o2} 0 R /Dest [{page1} 0 R /Fit] >>") + p.set(o2, f"<< /Title (The target) /Parent {outlines} 0 R /Prev {o1} 0 R /First {o3} 0 R /Last {o3} 0 R /Count 1 /Dest [{page2} 0 R /XYZ 50 760 0] >>") + p.set(o3, f"<< /Title (A box on that page) /Parent {o2} 0 R /A << /S /GoTo /D [{page2} 0 R /FitR 50 600 350 720] >> >>") + info = p.add("<< /Title (Annotations) /Author (exav project) /Subject (CC0-1.0) /Creator (exav make-pdf.py) >>") + p.set(catalog, f"<< /Type /Catalog /Pages {pages} 0 R /Outlines {outlines} 0 R /Names << /Dests << /Names [(target) [{page2} 0 R /XYZ 50 760 0]] >> >> /PageMode /UseOutlines /ViewerPreferences << /DisplayDocTitle true >> /Lang (en) >>") + p.write(path, catalog, info) + + +# ------------------------------------------------------------------- scan + +LETTER = [ + ["Harbour office, East quay", "", "Report of the harbour master", "for the month of March", "", "Berths let this month: 41 of 60.", "Visitors: 63 boats, of which 18 stayed more than two nights.", "", + "The breakwater light was out for three nights; it is repaired.", "The pontoon at berth 24 needs a new chain; quote attached.", "", "Weather: four days of gale from the south-west, no damage."], + ["Tide notes", "", "High water at the quay was at 06:12 and 18:34 on the first.", "The spring tides of the 14th and 15th reached 7.4 metres.", "Boats drawing more than 1.8 metres should wait for the", "top of the tide before they come in.", "", "The fairway buoy has been moved 50 metres to the east."], + ["Visitors' book (extract)", "", "Aurora, sloop 9.4 m, two nights.", "Brise, ketch 12.1 m, one night.", "Calypso, trawler 14.0 m, a week.", "Dorade, sloop 8.2 m, one night.", "", "Thanks to the office for the loan of the bicycle."], + ["Notes for the next month", "", "Order a new chain for berth 24.", "Paint the numbers on the east pontoon.", "Check the shore power at berths 30 to 40.", "", "Signed, the harbour master"], +] + + +def letter_page(n, w=1240, h=1754): + """A scanned-looking letter: paper tone, text a little off the straight, noise, a shadow.""" + rng = np.random.default_rng(n) + page = Image.new("L", (w, h), 255) + d = ImageDraw.Draw(page) + words = [] + y = 160 + for i, line in enumerate(LETTER[n]): + size = 54 if i == 0 else 38 + d.text((130, y), line, font=aileron(size), fill=25) + if line: + words.append((130, y, line, size)) + y += 88 if i == 0 else 62 + d.line((130, 140, w - 130, 140), fill=40, width=3) + d.rectangle((w - 420, h - 420, w - 140, h - 170), outline=60, width=4) + d.text((w - 400, h - 330), "STAMP", font=aileron(48), fill=60) + page = page.rotate(0.5 + 0.25 * n, resample=Image.BICUBIC, fillcolor=255, expand=False) + return page, words + + +def scan_variants(n): + page, words = letter_page(n) + arr = np.array(page).astype(float) + yy, xx = np.mgrid[0 : arr.shape[0], 0 : arr.shape[1]] + paper = 232 - 18 * (xx / arr.shape[1]) ** 3 - 14 * (yy / arr.shape[0]) ** 2 + grey = arr / 255 * paper + np.random.default_rng(100 + n).normal(0, 3.0, arr.shape) + scan_grey = Image.fromarray(np.clip(grey, 0, 255).astype(np.uint8), "L").filter(ImageFilter.GaussianBlur(0.6)) + bilevel = page.point(lambda v: 255 if v > 150 else 0).convert("1") + return scan_grey, bilevel, words + + +def scan_pdf(path): + if not (shutil.which("opj_compress") and shutil.which("jbig2") and shutil.which("tiffcp")): + print("scan-mixed.pdf skipped: opj_compress, jbig2 or tiffcp is missing", file=sys.stderr) + return + p = Pdf() + catalog, pages = p.reserve(), p.reserve() + font = p.add("<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>") + kids = [] + W, H = 1240, 1754 + with tempfile.TemporaryDirectory() as tmp: + for n in range(4): + grey, bilevel, words = scan_variants(n) + if n == 0: + buf = io.BytesIO() + grey.save(buf, "JPEG", quality=70, dpi=(150, 150)) + img = p.stream(f"/Type /XObject /Subtype /Image /Width {W} /Height {H} /ColorSpace /DeviceGray /BitsPerComponent 8 /Filter /DCTDecode", buf.getvalue()) + elif n == 1: + src = os.path.join(tmp, "p.tif") + inv = bilevel.convert("L").point(lambda v: 255 - v).convert("1") + inv.save(src) + dst = os.path.join(tmp, "g4.tif") + subprocess.run(["tiffcp", "-c", "g4", "-r", str(H), src, dst], check=True, capture_output=True) + raw = open(dst, "rb").read() + e = "<" if raw[:2] == b"II" else ">" + ifd = struct.unpack(e + "I", raw[4:8])[0] + tags = {} + for i in range(struct.unpack(e + "H", raw[ifd : ifd + 2])[0]): + tag, kind, count, value = struct.unpack(e + "HHII", raw[ifd + 2 + 12 * i : ifd + 14 + 12 * i]) + if kind == 3 and count == 1: + value = value & 0xFFFF if e == "<" else value >> 16 + tags[tag] = value + strip = raw[tags[273] : tags[273] + tags[279]] + img = p.stream(f"/Type /XObject /Subtype /Image /Width {W} /Height {H} /ColorSpace /DeviceGray /BitsPerComponent 1 /Filter /CCITTFaxDecode /DecodeParms << /K -1 /Columns {W} /Rows {H} >>", strip) + elif n == 2: + src = os.path.join(tmp, "p.png") + bilevel.save(src) + data = subprocess.run(["jbig2", "-p", src], check=True, capture_output=True).stdout + img = p.stream(f"/Type /XObject /Subtype /Image /Width {W} /Height {H} /ColorSpace /DeviceGray /BitsPerComponent 1 /Filter /JBIG2Decode", data) + else: + src = os.path.join(tmp, "p.png") + grey.save(src) + dst = os.path.join(tmp, "p.jp2") + subprocess.run(["opj_compress", "-i", src, "-o", dst, "-r", "30", "-n", "5"], check=True, capture_output=True) + img = p.stream(f"/Type /XObject /Subtype /Image /Width {W} /Height {H} /ColorSpace /DeviceGray /BitsPerComponent 8 /Filter /JPXDecode", open(dst, "rb").read()) + # The page is A4 at 150 dpi: 595 by 842 points. The invisible text sits over each line. + sx = 595.0 / W + ops = [f"q {595} 0 0 {842} 0 0 cm /Im0 Do Q", "BT 3 Tr"] + for x, y, line, size in words: + ops.append(f"/F1 {size * sx * 0.95:.1f} Tf 1 0 0 1 {x * sx:.1f} {842 - (y + size) * sx:.1f} Tm {pdf_str(line)} Tj") + ops.append("ET") + content = p.stream("", "\n".join(ops).encode("latin-1"), True) + kids.append(p.add(f"<< /Type /Page /Parent {pages} 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 {font} 0 R >> /XObject << /Im0 {img} 0 R >> >> /Contents {content} 0 R >>")) + p.set(pages, f"<< /Type /Pages /Kids [{' '.join(f'{k} 0 R' for k in kids)}] /Count {len(kids)} >>") + p.set(catalog, f"<< /Type /Catalog /Pages {pages} 0 R /Lang (en) >>") + info = p.add("<< /Title (Scanned letters) /Author (exav project) /Subject (CC0-1.0) /Creator (exav make-pdf.py) >>") + p.write(path, catalog, info) + + +# ------------------------------------------------------------ vector art + + +def vector_art(path): + c = canvas.Canvas(path, pagesize=A4, pageCompression=1) + c.setTitle("Vector art") + c.setAuthor("exav project") + w, h = A4 + c.setFont("Helvetica-Bold", 18) + c.drawString(40, h - 50, "Vector art") + c.setFont("Helvetica", 9) + c.drawString(40, h - 64, "Gradients, transparency, clipping, dashes, joins, curves and transformed text (CC0-1.0).") + # Axial and radial shadings. + # A shading paints everywhere inside the clip, so each is clipped to its box. + c.saveState() + box = c.beginPath() + box.roundRect(40, h - 200, 200, 110, 14) + c.clipPath(box, stroke=0, fill=0) + c.linearGradient(40, h - 200, 240, h - 90, (colors.HexColor("#0b4f6c"), colors.HexColor("#f6a01a"), colors.HexColor("#c0392b")), (0, 0.5, 1)) + c.restoreState() + c.saveState() + disc = c.beginPath() + disc.circle(400, h - 145, 70) + c.clipPath(disc, stroke=0, fill=0) + c.radialGradient(400, h - 145, 70, (colors.white, colors.HexColor("#146c94"), colors.black), (0, 0.6, 1)) + c.restoreState() + # Transparency: three overlapping discs. + for i, (cx, col) in enumerate([(80, "#c0392b"), (130, "#2c7a4b"), (105, "#146c94")]): + c.saveState() + c.setFillAlpha(0.55) + c.setFillColor(colors.HexColor(col)) + c.circle(cx, h - 290 + (i == 2) * 40, 45, stroke=0, fill=1) + c.restoreState() + # Clipping: a star clips a striped rectangle. + c.saveState() + p = c.beginPath() + cx, cy, r1, r2 = 330, h - 280, 60, 25 + for i in range(10): + a = math.pi / 5 * i - math.pi / 2 + r = r1 if i % 2 == 0 else r2 + (p.moveTo if i == 0 else p.lineTo)(cx + r * math.cos(a), cy + r * math.sin(a)) + p.close() + c.clipPath(p, stroke=0, fill=0) + for i in range(14): + c.setFillColor(colors.HexColor("#f6a01a") if i % 2 else colors.HexColor("#0b4f6c")) + c.rect(cx - 70 + i * 10, cy - 70, 10, 140, stroke=0, fill=1) + c.restoreState() + # Dashes, caps and joins. + y = h - 380 + for i, (dash, cap, join) in enumerate([((), 0, 0), ((6, 3), 1, 1), ((12, 4, 2, 4), 2, 2), ((1, 5), 1, 0)]): + c.saveState() + c.setLineWidth(10 if i != 3 else 3) + c.setDash(list(dash), 0) + c.setLineCap(cap) + c.setLineJoin(join) + c.setStrokeColor(colors.HexColor("#146c94")) + pth = c.beginPath() + pth.moveTo(50 + i * 130, y) + pth.lineTo(90 + i * 130, y - 50) + pth.lineTo(130 + i * 130, y) + c.drawPath(pth, stroke=1, fill=0) + c.restoreState() + # Bezier curves. + c.saveState() + c.setStrokeColor(colors.HexColor("#c0392b")) + c.setLineWidth(2) + pth = c.beginPath() + pth.moveTo(40, h - 500) + pth.curveTo(120, h - 400, 200, h - 600, 280, h - 500) + pth.curveTo(340, h - 440, 400, h - 560, 480, h - 480) + c.drawPath(pth, stroke=1, fill=0) + c.setFillColor(colors.HexColor("#8e44ad")) + c.setFillAlpha(0.4) + pth = c.beginPath() + pth.moveTo(60, h - 600) + pth.curveTo(60, h - 540, 160, h - 540, 160, h - 600) + pth.curveTo(160, h - 660, 60, h - 660, 60, h - 600) + c.drawPath(pth, stroke=1, fill=1) + c.restoreState() + # Even-odd fill: a ring. + c.saveState() + c.setFillColor(colors.HexColor("#2c7a4b")) + pth = c.beginPath() + pth.circle(260, h - 600, 50) + pth.circle(260, h - 600, 28) + c.drawPath(pth, stroke=0, fill=1, fillMode=0) + c.restoreState() + # Text: rotated, scaled, with a stroke and a fill (render modes). + c.saveState() + c.translate(420, h - 640) + c.rotate(25) + c.setFont("Times-BoldItalic", 34) + t = c.beginText(0, 0) + t.setTextRenderMode(2) + t.setFillColor(colors.HexColor("#f6a01a")) + t.setStrokeColor(colors.HexColor("#0b4f6c")) + t.textOut("exav") + c.drawText(t) + c.restoreState() + c.saveState() + c.setFont("Helvetica", 14) + for i, s in enumerate([1.0, 0.8, 0.6]): + c.saveState() + c.translate(40, h - 720 - i * 22) + c.scale(s * 1.5, s) + c.drawString(0, 0, "Scaled text: the horizontal scale and the size change.") + c.restoreState() + c.restoreState() + c.showPage() + c.save() + + +field_report(os.path.join(OUT, "field-report.pdf")) +application_form(os.path.join(OUT, "application-form.pdf")) +annotations(os.path.join(OUT, "annotations.pdf")) +scan_pdf(os.path.join(OUT, "scan-mixed.pdf")) +vector_art(os.path.join(OUT, "vector-art.pdf")) diff --git a/crates/exav-viewer/demo/examples/generate/make-text.py b/crates/exav-viewer/demo/examples/generate/make-text.py new file mode 100644 index 0000000..05be95d --- /dev/null +++ b/crates/exav-viewer/demo/examples/generate/make-text.py @@ -0,0 +1,800 @@ +#!/usr/bin/env python3 +"""Writes the demo's text examples into ../files/text/. + + python3 -I make-text.py [OUT_DIR] + +Output: CC0-1.0, a public domain dedication by the exav project. Everything +here is written for the demo: the prose, the data (made up, from a seeded +random generator) and the programs. + +Needs: Python 3. +""" +import json +import math +import os +import random +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +OUT = os.path.abspath(sys.argv[1]) if len(sys.argv) > 1 else os.path.join(HERE, "..", "files", "text") +os.makedirs(OUT, exist_ok=True) + + +def write(name, text): + with open(os.path.join(OUT, name), "w", encoding="utf-8", newline="\n") as f: + f.write(text) + + +FILES = {} + +FILES["field-guide.md"] = r"""# Field guide to Markdown + +A short document that uses most of what Markdown can say. It is written for the +exav demo and is in the public domain (CC0-1.0). + +## Emphasis and spans + +Text can be **bold**, *italic*, ***both***, ~~struck through~~ or `code`. A line +that ends with two spaces +breaks without starting a paragraph. A [link with a title](https://exav.org/ "exav.org"), +an autolink , and a reference link: [the demo][demo]. + +[demo]: https://exav.org/viewer/demo/ + +Escapes: \*not italic\*, 2 \< 3, a literal backtick \`, and entities: © & é. +Unicode goes through unchanged: café, naïve, Ωmega, Жук, 日本語, مرحبا, ☃. + +## Headings + +### Third level +#### Fourth level +##### Fifth level +###### Sixth level + +Setext heading +============== + +Another one +----------- + +## Lists + +- A bullet +- Another, with a nested list: + - second level + - third level + - back to the second +- And a last one + +1. Numbered +2. Items + 1. Nested numbers + 2. Continue +3. Done + +7. A list that starts at seven +8. and goes on + +- [x] A finished task +- [ ] An open task +- [ ] Another open task, with `code` in it + +Loose list: + +- First paragraph. + + A second paragraph inside the same item. + +- Next item. + +## Quotes + +> A quotation, which can wrap over several lines and holds +> *other* **formatting**. +> +> > A quotation inside it. +> +> - and a list + +## Tables + +| Left | Centre | Right | +| :--- | :----: | ----: | +| a | b | c | +| `code` | **bold** | 1,234.50 | +| A longer cell that holds more words | x | 7 | + +## Code + +Inline `let x = 1;` and a fenced block with a language: + +```rust +fn fib(n: u32) -> u64 { + let (mut a, mut b) = (0u64, 1u64); + for _ in 0..n { + (a, b) = (b, a + b); + } + a +} +``` + +```python +def fib(n): + a, b = 0, 1 + for _ in range(n): + a, b = b, a + b + return a +``` + +```diff +- old line ++ new line +``` + +An indented block: + + four spaces make this code + and it keeps its spacing + +## Rules, HTML and footnotes + +--- + +Inline HTML such as Ctrl + C and sub and sup is +shown as text or ignored, never run: does nothing. + +A sentence with a footnote.[^1] And another one.[^note] + +[^1]: The first footnote. +[^note]: A second, with *formatting*. + +![An image reference](https://example.invalid/not-fetched.png) + +The end. +""" + +FILES["field-notes.txt"] = """Field notes +=========== + +Plain text is shown as it is written: line breaks, indentation, tabs and +long lines are kept. + + A line that starts with a tab. + A line that starts with eight spaces. + +A very long line, to see how the viewer wraps or scrolls it: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + +Pangrams, one for each script: + + English The quick brown fox jumps over the lazy dog. + Français Portez ce vieux whisky au juge blond qui fume. + Deutsch Zwölf Boxkämpfer jagen Viktor quer über den großen Sylter Deich. + Español El pingüino Wenceslao hizo kilómetros bajo exhaustiva lluvia y frío. + Ελληνικά Ξεσκεπάζω την ψυχοφθόÏ�α βδελυγμία. + РуÑ�Ñ�кий Съешь же ещё Ñ�тих мÑ�гких французÑ�ких булок да выпей чаю. + 日本語 ã�„ã‚�ã�¯ã�«ã�»ã�¸ã�¨ ã�¡ã‚Šã�¬ã‚‹ã‚’ ã‚�ã�‹ã‚ˆã�Ÿã‚Œã�� ã�¤ã�­ã�ªã‚‰ã‚€ + العربية نص حكيم له سر قاطع وذو شأن عظيم مكتوب على ثوب أخضر ومزخرÙ� + עברית דג סקרן שט בי×� מ×�וכזב ולפתע מצ×� לו חברה ×�יך הקליטה + +Symbols and box drawing: + + ┌──────┬──────â”� â†� ↑ → ↓ ✓ ✗ ½ â…“ ¾ ± × ÷ ≠ ≤ ≥ ∞ + │ a │ b │ € £ Â¥ â‚¿ © ® â„¢ ☀ â˜� ☂ ☃ + └──────┴──────┘ + +The last line has no newline at the end.""" + +FILES["recipes.json"] = json.dumps( + { + "title": "A small recipe book", + "version": 3, + "published": True, + "updated": None, + "tags": ["cooking", "demo", "café", "日本語"], + "numbers": {"integer": 42, "negative": -7, "float": 3.14159, "exponent": 6.02e23, "tiny": 1e-9, "zero": 0}, + "recipes": [ + { + "name": "Crepes", + "serves": 4, + "time": {"prep_min": 10, "rest_min": 30, "cook_min": 20}, + "ingredients": [{"item": "flour", "amount": 250, "unit": "g"}, {"item": "milk", "amount": 0.5, "unit": "l"}, {"item": "eggs", "amount": 3, "unit": None}, {"item": "salt", "amount": "a pinch"}], + "steps": ["Whisk the flour and eggs.", "Add the milk slowly.", "Rest for 30 minutes.", "Cook in a hot pan, a minute a side."], + "nutrition": {"kcal": 210, "protein_g": 8.5, "vegetarian": True}, + }, + { + "name": "Ratatouille", + "serves": 6, + "time": {"prep_min": 25, "cook_min": 60}, + "ingredients": [{"item": "aubergine", "amount": 2}, {"item": "courgette", "amount": 3}, {"item": "tomatoes", "amount": 500, "unit": "g"}, {"item": "olive oil", "amount": 4, "unit": "tbsp"}], + "steps": ["Dice the vegetables.", "Fry each in turn.", "Stew together for an hour."], + "nutrition": {"kcal": 160, "protein_g": 3.1, "vegetarian": True, "vegan": True}, + }, + ], + "nested": {"a": {"b": {"c": {"d": {"e": [1, [2, [3, [4, [5]]]]]}}}}}, + "escapes": "quote \" backslash \\ slash / newline \n tab \t unicode é 中 😀", + "empty": {"object": {}, "array": [], "string": ""}, + }, + indent=2, + ensure_ascii=False, +) + "\n" + +FILES["config.yaml"] = """# A configuration file, to show YAML as text. +service: + name: harbour-register + port: 8080 + debug: false + tags: [boats, berths, "quay east"] + limits: + requests_per_minute: 600 + body_bytes: 1048576 +database: + url: postgres://register@localhost:5432/harbour + pool: {min: 2, max: 10} +berths: + - number: 1 + length_m: 6.5 + vessel: Aurora + - number: 2 + length_m: 8.2 + vessel: Brise +notes: | + A block of text that keeps + its line breaks. +folded: > + A block of text that is + folded into one line. +anchors: + base: &base {retries: 3, timeout_s: 30} + copy: *base +""" + +FILES["pyproject.toml"] = """# A project file, to show TOML as text. +[project] +name = "harbour-register" +version = "1.4.0" +description = "The mooring register of the east quay" +requires-python = ">=3.11" +dependencies = ["httpx>=0.27", "pydantic>=2"] + +[project.optional-dependencies] +test = ["pytest", "pytest-cov"] + +[tool.ruff] +line-length = 100 +select = ["E", "F", "I"] + +[[tool.harbour.berths]] +number = 1 +length = 6.5 + +[[tool.harbour.berths]] +number = 2 +length = 8.2 +""" + +FILES["feed.xml"] = """ + + + Notes from the east quay + Moorings, tides & weather + + + urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 + 2000-01-03T12:00:00Z + The harbour officeoffice@example.invalid + + New berths on the east quay + + urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a + 2000-01-03T12:00:00Z + Twelve berths for visiting boats open on 1 March. +

The east quay is longer by 40 metres.

+ +
+ + Tide tables for the year + + urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6b + 2000-01-01T08:00:00Z + + +
+""" + + +def gpx(): + pts = [] + for i in range(60): + t = i / 59 + lat = 48.3794 + 0.03 * math.sin(t * 5) + 0.01 * t + lon = -4.4900 + 0.06 * t + 0.01 * math.cos(t * 7) + ele = 20 + 15 * math.sin(t * 9) + 10 * t + pts.append(f' {ele:.1f}') + return ( + '\n' + '\n' + " Coastal walk (made up)A made-up track, 60 points.\n" + ' StartFlag\n' + ' ViewpointSeals on the rocks, in winter.\n' + " \n Morning walk\n \n" + "\n".join(pts) + "\n \n \n\n" + ) + + +FILES["route.gpx"] = gpx() + +FILES["places.kml"] = """ + + + Places (made up) + + + East quay + Moorings
for 60 boats.]]> + #harbour + -4.4860,48.3830,0 + + + Breakwater + 1-4.4900,48.3790,0 -4.4850,48.3820,0 -4.4800,48.3835,0 + + + Anchorage + #harbour + -4.4950,48.3850,0 -4.4900,48.3850,0 -4.4900,48.3900,0 -4.4950,48.3900,0 -4.4950,48.3850,0 + + + +""" + + +def harbour_csv(): + rng = random.Random(11) + boats = ["Aurora", "Brise", "Calypso", "Dorade", "Etoile", "Fauvette", "Goeland", "Hirondelle", "Iroise", "Jolie Brise", "Kerguelen", "La Mouette"] + kinds = ["sloop", "ketch", "trawler", "motor yacht", "catamaran", "dinghy"] + notes = ["", "", "", "Arrived late, \"quiet\" night", "Bill sent; paid by cheque", "Owner: M. Le Gall, tel. 02 98 00 00 00", "Two nights,\nleft at dawn", "Café voucher given", ""] + rows = ["date,vessel,type,length_m,beam_m,berth,nights,fee_eur,notes"] + + def q(s): + s = str(s) + return '"' + s.replace('"', '""') + '"' if any(c in s for c in ',"\n') else s + + for i in range(300): + d = 1 + i // 10 + month = 1 + (d - 1) // 28 + day = 1 + (d - 1) % 28 + length = round(rng.uniform(4.5, 16.0), 1) + nights = rng.randint(1, 5) + rows.append(",".join(q(v) for v in [f"2000-{month:02d}-{day:02d}", rng.choice(boats) + (f" {i // 40 + 2}" if i > 40 else ""), rng.choice(kinds), length, round(length * 0.33, 2), rng.randint(1, 60), nights, f"{nights * (8 + length * 1.6):.2f}", rng.choice(notes)])) + return "\n".join(rows) + "\n" + + +FILES["harbour-log.csv"] = harbour_csv() + +FILES["tides.tsv"] = "day\thigh_1\theight_1_m\tlow_1\theight_2_m\tcoefficient\n" + "\n".join( + f"{d}\t{(5 + d * 0.8) % 24:05.2f}\t{4.5 + 2.4 * math.sin(d / 4.7):.2f}\t{(11 + d * 0.8) % 24:05.2f}\t{1.2 + 0.8 * math.cos(d / 4.7):.2f}\t{int(70 + 40 * math.sin(d / 4.7))}" for d in range(1, 29) +) + "\n" + +FILES["prix.csv"] = "Région;Produit;Quantité;Prix unitaire (€);Total (€)\n" + "\n".join( + f"{r};{p};{q};{u:.2f}".replace(".", ",") + ";" + f"{q * u:.2f}".replace(".", ",") + for r, p, q, u in [("Bretagne", "Cidre", 120, 3.5), ("Bretagne", "Galettes", 300, 1.2), ("Normandie", "Cidre", 90, 3.8), ("Normandie", "Camembert", 200, 4.1), ("Alsace", "Riesling", 150, 7.9), ("Alsace", "Bretzels", 500, 0.6)] +) + "\n" + +FILES["life.py"] = '''"""Conway's Game of Life on a torus, printed as text. CC0-1.0, exav project.""" +import random +import sys + +WIDTH, HEIGHT = 40, 16 + + +def step(cells): + """The next generation of a set of (x, y) cells on a WIDTH by HEIGHT torus.""" + counts = {} + for (x, y) in cells: + for dx in (-1, 0, 1): + for dy in (-1, 0, 1): + if dx or dy: + key = ((x + dx) % WIDTH, (y + dy) % HEIGHT) + counts[key] = counts.get(key, 0) + 1 + return {cell for cell, n in counts.items() if n == 3 or (n == 2 and cell in cells)} + + +def show(cells): + return "\\n".join("".join("#" if (x, y) in cells else "." for x in range(WIDTH)) for y in range(HEIGHT)) + + +def main(generations=20, seed=7): + rng = random.Random(seed) + cells = {(x, y) for x in range(WIDTH) for y in range(HEIGHT) if rng.random() < 0.25} + for g in range(generations): + print(f"generation {g}: {len(cells)} cells") + print(show(cells)) + cells = step(cells) + + +if __name__ == "__main__": + main(*(int(a) for a in sys.argv[1:3])) +''' + +FILES["lru.rs"] = '''//! A small least-recently-used cache. CC0-1.0, exav project. +use std::collections::HashMap; +use std::hash::Hash; + +/// A cache that keeps at most `capacity` entries and drops the one used longest ago. +pub struct Lru { + capacity: usize, + tick: u64, + entries: HashMap, +} + +impl Lru { + pub fn new(capacity: usize) -> Self { + assert!(capacity > 0, "a cache holds at least one entry"); + Lru { capacity, tick: 0, entries: HashMap::with_capacity(capacity) } + } + + pub fn get(&mut self, key: &K) -> Option<&V> { + self.tick += 1; + let tick = self.tick; + self.entries.get_mut(key).map(|(v, used)| { + *used = tick; + &*v + }) + } + + pub fn put(&mut self, key: K, value: V) -> Option { + self.tick += 1; + if !self.entries.contains_key(&key) && self.entries.len() == self.capacity { + let oldest = self.entries.iter().min_by_key(|(_, (_, used))| *used).map(|(k, _)| k.clone()); + if let Some(k) = oldest { + self.entries.remove(&k); + } + } + self.entries.insert(key, (value, self.tick)).map(|(v, _)| v) + } + + pub fn len(&self) -> usize { + self.entries.len() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn drops_the_least_recently_used() { + let mut c = Lru::new(2); + c.put("a", 1); + c.put("b", 2); + assert_eq!(c.get(&"a"), Some(&1)); + c.put("c", 3); + assert_eq!(c.get(&"b"), None); + assert_eq!(c.len(), 2); + } +} +''' + +FILES["tokens.ts"] = '''// An arithmetic tokenizer and evaluator. CC0-1.0, exav project. +type Token = { kind: "num"; value: number } | { kind: "op"; value: "+" | "-" | "*" | "/" | "^" } | { kind: "paren"; value: "(" | ")" }; + +export function tokenize(source: string): Token[] { + const tokens: Token[] = []; + const re = /\\s*(?:(\\d+(?:\\.\\d+)?)|([-+*/^])|([()]))/y; + let match: RegExpExecArray | null; + while (re.lastIndex < source.length && (match = re.exec(source))) { + if (match[1] !== undefined) tokens.push({ kind: "num", value: Number(match[1]) }); + else if (match[2]) tokens.push({ kind: "op", value: match[2] as "+" }); + else tokens.push({ kind: "paren", value: match[3] as "(" }); + } + if (re.lastIndex < source.trimEnd().length) throw new SyntaxError(`unexpected character at ${re.lastIndex}`); + return tokens; +} + +const PRECEDENCE: Record = { "+": [1, "left"], "-": [1, "left"], "*": [2, "left"], "/": [2, "left"], "^": [3, "right"] }; + +/** Evaluates with the shunting-yard algorithm. */ +export function evaluate(source: string): number { + const out: number[] = []; + const ops: string[] = []; + const apply = (op: string) => { + const b = out.pop(); + const a = out.pop(); + if (a === undefined || b === undefined) throw new SyntaxError("missing operand"); + out.push(op === "+" ? a + b : op === "-" ? a - b : op === "*" ? a * b : op === "/" ? a / b : a ** b); + }; + for (const t of tokenize(source)) { + if (t.kind === "num") out.push(t.value); + else if (t.kind === "op") { + const [p, assoc] = PRECEDENCE[t.value]!; + while (ops.length) { + const top = ops[ops.length - 1]!; + const [tp] = PRECEDENCE[top] ?? [-1]; + if (top !== "(" && (tp > p || (tp === p && assoc === "left"))) apply(ops.pop()!); + else break; + } + ops.push(t.value); + } else if (t.value === "(") ops.push("("); + else { + while (ops.length && ops[ops.length - 1] !== "(") apply(ops.pop()!); + if (ops.pop() !== "(") throw new SyntaxError("unbalanced parenthesis"); + } + } + while (ops.length) { + const op = ops.pop()!; + if (op === "(") throw new SyntaxError("unbalanced parenthesis"); + apply(op); + } + return out[0] ?? NaN; +} + +console.log(evaluate("2 + 3 * (4 - 1) ^ 2")); +''' + +FILES["bits.c"] = '''/* Bit tricks on 32-bit words. CC0-1.0, exav project. */ +#include +#include + +/* The number of set bits, by the parallel sum. */ +static unsigned popcount32(uint32_t x) { + x = x - ((x >> 1) & 0x55555555u); + x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u); + x = (x + (x >> 4)) & 0x0f0f0f0fu; + return (x * 0x01010101u) >> 24; +} + +/* The index of the highest set bit, or -1 for zero. */ +static int high_bit(uint32_t x) { + int n = -1; + while (x) { + n++; + x >>= 1; + } + return n; +} + +/* The next power of two that is not below x. */ +static uint32_t next_pow2(uint32_t x) { + if (x <= 1) return 1; + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x + 1; +} + +/* The bits of x in reverse order. */ +static uint32_t reverse32(uint32_t x) { + x = ((x >> 1) & 0x55555555u) | ((x & 0x55555555u) << 1); + x = ((x >> 2) & 0x33333333u) | ((x & 0x33333333u) << 2); + x = ((x >> 4) & 0x0f0f0f0fu) | ((x & 0x0f0f0f0fu) << 4); + x = ((x >> 8) & 0x00ff00ffu) | ((x & 0x00ff00ffu) << 8); + return (x >> 16) | (x << 16); +} + +int main(void) { + const uint32_t samples[] = {0u, 1u, 255u, 1000u, 0xdeadbeefu}; + for (size_t i = 0; i < sizeof samples / sizeof samples[0]; i++) { + uint32_t v = samples[i]; + printf("%10u: bits %2u, high %2d, pow2 %10u, reversed %08x\\n", v, popcount32(v), high_bit(v), next_pow2(v), reverse32(v)); + } + return 0; +} +''' + +FILES["report.sql"] = """-- Moorings by month, with window functions. CC0-1.0, exav project. +CREATE TABLE vessel ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL UNIQUE, + length_m REAL NOT NULL CHECK (length_m > 0), + kind TEXT NOT NULL DEFAULT 'sloop' +); + +CREATE TABLE stay ( + id INTEGER PRIMARY KEY, + vessel_id INTEGER NOT NULL REFERENCES vessel (id), + berth INTEGER NOT NULL, + arrived DATE NOT NULL, + nights INTEGER NOT NULL, + fee_eur NUMERIC(8, 2) +); + +CREATE INDEX stay_by_arrival ON stay (arrived); + +WITH monthly AS ( + SELECT strftime('%Y-%m', arrived) AS month, + count(*) AS stays, + sum(nights) AS nights, + sum(fee_eur) AS income + FROM stay + GROUP BY 1 +) +SELECT month, + stays, + income, + income - lag(income) OVER (ORDER BY month) AS change, + round(100.0 * income / sum(income) OVER (), 1) AS share_pct, + rank() OVER (ORDER BY income DESC) AS income_rank +FROM monthly +ORDER BY month; + +-- The ten longest boats that stayed more than three nights. +SELECT v.name, v.length_m, s.nights +FROM vessel AS v +JOIN stay AS s ON s.vessel_id = v.id +WHERE s.nights > 3 AND v.kind IN ('ketch', 'trawler') +ORDER BY v.length_m DESC +LIMIT 10; +""" + +FILES["deploy.sh"] = """#!/usr/bin/env bash +# Build, check and copy a static site. CC0-1.0, exav project. +set -euo pipefail + +SITE_DIR="${SITE_DIR:-./public}" +REMOTE="${REMOTE:-deploy@example.invalid:/var/www/site}" +LOG="$(mktemp)" + +cleanup() { + local status=$? + rm -f "$LOG" + if [ "$status" -ne 0 ]; then + echo "deploy failed with status $status" >&2 + fi +} +trap cleanup EXIT + +log() { printf '[%s] %s\\n' "$(date +%H:%M:%S)" "$*"; } + +build() { + log "building" + npm ci --silent >"$LOG" 2>&1 || { cat "$LOG" >&2; return 1; } + npm run build --silent +} + +check() { + local broken=0 + while IFS= read -r -d '' file; do + if ! grep -q '' "$file"; then + log "incomplete page: $file" + broken=$((broken + 1)) + fi + done < <(find "$SITE_DIR" -name '*.html' -print0) + return "$broken" +} + +case "${1:-all}" in + build) build ;; + check) check ;; + all) build && check && rsync -az --delete "$SITE_DIR/" "$REMOTE" && log "done" ;; + *) echo "usage: $0 [build|check|all]" >&2; exit 2 ;; +esac +""" + +FILES["style.css"] = """/* A small stylesheet with custom properties, grid and a media query. CC0-1.0, exav project. */ +:root { + --ink: #1b2430; + --paper: #fbfaf7; + --accent: #0b7285; + --radius: 0.5rem; + --gap: clamp(0.75rem, 2vw, 1.5rem); + color-scheme: light dark; +} + +@media (prefers-color-scheme: dark) { + :root { --ink: #e7edf3; --paper: #12171d; --accent: #66d9e8; } +} + +*, *::before, *::after { box-sizing: border-box; } + +body { + margin: 0; + background: var(--paper); + color: var(--ink); + font: 1rem/1.55 system-ui, sans-serif; +} + +.cards { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); + gap: var(--gap); + padding: var(--gap); +} + +.card { + padding: 1rem; + border: 1px solid color-mix(in srgb, var(--ink) 20%, transparent); + border-radius: var(--radius); + transition: transform 120ms ease, box-shadow 120ms ease; +} + +.card:hover, +.card:focus-within { + transform: translateY(-2px); + box-shadow: 0 6px 18px rgb(0 0 0 / 0.12); +} + +.card > h2::after { content: " \\2192"; color: var(--accent); } + +a:not([class]) { color: var(--accent); text-underline-offset: 0.2em; } + +@media (max-width: 40rem) { + .cards { grid-template-columns: 1fr; } +} +""" + +FILES["page.html"] = """ + + + + A page, shown as its source + + + + + + +

Harbour office

+
+
+

Berths

+ + + +
BerthLength
16.5 m
28.2 m
+

Lengths are over all, in metres.

+
+
+
+ + + +""" + +FILES["changes.diff"] = """diff --git a/src/berths.py b/src/berths.py +index 3f2a1c4..9b7d0e8 100644 +--- a/src/berths.py ++++ b/src/berths.py +@@ -10,12 +10,16 @@ class Berth: + number: int + length_m: float ++ max_draught_m: float = 1.5 + + def fits(self, boat): +- return boat.length_m <= self.length_m ++ return boat.length_m <= self.length_m and boat.draught_m <= self.max_draught_m + + def label(self): +- return "Berth %d" % self.number ++ return f"Berth {self.number} ({self.length_m:.1f} m)" +@@ -40,7 +44,7 @@ def free_berths(register, boat): + for berth in register: + if berth.fits(boat): + yield berth +- return ++ return None +diff --git a/README.md b/README.md +index 1e2d3f4..5a6b7c8 100644 +--- a/README.md ++++ b/README.md +@@ -1,4 +1,5 @@ + # Harbour register + + The mooring register of the east quay. ++Berths now have a maximum draught. +""" + +FILES["subtitles.srt"] = "\n".join( + f"{i}\n00:00:{2 * i:02d},000 --> 00:00:{2 * i + 1:02d},800\n{line}\n" + for i, line in enumerate(["The tide is coming in.", "Berth fourteen is free.", "A gull laughs.", "Take the line, please.", "Engine off, thank you.", "Welcome to the east quay."], 1) +) + +FILES["server.log"] = "".join( + f'2000-01-01T{8 + i // 60:02d}:{i % 60:02d}:{(i * 7) % 60:02d}Z {["INFO", "INFO", "INFO", "WARN", "ERROR"][i % 5]} request id={1000 + i} path=/berths/{i % 60 + 1} status={[200, 200, 304, 404, 500][i % 5]} ms={12 + (i * 37) % 250}\n' for i in range(120) +) + +for name, text in FILES.items(): + write(name, text) diff --git a/crates/exav-viewer/demo/examples/generate/verify-evidence.mjs b/crates/exav-viewer/demo/examples/generate/verify-evidence.mjs new file mode 100644 index 0000000..7608110 --- /dev/null +++ b/crates/exav-viewer/demo/examples/generate/verify-evidence.mjs @@ -0,0 +1,96 @@ +#!/usr/bin/env node +// Fetches the page that states each third-party example's licence and checks +// that the words recorded in examples.json (`evidence_quote`) are on it. +// +// node generate/verify-evidence.mjs [name-fragment ...] +// +// A name fragment also matches the evidence address (`commons.wikimedia.org`). +// It needs the network and is slow on purpose (one request at a time, with a +// pause), so it is not part of the demo build. A page that is a PDF is read with +// pdftotext, and a web page is read without its tags. An entry with `evidence_row` names a field (the file's SHA-256) that +// must sit in the same row of a JSON table as the quote. Exit 1 when a quote is +// missing or a page cannot be read. +import { execFileSync } from "node:child_process"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const here = path.dirname(fileURLToPath(import.meta.url)); +const { examples } = JSON.parse(fs.readFileSync(path.join(here, "..", "examples.json"), "utf8")); +const only = process.argv.slice(2); +const USER_AGENT = "exav-examples/1.0 (https://github.com/sylvinus/exav)"; + +const norm = (s) => + s + .replace(/\\\//g, "/") + .replace(/&/g, "&") + .replace(/"/g, '"') + .replace(/�?39;|'/g, "'") + .replace(/ /g, " ") + .replace(/\\"/g, '"') + .replace(/\s+/g, " ") + .replace(/ ([.,;:!?)])/g, "$1"); + +const cache = new Map(); +async function page(url) { + if (cache.has(url)) return cache.get(url); + let last; + for (let attempt = 1; attempt <= 4; attempt++) { + try { + const res = await fetch(url, { headers: { "User-Agent": USER_AGENT, Accept: "*/*" }, redirect: "follow" }); + if (res.ok) { + const buf = Buffer.from(await res.arrayBuffer()); + let raw; + const texts = []; + if (buf.subarray(0, 5).toString() === "%PDF-") { + const tmp = path.join(os.tmpdir(), `exav-evidence-${process.pid}.pdf`); + fs.writeFileSync(tmp, buf); + raw = execFileSync("pdftotext", [tmp, "-"], { maxBuffer: 1 << 28 }).toString(); + fs.rmSync(tmp); + } else { + raw = buf.toString("utf8"); + // A web page is also read as a person sees it, tags apart. + if (/]/i.test(raw.slice(0, 2000)) || /^\s*/gi, " ").replace(/<[^>]*>/g, " ")); + } + } + texts.push(raw); + cache.set(url, texts); + return texts; + } + last = new Error(`HTTP ${res.status}`); + if (res.status !== 429 && res.status < 500) break; + } catch (e) { + last = e; + } + await new Promise((r) => setTimeout(r, 2000 * attempt)); + } + throw new Error(`${url}: ${last?.message ?? last}`); +} + +let failed = 0; +let checked = 0; +for (const e of examples) { + if (e.generated || (only.length && !only.some((o) => e.file.includes(o) || e.evidence.includes(o)))) continue; + checked++; + try { + const texts = await page(e.evidence); + const quote = norm(e.evidence_quote); + let ok; + if (e.evidence_row) { + const row = norm(texts.at(-1)).split(/\],\s?\[/).find((r) => r.includes(e[e.evidence_row])); + ok = Boolean(row) && row.includes(quote); + } else { + ok = texts.some((t) => norm(t).includes(quote)); + } + console.log(`${ok ? "ok " : "FAIL"} ${e.file}: ${e.evidence}`); + if (!ok) failed++; + } catch (err) { + console.log(`FAIL ${e.file}: ${err.message}`); + failed++; + } + await new Promise((r) => setTimeout(r, 400)); +} +console.log(`${checked} pages checked, ${failed} failed`); +process.exit(failed ? 1 : 0); diff --git a/crates/exav-viewer/demo/examples/verify-open.mjs b/crates/exav-viewer/demo/examples/verify-open.mjs new file mode 100644 index 0000000..dbe2549 --- /dev/null +++ b/crates/exav-viewer/demo/examples/verify-open.mjs @@ -0,0 +1,205 @@ +#!/usr/bin/env node +// Checks that the viewer's own engines read every example, in Node, without a browser: +// +// node demo/examples/verify-open.mjs [name-fragment ...] +// +// For each example (from demo/public/examples/ after `npm run demo:examples`, else +// the committed files/), it asks the viewer's detection (dist/core, from `npm run +// build`) which format claims it, and then reads it with the engine for that +// format: the wasm decoders and converters of wasm/ (`npm run build:wasm`), +// @exav/unpack-wasm for archives and pdf.js for PDF. A file of the `unsupported` +// group must fail; any other must open. Exit 1 on a surprise. +// +// What it does not check: that the picture drawn is right (it counts what the +// engine returns), and the browser-only formats (the browser draws PNG, JPEG, +// GIF, WebP and SVG; its media players play audio and video): those are checked +// by their signature. +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath, pathToFileURL } from "node:url"; + +const here = path.dirname(fileURLToPath(import.meta.url)); +const pkg = path.join(here, "..", ".."); +const only = process.argv.slice(2); +const { examples } = JSON.parse(fs.readFileSync(path.join(here, "examples.json"), "utf8")); + +const wasm = (name) => path.join(pkg, "wasm", name); +const need = (p) => { + if (!fs.existsSync(p)) throw new Error(`${path.relative(pkg, p)} is missing: run npm run build:wasm and npm run build first`); + return p; +}; +const load = async (name) => { + const mod = await import(pathToFileURL(need(wasm(`exav_viewer_${name}.js`))).href); + mod.initSync({ module: fs.readFileSync(wasm(`exav_viewer_${name}_bg.wasm`)) }); + return mod; +}; +const cache = {}; +const engine = async (name) => (cache[name] ??= await load(name)); + +const formats = await import(pathToFileURL(need(path.join(pkg, "dist", "core", "formats.js"))).href); +const { createDetector } = await import(pathToFileURL(path.join(pkg, "dist", "core", "detect.js")).href); +const merge = (a, b) => ({ ...a, types: [...(a.types ?? []), ...(b.types ?? [])], extensions: [...(a.extensions ?? []), ...(b.extensions ?? [])], extensionOverrides: [...(a.extensionOverrides ?? []), ...(b.extensionOverrides ?? [])] }); +const detector = createDetector(formats.BUILTIN_ORDER.map((id) => ({ id, match: id === "image" ? merge(formats.MATCHERS.image, formats.WASM_IMAGES) : formats.MATCHERS[id] }))); + +let unpack; +const archive = async () => { + if (!unpack) { + const dir = path.join(pkg, "..", "exav-unpack-wasm", "pkg"); + unpack = await import(pathToFileURL(need(path.join(dir, "exav_unpack_wasm.js"))).href); + unpack.initSync({ module: fs.readFileSync(path.join(dir, "exav_unpack_wasm_bg.wasm")) }); + } + return unpack; +}; + +let pdfjs; +const pdf = async () => (pdfjs ??= await import(pathToFileURL(path.join(pkg, "node_modules", "pdfjs-dist", "legacy", "build", "pdf.mjs")).href)); + +const ext = (name) => path.extname(name).slice(1).toLowerCase(); +const GB = 1 << 30; + +/** One check per detected format: returns a short description, or throws. */ +const READ = { + async image(name, bytes) { + const e = ext(name); + if (["png", "jpg", "jpeg", "gif", "webp"].includes(e)) { + const type = detector.sniff(bytes.subarray(0, 512)); + if (!type.startsWith("image/")) throw new Error(`sniffed as "${type}"`); + return `browser draws it (${type})`; + } + if (e === "svg") { + if (!/]/.test(new TextDecoder().decode(bytes.subarray(0, 4096)))) throw new Error("no element at the start"); + return "browser draws it (SVG)"; + } + const m = await engine("image"); + const d = m.decodeImage(bytes, 1 << 29); + const px = d.takeRgba(); + let sum = 0; + for (let i = 0; i < px.length; i += 4) sum += px[i] + px[i + 1] + px[i + 2]; + if (px.length === 0 || sum === 0) throw new Error("decoded to nothing, or all black"); + return `${m.imageFormat(bytes.subarray(0, 512)) ?? "?"} ${d.width}x${d.height}`; + }, + async dwg(name, bytes) { + const m = await engine("dwg"); + const doc = m.parseDrawing(bytes, GB / 2); + const layouts = JSON.parse(doc.layoutsJson()); + let best = 0; + for (const l of layouts) { + const d = doc.tessellate(l.name, new Uint8Array([255, 255, 255]), 50_000_000); + best = Math.max(best, d.opaqueStrokes() + d.opaqueFills()); + } + if (!best) throw new Error("nothing drawn"); + return `${layouts.length} layout(s), ${best} strokes and fills`; + }, + async model(name, bytes, id) { + const m = await engine("model"); + const model = { stl: m.parseStl, obj: m.parseObj, ply: m.parsePly, gltf: m.parseGltf, ifc: m.parseIfc }[id](bytes, 20_000_000); + const meta = JSON.parse(model.metaJson()); + const tris = meta.batches.reduce((n, b) => n + b.indices / 3, 0); + if (!tris) throw new Error("no triangles"); + return `${tris} triangles, ${meta.elements.length} element(s)`; + }, + async ooxml(name, bytes, id) { + const a = (await archive()).Archive.open(bytes); + const names = a.list().map((e) => e.name); + const part = { docx: "word/document.xml", xlsx: "xl/workbook.xml", pptx: "ppt/presentation.xml" }[id]; + if (!names.includes(part)) throw new Error(`no ${part}`); + return `${names.length} parts`; + }, + async docs(name, bytes) { + const c = (await engine("docs")).convertDocs(bytes, ext(name), 1e6, GB); + return `${c.paragraphs} paragraphs, ${c.takeDocx().length} bytes of DOCX`; + }, + async sheets(name, bytes) { + const c = (await engine("sheets")).convertSheets(bytes, ext(name), 1e7, GB); + return `${c.takeXlsx().length} bytes of XLSX`; + }, + async slides(name, bytes) { + const c = (await engine("slides")).convertSlides(bytes, ext(name), 1e6, GB, Infinity); + return `${c.slides} slide(s)`; + }, + async pdf(name, bytes) { + const lib = await pdf(); + const task = lib.getDocument({ data: new Uint8Array(bytes), useSystemFonts: false, isEvalSupported: false, verbosity: 0 }); + try { + const doc = await task.promise; + const outline = await doc.getOutline(); + const page = await doc.getPage(1); + const annots = (await page.getAnnotations()).length; + return `${doc.numPages} page(s), ${outline?.length ?? 0} outline entries, ${annots} annotations on page 1`; + } finally { + await task.destroy(); + } + }, + async text(name, bytes) { + const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes); + if (["json", "geojson"].includes(ext(name))) JSON.parse(text); + if (["md", "markdown"].includes(ext(name))) { + const doc = JSON.parse((await engine("text")).parseMarkdown(text)); + return `markdown, ${JSON.stringify(doc).length} bytes of tree`; + } + return `${text.split("\n").length} lines`; + }, + async csv(name, bytes) { + const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes); + const lines = text.split(/\r?\n/).filter(Boolean); + if (lines.length < 2) throw new Error("fewer than two rows"); + return `${lines.length} lines`; + }, + async archive(name, bytes) { + const a = (await archive()).Archive.open(bytes); + const list = a.list(); + if (!list.length) throw new Error("no members"); + return `${a.format()}, ${list.length} member(s)${list.some((m) => m.encrypted) ? ", encrypted" : ""}`; + }, + async media(name, bytes) { + // The browser's players decode them; here only that the head is a media container's or an MP3 frame's. + const type = detector.sniff(bytes.subarray(0, 512)); + const mp3Frame = bytes[0] === 0xff && (bytes[1] & 0xe0) === 0xe0; + if (!/^(audio|video|application\/ogg)/.test(type) && !mp3Frame) throw new Error(`sniffed as "${type}"`); + return `plays in the browser (${type || "MP3 frames"})`; + }, +}; + +const ROUTE = { + image: READ.image, dwg: READ.dwg, dxf: READ.dwg, ifc: (n, b) => READ.model(n, b, "ifc"), stl: (n, b) => READ.model(n, b, "stl"), obj: (n, b) => READ.model(n, b, "obj"), + ply: (n, b) => READ.model(n, b, "ply"), gltf: (n, b) => READ.model(n, b, "gltf"), docx: (n, b) => READ.ooxml(n, b, "docx"), xlsx: (n, b) => READ.ooxml(n, b, "xlsx"), + pptx: (n, b) => READ.ooxml(n, b, "pptx"), rtf: READ.docs, doc: READ.docs, odt: READ.docs, xls: READ.sheets, ods: READ.sheets, numbers: READ.sheets, + ppt: READ.slides, odp: READ.slides, keynote: READ.slides, odg: READ.slides, visio: READ.slides, pdf: READ.pdf, text: READ.text, csv: READ.csv, + archive: READ.archive, video: READ.media, audio: READ.media, +}; + +let surprises = 0; +let count = 0; +for (const e of examples) { + if (only.length && !only.some((o) => e.file.includes(o))) continue; + const served = path.join(pkg, "demo", "public", "examples", e.file); + const file = fs.existsSync(served) ? served : e.path ? path.join(here, "files", e.path) : null; + if (!file || !fs.existsSync(file)) { + console.log(`skip ${e.file}: not downloaded`); + continue; + } + count++; + const bytes = new Uint8Array(fs.readFileSync(file)); + // As the demo does it: a file given by its address has a name and no type. + const id = detector.detect({ type: "", name: e.file, path: e.file }); + const expectFail = e.group === "unsupported"; + let result; + try { + if (!id) throw new Error("no plugin claims it"); + if (["pages", "coreldraw", "publisher", "pagemaker", "freehand", "quarkxpress", "zonerdraw", "wpg"].includes(id)) throw new Error(`${id} needs an external converter`); + if (!ROUTE[id]) throw new Error(`no check for ${id}`); + result = { ok: true, text: `${id}: ${await ROUTE[id](e.file, bytes)}` }; + } catch (err) { + result = { ok: false, text: `${id ?? "none"}: ${String(err.message ?? err).slice(0, 120)}` }; + } + // The ODG converter is newer than some builds of wasm/: say so rather than fail. + if (!result.ok && id === "odg" && /unsupported/.test(result.text) && !expectFail) { + console.log(`warn ${e.file.padEnd(44)} ${result.text} (wasm/ may predate ODG: run npm run build:wasm)`); + continue; + } + const fine = result.ok !== expectFail; + if (!fine) surprises++; + console.log(`${fine ? "ok " : "FAIL"} ${e.file.padEnd(44)} ${expectFail ? "(unsupported on purpose) " : ""}${result.text}`); +} +console.log(`${count} examples read, ${surprises} surprise${surprises === 1 ? "" : "s"}`); +process.exit(surprises ? 1 : 0); diff --git a/crates/exav-viewer/demo/headless.html b/crates/exav-viewer/demo/headless.html new file mode 100644 index 0000000..59d0e57 --- /dev/null +++ b/crates/exav-viewer/demo/headless.html @@ -0,0 +1,32 @@ + + + + + + + + exav viewer, the host's own controls + + +
+

The host's own controls

+

Each file in the sandboxed frame; every button on this page is the page's, driven by the session's controllers. No React.

+ + + +
+
+ +
+
+
+
+
+
+
    + + + diff --git a/crates/exav-viewer/demo/src/App.tsx b/crates/exav-viewer/demo/src/App.tsx index e58f2d1..84b20eb 100644 --- a/crates/exav-viewer/demo/src/App.tsx +++ b/crates/exav-viewer/demo/src/App.tsx @@ -1,17 +1,45 @@ import { useCallback, useEffect, useMemo, useRef, useState, type DragEvent, type ReactNode } from "react"; -import type { ViewerFile } from "@exav/viewer"; +import { BUILTIN_ORDER, type Session, type ViewerFile } from "@exav/viewer"; import { allPlugins } from "@exav/viewer/all"; +import { + coreldraw, + doc, + freehand, + keynote, + numbers, + odg, + odp, + ods, + odt, + pagemaker, + ppt, + publisher, + quarkxpress, + rtf, + visio, + wpg, + xls, + zonerdraw, +} from "@exav/viewer/office"; import { ViewerBody, ViewerProvider } from "@exav/viewer/react"; import { SandboxedViewerProvider } from "@exav/viewer/react/sandbox"; -import { GROUPS, type Sample } from "./showcase.js"; +import { ExportImage } from "./ExportImage.js"; +import { credit, GROUPS, type Example, type Sample } from "./showcase.js"; type Locale = "en" | "fr"; /** A file in the list, shown by its name. */ type Item = ViewerFile; +/** A sample or an example in the sidebar: its section, and who made it, under what licence. */ +interface Listed { + group: string; + note: string; + item: Item; +} + const TEXT = { en: { tagline: "Files viewed in the browser. Nothing you open here leaves your device.", @@ -21,7 +49,7 @@ const TEXT = { docs: "Documentation", licences: "Licences", upload: "Drop files here, or click to choose", - formats: "PDF, images, DWG and DXF drawings, Word, Excel, PowerPoint, CSV, IFC and STL models, video, audio and archives. Or pick a sample on the left.", + formats: "PDF, images, DWG and DXF drawings, Word, Excel, PowerPoint, CSV, text, Markdown, JSON and XML, IFC, STL, OBJ, PLY and glTF models, video, audio and archives. Or pick a sample on the left.", }, fr: { tagline: "Des fichiers affichés dans le navigateur. Rien de ce que vous ouvrez ici ne quitte votre appareil.", @@ -31,7 +59,7 @@ const TEXT = { docs: "Documentation", licences: "Licences", upload: "Déposez des fichiers ici, ou cliquez pour les choisir", - formats: "PDF, images, plans DWG et DXF, Word, Excel, PowerPoint, CSV, maquettes IFC et STL, vidéo, audio et archives. Ou choisissez un exemple à gauche.", + formats: "PDF, images, plans DWG et DXF, Word, Excel, PowerPoint, CSV, texte, Markdown, JSON et XML, maquettes IFC, STL, OBJ, PLY et glTF, vidéo, audio et archives. Ou choisissez un exemple à gauche.", }, } satisfies Record>; @@ -47,21 +75,54 @@ const IN_PAGE = QUERY.get("mode") === "page"; /** Where the demo is deployed (vite.config.ts): the frame may show media and fetch from it. */ declare const __DEMO_ORIGIN__: string; +/** The external converter the demo was built with (`EXAV_EXTERNAL_CONVERTER`), or null. */ +declare const __EXTERNAL_CONVERTER__: string | null; /** * The frame's delivery per kind of file, defaults unless `?delivery=pdf:url,media:blob` * says otherwise (the browser tests). */ const DELIVERY = Object.fromEntries((QUERY.get("delivery") ?? "").split(",").filter(Boolean).map((d) => d.split(":"))); + +// Every format, the converted Office ones included: where no external +// converter was copied in, a format only it reads ends in "needs_converter". +/** + * `?converter=exav` or `?converter=external` (the browser tests): without + * it, text documents (DOC, ODT, RTF) go to the external converter when the + * demo has one, else to exav-render's `docs`. + */ +const CONVERTER = { + ...(QUERY.get("converter") === "exav" || QUERY.get("converter") === "external" ? { converter: QUERY.get("converter") as "exav" | "external" } : {}), + // `?timeoutMs=500&maxMemory=5000000` (the browser tests). + ...(QUERY.get("timeoutMs") ? { timeoutMs: Number(QUERY.get("timeoutMs")) } : {}), + ...(QUERY.get("maxMemory") ? { maxMemory: Number(QUERY.get("maxMemory")) } : {}), + // `?externalConverter=/e2e/fake-converter.js`: a converter by its URL (the browser tests). + ...(QUERY.get("externalConverter") || __EXTERNAL_CONVERTER__ ? { externalConverter: QUERY.get("externalConverter") ?? __EXTERNAL_CONVERTER__! } : {}), +}; + const SANDBOX = { url: `${BASE}frame/index.html`, + options: { conversion: CONVERTER }, origins: { media: [__DEMO_ORIGIN__], connect: [__DEMO_ORIGIN__] }, delivery: DELIVERY, + formats: BUILTIN_ORDER, }; /** `?url=
    `: a file by its address, opened first. */ const LINKED = QUERY.get("url"); +/** `?cad=monochrome`: drawings in ink, as plotted; `?rasterTile=64`: pictures drawn in small tiles (the browser tests). */ +const CAD = { + ...(QUERY.get("cad") === "monochrome" ? { monochrome: true } : {}), + ...(QUERY.get("rasterTile") ? { rasterTile: Number(QUERY.get("rasterTile")) } : {}), +}; + +/** `?rasterTile=64` and `?rasterSupersample=2`: the models' pictures drawn in small tiles, or supersampled (the browser tests). */ +const MODEL = { + ...(QUERY.get("rasterTile") ? { rasterTile: Number(QUERY.get("rasterTile")) } : {}), + ...(QUERY.get("rasterSupersample") ? { rasterSupersample: Number(QUERY.get("rasterSupersample")) } : {}), +}; + /** The engines in the page (`?mode=page`), or each file in a sandboxed frame, the default. */ function Provider({ plugins, locale, children }: { plugins: ReturnType; locale: Locale; children: ReactNode }) { return IN_PAGE ? ( @@ -81,40 +142,71 @@ function initialLocale(): Locale { return navigator.language.toLowerCase().startsWith("fr") ? "fr" : "en"; } +/** Hands the viewer's session to the page around it, and takes it back when the file goes. */ +function SessionOut({ session, onSession }: { session: Session | null; onSession: (s: Session | null) => void }) { + useEffect(() => { + onSession(session); + return () => onSession(null); + }, [session, onSession]); + return null; +} + export function App() { const [locale, setLocale] = useState(initialLocale); const [own, setOwn] = useState([]); // Nothing open until a file is chosen, unless the address names one. const [selected, setSelected] = useState(() => (LINKED ? "linked" : QUERY.get("file"))); const [dragging, setDragging] = useState(false); + // The session of the file on screen, for the host's controls beside its name. + const [session, setSession] = useState(null); const input = useRef(null); const counter = useRef(0); const t = TEXT[locale]; // One plugin list for the page: `ViewerProvider` starts a viewer per list. - const plugins = useMemo(() => allPlugins(), []); - // The sidebar's files, from showcase/samples.json (`npm run demo:showcase`); - // none when it was not copied in. + const plugins = useMemo( + () => [ + ...allPlugins({ cad: CAD, ifc: MODEL, model: MODEL }), + ...[rtf(CONVERTER), doc(CONVERTER), odt(CONVERTER), ppt(CONVERTER), odp(CONVERTER), keynote(CONVERTER), xls(CONVERTER), ods(CONVERTER), numbers(CONVERTER)], + ...[odg(CONVERTER), visio(CONVERTER), coreldraw(CONVERTER), publisher(CONVERTER), pagemaker(CONVERTER), freehand(CONVERTER), quarkxpress(CONVERTER), zonerdraw(CONVERTER), wpg(CONVERTER)], + ], + [], + ); + // The sidebar's files, from showcase/samples.json (`npm run demo:showcase`) + // and examples/examples.json (`npm run demo:examples`); none when they were + // not copied in. A file is fetched only when it is selected. const [samples, setSamples] = useState([]); + const [examples, setExamples] = useState([]); useEffect(() => { fetch(`${BASE}showcase/samples.json`) .then((r) => (r.ok ? r.json() : { samples: [] })) .then((j: { samples: Sample[] }) => setSamples(j.samples)) .catch(() => setSamples([])); + fetch(`${BASE}examples/examples.json`) + .then((r) => (r.ok ? r.json() : { examples: [] })) + .then((j: { examples: Example[] }) => setExamples(j.examples)) + .catch(() => setExamples([])); }, []); - const showcase = useMemo( - () => samples.map((s): Item => ({ id: `showcase:${s.file}`, name: s.file, source: { url: `${BASE}showcase/${s.file}` } })), - [samples], - ); + const showcase = useMemo((): Listed[] => { + // An example wins over a sample of the same file name. + const named = new Set(examples.map((e) => e.file)); + return [ + ...samples + .filter((s) => !named.has(s.file)) + .map((s): Listed => ({ group: s.group, note: `${s.credit}. ${s.licence}`, item: { id: `showcase:${s.file}`, name: s.file, source: { url: `${BASE}showcase/${s.file}` } } })), + ...examples.map((e): Listed => ({ group: e.group, note: e.attribution || `${credit(e)}. ${e.licence}`, item: { id: `example:${e.file}`, name: e.file, source: { url: `${BASE}examples/${e.file}` } } })), + ]; + }, [samples, examples]); // Known groups in their order, then any other, in the order they come. - const groups = useMemo(() => [...new Set([...Object.keys(GROUPS), ...samples.map((s) => s.group)])], [samples]); + const groups = useMemo(() => [...new Set([...Object.keys(GROUPS), ...showcase.map((l) => l.group)])], [showcase]); const linked = useMemo((): Item[] => { if (!LINKED) return []; const name = decodeURIComponent(new URL(LINKED, location.href).pathname.split("/").pop() || "file"); return [{ id: "linked", name, source: { url: LINKED } }]; }, []); - const items = useMemo(() => [...linked, ...own, ...showcase], [linked, own, showcase]); + const items = useMemo(() => [...linked, ...own, ...showcase.map((l) => l.item)], [linked, own, showcase]); const current = items.find((i) => i.id === selected) ?? null; + const note = showcase.find((l) => l.item.id === selected)?.note; useEffect(() => { document.documentElement.lang = locale; @@ -154,9 +246,9 @@ export function App() { add(e.dataTransfer.files); }; - const entry = (item: Item) => ( + const entry = (item: Item, note?: string) => (
  1. -
  2. @@ -209,17 +301,16 @@ export function App() { {own.length > 0 && ( <>

    {t.yours}

    -
      {own.map(entry)}
    +
      {own.map((item) => entry(item))}
    )} {groups.map((group) => { - // `showcase` follows `samples`' order. - const list = showcase.filter((_, i) => samples[i]!.group === group); + const list = showcase.filter((l) => l.group === group); return ( list.length > 0 && (

    {GROUPS[group]?.[locale] ?? group}

    -
      {list.map(entry)}
    +
      {list.map((l) => entry(l.item, l.note))}
    ) ); @@ -229,12 +320,20 @@ export function App() { {current ? ( <>
    -

    - {current.name} -

    +
    +

    {current.name}

    + +
    + {note && ( + + {note} + + )}
    - + + {({ session }) => } +
    ) : ( diff --git a/crates/exav-viewer/demo/src/ExportImage.tsx b/crates/exav-viewer/demo/src/ExportImage.tsx new file mode 100644 index 0000000..26841ee --- /dev/null +++ b/crates/exav-viewer/demo/src/ExportImage.tsx @@ -0,0 +1,184 @@ +/** + * "Export image": the session's pictures (`controllers.pictures`) saved as a + * file, for any format that draws something. A button beside the file's name, + * as it belongs to the host and not to the viewer, opening a dialog of + * options. The region is the whole page or what the viewer shows when the + * dialog opens (`controllers.viewport`). `window.exavDemo` is for the + * browser tests. + */ +import { useEffect, useId, useRef, useState } from "react"; + +import { RasterError, type Raster, type RasterOptions, type RasterType, type Session } from "@exav/viewer"; +import { useStore } from "@exav/viewer/react"; + +type Result = { url: string; name: string; info: string } | { error: string }; + +/** The session of the file on screen, or of the member of an archive that is open in it. */ +function Export({ session, base }: { session: Session; base: string }) { + const controllers = useStore(session.controllers); + const opened = useStore(controllers?.archive)?.opened; + const pictures = controllers?.pictures; + const count = useStore(pictures)?.count ?? 0; + const space = useStore(pictures)?.space; + const [page, setPage] = useState(1); + const [longEdge, setLongEdge] = useState(1600); + const [region, setRegion] = useState<"whole" | "current">("whole"); + const dialog = useRef(null); + const titleId = useId(); + const [open, setOpen] = useState(false); + // Working out the viewport costs: it is followed only while the dialog shows "What I see". + const viewport = useStore(open && region === "current" ? controllers?.viewport : undefined); + const [type, setType] = useState("png"); + const [background, setBackground] = useState<"default" | "transparent" | "white">("default"); + const [fit, setFit] = useState<"contain" | "cover">("contain"); + const [lineweight, setLineweight] = useState<"screen" | "scaled">("screen"); + const [busy, setBusy] = useState(null); + const [result, setResult] = useState(null); + useEffect(() => () => void (result && "url" in result && URL.revokeObjectURL(result.url)), [result]); + // The page in view follows the viewer when the region is what it shows. + const shown = region === "current" && viewport ? viewport.page : page; + + if (opened) return ; + if (!pictures || count < 1) return null; + + const run = async () => { + const abort = new AbortController(); + setBusy(abort); + setResult(null); + const options: RasterOptions & { type: RasterType } = { + longEdge, + fit, + type, + signal: abort.signal, + ...(region === "current" && { region: "current" as const }), + ...(background !== "default" && { background: background === "white" ? "#ffffff" : "transparent" }), + ...(space === "drawing" && { lineweight }), + ...(region === "current" && viewport?.layout !== undefined && { layout: viewport.layout }), + }; + try { + const { blob, ...raster } = await pictures.toBlob(shown, options); + const info = describe(raster); + setResult({ url: URL.createObjectURL(blob), name: `${base}-${shown}.${type === "jpeg" ? "jpg" : type}`, info }); + } catch (error) { + setResult({ error: error instanceof RasterError ? `${error.code}: ${error.message}` : String(error) }); + } finally { + setBusy(null); + } + }; + + return ( + <> + + setOpen(false)} + onClick={(e) => e.target === e.currentTarget && dialog.current?.close()} + > +
    +

    Export image

    + +
    +
    + + + + + + + {space === "drawing" && ( + + )} + {busy ? ( + + ) : ( + + )} + {result && + ("error" in result ? ( +

    + {result.error} +

    + ) : ( +

    + + {result.name} + {" "} + {result.info} +

    + ))} +
    +
    + + ); +} + +function describe(r: Omit): string { + const region = r.region ? ` of ${JSON.stringify(r.region, (_, v) => (typeof v === "number" ? Math.round(v * 1000) / 1000 : v))}` : ""; + return `${r.width} x ${r.height} px, page ${r.page}${r.layout !== undefined ? ` (${r.layout})` : ""}${region}`; +} + +export function ExportImage({ session, name }: { session: Session | null; name: string }) { + useEffect(() => { + Object.assign(window, { exavDemo: { session: () => session } }); + }, [session]); + return session ? : null; +} diff --git a/crates/exav-viewer/demo/src/demo.css b/crates/exav-viewer/demo/src/demo.css index 69f46a6..bd801da 100644 --- a/crates/exav-viewer/demo/src/demo.css +++ b/crates/exav-viewer/demo/src/demo.css @@ -19,18 +19,18 @@ --demo-selected: #134e4a; color-scheme: dark; } - .demo .exv-body, - .exv-dialog { - --exv-surface: #1e293b; - --exv-panel: #111827; - --exv-border: #334155; - --exv-text: #cbd5e1; - --exv-text-strong: #f8fafc; - --exv-muted: #94a3b8; - --exv-hover: #1f2937; - --exv-active: #334155; - --exv-accent: #5eead4; - --exv-on-accent: #0f172a; + .demo .exav-viewer-body, + .exav-viewer-dialog { + --exav-viewer-surface: #1e293b; + --exav-viewer-panel: #111827; + --exav-viewer-border: #334155; + --exav-viewer-text: #cbd5e1; + --exav-viewer-text-strong: #f8fafc; + --exav-viewer-muted: #94a3b8; + --exav-viewer-hover: #1f2937; + --exav-viewer-active: #334155; + --exav-viewer-accent: #5eead4; + --exav-viewer-on-accent: #0f172a; } } @@ -156,12 +156,23 @@ body { padding: 0.5rem 1rem; } .demo-bar h1 { + min-width: 0; margin: 0; overflow: hidden; font-size: 1.125rem; text-overflow: ellipsis; white-space: nowrap; } +.demo-credit { + min-width: 0; + overflow: hidden; + color: var(--demo-muted); + font-size: 0.75rem; + text-align: right; + text-decoration: none; + text-overflow: ellipsis; + white-space: nowrap; +} .demo-frame { flex: 1; min-height: 0; @@ -170,6 +181,83 @@ body { border: 1px solid var(--demo-border); border-radius: 0.5rem; } +.demo-title { + display: flex; + align-items: center; + gap: 0.75rem; + min-width: 0; +} +.demo-export-open { + flex: none; + padding: 0.25rem 0.75rem; + border: 1px solid var(--demo-border); + border-radius: 0.375rem; + background: var(--demo-panel); + color: var(--demo-text); + font: inherit; + font-size: 0.8125rem; + cursor: pointer; +} +.demo-export-open:hover, +.demo-export-open:focus-visible { + border-color: var(--demo-accent); +} +.demo-export { + width: 36rem; + max-width: calc(100% - 32px); + padding: 0; + border: 1px solid var(--demo-border); + border-radius: 0.5rem; + background: var(--demo-panel); + color: var(--demo-text); + font-size: 0.8125rem; +} +.demo-export::backdrop { + background: rgb(15 23 42 / 0.45); +} +.demo-export-head { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.5rem 0.5rem 0.5rem 1rem; + border-bottom: 1px solid var(--demo-border); +} +.demo-export-head h2 { + margin: 0; + font-size: 1rem; +} +.demo-export-close { + width: 2rem; + height: 2rem; + border: 0; + border-radius: 0.375rem; + background: transparent; + color: var(--demo-muted); + font-size: 1.25rem; + line-height: 1; + cursor: pointer; +} +.demo-export-close:hover, +.demo-export-close:focus-visible { + color: var(--demo-text); +} +.demo-export-body { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); + gap: 0.75rem; + max-height: 70vh; + padding: 1rem; + overflow: auto; +} +.demo-export-body label { + display: grid; + gap: 0.125rem; +} +.demo-export-body p { + grid-column: 1 / -1; + margin: 0; + overflow-wrap: anywhere; +} .demo-upload { display: flex; flex: 1; diff --git a/crates/exav-viewer/demo/src/headless.css b/crates/exav-viewer/demo/src/headless.css new file mode 100644 index 0000000..947659e --- /dev/null +++ b/crates/exav-viewer/demo/src/headless.css @@ -0,0 +1,110 @@ +/* The page's own look: the frame is given these values (`theme: "inherit"`). */ +:root { + color-scheme: light; + --page-bg: #fbfaf7; + --page-text: #2b2a27; + --exav-viewer-surface: #ece8df; + --exav-viewer-panel: #fffdf8; + --exav-viewer-text: #3d3a33; + --exav-viewer-text-strong: #1d1b17; + --exav-viewer-border: #d9d2c3; + --exav-viewer-accent: #9a3412; + --exav-viewer-pager-room: 1rem; + --exav-viewer-font: Georgia, serif; +} +:root.dark { + color-scheme: dark; + --page-bg: #17161a; + --page-text: #e8e6ef; + --exav-viewer-surface: #212026; + --exav-viewer-panel: #2a2930; + --exav-viewer-text: #d6d3df; + --exav-viewer-text-strong: #f4f2fa; + --exav-viewer-border: #3b3944; + --exav-viewer-accent: #f59e0b; +} +body { + margin: 0; + padding: 1rem; + background: var(--page-bg); + color: var(--page-text); + font: 0.9375rem/1.5 system-ui, sans-serif; +} +h1 { + margin: 0; + font-size: 1.25rem; +} +main { + display: grid; + grid-template-columns: auto 1fr; + gap: 1rem; + margin-top: 1rem; +} +#thumbs { + display: flex; + flex-direction: column; + gap: 0.5rem; + max-height: 75vh; + overflow-y: auto; +} +#thumbs:empty { + display: none; +} +#thumbs button { + padding: 0; + border: 1px solid var(--exav-viewer-border); + background: white; + cursor: pointer; +} +#thumbs canvas { + display: block; + max-width: 80px; + height: auto; +} +#viewer { + display: flex; + flex-direction: column; + min-width: 0; + background: var(--exav-viewer-surface); +} +#stage { + position: relative; + height: 65vh; +} +#viewer:fullscreen #stage { + height: auto; + flex: 1; +} +#sheets { + display: flex; + gap: 0.25rem; + overflow-x: auto; +} +#sheets button[aria-selected="true"] { + border-bottom: 2px solid var(--exav-viewer-accent); + font-weight: 600; +} +#controls { + display: flex; + flex-wrap: wrap; + gap: 0.75rem; + padding: 0.5rem; + background: var(--exav-viewer-panel); +} +#controls .group { + display: flex; + align-items: center; + gap: 0.25rem; +} +#controls input[type="number"] { + width: 4rem; +} +.members { + margin: 0; + padding: 0; + list-style: none; +} +#keys { + font-size: 0.8125rem; + opacity: 0.7; +} diff --git a/crates/exav-viewer/demo/src/headless.ts b/crates/exav-viewer/demo/src/headless.ts new file mode 100644 index 0000000..d27ed05 --- /dev/null +++ b/crates/exav-viewer/demo/src/headless.ts @@ -0,0 +1,234 @@ +/** + * A host that draws its own UI: each file in the sandboxed frame, and every + * control on this page, made from the session's controllers. The frame + * draws the document alone (the player's controls too are this page's: + * `media.controls: "none"`), takes this page's colours (`theme`, read from + * its CSS custom properties) and hands back the keys the document does not + * use. `window.headless` is for the browser tests. + */ +import "./headless.css"; + +import { builtinTranslate, printPictures, type Controllers, type MessageKey, type Session, type Status, type Store } from "@exav/viewer"; +import { createSandboxedViewer } from "@exav/viewer/frame"; + +declare const __DEMO_ORIGIN__: string; + +const BASE = import.meta.env.BASE_URL; +const t = builtinTranslate(new URLSearchParams(location.search).get("lang") ?? navigator.language); + +const viewer = createSandboxedViewer({ + url: `${BASE}frame/index.html`, + origins: { media: [__DEMO_ORIGIN__], connect: [__DEMO_ORIGIN__] }, + options: { media: { controls: "none" } }, +}); + +const $ = (id: string) => document.getElementById(id)!; +const stage = $("stage"); +const controls = $("controls"); +const sheetTabs = $("sheets"); +const thumbs = $("thumbs"); +const statusLine = $("status"); + +function el(tag: K, props: Partial = {}, ...children: (Node | string)[]): HTMLElementTagNameMap[K] { + const e = Object.assign(document.createElement(tag), props); + e.append(...children); + return e; +} + +const button = (label: string, onclick: () => void, title = label) => el("button", { type: "button", textContent: label, title, onclick }); + +/** Calls `draw` with the store's value now and on each change; returns the unsubscribe. */ +function follow(store: Store | undefined, draw: (value: T) => void): () => void { + if (!store) return () => {}; + draw(store.get()); + return store.subscribe(draw); +} + +function statusText(s: Status): string { + switch (s.phase) { + case "loading": + case "converting": + return t("loading"); + case "error": + return t(s.error.code === "pdf" ? "error" : (`error_${s.error.code}` as MessageKey)); + case "empty": + return t("empty_model"); + default: + return ""; + } +} + +const seconds = (s: number) => (Number.isFinite(s) ? `${Math.floor(s / 60)}:${String(Math.floor(s % 60)).padStart(2, "0")}` : "∞"); + +let session: Session | null = null; +/** What follows the file on screen, dropped on each redraw. */ +let widgets: (() => void)[] = []; +let thumbsAbort: AbortController | null = null; + +const clearWidgets = () => { + for (const stop of widgets) stop(); + widgets = []; + thumbsAbort?.abort(); + controls.replaceChildren(); + sheetTabs.replaceChildren(); + thumbs.replaceChildren(); +}; + +/** + * The controls of the session shown: an archive's open member, down as many + * levels as are open, drawn again when anything on the way changes. + */ +function render(root: Session) { + clearWidgets(); + let scheduled = false; + const redraw = () => { + if (scheduled) return; + scheduled = true; + queueMicrotask(() => session === root && render(root)); + }; + let shown = root; + let back: Controllers["archive"] | null = null; + for (;;) { + const c = shown.controllers.get(); + widgets.push(shown.controllers.subscribe(redraw)); + const opened = c.archive?.get().opened; + if (c.archive) { + // Redrawn when a member opens or closes, not on each extraction step. + const was = opened; + widgets.push(c.archive.subscribe((a) => a.opened !== was && redraw())); + } + if (!opened) break; + back = c.archive!; + shown = opened.session; + } + widgets.push(follow(shown.status, (status) => (statusLine.textContent = statusText(status)))); + draw(shown.controllers.get(), back); +} + +function draw(c: Controllers, archiveOf: Controllers["archive"] | null) { + const bar = (...children: (Node | string)[]) => controls.append(el("div", { className: "group" }, ...children)); + if (archiveOf) bar(button(t("archive_back"), () => archiveOf.back())); + if (c.archive) { + const list = el("ul", { className: "members" }); + widgets.push( + follow(c.archive, (a) => + list.replaceChildren( + ...a.members.map((m) => el("li", {}, button(m.name, () => void c.archive!.open(m.index)))), + ...(a.refused ? [el("li", { textContent: t(a.refused.key) })] : []), + ), + ), + ); + bar(list); + } + if (c.pages) { + const pages = c.pages; + const field = el("input", { type: "number", min: "1", ariaLabel: t("page_short", { page: "" }).trim() }); + const total = el("span"); + field.onchange = () => pages.goTo?.(Number(field.value)); + widgets.push( + follow(pages, (p) => { + if (document.activeElement !== field) field.value = String(p?.current ?? ""); + total.textContent = `/ ${p?.total ?? "…"}`; + }), + ); + bar(...(pages.prev ? [button("‹", () => void pages.prev!(), t("prev"))] : []), field, total, ...(pages.next ? [button("›", () => void pages.next!(), t("next"))] : [])); + } + if (c.zoom) { + const zoom = c.zoom; + const label = el("span", { className: "zoom" }); + widgets.push(follow(zoom, (z) => (label.textContent = `${Math.round(z.scale * 100)} %`))); + bar(button("−", () => zoom.setScale(zoom.get().scale / 1.25), t("zoom_out")), label, button("+", () => zoom.setScale(zoom.get().scale * 1.25), t("zoom_in")), button("⤢", () => zoom.fit(), t("zoom_fit"))); + } + if (c.media) { + const media = c.media; + const play = button("▶", () => void (media.get().paused ? media.play() : media.pause())); + play.dataset.testid = "play"; + const time = el("input", { type: "range", min: "0", step: "0.1", ariaLabel: "Time" }); + const clock = el("span", { className: "clock" }); + const mute = button("🔊", () => media.setMuted(!media.get().muted)); + time.oninput = () => media.seek(Number(time.value)); + widgets.push( + follow(media, (m) => { + play.textContent = m.paused ? "▶" : "�"; + time.max = String(Number.isFinite(m.duration) ? m.duration : 0); + time.value = String(m.currentTime); + clock.textContent = `${seconds(m.currentTime)} / ${seconds(m.duration)}`; + mute.textContent = m.muted ? "🔇" : "🔊"; + }), + ); + // Fullscreen is the page's: the frame may not, the element holding it may. + bar(play, time, clock, mute, button("⛶", () => void $("viewer").requestFullscreen())); + } + if (c.sheets) { + const sheets = c.sheets; + widgets.push( + follow(sheets, (s) => + sheetTabs.replaceChildren( + ...s.items.map((sheet) => { + const tab = button(sheet.name, () => void sheets.select(sheet.index)); + tab.role = "tab"; + tab.ariaSelected = String(sheet.index === s.current); + return tab; + }), + ), + ), + ); + } + if (c.pictures) { + const pictures = c.pictures; + bar(button("⎙", () => void printPictures(pictures), "Print")); + drawThumbs(pictures, c.pages); + } +} + +/** A picture of each page (the first 50), drawn one after the other, a click going to it. */ +function drawThumbs(pictures: NonNullable, pages: Controllers["pages"]) { + const abort = new AbortController(); + thumbsAbort = abort; + const count = Math.min(pictures.get().count, 50); + if (count < 2) return; + void (async () => { + for (let page = 1; page <= count && !abort.signal.aborted; page++) { + const bitmap = await pictures.render(page, 160 * Math.min(devicePixelRatio || 1, 2)); + if (!bitmap) continue; + if (abort.signal.aborted) { + bitmap.close(); + return; + } + const canvas = el("canvas", { width: bitmap.width, height: bitmap.height }); + canvas.getContext("bitmaprenderer")?.transferFromImageBitmap(bitmap); + thumbs.append(el("button", { type: "button", title: t("page_short", { page }), onclick: () => pages?.goTo?.(page) }, canvas)); + } + })(); +} + +function showFile(file: File) { + session?.destroy(); + clearWidgets(); + session = viewer.mount(stage, { id: `${file.name}:${file.size}:${file.lastModified}`, name: file.name, type: file.type, source: { blob: file } }); + render(session); +} + +$("scheme").onclick = () => { + const dark = document.documentElement.classList.toggle("dark"); + $("scheme").textContent = dark ? "Light" : "Dark"; + viewer.restyle(); +}; + +(document.querySelector('[data-testid="file-input"]') as HTMLInputElement).onchange = (e) => { + const file = (e.target as HTMLInputElement).files?.[0]; + if (file) showFile(file); +}; + +// The keys the frame hands back reach this page's listeners as the page's own. +document.addEventListener("keydown", (e) => { + $("keys").append(el("li", { textContent: `${e.key}${e.isTrusted ? "" : " (from the frame)"}` })); + if (e.key === "Escape" && session) { + session.destroy(); + session = null; + clearWidgets(); + statusLine.textContent = ""; + } +}); + +Object.assign(window, { headless: { viewer, session: () => session } }); diff --git a/crates/exav-viewer/demo/src/showcase.ts b/crates/exav-viewer/demo/src/showcase.ts index 7f186a7..9e39109 100644 --- a/crates/exav-viewer/demo/src/showcase.ts +++ b/crates/exav-viewer/demo/src/showcase.ts @@ -1,14 +1,22 @@ /** * The files the demo lists: demo/public/showcase/, copied from * github.com/sylvinus/exav-samples by `npm run demo:showcase`, and described - * by its samples.json. The browser tests use the generated files of - * e2e/.out/samples/ instead (e2e/fixtures/make-samples.mjs). + * by its samples.json; and demo/public/examples/, put there by `npm run + * demo:examples` and described by examples.json (demo/examples/). When both + * have a file of the same name, the example is listed and the sample is not. + * The browser tests use the generated files of e2e/.out/samples/ instead + * (e2e/fixtures/make-samples.mjs). */ /** The sidebar's sections, in this order; a group not named here comes last, under its own name. */ export const GROUPS: Record = { documents: { en: "Documents", fr: "Documents" }, + pdf: { en: "PDF", fr: "PDF" }, + office: { en: "Word, Excel, PowerPoint", fr: "Word, Excel, PowerPoint" }, + converted: { en: "Other office formats", fr: "Autres formats bureautiques" }, + text: { en: "Text and code", fr: "Texte et code" }, images: { en: "Images", fr: "Images" }, + raw: { en: "Camera RAW", fr: "Photos RAW" }, cad: { en: "CAD", fr: "CAO" }, "3d": { en: "3D", fr: "3D" }, media: { en: "Audio and video", fr: "Audio et vidéo" }, @@ -29,3 +37,24 @@ export interface Sample { bytes: number; sha256: string; } + +/** One entry of examples.json (demo/examples/): the facts the demo shows, a few of those it keeps. */ +export interface Example { + file: string; + group: string; + family: string; + title: string; + author: string; + source: string; + /** The SPDX id, or "public-domain (reason)". */ + licence: string; + /** The line CC-BY, MIT, BSD and Apache ask to keep; "" for the others. */ + attribution: string; + bytes: number; + sha256: string; +} + +/** Who made a file and what it is, one line (the line the licence asks to keep is `attribution`). */ +export function credit(e: Example): string { + return `${e.author}: ${e.title}`; +} diff --git a/crates/exav-viewer/demo/vite.config.ts b/crates/exav-viewer/demo/vite.config.ts index 8eca8e0..ca2d43c 100644 --- a/crates/exav-viewer/demo/vite.config.ts +++ b/crates/exav-viewer/demo/vite.config.ts @@ -12,7 +12,7 @@ import { fileURLToPath } from "node:url"; import { defineConfig, type Plugin } from "vite"; import { exavViewer } from "../dist/vite/index.js"; -import type { Sample } from "./src/showcase.js"; +import type { Example, Sample } from "./src/showcase.js"; const pkgDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const pkg = JSON.parse(fs.readFileSync(path.join(pkgDir, "package.json"), "utf8")); @@ -29,6 +29,14 @@ const nodeModules = fs.realpathSync(path.join(pkgDir, "node_modules")); // A `file:` dependency resolves outside node_modules (to its crate), and the // dev server serves its worker and wasm from there. const unpackWasm = fs.realpathSync(path.join(nodeModules, "@exav", "unpack-wasm")); +/** + * An external converter for the formats the package's own converters do not + * read: the name of an installed package, from `EXAV_EXTERNAL_CONVERTER` when + * the demo is built. None by default. + */ +const externalConverter = process.env.EXAV_EXTERNAL_CONVERTER || undefined; +// Its files are served from where it is installed (a `file:` dependency lives outside node_modules). +const externalDir = externalConverter && fs.existsSync(path.join(nodeModules, externalConverter)) ? fs.realpathSync(path.join(nodeModules, externalConverter)) : undefined; /** The packages the demo bundles or copies, whose licences travel with it. */ const ENGINES = ["pdfjs-dist", "three", "@silurus/ooxml", "@exav/unpack-wasm", "react", "react-dom"]; @@ -58,12 +66,25 @@ function licenceFiles(): Map { "Of pdfjs-dist's wasm/, only its ICC engine (qcms, MIT; LICENSE_QCMS beside it under exav-viewer/pdfjs/) is in the build.", "Its OpenJPEG and PDFium image decoders are not: @exav/viewer's own decoders take their place (see its NOTICE).", ); - // The samples copied in by `npm run demo:showcase`, if they were. + // The example files copied in by `npm run demo:examples`, if they were (an + // example replaces a sample of the same file name in the list), and the samples + // copied in by `npm run demo:showcase`. + const examplesList = path.join(pkgDir, "demo", "public", "examples", "examples.json"); + const examples = fs.existsSync(examplesList) ? (JSON.parse(fs.readFileSync(examplesList, "utf8")) as { examples: Example[] }).examples : []; + if (examples.length) { + index.push("", "The example files, under examples/ (the full list is examples-NOTICE.md; one that has the name of a sample replaces it):"); + for (const e of examples) { + index.push("", e.file, ` ${e.author}: ${e.title}`, ` ${e.source}`, ` ${e.licence}`); + if (e.attribution) index.push(` ${e.attribution}`); + } + add("examples-NOTICE.md", path.join(pkgDir, "demo", "examples", "NOTICE.md")); + } const list = path.join(pkgDir, "demo", "public", "showcase", "samples.json"); if (fs.existsSync(list)) { const { samples } = JSON.parse(fs.readFileSync(list, "utf8")) as { samples: Sample[] }; + const replaced = new Set(examples.map((e) => e.file)); index.push("", "The sample files, under showcase/, from https://github.com/sylvinus/exav-samples:"); - for (const s of samples) index.push("", s.file, ` ${s.credit}`, ` ${s.source}`, ` ${s.licence}`); + for (const s of samples) index.push("", s.file, ` ${s.credit}`, ` ${s.source}`, ` ${s.licence}`, ...(replaced.has(s.file) ? [" Not listed: an example of the same name replaces it."] : [])); } files.set("README.txt", Buffer.from(`${index.join("\n")}\n`)); return files; @@ -102,7 +123,7 @@ function licences(): Plugin { */ function e2eFiles(): Plugin { const dir = path.join(pkgDir, "e2e", ".out"); - const TYPES: Record = { ".pdf": "application/pdf", ".zip": "application/zip", ".webm": "video/webm", ".png": "image/png" }; + const TYPES: Record = { ".pdf": "application/pdf", ".zip": "application/zip", ".webm": "video/webm", ".png": "image/png", ".js": "text/javascript" }; // A third above clip.webm's bitrate (10 MB for 13 s): it plays without stalling. const PACE = 1024 * 1024; const send = (file: string, res: ServerResponse, paced: boolean, range?: { start: number; end: number }) => { @@ -167,11 +188,12 @@ export default defineConfig({ base: process.env.DEMO_BASE ?? "/", resolve: { alias }, esbuild: { jsx: "automatic" }, - define: { __DEMO_ORIGIN__: JSON.stringify(origin) }, + define: { __DEMO_ORIGIN__: JSON.stringify(origin), __EXTERNAL_CONVERTER__: JSON.stringify(externalConverter ?? null) }, // The sandboxed frame at `${base}frame/`, served with its headers by `vite // preview`. It may play the demo's own media by URL and fetch from it. - plugins: [exavViewer({ frameDir: "frame", frameOrigin: origin, mediaOrigins: [origin], connectOrigins: [origin] }), licences(), e2eFiles()], + plugins: [exavViewer({ frameDir: "frame", frameOrigin: origin, mediaOrigins: [origin], connectOrigins: [origin], externalConverter }), licences(), e2eFiles()], // Beside the docs site's 4321. - server: { port: 4322, strictPort: true, host: true, fs: { allow: [pkgDir, nodeModules, unpackWasm] } }, - build: { outDir: "dist", emptyOutDir: true, target: "es2022" }, + server: { port: 4322, strictPort: true, host: true, fs: { allow: [pkgDir, nodeModules, unpackWasm, ...(externalDir ? [externalDir] : [])] } }, + // headless.html: a host drawing its own controls, without React. + build: { outDir: "dist", emptyOutDir: true, target: "es2022", rollupOptions: { input: { main: path.join(pkgDir, "demo", "index.html"), headless: path.join(pkgDir, "demo", "headless.html") } } }, }); diff --git a/crates/exav-viewer/e2e/cad-raster.spec.ts b/crates/exav-viewer/e2e/cad-raster.spec.ts new file mode 100644 index 0000000..779a64f --- /dev/null +++ b/crates/exav-viewer/e2e/cad-raster.spec.ts @@ -0,0 +1,684 @@ +// Pictures of DWG and DXF drawings (`controllers.pictures`) and the viewport +// store: drawn again from the vectors in a context of their own, at the asked +// size and region, whatever the viewer shows. In the page (`mode=page`), where +// `rasterTile=64` forces tiles; the sandboxed frame is the last test. +import { expect, test, type Locator, type Page } from "@playwright/test"; + +import { failOnViolations } from "./csp.js"; +import { decodePng, difference, find, type Pixels } from "./pixels.js"; +import { openSample, sample } from "./samples.js"; + +failOnViolations(); + +interface Info { + width: number; + height: number; + page: number; + layout?: string; + space: string; + region: { x: number; y: number; width: number; height: number }; +} +interface Picture extends Pixels { + info: Info; +} + +type Options = Record; + +/** `pictures.raster(page, options)` in the page, its bitmap read back as pixels. */ +async function raster(page: Page, n: number, options: Options): Promise { + const out = await page.evaluate( + async ([n, options]) => { + const session = (window as unknown as { exavDemo: { session(): { controllers: { get(): { pictures: { raster(n: number, o: object): Promise<{ bitmap: ImageBitmap } & Record> } } } } } }).exavDemo.session(); + const r = await session.controllers.get().pictures.raster(n, options as object); + const canvas = new OffscreenCanvas(r.bitmap.width, r.bitmap.height); + canvas.getContext("2d")!.drawImage(r.bitmap, 0, 0); + r.bitmap.close(); + const bytes = new Uint8Array(await (await canvas.convertToBlob({ type: "image/png" })).arrayBuffer()); + let binary = ""; + for (let i = 0; i < bytes.length; i += 0x8000) binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000)); + const { bitmap: _bitmap, ...info } = r; + return { png: btoa(binary), info }; + }, + [n, options] as const, + ); + return { ...decodePng(Buffer.from(out.png, "base64")), info: out.info as unknown as Info }; +} + +/** The code of the RasterError a raster is refused with. */ +async function refused(page: Page, n: number, options: Options): Promise { + return page.evaluate( + async ([n, options]) => { + const session = (window as unknown as { exavDemo: { session(): { controllers: { get(): { pictures: { raster(n: number, o: object): Promise } } } } } }).exavDemo.session(); + try { + await session.controllers.get().pictures.raster(n, options as object); + return "none"; + } catch (e) { + return (e as { code?: string }).code ?? String(e); + } + }, + [n, options] as const, + ); +} + +interface View { + space: string; + page: number; + layout?: string; + region: { x: number; y: number; width: number; height: number }; +} +const viewport = (page: Page) => + page.evaluate(() => { + const s = (window as unknown as { exavDemo: { session(): { controllers: { get(): { viewport: { get(): unknown } } } } } }).exavDemo.session(); + return s.controllers.get().viewport.get() as View | null; + }); + +async function shot(target: Locator): Promise { + const tools = target.page().locator(".exav-viewer-tools"); + await tools.evaluateAll((els) => els.forEach((e) => ((e as HTMLElement).style.visibility = "hidden"))); + try { + return decodePng(await target.screenshot({ animations: "disabled" })); + } finally { + await tools.evaluateAll((els) => els.forEach((e) => ((e as HTMLElement).style.visibility = ""))); + } +} + +/** Two screenshots in a row that agree: the canvas has settled. */ +async function settled(target: Locator): Promise { + // A zoom scales the canvas as drawn until it pauses: its box is not its own. + await expect.poll(() => target.evaluate((e) => (e as HTMLElement).style.transform)).toBe(""); + let last = await shot(target); + for (let i = 0; i < 20; i++) { + await target.page().waitForTimeout(150); + const next = await shot(target); + if (difference(last, next) === 0) return next; + last = next; + } + return last; +} + +async function open(page: Page, name: string, params: Record = {}): Promise { + await openSample(page, name, { mode: "page", ...params }); + await expect(page.locator(".demo-frame .exav-viewer-body")).toHaveAttribute("data-phase", "ready"); + await expect.poll(() => viewport(page)).not.toBeNull(); + const canvas = page.locator(".demo-frame .exav-viewer-cad-canvas"); + // A whole number of pixels, so that a screenshot of the canvas is its own pixels. + await page.locator(".demo-frame .exav-viewer-cad").evaluate((e) => Object.assign(e.style, { position: "fixed", left: "0px", top: "0px", zIndex: "10", flex: "none", width: "700px", height: "500px" })); + await expect.poll(() => canvas.evaluate((c: HTMLCanvasElement) => [c.width, c.height])).toEqual([700, 500]); + return canvas; +} + +/** The page a layout is: its place in the layouts controller, model space first. */ +const pageOf = (page: Page, id: string) => + page.evaluate((id) => { + const s = (window as unknown as { exavDemo: { session(): { controllers: { get(): { layouts: { get(): { items: { id: string }[] } } } } } } }).exavDemo.session(); + return s.controllers.get().layouts.get().items.findIndex((l) => l.id === id) + 1; + }, id); + +async function layout(page: Page, name: string): Promise { + // By the DOM: the canvas is fixed over the corner of the page (see `open`). + await page.locator(".exav-viewer-layouts").getByRole("button", { name }).evaluate((b) => (b as HTMLElement).click()); + await expect(page.locator(".demo-frame .exav-viewer-body")).toHaveAttribute("data-phase", "ready"); + await expect.poll(async () => (await viewport(page))?.layout).toBe(name); +} + +const at = (p: Pixels, x: number, y: number): [number, number, number, number] => { + const i = (y * p.width + x) * 4; + return [p.data[i]!, p.data[i + 1]!, p.data[i + 2]!, p.data[i + 3]!]; +}; +const near = (a: readonly number[], b: readonly number[], tolerance = 24) => a.every((v, i) => Math.abs(v - b[i]!) <= tolerance); +const ink = (r: number, g: number, b: number) => r < 160 && g < 160 && b < 160; +/** The largest difference of any channel of any pixel. */ +function worst(a: Pixels, b: Pixels): number { + expect([a.width, a.height]).toEqual([b.width, b.height]); + let m = 0; + for (let i = 0; i < a.data.length; i++) m = Math.max(m, Math.abs(a.data[i]! - b.data[i]!)); + return m; +} +/** Rows from `from` to `to` (inclusive) of column `x` that `test` accepts. */ +function column(p: Pixels, x: number, test: (r: number, g: number, b: number) => boolean): number[] { + const rows: number[] = []; + for (let y = 0; y < p.height; y++) { + const [r, g, b] = at(p, x, y); + if (test(r, g, b)) rows.push(y); + } + return rows; +} +function row(p: Pixels, y: number, test: (r: number, g: number, b: number) => boolean): number[] { + const cols: number[] = []; + for (let x = 0; x < p.width; x++) { + const [r, g, b] = at(p, x, y); + if (test(r, g, b)) cols.push(x); + } + return cols; +} + +const red = (r: number, g: number, b: number) => r > 200 && g < 80 && b < 80; +const cyan = (r: number, g: number, b: number) => r < 80 && g > 200 && b > 200; +const notWhite = (r: number, g: number, b: number) => r < 250 || g < 250 || b < 250; + +test.describe("a region of the drawing", () => { + // colours.dxf: a yellow line (y 0), a red one (y 20), both 100 long and 2.11 mm + // wide, and a cyan band from y 40 to 60, all from x 0 to 100. + test("is drawn where its drawing units are: x to the right, y up", async ({ page }) => { + await open(page, "cad-colours.dxf"); + // 200 x 50 units in 800 x 200 px: 4 px a unit, x from -50, y from 15 to 65. + const p = await raster(page, 1, { region: { x: -50, y: 15, width: 200, height: 50 }, width: 800, height: 200 }); + expect(p.info).toMatchObject({ width: 800, height: 200, page: 1, layout: "", space: "drawing" }); + expect(p.info.region).toMatchObject({ x: -50, y: 15, width: 200, height: 50 }); + // The band, from y 60 (row 20) to 40 (row 100), across x 0..100 (columns 200..600). + const band = find(p, cyan).box!; + expect(band.minX).toBeGreaterThanOrEqual(198); + expect(band.maxX).toBeLessThanOrEqual(602); + expect(Math.abs(band.minY - 20)).toBeLessThanOrEqual(2); + expect(Math.abs(band.maxY - 100)).toBeLessThanOrEqual(2); + // The red line at y 20: row 180, below the band. Round caps reach 4 px past its ends. + const line = find(p, red).box!; + expect(Math.abs((line.minY + line.maxY) / 2 - 180)).toBeLessThanOrEqual(2); + expect(Math.abs(line.minX - 196)).toBeLessThanOrEqual(3); + expect(Math.abs(line.maxX - 604)).toBeLessThanOrEqual(3); + // The paper outside is the ground. + expect(near(at(p, 20, 100), [255, 255, 255, 255], 2)).toBe(true); + expect(near(at(p, 700, 20), [255, 255, 255, 255], 2)).toBe(true); + }); + + test("is widened to the picture's shape (contain) or narrowed to it (cover), and reported as drawn", async ({ page }) => { + await open(page, "cad-colours.dxf"); + const region = { x: 0, y: 40, width: 100, height: 20 }; + const wide = await raster(page, 1, { region, width: 400, height: 400 }); + expect(wide.info.region.width).toBeCloseTo(100, 6); + expect(wide.info.region.height).toBeCloseTo(100, 6); + expect(wide.info.region.x).toBeCloseTo(0, 6); + expect(wide.info.region.y).toBeCloseTo(0, 6); + // The band is in the middle of the picture, a fifth of its height. + const band = find(wide, cyan).box!; + expect(Math.abs(band.minY - 160)).toBeLessThanOrEqual(2); + expect(Math.abs(band.maxY - 240)).toBeLessThanOrEqual(2); + const cover = await raster(page, 1, { region, width: 400, height: 400, fit: "cover" }); + expect(cover.info.region.width).toBeCloseTo(20, 6); + expect(cover.info.region.height).toBeCloseTo(20, 6); + expect(cover.info.region.x).toBeCloseTo(40, 6); + // Cover: the band fills the picture. + expect(find(cover, cyan).count).toBe(400 * 400); + }); + + test("takes its shape from a longEdge alone, and refuses what is no size or region", async ({ page }) => { + await open(page, "cad-colours.dxf"); + const p = await raster(page, 1, { region: { x: 0, y: 0, width: 100, height: 25 }, longEdge: 200 }); + expect([p.width, p.height]).toEqual([200, 50]); + expect(p.info.region.width / p.info.region.height).toBeCloseTo(4, 2); + expect(await refused(page, 1, { longEdge: 0 })).toBe("invalid"); + expect(await refused(page, 1, { longEdge: 100, region: { x: 0, y: 0, width: 0, height: 5 } })).toBe("invalid"); + expect(await refused(page, 1, { longEdge: 100, lineweight: "heavy" })).toBe("invalid"); + expect(await refused(page, 1, { longEdge: 100, background: "url(x)" })).toBe("invalid"); + expect(await refused(page, 1, { width: 20000, height: 20000 })).toBe("too-large"); + expect(await refused(page, 99, { longEdge: 100 })).toBe("invalid"); + expect(await refused(page, 1, { longEdge: 100, layout: "Nope" })).toBe("invalid"); + // So close that the f32 coordinates cannot place it. + expect(await refused(page, 1, { longEdge: 100, region: { x: 0, y: 0, width: 1e-9, height: 1e-9 } })).toBe("invalid"); + }); + + test("the whole layout by default, on the viewer's ground", async ({ page }) => { + await open(page, "cad-colours.dxf"); + const p = await raster(page, 1, { longEdge: 600 }); + expect(p.info.region.width / p.info.region.height).toBeGreaterThan(1.5); + // The extents with the viewer's margin around them: the drawing is inside, the edge is ground. + const box = find(p, notWhite).box!; + expect(box.minX).toBeGreaterThan(5); + expect(box.maxX).toBeLessThan(p.width - 5); + expect(near(at(p, 0, 0), [255, 255, 255, 255], 2)).toBe(true); + }); +}); + +test.describe("the viewport", () => { + test("follows the camera, in drawing units, and 'current' draws it as the viewer shows it", async ({ page }) => { + const canvas = await open(page, "cad-colours.dxf"); + const box = (await canvas.boundingBox())!; + const fitted = (await viewport(page))!; + expect(fitted).toMatchObject({ space: "drawing", page: 1, layout: "" }); + // The drawing's extents (x 0..100, y 0..60 less the band's edge) are inside it. + expect(fitted.region.x).toBeLessThan(0); + expect(fitted.region.x + fitted.region.width).toBeGreaterThan(100); + await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2); + await page.mouse.wheel(0, -500); + await expect.poll(async () => (await viewport(page))!.region.width).toBeLessThan(fitted.region.width * 0.6); + const screen = await settled(canvas); + const view = (await viewport(page))!; + const [cw, ch] = await canvas.evaluate((c: HTMLCanvasElement) => [c.width, c.height]); + expect([screen.width, screen.height]).toEqual([cw, ch]); + const p = await raster(page, 1, { region: "current", width: cw, height: ch }); + expect(p.info.region.x).toBeCloseTo(view.region.x, 6); + expect(p.info.region.y).toBeCloseTo(view.region.y, 6); + expect(p.info.region.width).toBeCloseTo(view.region.width, 6); + expect(p.info.region.height).toBeCloseTo(view.region.height, 6); + expect(difference(screen, p)).toBeLessThan(0.5); + expect(worst(screen, p)).toBeLessThan(80); + }); + + test("a drawing with text: 'current' at the canvas's size is the picture on screen", async ({ page }) => { + const canvas = await open(page, "plan.dxf"); + const box = (await canvas.boundingBox())!; + await page.mouse.move(box.x + box.width * 0.25, box.y + box.height * 0.5); + await page.mouse.wheel(0, -600); + await page.waitForTimeout(600); + const screen = await settled(canvas); + const [cw, ch] = await canvas.evaluate((c: HTMLCanvasElement) => [c.width, c.height]); + const p = await raster(page, 1, { region: "current", width: cw, height: ch }); + // Another glyph atlas, at the size the picture wants: a hair apart. + expect(difference(screen, p)).toBeLessThan(1.5); + expect(find(p, notWhite).count).toBeGreaterThan(200); + }); + + test("is a pan, a zoom and a resize away from where it was, and dedupes", async ({ page }) => { + const canvas = await open(page, "cad-colours.dxf"); + const seen = await page.evaluate(() => { + const s = (window as unknown as { exavDemo: { session(): { controllers: { get(): { viewport: { subscribe(f: (v: unknown) => void): () => void } } } } } }).exavDemo.session(); + const log: unknown[] = []; + (window as unknown as { log: unknown[] }).log = log; + s.controllers.get().viewport.subscribe((v) => log.push(v)); + return log.length; + }); + expect(seen).toBe(0); + const before = (await viewport(page))!; + const box = (await canvas.boundingBox())!; + await page.mouse.move(box.x + 100, box.y + 100); + await page.mouse.down(); + await page.mouse.move(box.x + 160, box.y + 100, { steps: 4 }); + await page.mouse.up(); + const after = (await viewport(page))!; + expect(after.region.width).toBeCloseTo(before.region.width, 6); + // Dragged to the right by 60 px: the view moves left. + expect(after.region.x).toBeLessThan(before.region.x); + const notified = await page.evaluate(() => (window as unknown as { log: unknown[] }).log.length); + expect(notified).toBeGreaterThan(0); + // A store set again with what it had does not notify. + await page.evaluate(() => window.dispatchEvent(new Event("resize"))); + await page.waitForTimeout(300); + expect(await page.evaluate(() => (window as unknown as { log: unknown[] }).log.length)).toBe(notified); + }); + + test("is the sheet's, in paper units, once a layout is shown; 'current' is refused for the layout not shown", async ({ page }) => { + await open(page, "cad-sheets.dxf"); + const metric = await pageOf(page, "Metric"); + const imperial = await pageOf(page, "Imperial"); + expect(await refused(page, metric, { longEdge: 100, region: "current" })).toBe("invalid"); + await layout(page, "Metric"); + const view = (await viewport(page))!; + expect(view).toMatchObject({ space: "drawing", page: metric, layout: "Metric" }); + // A sheet of 297 by 210 mm is inside the view. + expect(view.region.width).toBeGreaterThan(297); + const p = await raster(page, metric, { region: "current", longEdge: 300 }); + expect(p.info.layout).toBe("Metric"); + // The sheet's view, to the hair a picture of whole pixels widens it by. + expect(Math.abs(p.info.region.width / view.region.width - 1)).toBeLessThan(0.01); + expect(await refused(page, 1, { longEdge: 100, region: "current" })).toBe("invalid"); + expect(await refused(page, imperial, { longEdge: 100, region: "current" })).toBe("invalid"); + }); +}); + +test.describe("layouts", () => { + // sheets.dxf: model space holds a line; "Metric" and "Imperial" are sheets + // (A4 in mm, letter in inches) with a square of an inch and, below it, a line + // 2.11 mm wide: the square is 25.4 units on the first, 1 on the other. + test("a paper layout is drawn as its sheet: the paper on a surround, in paper units", async ({ page }) => { + const canvas = await open(page, "cad-sheets.dxf"); + const before = await settled(canvas); + const p = await raster(page, await pageOf(page, "Metric"), { longEdge: 900 }); + expect(p.info).toMatchObject({ page: await pageOf(page, "Metric"), layout: "Metric" }); + const surround = (r: number, g: number, b: number) => Math.abs(r - 224) < 8 && Math.abs(g - 224) < 8 && Math.abs(b - 224) < 8; + const white = (r: number, g: number, b: number) => r > 250 && g > 250 && b > 250; + expect(find(p, surround).count).toBeGreaterThan(1000); + const sheet = find(p, white).box!; + expect(sheet.width / sheet.height).toBeGreaterThan(1.37); + expect(sheet.width / sheet.height).toBeLessThan(1.46); + // Paper units: the sheet is 297 wide, so it is that many units of the region. + const unit = p.width / p.info.region.width; + expect(sheet.width / unit).toBeGreaterThan(290); + expect(sheet.width / unit).toBeLessThan(300); + // What the viewer shows was not touched. + expect(await refused(page, 1, { longEdge: 50 })).toBe("none"); + expect(difference(before, await settled(canvas))).toBe(0); + expect((await viewport(page))!.layout).toBe(""); + }); + + test("the layout option selects by id and wins over the page", async ({ page }) => { + await open(page, "cad-sheets.dxf"); + const p = await raster(page, 1, { layout: "Imperial", longEdge: 200 }); + expect(p.info).toMatchObject({ page: await pageOf(page, "Imperial"), layout: "Imperial" }); + const q = await raster(page, 2, { layout: "", longEdge: 200 }); + expect(q.info).toMatchObject({ page: 1, layout: "" }); + }); + + test("a lineweight on a sheet is millimetres on the page; screen follows the viewer, scaled the picture", async ({ page }) => { + const canvas = await open(page, "cad-sheets.dxf"); + // Metric: 10 px a unit; the line, 2.11 mm wide, at y -25.4: row 554. + const region = { x: -10, y: -30, width: 60, height: 60 }; + const size = { width: 600, height: 600 }; + const thickness = (p: Pixels) => column(p, 250, ink).length; + const scaled = await raster(page, 1, { layout: "Metric", region, ...size, lineweight: "scaled" }); + const lines = column(scaled, 250, ink); + // The line is the lowest ink in the column. + const bottom = lines.filter((y) => y > 450); + expect(bottom.length).toBeGreaterThan(18); + expect(bottom.length).toBeLessThan(24); + expect(Math.abs((bottom[0]! + bottom.at(-1)!) / 2 - 554)).toBeLessThanOrEqual(3); + // On screen: the width the viewer would have when its canvas shows the region. + const screen = await raster(page, 1, { layout: "Metric", region, ...size }); + const cw = (await canvas.evaluate((c: HTMLCanvasElement) => [c.width, c.height])) as [number, number]; + const k = Math.max(60 / cw[0], 60 / cw[1]) / 0.1; + const wanted = 21.1 / k; + const got = column(screen, 250, ink).filter((y) => y > 450).length; + expect(Math.abs(got - Math.max(wanted, 1))).toBeLessThanOrEqual(3); + expect(thickness(scaled)).toBeGreaterThan(got); + }); + + test("a viewport's content is clipped to its window, as the viewer shows it", async ({ page }) => { + // A text 60 long and a viewport onto x -10 to 30 of it, 40 by 20 on the sheet. + await open(page, "cad-viewport_text.dxf"); + const p = await raster(page, 1, { layout: "Sheet", longEdge: 1200 }); + expect(p.info.layout).toBe("Sheet"); + const box = find(p, ink).box!; + expect(box.width / box.height).toBeGreaterThan(4.5); + expect(box.width / box.height).toBeLessThan(7); + // The model itself has all the text, and the other one far to the right. + const model = await raster(page, 1, { longEdge: 1200 }); + expect(find(model, ink).box!.width / find(model, ink).box!.height).toBeGreaterThan(10); + }); +}); + +test.describe("tiles", () => { + /** The same picture in one pass, and in tiles of 64 px (the page's `rasterTile`). */ + async function both(browserPage: Page, name: string, n: number, options: Options) { + // The tiles drawn: one GL canvas read back each. + await browserPage.addInitScript(() => { + if ((window as unknown as { tiles?: number }).tiles !== undefined) return; + (window as unknown as { tiles: number }).tiles = 0; + const original = OffscreenCanvas.prototype.transferToImageBitmap; + OffscreenCanvas.prototype.transferToImageBitmap = function (this: OffscreenCanvas) { + (window as unknown as { tiles: number }).tiles++; + return original.call(this); + }; + }); + const drawn = () => browserPage.evaluate(() => (window as unknown as { tiles: number }).tiles); + await open(browserPage, name); + const whole = await raster(browserPage, n, options); + const single = await drawn(); + await open(browserPage, name, { rasterTile: "64" }); + const tiled = await raster(browserPage, n, options); + // Tiles of 64 px, so many of them: the tiled picture is not the single pass. (One more read, of the composed picture.) + expect([single - 1, (await drawn()) - 1]).toEqual([1, Math.ceil(tiled.width / 64) * Math.ceil(tiled.height / 64)]); + return { whole, tiled }; + } + + test("a picture drawn in small tiles is the picture drawn in one pass, no gap and no line twice at the seams", async ({ page }) => { + const { whole, tiled } = await both(page, "cad-halo.dxf", 1, { longEdge: 500 }); + expect([tiled.width, tiled.height]).toEqual([whole.width, whole.height]); + expect(tiled.info.region).toEqual(whole.info.region); + // A red band 8 px wide and a thin line cross the seams every 64 px. + expect(find(whole, red).count).toBeGreaterThan(500); + expect(worst(whole, tiled)).toBeLessThanOrEqual(2); + expect(difference(whole, tiled)).toBeLessThan(0.01); + }); + + test("with text, fills and the sheet's paper", async ({ page }) => { + const text = await both(page, "plan.dxf", 1, { longEdge: 600 }); + expect(find(text.whole, ink).count).toBeGreaterThan(300); + expect(worst(text.whole, text.tiled)).toBeLessThanOrEqual(6); + expect(difference(text.whole, text.tiled)).toBeLessThan(0.05); + const sheet = await both(page, "cad-sheets.dxf", 1, { layout: "Metric", longEdge: 700 }); + expect(worst(sheet.whole, sheet.tiled)).toBeLessThanOrEqual(2); + expect(difference(sheet.whole, sheet.tiled)).toBeLessThan(0.01); + const fills = await both(page, "cad-colours.dxf", 1, { region: { x: 10, y: 30, width: 50, height: 40 }, width: 330, height: 270 }); + expect(find(fills.whole, cyan).count).toBeGreaterThan(1000); + expect(worst(fills.whole, fills.tiled)).toBeLessThanOrEqual(2); + }); + + test("a picture past the default tile, over two sides, is composed", async ({ page }) => { + await open(page, "cad-colours.dxf"); + // 2600 px wide: two tiles of 2048 across. + const p = await raster(page, 1, { region: { x: 0, y: 0, width: 100, height: 60 }, width: 2600, height: 1560 }); + expect([p.width, p.height]).toEqual([2600, 1560]); + const band = find(p, cyan).box!; + // x 0..100 is the whole width; y 40..60 is the top third of the region. + expect(band.minX).toBeLessThanOrEqual(1); + expect(band.maxX).toBeGreaterThanOrEqual(2598); + expect(Math.abs(band.minY - 0)).toBeLessThanOrEqual(2); + expect(Math.abs(band.maxY - 520)).toBeLessThanOrEqual(2); + // Across the tile seam at column 2048, nothing is missing. + expect(column(p, 2047, cyan).length).toBe(column(p, 2048, cyan).length); + expect(column(p, 2047, cyan).length).toBeGreaterThan(500); + }); +}); + +test.describe("sharpness", () => { + test("a hairline stays a pixel wide at four times the zoom on screen", async ({ page }) => { + const canvas = await open(page, "cad-halo.dxf"); + const screen = await settled(canvas); + const view = (await viewport(page))!; + // halo.dxf: a thin vertical line at x 50 below a wide red one. + const w = screen.width * 4; + const h = screen.height * 4; + const p = await raster(page, 1, { region: "current", width: w, height: h }); + const y = Math.round(h * 0.85); + const touched = (r: number, g: number, b: number) => r < 235 || g < 235 || b < 235; + // How much ink a row has, in pixels of the line's colour (a grey of 51: 204 under white). + const inkOf = (q: Pixels) => row(q, y, touched).reduce((n, x) => n + (255 - at(q, x, y)[0]) / 204, 0); + const dark = row(p, y, touched); + expect(dark.length).toBeGreaterThan(0); + expect(dark.length).toBeLessThanOrEqual(3); + // One pixel of ink, not an upscaled one's four. + expect(inkOf(p)).toBeGreaterThan(0.75); + expect(inkOf(p)).toBeLessThan(1.35); + // In the picture where the line is: the middle of the region. + const centre = Math.round(((50 - view.region.x) / view.region.width) * w); + expect(Math.abs(dark[0]! - centre)).toBeLessThanOrEqual(3); + // Scaled with the picture it is four times as wide. + const scaled = await raster(page, 1, { region: "current", width: w, height: h, lineweight: "scaled" }); + expect(inkOf(scaled)).toBeGreaterThan(3.4); + expect(inkOf(scaled)).toBeLessThan(4.7); + }); + + test("text is drawn at the picture's scale, not magnified: edges a pixel or two wide", async ({ page }) => { + await open(page, "cad-text_many.dxf"); + const view = (await viewport(page))!; + // The middle of the drawing, zoomed thirty times. + const cx = view.region.x + view.region.width / 2; + const cy = view.region.y + view.region.height / 2; + const w = view.region.width / 30; + const p = await raster(page, 1, { region: { x: cx - w / 2, y: cy - w / 4, width: w, height: w / 2 }, width: 1200, height: 600 }); + const lum = (r: number, g: number, b: number) => (r + g + b) / 3; + const dark = find(p, (r, g, b) => lum(r, g, b) < 80).count; + const edge = find(p, (r, g, b) => lum(r, g, b) >= 80 && lum(r, g, b) < 200).count; + expect(dark).toBeGreaterThan(2000); + expect(edge / dark).toBeLessThan(0.15); + }); +}); + +test.describe("the ground", () => { + test("is any CSS colour, the viewer's ground by default", async ({ page }) => { + await open(page, "cad-colours.dxf"); + const p = await raster(page, 1, { region: { x: 200, y: 200, width: 10, height: 10 }, width: 20, height: 20, background: "rgb(10 200 30)" }); + expect(near(at(p, 10, 10), [10, 200, 30, 255], 1)).toBe(true); + const q = await raster(page, 1, { region: { x: 200, y: 200, width: 10, height: 10 }, width: 20, height: 20, background: "#ff000080" }); + expect(near(at(q, 10, 10), [255, 0, 0, 128], 2)).toBe(true); + // The dark ground of the session: a drawing resolved against it. + const dark = await raster(page, 1, { region: { x: 200, y: 200, width: 10, height: 10 }, width: 20, height: 20, background: "#212830" }); + expect(near(at(dark, 3, 3), [0x21, 0x28, 0x30, 255], 1)).toBe(true); + }); + + test("transparent has no ground, and its edges and text are premultiplied right", async ({ page }) => { + await open(page, "plan.dxf"); + const options = { longEdge: 700 }; + const opaque = await raster(page, 1, { ...options, background: "#ffffff" }); + const clear = await raster(page, 1, { ...options, background: "transparent" }); + expect(at(clear, 0, 0)[3]).toBe(0); + let partial = 0; + let solid = 0; + for (let i = 0; i < clear.data.length; i += 4) { + const a = clear.data[i + 3]!; + if (a === 255) solid++; + else if (a > 0) partial++; + } + expect(solid).toBeGreaterThan(300); + expect(partial).toBeGreaterThan(300); + // The picture on white is the picture with a white ground: a premultiplied edge + // read as straight, or a glyph's twice over, would darken or lighten it. + const over = new Uint8Array(clear.data.length); + for (let i = 0; i < over.length; i += 4) { + const a = clear.data[i + 3]! / 255; + for (let c = 0; c < 3; c++) over[i + c] = Math.round(clear.data[i + c]! * a + 255 * (1 - a)); + over[i + 3] = 255; + } + const composed = { width: clear.width, height: clear.height, data: over }; + expect(difference(composed, opaque)).toBeLessThan(0.1); + expect(worst(composed, opaque)).toBeLessThanOrEqual(24); + // A pixel that is part ink keeps the ink's own colour (the circle's cyan, 0 194 194 on a light ground), not a darker one. + let tinted = 0; + for (let i = 0; i < clear.data.length; i += 4) { + const a = clear.data[i + 3]!; + if (a > 60 && a < 200 && clear.data[i]! < 20 && Math.abs(clear.data[i + 1]! - 194) < 8 && Math.abs(clear.data[i + 2]! - 194) < 8) tinted++; + } + expect(tinted).toBeGreaterThan(20); + }); + + test("a sheet on transparency is its content alone, without paper or surround", async ({ page }) => { + await open(page, "cad-sheets.dxf"); + const p = await raster(page, 1, { layout: "Metric", longEdge: 400, background: "transparent" }); + expect(at(p, 2, 2)[3]).toBe(0); + expect(at(p, p.width / 2, p.height / 2)[3]).toBe(0); + }); +}); + +test.describe("resources", () => { + /** Records the WebGL2 contexts of off screen canvases (the exports'), and how many were live when each was made. */ + async function track(page: Page) { + await page.addInitScript(() => { + const log: { gl: WebGL2RenderingContext; before: number }[] = []; + (window as unknown as { exports: typeof log }).exports = log; + const original = OffscreenCanvas.prototype.getContext; + OffscreenCanvas.prototype.getContext = function (this: OffscreenCanvas, kind: string, ...rest: unknown[]) { + const gl = (original as (...a: unknown[]) => unknown).call(this, kind, ...rest); + if (kind === "webgl2" && gl) log.push({ gl: gl as WebGL2RenderingContext, before: log.filter((e) => !e.gl.isContextLost()).length }); + return gl; + } as typeof original; + }); + } + const contexts = (page: Page) => + page.evaluate(() => { + const log = (window as unknown as { exports: { gl: WebGL2RenderingContext; before: number }[] }).exports; + return { made: log.length, live: log.filter((e) => !e.gl.isContextLost()).length, before: log.map((e) => e.before) }; + }); + + test("a context is made for a picture and given back, on success and on error", async ({ page }) => { + await track(page); + await open(page, "cad-colours.dxf"); + await raster(page, 1, { longEdge: 300 }); + expect(await contexts(page)).toMatchObject({ made: 1, live: 0 }); + expect(await refused(page, 1, { longEdge: 300, region: { x: 0, y: 0, width: 1e-9, height: 1e-9 } })).toBe("invalid"); + expect(await contexts(page)).toMatchObject({ live: 0 }); + }); + + test("pictures are drawn one at a time", async ({ page }) => { + await track(page); + await open(page, "cad-colours.dxf", { rasterTile: "64" }); + const sizes = await page.evaluate(async () => { + const s = (window as unknown as { exavDemo: { session(): { controllers: { get(): { pictures: { raster(n: number, o: object): Promise<{ bitmap: ImageBitmap; width: number }> } } } } } }).exavDemo.session(); + const p = s.controllers.get().pictures; + const all = await Promise.all([p.raster(1, { longEdge: 300 }), p.raster(1, { longEdge: 200 }), p.raster(1, { longEdge: 100 })]); + all.forEach((r) => r.bitmap.close()); + return all.map((r) => r.width); + }); + expect(sizes).toEqual([300, 200, 100]); + const { made, before, live } = await contexts(page); + expect(made).toBe(3); + expect(before).toEqual([0, 0, 0]); + expect(live).toBe(0); + }); + + test("an abort in the middle of tiles stops the drawing and frees the context", async ({ page }) => { + await track(page); + await open(page, "plan.dxf", { rasterTile: "32" }); + const result = await page.evaluate(async () => { + const s = (window as unknown as { exavDemo: { session(): { controllers: { get(): { pictures: { raster(n: number, o: object): Promise } } } } } }).exavDemo.session(); + const abort = new AbortController(); + const started = performance.now(); + const done = s.controllers.get().pictures.raster(1, { width: 1500, height: 1000, signal: abort.signal }).then( + () => "drawn", + (e: { code?: string }) => e.code ?? String(e), + ); + // Once the first context has been made, the tiles are being drawn. + const log = (window as unknown as { exports: unknown[] }).exports; + while (log.length === 0 && performance.now() - started < 20000) await new Promise((r) => setTimeout(r, 5)); + await new Promise((r) => setTimeout(r, 150)); + abort.abort(); + return { code: await done, ms: performance.now() - started }; + }); + expect(result.code).toBe("aborted"); + await page.waitForTimeout(200); + expect(await contexts(page)).toMatchObject({ made: 1, live: 0 }); + // The session goes on, and a picture can be asked again. + const p = await raster(page, 1, { longEdge: 100 }); + expect(p.width).toBe(100); + }); + + test("an abort while the worker draws the layout is at once, before any context", async ({ page }) => { + await track(page); + await open(page, "cad-sheets.dxf"); + const code = await page.evaluate(async () => { + const s = (window as unknown as { exavDemo: { session(): { controllers: { get(): { pictures: { raster(n: number, o: object): Promise } } } } } }).exavDemo.session(); + const abort = new AbortController(); + const done = s.controllers.get().pictures.raster(2, { longEdge: 300, signal: abort.signal }).then( + () => "drawn", + (e: { code?: string }) => e.code ?? String(e), + ); + abort.abort(); + return done; + }); + expect(code).toBe("aborted"); + const p = await raster(page, 1, { layout: "Metric", longEdge: 100 }); + expect(p.width).toBeGreaterThan(0); + expect((await contexts(page)).live).toBe(0); + }); + + test("the visible canvas keeps no drawing buffer", async ({ page }) => { + const canvas = await open(page, "cad-colours.dxf"); + expect(await canvas.evaluate((c: HTMLCanvasElement) => c.getContext("webgl2")!.getContextAttributes()!.preserveDrawingBuffer)).toBe(false); + await raster(page, 1, { longEdge: 200 }); + expect(await canvas.evaluate((c: HTMLCanvasElement) => c.getContext("webgl2")!.getContextAttributes()!.preserveDrawingBuffer)).toBe(false); + }); +}); + +test.describe("in the sandboxed frame", () => { + test("a picture has the size, region and pixels it has in the page", async ({ page }) => { + await open(page, "cad-colours.dxf"); + const options = { region: { x: -50, y: 15, width: 200, height: 50 }, width: 800, height: 200 }; + const inPage = await raster(page, 1, options); + + await page.goto("./headless.html?lang=en"); + await page.getByTestId("file-input").setInputFiles({ name: "cad-colours.dxf", mimeType: "", buffer: sample("cad-colours.dxf") }); + await expect + .poll(() => page.evaluate(() => (window as unknown as { headless: { session(): { status: { get(): { phase: string } } } | null } }).headless.session()?.status.get().phase)) + .toBe("ready"); + const out = await page.evaluate(async (options) => { + const s = (window as unknown as { headless: { session(): { controllers: { get(): { pictures: { raster(n: number, o: object): Promise<{ bitmap: ImageBitmap } & Record> }; viewport: { get(): unknown } } } } } }).headless.session(); + let c = s.controllers.get(); + for (let i = 0; i < 100 && !(c.pictures && c.viewport.get()); i++) { + await new Promise((r) => setTimeout(r, 100)); + c = s.controllers.get(); + } + const r = await c.pictures.raster(1, options); + const canvas = new OffscreenCanvas(r.bitmap.width, r.bitmap.height); + canvas.getContext("2d")!.drawImage(r.bitmap, 0, 0); + r.bitmap.close(); + const bytes = new Uint8Array(await (await canvas.convertToBlob({ type: "image/png" })).arrayBuffer()); + let binary = ""; + for (let i = 0; i < bytes.length; i += 0x8000) binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000)); + const { bitmap: _bitmap, ...info } = r; + return { png: btoa(binary), info, view: c.viewport.get() }; + }, options); + const inFrame = decodePng(Buffer.from(out.png, "base64")); + expect([inFrame.width, inFrame.height]).toEqual([inPage.width, inPage.height]); + expect(out.info).toMatchObject({ width: 800, height: 200, page: 1, layout: "", space: "drawing", region: options.region }); + expect(out.view).toMatchObject({ space: "drawing", page: 1, layout: "" }); + expect(difference(inPage, inFrame)).toBeLessThan(0.05); + }); +}); diff --git a/crates/exav-viewer/e2e/cad.spec.ts b/crates/exav-viewer/e2e/cad.spec.ts new file mode 100644 index 0000000..37ce083 --- /dev/null +++ b/crates/exav-viewer/e2e/cad.spec.ts @@ -0,0 +1,305 @@ +// What the DWG and DXF renderer draws its own way, on exav-render's drawings +// built to show each thing (its tests/fixtures/dwg/make.py, copied as +// cad-*.dxf by make-samples.mjs), measured on the picture. In the page: the +// sandboxed frame draws the same pixels (demo.spec.ts compares the two). +import { fileURLToPath } from "node:url"; + +import { expect, test, type Locator, type Page } from "@playwright/test"; + +import { failOnViolations } from "./csp.js"; +import { bands, decodePng, difference, find, type Pixels } from "./pixels.js"; +import { openSample } from "./samples.js"; + +failOnViolations(); + +const ink = (r: number, g: number, b: number) => r < 160 && g < 160 && b < 160; + +/** One of the demo's example drawings (demo/examples/generate/make-cad.py). */ +const HOUSE = fileURLToPath(new URL("../demo/examples/files/cad/house-plan.dxf", import.meta.url)); + +async function shot(target: Locator): Promise { + const page = target.page(); + // The viewer's tools float over the canvas. + const tools = page.locator(".exav-viewer-tools"); + await tools.evaluateAll((els) => els.forEach((e) => ((e as HTMLElement).style.visibility = "hidden"))); + try { + return decodePng(await target.screenshot({ animations: "disabled" })); + } finally { + await tools.evaluateAll((els) => els.forEach((e) => ((e as HTMLElement).style.visibility = ""))); + } +} + +/** Two screenshots in a row that agree: the canvas has settled. */ +async function settled(target: Locator): Promise { + // A zoom scales the canvas as drawn until it pauses: its box is not its own. + await expect.poll(() => target.evaluate((e) => (e as HTMLElement).style.transform)).toBe(""); + let last = await shot(target); + for (let i = 0; i < 20; i++) { + await target.page().waitForTimeout(150); + const next = await shot(target); + if (difference(last, next) === 0) return next; + last = next; + } + return last; +} + +async function open(page: Page, name: string): Promise { + await openSample(page, name, { mode: "page" }); + await expect(page.locator(".demo-frame .exav-viewer-body")).toHaveAttribute("data-phase", "ready"); + return page.locator(".demo-frame .exav-viewer-cad-canvas"); +} + +async function layout(page: Page, name: string): Promise { + await page.locator(".exav-viewer-layouts").getByRole("button", { name }).click(); + await expect(page.locator(".demo-frame .exav-viewer-body")).toHaveAttribute("data-phase", "ready"); +} + +test.describe("clipping", () => { + // A viewport onto model x -10 to 30 of a text 5 high running from 0 to + // about 66: 30 of it shows, some 6 times its height, not 13. + test("text crossing a viewport's edge is cut at the edge", async ({ page }) => { + const canvas = await open(page, "cad-viewport_text.dxf"); + await layout(page, "Sheet"); + const box = find(await settled(canvas), ink).box!; + expect(box.width / box.height).toBeGreaterThan(4.5); + expect(box.width / box.height).toBeLessThan(7); + }); +}); + +type Test = (r: number, g: number, b: number) => boolean; + +/** The pixels `test` accepts inside `box`, less `inset` on every side. */ +function countIn(p: Pixels, box: { minX: number; minY: number; maxX: number; maxY: number }, inset: number, test: Test): number { + let n = 0; + for (let y = box.minY + inset; y <= box.maxY - inset; y++) + for (let x = box.minX + inset; x <= box.maxX - inset; x++) { + const i = (y * p.width + x) * 4; + if (test(p.data[i]!, p.data[i + 1]!, p.data[i + 2]!)) n++; + } + return n; +} + +const near = (v: number, to: number) => Math.abs(v - to) < 32; + +test.describe("transparency", () => { + // Each at half opacity: a red hatch over a green line, a blue V, a cyan + // hatch over magenta text, each drawn after what it covers. + test("an opaque line behind a translucent hatch shows through it", async ({ page }) => { + const p = await settled(await open(page, "cad-transparency.dxf")); + const pink = find(p, (r, g, b) => r > 220 && near(g, 128) && near(b, 128)).box!; + expect(countIn(p, pink, 2, (r, g, b) => near(r, 128) && near(g, 128) && b < 40)).toBeGreaterThan(0); + expect(countIn(p, pink, 2, (r, g, b) => g > 200 && r < 60 && b < 60)).toBe(0); + }); + + test("a translucent polyline is no darker where its segments meet", async ({ page }) => { + const p = await settled(await open(page, "cad-transparency.dxf")); + expect(find(p, (r, g, b) => near(r, 128) && near(g, 128) && b > 220).count).toBeGreaterThan(0); + expect(find(p, (r, g, b) => r < 90 && g < 90 && b > 200).count).toBe(0); + }); + + test("text behind a translucent hatch is tinted by it", async ({ page }) => { + const p = await settled(await open(page, "cad-transparency.dxf")); + const cyan = find(p, (r, g, b) => near(r, 128) && g > 220 && b > 220).box!; + expect(countIn(p, cyan, 2, (r, g, b) => near(r, 128) && near(g, 128) && b > 220)).toBeGreaterThan(0); + expect(countIn(p, cyan, 2, (r, g, b) => r > 200 && g < 60 && b > 200)).toBe(0); + }); +}); + +test.describe("what is not drawn", () => { + test("is said by type, and the files the drawing points at by name", async ({ page }) => { + await open(page, "cad-not_drawn.dxf"); + const warnings = page.locator(".demo-frame .exav-viewer-warnings"); + await expect(warnings).toContainText("3 objects are of a kind not drawn here. 3DSOLID (2), REGION"); + await expect(warnings).toContainText("3 external references are not drawn. photo.png, walls.dwg"); + }); + + test("a drawing with nothing drawn here keeps the thumbnail it was saved with", async ({ page }) => { + await open(page, "cad-solid_only.dxf"); + const preview = page.locator(".demo-frame .exav-viewer-cad-preview"); + await expect(preview).toHaveCount(1); + expect(await preview.evaluate((img: HTMLImageElement) => [img.naturalWidth, img.naturalHeight])).toEqual([8, 8]); + await expect(page.locator(".demo-frame .exav-viewer-warnings")).toContainText("the picture saved with it is shown"); + }); +}); + +test.describe("antialiasing", () => { + // A thin dark line drawn before the wide red one it crosses in front of: + // its anti-aliased edges blend over the red, not over the paper. + test("a line's soft edge shows what lies behind it, not the background", async ({ page }) => { + const p = await settled(await open(page, "cad-halo.dxf")); + const band = find(p, (r, g, b) => r > 200 && g < 80 && b < 80).box!; + const grey = (r: number, g: number, b: number) => + Math.max(r, g, b) - Math.min(r, g, b) < 30 && r > 70 && r < 235; + expect(countIn(p, band, 2, grey)).toBe(0); + // The dark line is there, across the band: red darkened by it. + expect(countIn(p, band, 2, (r, g, b) => r < 210 && g < 70 && b < 70)).toBeGreaterThan(0); + }); + + // Nothing but filled bands: ink and paper only, but where a pixel is part + // of each, which a slanted or curved edge has all along it. + test("a fill's edge is anti-aliased, and no wider for it", async ({ page }) => { + const p = await settled(await open(page, "cad-wide.dxf")); + const grey = (r: number, g: number, b: number) => r > 60 && r < 200 && Math.max(r, g, b) - Math.min(r, g, b) < 30; + const dark = (r: number, g: number, b: number) => r < 60 && g < 60 && b < 60; + expect(find(p, grey).count).toBeGreaterThan(60); + // Partly covered pixels outside the bands, at most half each: the ink + // stays where it was. + expect(find(p, grey).count).toBeLessThan(find(p, dark).count / 2); + }); +}); + +test.describe("curves", () => { + // Zoomed thirtyfold onto a circle's rightmost point, its edge runs down + // the canvas: a true arc leaves the vertical by about six pixels by the + // canvas's top and bottom, the seventy-sided polygon it used to be by + // fifteen on at least one side. Deeper, the pixel the zoom anchors on + // sends the edge off the canvas. + test("a circle stays round however close the view", async ({ page }) => { + const canvas = await open(page, "cad-circle.dxf"); + const fitted = await settled(canvas); + const ring = find(fitted, ink).box!; + const box = (await canvas.boundingBox())!; + const right = { x: ring.maxX, y: Math.round((ring.minY + ring.maxY) / 2) }; + await page.mouse.move(box.x + right.x, box.y + right.y); + await page.mouse.wheel(0, -1100); + const p = await settled(canvas); + const inkAt = (y: number) => { + let x = -1; + for (let i = 0; i < p.width; i++) { + const o = (y * p.width + i) * 4; + if (ink(p.data[o]!, p.data[o + 1]!, p.data[o + 2]!)) x = i; + } + return x; + }; + const middle = inkAt(right.y); + const top = inkAt(4); + const bottom = inkAt(p.height - 5); + expect(middle).toBeGreaterThan(0); + expect(top).toBeGreaterThan(0); + expect(bottom).toBeGreaterThan(0); + expect(middle - top).toBeLessThan(10); + expect(middle - bottom).toBeLessThan(10); + }); +}); + +test.describe("colours", () => { + const brightYellow = (r: number, g: number, b: number) => r > 220 && g > 220 && b < 90; + const darkYellow = (r: number, g: number, b: number) => r > 110 && g > 110 && b < 60 && r < 200; + const cyan = (r: number, g: number, b: number) => r < 60 && g > 220 && b > 220; + const red = (r: number, g: number, b: number) => r > 200 && g < 60 && b < 60; + + test("a yellow line on white is darkened to be seen; a fill keeps its colour", async ({ page }) => { + const p = await settled(await open(page, "cad-colours.dxf")); + expect(find(p, brightYellow).count).toBe(0); + expect(find(p, darkYellow).count).toBeGreaterThan(100); + expect(find(p, cyan).count).toBeGreaterThan(1000); + }); + + test("monochrome draws everything in ink", async ({ page }) => { + await openSample(page, "cad-colours.dxf", { mode: "page", cad: "monochrome" }); + await expect(page.locator(".demo-frame .exav-viewer-body")).toHaveAttribute("data-phase", "ready"); + const p = await settled(page.locator(".demo-frame .exav-viewer-cad-canvas")); + expect(find(p, red).count + find(p, cyan).count + find(p, darkYellow).count).toBe(0); + expect(find(p, (r, g, b) => r < 40 && g < 40 && b < 40).count).toBeGreaterThan(1000); + }); +}); + +test.describe("context", () => { + test("a lost GL context comes back with the drawing on it", async ({ page }) => { + const canvas = await open(page, "cad-halo.dxf"); + const before = await settled(canvas); + await canvas.evaluate(async (c: HTMLCanvasElement) => { + const lose = c.getContext("webgl2")!.getExtension("WEBGL_lose_context")!; + lose.loseContext(); + await new Promise((r) => setTimeout(r, 300)); + lose.restoreContext(); + }); + await page.waitForTimeout(1500); + expect(difference(before, await settled(canvas))).toBeLessThan(1); + }); +}); + +test.describe("text", () => { + // Twelve faces' worth of characters, more than the atlas budget affords + // at the em a close view wants: "HE" in the middle, zoomed into, keeps + // edges a pixel or two wide rather than the blur of a magnified bitmap. + test("a character set too large for the atlas stays sharp zoomed in", async ({ page }) => { + const canvas = await open(page, "cad-text_many.dxf"); + const box = (await canvas.boundingBox())!; + await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2); + await page.mouse.wheel(0, -1400); + await page.waitForTimeout(1000); + const p = await settled(canvas); + const lum = (r: number, g: number, b: number) => (r + g + b) / 3; + const dark = find(p, (r, g, b) => lum(r, g, b) < 80).count; + const edge = find(p, (r, g, b) => lum(r, g, b) >= 80 && lum(r, g, b) < 200).count; + expect(dark).toBeGreaterThan(2000); + expect(edge / dark).toBeLessThan(0.15); + }); + + // A drawing of a house, zoomed into by ten: the glyph page for that view is + // made of distance fields, which take the better part of a second. Made a + // slice at a time, the page keeps answering while they are (the longest + // wait was 940 ms in one piece, 95 ms in slices, in software GL). + test("the glyph page made for a closer view does not stop the page", async ({ page }) => { + await page.goto("./?lang=en&mode=page"); + await page.getByTestId("file-input").setInputFiles(HOUSE); + await expect(page.locator(".demo-frame .exav-viewer-body")).toHaveAttribute("data-phase", "ready"); + const canvas = page.locator(".demo-frame .exav-viewer-cad-canvas"); + // What loading left to do is done. + await settled(canvas); + const box = (await canvas.boundingBox())!; + await page.mouse.move(box.x + box.width * 0.6, box.y + box.height * 0.45); + await page.evaluate(() => { + const w = window as unknown as { gaps: number[] }; + w.gaps = []; + let last = performance.now(); + setInterval(() => { + const now = performance.now(); + w.gaps.push(now - last); + last = now; + }, 5); + }); + await page.mouse.wheel(0, -1000); + await page.waitForTimeout(2500); + const gaps = await page.evaluate(() => (window as unknown as { gaps: number[] }).gaps); + expect(gaps.length).toBeGreaterThan(100); + expect(Math.max(...gaps)).toBeLessThan(300); + }); +}); + +test.describe("paper", () => { + test("a layout is drawn on its sheet of paper, model space on the ground", async ({ page }) => { + const canvas = await open(page, "cad-sheets.dxf"); + const surround = (r: number, g: number, b: number) => Math.abs(r - 224) < 8 && Math.abs(g - 224) < 8 && Math.abs(b - 224) < 8; + const white = (r: number, g: number, b: number) => r > 250 && g > 250 && b > 250; + expect(find(await settled(canvas), surround).count).toBe(0); + await layout(page, "Metric"); + const p = await settled(canvas); + expect(find(p, surround).count).toBeGreaterThan(1000); + // A4 in landscape: the white sheet is 297 by 210. + const sheet = find(p, white).box!; + expect(sheet.width / sheet.height).toBeGreaterThan(1.37); + expect(sheet.width / sheet.height).toBeLessThan(1.46); + }); +}); + +test.describe("sheets", () => { + // Each layout has a square an inch across and, below it, a line 2.11 mm + // wide: a twelfth of the square on either sheet, whatever its units. + for (const name of ["Metric", "Imperial"]) { + test(`a lineweight on a sheet in ${name.toLowerCase()} units is millimetres on the page`, async ({ page }) => { + const canvas = await open(page, "cad-sheets.dxf"); + await layout(page, name); + const p = await settled(canvas); + // Rows with ink most of the way across: the square's two edges and the line. + const rows = bands(p, ink, 20); + expect(rows.length).toBe(3); + const [top, bottom, line] = rows as [{ from: number; to: number }, { from: number; to: number }, { from: number; to: number }]; + const side = bottom.from - top.from; + const width = line.to - line.from + 1; + expect(width / side).toBeGreaterThan(0.05); + expect(width / side).toBeLessThan(0.13); + }); + } +}); diff --git a/crates/exav-viewer/e2e/converted.spec.ts b/crates/exav-viewer/e2e/converted.spec.ts new file mode 100644 index 0000000..00f6bdc --- /dev/null +++ b/crates/exav-viewer/e2e/converted.spec.ts @@ -0,0 +1,134 @@ +// The converted Office formats of `@exav/viewer/office` (`rtf()`, `doc()`...) +// with a real external converter, shown by the viewer's PDF and XLSX plugins, +// in the page and in the sandboxed frame. The converter is a package that +// exports the contract (see `ExternalConverter`) and carries its fixtures in +// `tests/fixtures`: name it in EXAV_EXTERNAL_CONVERTER when you build the demo +// (`EXAV_EXTERNAL_CONVERTER= npm run demo:build`) and run these tests. +// Skipped, saying why, when it is not set or the demo was built without it; +// external.spec.ts checks the contract itself with a converter of its own. +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +import { expect, test, type FrameLocator, type Locator, type Page } from "@playwright/test"; + +import { failOnViolations, screenshotting } from "./csp.js"; +import { decodePng, find } from "./pixels.js"; + +const CONVERTER = process.env.EXAV_EXTERNAL_CONVERTER; + +/** The converter's own fixtures: a short letter, a two-slide presentation, a two-page drawing, a small table, and Keynote, Numbers and CorelDRAW files. */ +const FIXTURES = CONVERTER ? path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "node_modules", ...CONVERTER.split("/"), "tests", "fixtures") : ""; + +failOnViolations(); + +test.beforeEach(async ({ page }) => { + test.skip(!CONVERTER, "no real external converter: set EXAV_EXTERNAL_CONVERTER to an installed converter package, and build the demo with it"); + await page.goto("./?lang=en"); + const manifest = await page.evaluate(() => fetch("./exav-viewer/manifest.json").then((r) => r.json())); + test.skip(!manifest.converters?.[CONVERTER!], `the demo was built without ${CONVERTER}: build it with EXAV_EXTERNAL_CONVERTER=${CONVERTER}`); +}); + +const ink = (r: number, g: number, b: number) => r < 160 && g < 160 && b < 160; + +for (const mode of ["sandbox", "page"] as const) { + async function open(page: Page, name: string, as = name, params: Record = {}) { + await page.goto(`./?${new URLSearchParams({ lang: "en", ...params, ...(mode === "page" && { mode }) })}`); + await page.getByTestId("file-input").setInputFiles({ name: as, mimeType: "", buffer: fs.readFileSync(path.join(FIXTURES, name)) }); + await expect(page.locator(".demo-frame .exav-viewer-body")).toHaveAttribute("data-phase", "ready", { timeout: 60_000 }); + } + + /** Dark pixels on the surface: the document is drawn, not a blank page. */ + const drawn = async (page: Page) => { + screenshotting(page); + return find(decodePng(await page.locator(".demo-frame .exav-viewer-surface").screenshot()), ink).count; + }; + + /** What the engine put on screen: in the frame's document, or in the page's. */ + const engine = (page: Page): FrameLocator | Locator => + mode === "sandbox" ? page.frameLocator(".demo-frame iframe.exav-viewer-sandbox") : page.locator(".demo-frame"); + + test.describe(mode, () => { + test("a Word 97 document is converted to PDF and shown page by page", async ({ page }) => { + await open(page, "sample.doc"); + await expect(engine(page).locator(".exav-viewer-pdf-page")).toHaveCount(2); + await expect.poll(() => drawn(page)).toBeGreaterThan(200); + }); + + test("a conversion shows its steps, with a bar for those it counts", async ({ page }) => { + await page.goto(`./?${new URLSearchParams({ lang: "en", ...(mode === "page" && { mode }) })}`); + // Every message the status overlay shows, and whether a bar came with it. + await page.evaluate(() => { + const seen = new Set(); + (window as unknown as { steps: Set }).steps = seen; + new MutationObserver(() => { + const status = document.querySelector(".demo-frame .exav-viewer-status"); + const text = status?.querySelector("p")?.textContent; + if (text) seen.add(`${text}${status!.querySelector('[role="progressbar"]') ? " [bar]" : ""}`); + }).observe(document.body, { subtree: true, childList: true, characterData: true, attributes: true }); + }); + await page.getByTestId("file-input").setInputFiles({ name: "sample.doc", mimeType: "", buffer: fs.readFileSync(path.join(FIXTURES, "sample.doc")) }); + await expect(page.locator(".demo-frame .exav-viewer-body")).toHaveAttribute("data-phase", "ready", { timeout: 60_000 }); + const steps = await page.evaluate(() => [...(window as unknown as { steps: Set }).steps]); + expect(steps).toContain("Downloading the viewer… [bar]"); + expect(steps).toContain("Starting the viewer…"); + expect(steps).toContain("Converting the document… [bar]"); + }); + + test("an RTF saved under .doc is read as the RTF it is", async ({ page }) => { + await open(page, "sample.rtf", "letter.doc"); + await expect(engine(page).locator(".exav-viewer-pdf-page")).toHaveCount(2); + }); + + test("an OpenDocument presentation is converted by exav-render's slides and shown as slides", async ({ page }) => { + await open(page, "sample.odp"); + await expect(engine(page).locator(".exav-viewer-pdf-page")).toHaveCount(0); + await expect(engine(page).locator("canvas").first()).toBeVisible(); + await expect.poll(() => drawn(page)).toBeGreaterThan(200); + }); + + test("a Keynote 1 presentation is converted by exav-render's slides and shown as slides, not as PDF", async ({ page }) => { + await open(page, "keynote1.key"); + await expect(engine(page).locator(".exav-viewer-pdf-page")).toHaveCount(0); + await expect(page.locator(".exav-viewer-pager span")).toHaveText("Slide 1 / 2"); + await expect.poll(() => drawn(page)).toBeGreaterThan(200); + }); + + test("an OpenDocument drawing is converted by exav-render's slides, a page to a slide, not to PDF", async ({ page }) => { + await open(page, "sample.odg"); + await expect(engine(page).locator(".exav-viewer-pdf-page")).toHaveCount(0); + await expect(page.locator(".exav-viewer-pager span")).toHaveText("Slide 1 / 2"); + await expect.poll(() => drawn(page)).toBeGreaterThan(50); + }); + + test("an OpenDocument drawing is converted to PDF, a page per page, when the external converter is asked for", async ({ page }) => { + await open(page, "sample.odg", "sample.odg", { converter: "external" }); + await expect(engine(page).locator(".exav-viewer-pdf-page")).toHaveCount(2); + await expect.poll(() => drawn(page)).toBeGreaterThan(50); + }); + + test("a CorelDRAW drawing is converted to PDF", async ({ page }) => { + await open(page, "corel.cdr"); + await expect(engine(page).locator(".exav-viewer-pdf-page")).toHaveCount(1); + await expect.poll(() => drawn(page)).toBeGreaterThan(200); + }); + + test("a Numbers spreadsheet is converted to XLSX and shown as a workbook", async ({ page }) => { + await open(page, "sample.numbers"); + await expect(engine(page).locator("canvas").first()).toBeVisible(); + await expect.poll(() => drawn(page)).toBeGreaterThan(200); + }); + + test("an Excel 97 workbook is converted to XLSX and shown as a workbook", async ({ page }) => { + await open(page, "sample.xls"); + await expect(engine(page).locator("canvas").first()).toBeVisible(); + await expect(engine(page).locator(".exav-viewer-pdf-page")).toHaveCount(0); + await expect.poll(() => drawn(page)).toBeGreaterThan(200); + }); + + test("an XLSX named .xls is shown as it is", async ({ page }) => { + await open(page, "sample.xlsx", "renamed.xls"); + await expect.poll(() => drawn(page)).toBeGreaterThan(200); + }); + }); +} diff --git a/crates/exav-viewer/e2e/csp.ts b/crates/exav-viewer/e2e/csp.ts index 688b396..b68dba7 100644 --- a/crates/exav-viewer/e2e/csp.ts +++ b/crates/exav-viewer/e2e/csp.ts @@ -6,12 +6,25 @@ import { expect, test, type Page } from "@playwright/test"; const seen = new WeakMap(); +const screenshots = new WeakMap(); /** The violations reported so far on `page`. */ export function violations(page: Page): string[] { return seen.get(page) ?? []; } +/** + * Says a screenshot of `page` is taken. In WebKit, Playwright adds a + * `", + "
    ", + "
    ", + "bold", + "", + "", + "", + "", + "

    ", + ]; + + it("shows each of these as written and creates none of their elements", async () => { + for (const html of hostile) { + const r = await render(html); + expect(r.querySelector("script,img,svg,iframe,a,style,form,input,details,math,meta,link,base,b"), html).toBeNull(); + expectInert(r, html); + expect(r.textContent, html).toBe(html); + } + }); + + it("does so inside every Markdown construct", async () => { + const html = ""; + const wrapped = [`# ${html}`, `> ${html}`, `- ${html}`, `1. ${html}`, `*${html}*`, `**${html}**`, `[${html}](https://example.com)`, `![${html}](https://example.com/i.png)`, `| ${html} |\n|---|\n| ${html} |`, `\`${html}\``, `\`\`\`\n${html}\n\`\`\``, ` ${html}`]; + for (const md of wrapped) { + const r = await render(md); + expect(r.querySelector("img"), md).toBeNull(); + expectInert(r, md); + expect(r.textContent, md).toContain(html.slice(0, 4)); + } + }); +}); + +describe("limits", () => { + const sizes = (n: number, s: string) => s.repeat(n); + const inputs: [string, string][] = [ + ["100k stars", sizes(100_000, "*")], + ["closers only", sizes(40, `${sizes(3000, "a* ")}\n`)], + ["alternating emphasis", sizes(50_000, "*a_b")], + ["100k open brackets", sizes(100_000, "[")], + ["100k link openers", sizes(100_000, "[](")], + ["100k image openers", sizes(100_000, "![")], + ["nested links", sizes(20_000, "[a](") + sizes(20_000, ")")], + ["ascending backtick runs", Array.from({ length: 1500 }, (_, i) => "`".repeat(i + 1)).join(" ")], + ["autolink openers", sizes(30_000, " ") + "deep"], + ["quote staircase", Array.from({ length: 2000 }, (_, i) => "> ".repeat(i % 40) + "x").join("\n")], + ["nested list on one line", sizes(10_000, "- ") + "deep"], + ["list staircase", Array.from({ length: 3000 }, (_, i) => " ".repeat(2 * (i % 60)) + "- item").join("\n")], + ["20k blank-separated items", sizes(20_000, "- a\n\n")], + ["50k headings", sizes(50_000, "# h\n")], + ["wide table", "|" + sizes(5000, "a|") + "\n|" + sizes(5000, "-|") + "\n" + sizes(2000, "|" + sizes(100, "x|") + "\n")], + ["long table", "|a|b|\n|-|-|\n" + sizes(50_000, "|1|2|\n")], + ["html storm", sizes(30_000, "
    Hi & bye')); + expect(shownText(o.host)).toBe( + ['', "", " ", ' ', " Hi & bye", " ", ""].join("\n"), + ); + expect(o.host.querySelector("script,feed,entry,title")).toBeNull(); + expect(o.warnings).toEqual([]); + }); + + it("notes markup that is not well formed", async () => { + const o = await open("bad.xml", enc("")); + expect(o.warnings).toEqual([{ key: "text_not_xml", count: 1 }]); + const plain = await open("no.xml", enc("just words")); + expect(shownText(plain.host)).toBe("just words"); + expect(plain.warnings).toEqual([{ key: "text_not_xml", count: 1 }]); + }); + + it("does not show a SVG that way unless it is named as XML, and never draws it", async () => { + const svg = ''; + const o = await open("x.xml", enc(svg)); + expect(o.host.querySelector("svg,script")).toBeNull(); + }); +}); + +describe("HTML", () => { + it("is source text, with a note, and nothing in it is live", async () => { + const html = 'x'; + for (const name of ["page.html", "page.htm", "page.xhtml"]) { + const o = await open(name, enc(html)); + expect(shownText(o.host), name).toBe(html); + expect(o.warnings, name).toEqual([{ key: "text_html_source", count: 1 }]); + expect(o.host.querySelector("script,img,a,html,body,iframe,link,style"), name).toBeNull(); + } + }); +}); + +describe("Markdown", () => { + it("draws the document", async () => { + const o = await open("README.md", enc("# Title\n\nSome *text* with [a link](https://example.com).\n\n- one\n- two\n")); + expect(o.host.querySelector("h1")!.textContent).toBe("Title"); + expect(o.host.querySelector("em")!.textContent).toBe("text"); + expect(o.host.querySelector(".exav-viewer-text-link")!.textContent).toBe("a link"); + expect(o.host.querySelectorAll("li").length).toBe(2); + }); + + it("follows an http or https link on a click or Enter, as a PDF's links are, and no other", async () => { + const opened: unknown[][] = []; + const real = window.open; + window.open = ((...args: unknown[]) => { + opened.push(args); + return null; + }) as typeof window.open; + try { + const o = await open("links.md", enc("[a](https://example.com/a) [b](http://example.com/b) [m](mailto:me@example.com) [x](javascript:alert(1))\n")); + const links = [...o.host.querySelectorAll(".exav-viewer-text-link")]; + expect(links.map((l) => l.textContent)).toEqual(["a", "b", "https://example.com/c", "m"]); + expect(links.map((l) => l.getAttribute("role"))).toEqual(["link", "link", "link", null]); + expect(o.host.querySelector("a")).toBeNull(); + links[0]!.click(); + links[1]!.dispatchEvent(new KeyboardEvent("keydown", { key: "Enter", bubbles: true })); + links[1]!.dispatchEvent(new KeyboardEvent("keydown", { key: " ", bubbles: true })); + links[2]!.click(); + // The mail address is only text, and nothing else is a link. + links[3]!.click(); + expect(opened).toEqual([ + ["https://example.com/a", "_blank", "noopener,noreferrer"], + ["http://example.com/b", "_blank", "noopener,noreferrer"], + ["https://example.com/c", "_blank", "noopener,noreferrer"], + ]); + } finally { + window.open = real; + } + }); + + it("makes nothing live of a hostile document", async () => { + const md = [ + "# ", + "", + "[x](javascript:alert(1)) [y](data:text/html,x) [z](/relative) [w](https://a.example@b.example/)", + "![tracker](https://evil.example/pixel.png) ![d](data:image/svg+xml;base64,PHN2Zz4=)", + "", + ].join("\n\n"); + const o = await open("evil.md", enc(md)); + expect(o.host.querySelector("a,img,script,iframe,svg,object,embed,link,style,form")).toBeNull(); + expect(o.host.querySelector(".exav-viewer-text-link")).toBeNull(); + for (const e of o.host.querySelectorAll("*")) for (const a of e.getAttributeNames()) expect(["class", "tabindex", "role"], a).toContain(a); + expect(shownText(o.host)).toContain(""); + expect(shownText(o.host)).toContain("[tracker]"); + }); + + it("shows the text as it is, and says so, when the reader fails", async () => { + engine.fail = true; + try { + const o = await open("broken.md", enc("# Title\n\n*text*\n")); + expect(o.warnings).toEqual([{ key: "text_markdown_failed", count: 1 }]); + expect(o.host.querySelector("h1,em")).toBeNull(); + expect(shownText(o.host)).toBe("# Title\n\n*text*"); + expect(o.statuses.at(-1)).toEqual({ phase: "ready" }); + } finally { + engine.fail = false; + } + }); + + it("cuts a long line and says so", async () => { + const o = await open("long.md", enc(`${"word ".repeat(MAX_LINE)}\n\nend`)); + expect(o.warnings).toContainEqual({ key: "text_long_lines", count: 1 }); + expect(o.host.querySelector("p:last-child")!.textContent).toBe("end"); + }); +}); + +describe("diffs and subtitles", () => { + it("colours added, removed and hunk lines by class and leaves the text as it is", async () => { + const diff = ["diff --git a/f b/f", "index 1..2 100644", "--- a/f", "+++ b/f", "@@ -1,2 +1,2 @@", " same", "-old", "+new"].join("\n"); + const o = await open("fix.patch", enc(diff)); + expect(shownText(o.host)).toBe(diff); + const cls = (c: string) => [...o.host.querySelectorAll(`.${c}`)].map((e) => e.textContent); + expect(cls("exav-viewer-text-add")).toEqual(["+new"]); + expect(cls("exav-viewer-text-del")).toEqual(["-old"]); + expect(cls("exav-viewer-text-hunk")).toEqual(["@@ -1,2 +1,2 @@"]); + expect(cls("exav-viewer-text-meta")).toEqual(["diff --git a/f b/f", "index 1..2 100644", "--- a/f", "+++ b/f"]); + }); + + it("shows subtitles, YAML and source code as plain text", async () => { + const srt = "1\n00:00:01,000 --> 00:00:02,500\nHello there\n"; + const o = await open("film.srt", enc(srt)); + expect(shownText(o.host)).toBe(srt.trimEnd()); + expect(o.host.querySelector("i")).toBeNull(); + }); +}); diff --git a/crates/exav-viewer/ts/text/renderer.ts b/crates/exav-viewer/ts/text/renderer.ts new file mode 100644 index 0000000..55df10f --- /dev/null +++ b/crates/exav-viewer/ts/text/renderer.ts @@ -0,0 +1,204 @@ +import { TEXT_KINDS } from "../core/formats.js"; +import { writable } from "../core/store.js"; +import type { Renderer } from "../core/types.js"; +import { clip, decodeText, MAX_BYTES, MAX_LINE, MAX_LINES, sanitize, splitLines } from "./decode.js"; +import { formatJson } from "./json.js"; +import { lineLength, type Line } from "./lines.js"; +import type { Parsed } from "./markdown.js"; +import { readMarkdown } from "./markdown-engine.js"; +import { drawBlocks } from "./markdown-view.js"; +import { formatXml } from "./xml.js"; + +export type TextKind = keyof typeof TEXT_KINDS; + +/** How `path` (or, failing that, `type`) says the text is to be shown. */ +export function kindOf(path: string, type = ""): TextKind { + const p = path.toLowerCase(); + const t = type.toLowerCase().split(";")[0]!.trim(); + const kinds = Object.entries(TEXT_KINDS) as [TextKind, (typeof TEXT_KINDS)[TextKind]][]; + return ( + kinds.find(([, m]) => m.extensions.some((e) => p.endsWith(e)))?.[0] ?? kinds.find(([, m]) => m.types.includes(t))?.[0] ?? "plain" + ); +} + +/** Lines drawn together, in one element that the browser may skip while it is off screen. */ +const CHUNK = 200; +/** Chunks drawn before the first paint; the others follow without blocking. */ +const FIRST_CHUNKS = 5; +/** Time the following chunks may take before the page gets a turn. */ +const SLICE_MS = 12; + +/** A diff line's class: what it adds, removes or introduces. */ +function diffClass(line: string): string | undefined { + if (line.startsWith("+++") || line.startsWith("---") || line.startsWith("diff ") || line.startsWith("index ")) return "exav-viewer-text-meta"; + if (line.startsWith("@@")) return "exav-viewer-text-hunk"; + if (line[0] === "+") return "exav-viewer-text-add"; + if (line[0] === "-") return "exav-viewer-text-del"; + return undefined; +} + +/** Draws `lines[from, to)` as one block of text. */ +function chunk(lines: Line[], from: number, to: number): HTMLElement { + const pre = document.createElement("pre"); + pre.className = "exav-viewer-text-chunk"; + let buffer = ""; + const flush = () => { + if (buffer) pre.appendChild(document.createTextNode(buffer)); + buffer = ""; + }; + for (let i = from; i < to; i++) { + if (i > from) buffer += "\n"; + const line = lines[i]!; + if (typeof line === "string") { + buffer += line; + continue; + } + for (const [text, cls] of line) { + if (!cls) buffer += text; + else { + flush(); + const span = document.createElement("span"); + span.className = cls; + span.textContent = text; + pre.appendChild(span); + } + } + } + flush(); + return pre; +} + +/** `line` cut to `MAX_LINE` characters; null when it already fits. */ +function clipped(line: Line): Line | null { + if (lineLength(line) <= MAX_LINE) return null; + if (typeof line === "string") return clip(line); + const out: [string, string?][] = []; + let room = MAX_LINE; + for (const [text, cls] of line) { + if (room <= 0) break; + out.push([clip(text, room), cls]); + room -= text.length; + } + return out; +} + +export const renderer: Renderer> = { + async mount(host, ctx) { + ctx.status({ phase: "loading" }); + const blob = await ctx.source.blob(); + const partial = blob.size > MAX_BYTES; + const bytes = new Uint8Array(await blob.slice(0, MAX_BYTES).arrayBuffer()); + if (ctx.signal.aborted) throw new DOMException("aborted", "AbortError"); + const decoded = decodeText(bytes, partial); + if (!decoded) { + ctx.status({ phase: "error", error: { code: "text_binary" } }); + return { controllers: {}, destroy() {} }; + } + + const kind = kindOf(ctx.file.path ?? ctx.file.name, ctx.file.type); + const text = sanitize(decoded.text); + const warnings: { key: string; count: number }[] = []; + let truncated = partial; + let lines: Line[]; + let markdown: Parsed | null = null; + + const plain = () => { + const split = splitLines(text); + truncated ||= split.more; + return split.lines; + }; + if (kind === "markdown") { + const split = splitLines(text); + truncated ||= split.more; + lines = split.lines.map((l) => clip(l)); + try { + markdown = await readMarkdown((lines as string[]).join("\n"), ctx.signal); + truncated ||= markdown.truncated; + } catch { + if (ctx.signal.aborted) throw new DOMException("aborted", "AbortError"); + // The reader failed (its worker was stopped, or the module did not load): the text is shown as it is. + warnings.push({ key: "text_markdown_failed", count: 1 }); + } + } else if (kind === "json") { + // A cut file is not valid JSON: it is not judged. + const r = partial ? null : formatJson(text); + if (r) { + lines = r.lines; + truncated ||= r.more; + } else { + lines = plain(); + if (!partial) warnings.push({ key: "text_not_json", count: 1 }); + } + } else if (kind === "xml") { + const r = formatXml(text); + if (r) { + lines = r.lines; + truncated ||= r.more; + if (!r.wellFormed && !partial) warnings.push({ key: "text_not_xml", count: 1 }); + } else { + lines = plain(); + warnings.push({ key: "text_not_xml", count: 1 }); + } + } else if (kind === "diff") { + lines = plain().map((l): Line => { + const cls = diffClass(l); + return cls ? [[l, cls]] : l; + }); + } else { + lines = plain(); + if (kind === "html") warnings.push({ key: "text_html_source", count: 1 }); + } + // The newline that ends the file is not a line. + if (lines.length > 1 && lineLength(lines[lines.length - 1]!) === 0) lines.pop(); + + let cut = 0; + if (!markdown) { + lines = lines.map((l) => { + const c = clipped(l); + if (c) cut++; + return c ?? l; + }); + } else cut = (lines as string[]).filter((l) => l.length > MAX_LINE).length; + if (truncated) warnings.push({ key: "text_truncated", count: Math.min(lines.length, MAX_LINES) }); + if (cut) warnings.push({ key: "text_long_lines", count: cut }); + + const root = document.createElement("div"); + root.className = `exav-viewer-text exav-viewer-text-${kind}`; + root.tabIndex = 0; + host.append(root); + let destroyed = false; + let timer: ReturnType | undefined; + + if (markdown) drawBlocks(root, markdown.blocks); + else { + let at = 0; + const next = (count: number) => { + for (let k = 0; k < count && at < lines.length; k++) { + root.appendChild(chunk(lines, at, Math.min(at + CHUNK, lines.length))); + at += CHUNK; + } + }; + next(FIRST_CHUNKS); + const more = () => { + timer = undefined; + if (destroyed || at >= lines.length) return; + // As many blocks as fit in a slice of time, so that the page stays responsive. + const start = performance.now(); + do next(1); + while (at < lines.length && performance.now() - start < SLICE_MS); + timer = setTimeout(more, 0); + }; + if (at < lines.length) timer = setTimeout(more, 0); + } + + ctx.status({ phase: "ready" }); + return { + controllers: { warnings: writable(warnings) }, + destroy() { + destroyed = true; + if (timer !== undefined) clearTimeout(timer); + root.remove(); + }, + }; + }, +}; diff --git a/crates/exav-viewer/ts/text/xml.test.ts b/crates/exav-viewer/ts/text/xml.test.ts new file mode 100644 index 0000000..7c0fb48 --- /dev/null +++ b/crates/exav-viewer/ts/text/xml.test.ts @@ -0,0 +1,109 @@ +import { describe, expect, it } from "vitest"; + +import { lineText } from "./lines.js"; +import { formatXml } from "./xml.js"; + +const show = (text: string, max?: number) => { + const r = formatXml(text, max); + return r && r.lines.map(lineText).join("\n"); +}; + +describe("formatXml", () => { + it("indents elements and keeps text on its element's line", () => { + const out = show('Hello'); + expect(out).toBe( + ['', "", ' ', " Hello", " ", " ", " ", " ", ""].join("\n"), + ); + }); + + it("puts long or multi-line text on lines of its own", () => { + expect(show("one\n two")).toBe(["", " one", " two", ""].join("\n")); + const long = "x".repeat(300); + expect(show(`${long}`)).toBe(["", ` ${long}`, ""].join("\n")); + }); + + it("shows CDATA, comments, processing instructions and a DOCTYPE as written", () => { + const out = show('y">]>&a;]]>')!; + expect(out).toBe(['y">]>', "", " &a;]]>", " ", ""].join("\n")); + }); + + it("never expands an entity or follows an external one", () => { + const xxe = ']>&xxe; &lol2; <script>'; + const out = show(xxe)!; + expect(out).toContain(''); + expect(out).toContain("&xxe; &lol2; <script>"); + expect(out).not.toContain("

    Click here to https://www.paypal.com/login

    \"a
    ab
    ") +put("fragment.html", 1, "Hi run
    ♥¬it;A&zzz;") +put("document.xml", 2, 'HelloHYPERLINK "http://x"gone world & A') +put("sheet.xml", 3, '0HYPERLINK("http://x","y")z') +put("shared.xml", 4, "onetwo") +put("slide.xml", 5, "TitleBody") +put("content.xml", 6, "Heada bcdx") +content = "BT /F1 12 Tf 72 700 Td [(Pay to ev) 10 (il.exa) 5 (mple)] TJ 0 -20 Td (Second line) Tj ET" +pdf = (f"%PDF-1.4\n1 0 obj<>endobj\n2 0 obj<>endobj\n" + f"3 0 obj<>>>/Contents 4 0 R>>endobj\n" + f"4 0 obj<>\nstream\n{content}\nendstream\nendobj\n" + f"5 0 obj<>endobj\ntrailer<>\n%%EOF\n") +put("page.pdf", 7, pdf) +z = zlib.compress(content.encode()) +put("flate.pdf", 7, (f"%PDF-1.4\n1 0 obj<>endobj\n2 0 obj<>endobj\n" + f"3 0 obj<>>>/Contents 4 0 R>>endobj\n" + f"4 0 obj<>\nstream\n").encode() + z + + b"\nendstream\nendobj\n5 0 obj<>endobj\ntrailer<>\n%%EOF\n") +put("mtext.dxf", 8, " 0\nSECTION\n 2\nENTITIES\n 0\nMTEXT\n 8\n0\n 10\n0.0\n 20\n0.0\n 30\n0.0\n 40\n2.5\n 1\nPay\\Pnow\n 0\nENDSEC\n 0\nEOF\n") +for pick, seeds in ((8, "cad_dxf"), (9, "cad_dwg")): + for path in sorted(glob.glob(f"{out}/{seeds}/*"))[:6]: + put("cad-" + os.path.basename(path), pick, open(path, "rb").read()) +PY + +# The sheets targets: the `sheets` fixtures, and for sheets_numbers the +# fixture's IWA streams joined, which the target stores in a ZIP itself (a +# joined stream is one stream to the reader), and a Numbers '09 index.xml, +# plain and gzipped, which it stores the same way. +SHEETS=crates/exav-render/tests/fixtures/office/sheets +for f in "$SHEETS/sample.xls"; do add "$f" "$OUT/sheets_xls"; done +for f in "$SHEETS/sample.ods" "$SHEETS/sample.fods"; do add "$f" "$OUT/sheets_ods"; done +for f in "$SHEETS/sample.numbers" fuzz/seeds/sheets_numbers/*; do add "$f" "$OUT/sheets_numbers"; done +python3 - "$SHEETS/sample.numbers" "$OUT/sheets_numbers/sample.iwa" fuzz/seeds/sheets_numbers/index09.xml "$OUT/sheets_numbers/index09.xml.gz" <<'PY' +import gzip, sys, zipfile +z = zipfile.ZipFile(sys.argv[1]) +open(sys.argv[2], "wb").write(b"".join(z.read(n) for n in z.namelist() if n.endswith(".iwa"))) +open(sys.argv[4], "wb").write(gzip.compress(open(sys.argv[3], "rb").read(), mtime=0)) +PY +# sheets_text: the text fixtures behind the byte that picks their reader. +python3 - "$OUT/sheets_text" <<'PY' +import sys +d = "crates/exav-render/tests/fixtures/office/sheets/" +for pick, name in ((0, "sample-2003.xml"), (1, "sample.html"), (2, "sample.slk")): + open(f"{sys.argv[1]}/{name}", "wb").write(bytes([pick]) + open(d + name, "rb").read()) +PY + +# The slides targets: the `slides` fixtures. slides_ppt gets the PPT's +# `PowerPoint Document` stream, which the target stores in a compound file +# itself (the fixture is over MAX_BYTES with its thumbnail); slides_keynote the +# Keynote document's IWA streams joined, but its package metadata. +SLIDES=crates/exav-render/tests/fixtures/office/slides +for f in "$SLIDES/sample.odp" "$SLIDES/sample.fodp" "$SLIDES/chart.fodp"; do add "$f" "$OUT/slides_odp"; done +DRAW=crates/exav-render/tests/fixtures/office/draw +for f in "$DRAW/sample.odg" "$DRAW/sample.fodg"; do add "$f" "$OUT/slides_odg"; done +for f in "$DRAW/sample.vsdx" "$DRAW/themed.vsdx"; do add "$f" "$OUT/slides_vsdx"; done +# Keynote 1 to 5's XML and a PowerPoint 95 stream, written by hand. +for f in fuzz/seeds/slides_keynote/*; do add "$f" "$OUT/slides_keynote"; done +add fuzz/seeds/slides_ppt/powerpoint95.bin "$OUT/slides_ppt" +python3 - "$SLIDES" "$OUT" <<'PY' +import struct, sys, zipfile +d, out = sys.argv[1], sys.argv[2] +z = zipfile.ZipFile(f"{d}/sample.key") +iwa = [n for n in z.namelist() if n.endswith(".iwa") and not n.endswith("/Metadata.iwa")] +open(f"{out}/slides_keynote/sample.iwa", "wb").write(b"".join(z.read(n) for n in iwa)) +# The one stream, from the FAT: version 3, its first 109 FAT sectors. +b = open(f"{d}/sample.ppt", "rb").read() +ss = 1 << struct.unpack_from(" OUT/list.txt; node pdfjs.mjs OUT/list.txt OUT/png-pdfjs 3 > OUT/pdfjs.jsonl` (needs the viewer's `node_modules`: `EXAV_VIEWER_DIR`) | +| poppler | `python3 run_poppler.py CORPUS OUT 3` (needs `pdftoppm`) | +| hayro, in wasm, in Chromium | `cd hayro-wasm && cargo rustc --release --target wasm32-unknown-unknown --crate-type cdylib` (add `RUSTFLAGS="-C target-feature=+simd128"` for the SIMD build), `wasm-bindgen --target web`, `wasm-opt -Oz --enable-simd`, then `node hayro-wasm.mjs OUT/list.txt 3 > OUT/hayrowasm.jsonl` (`HAYRO_WASM_PKG`) | +| compare | `python3 compare3.py OUT` (numpy, Pillow) | + +`run_hayro.py` rewrites its output whole every 25 PDFs, as the scripts here never append. + +The corpus of the evaluation is the 990 PDFs of `test/pdfs` in mozilla/pdf.js, the 364 of +`hayro-tests/pdfs` in LaurenzV/hayro, and 16 of our own, deduplicated by hash. Both projects' corpora are +regression tests chosen for hard cases, not a sample of PDFs in the wild. diff --git a/scripts/pdf-compare/compare3.py b/scripts/pdf-compare/compare3.py new file mode 100644 index 0000000..ee4ffaf --- /dev/null +++ b/scripts/pdf-compare/compare3.py @@ -0,0 +1,128 @@ +"""python3 -I compare3.py OUT: hayro, pdf.js and poppler on the same pages (first three of each PDF, 72 dpi). + +Poppler is the reference: a page's distance to it is the mean absolute luminance difference after a 3x3 box +blur (0 to 255) and the share of pixels differing by more than 64 ("bad"). Pages over 25 million pixels are +left out of the pixel comparison. Prints the figures the report quotes and writes OUT/compare3.json. +""" +import collections, json, os, re, sys +import numpy as np +from PIL import Image + +Image.MAX_IMAGE_PIXELS = None +out = sys.argv[1] +names = ["hayro", "pdfjs", "poppler"] + +def read(n): + rows = {} + for l in open(f"{out}/{n}.jsonl"): + l = l.strip() + if l.startswith("{"): + try: + r = json.loads(l) + except Exception: + continue + rows.setdefault(r["pdf"], []).append(r) + return rows + +logs = {n: read(n) for n in names} +pdfs = sorted(set().union(*[set(v) for v in logs.values()])) + +def doc_state(n, pdf): + rs = logs[n].get(pdf, []) + if any(r["page"] >= 1 and r["status"] == "ok" for r in rs): + return "ok" + for r in rs: + if r["page"] == 0: + return r["status"].split(":")[0].split("(")[0] + return "none" + +print(f"PDFs: {len(pdfs)}") +for n in names: + c = collections.Counter(doc_state(n, p) for p in pdfs) + print(f" {n}: " + ", ".join(f"{k} {v}" for k, v in c.most_common())) +both_ok_ref = [p for p in pdfs if doc_state("poppler", p) == "ok"] +print(f" where poppler renders ({len(both_ok_ref)}): hayro fails {sum(1 for p in both_ok_ref if doc_state('hayro', p) != 'ok')}, pdf.js fails {sum(1 for p in both_ok_ref if doc_state('pdfjs', p) != 'ok')}") +print(f" where poppler fails ({len(pdfs) - len(both_ok_ref)}): hayro renders {sum(1 for p in pdfs if doc_state('poppler', p) != 'ok' and doc_state('hayro', p) == 'ok')}, pdf.js renders {sum(1 for p in pdfs if doc_state('poppler', p) != 'ok' and doc_state('pdfjs', p) == 'ok')}") + +pages = collections.defaultdict(dict) +for n in names: + for pdf, rs in logs[n].items(): + for r in rs: + if r["page"] >= 1 and r["status"] == "ok": + pages[(pdf, r["page"])][n] = r + +def lum(n, pdf, page): + return np.asarray(Image.open(f"{out}/png-{n}/{pdf}-{page}.png").convert("L"), dtype=np.float32) + +def blur(x): + p = np.pad(x, 1, mode="edge") + return sum(p[i:i + x.shape[0], j:j + x.shape[1]] for i in range(3) for j in range(3)) / 9.0 + +res = {n: [] for n in ("hayro", "pdfjs")} +size = {n: collections.Counter() for n in ("hayro", "pdfjs")} +for key, r in sorted(pages.items()): + if "poppler" not in r: + continue + pw, ph = r["poppler"]["w"], r["poppler"]["h"] + for n in ("hayro", "pdfjs"): + if n not in r: + continue + w, h = r[n]["w"], r[n]["h"] + if (w, h) == (pw, ph): + size[n]["same"] += 1 + elif (w, h) == (ph, pw): + size[n]["rotated"] += 1 + elif abs(w - pw) <= 1 and abs(h - ph) <= 1: + size[n]["off by one"] += 1 + else: + size[n]["different"] += 1 +for n in size: + print(f" page size vs poppler, {n}: " + ", ".join(f"{k} {v}" for k, v in size[n].items())) + +per = {} +for key, r in sorted(pages.items()): + if not all(n in r for n in names): + continue + sizes = {(r[n]["w"], r[n]["h"]) for n in names} + if len(sizes) != 1: + continue + w, h = next(iter(sizes)) + if w * h > 25_000_000: + continue + ref = blur(lum("poppler", *key)) + for n in ("hayro", "pdfjs"): + d = np.abs(blur(lum(n, *key)) - ref) + res[n].append((key, float(d.mean()), float((d > 64).mean()))) + per[key] = {n: res[n][-1][1:] for n in res} + +k = len(res["hayro"]) +print(f" pages with the same size in all three: {k}") +for n in res: + mad = np.array([x[1] for x in res[n]]); bad = np.array([x[2] for x in res[n]]) + print(f" {n} vs poppler: MAD median {np.median(mad):.2f}, p90 {np.percentile(mad, 90):.2f}; pages <0.5% pixels far {int((bad < .005).sum())} ({100 * (bad < .005).mean():.1f}%), 0.5-5% {int(((bad >= .005) & (bad < .05)).sum())}, over 5% {int((bad >= .05).sum())} ({100 * (bad >= .05).mean():.1f}%)") +hb = np.array([x[2] for x in res["hayro"]]); pb = np.array([x[2] for x in res["pdfjs"]]) +print(f" closer to poppler by 'bad' (more than 1 point apart): hayro {int((hb + .01 < pb).sum())}, pdf.js {int((pb + .01 < hb).sum())}, level {int((abs(hb - pb) <= .01).sum())}") + +# By what the file name says it tests. +cats = {"shading": "shad", "tiling/pattern": "patt|tiling", "jpx": "jpx|jpeg2000|jp2", "jbig2": "jbig2", "ccitt": "ccitt|fax", "mask/blend/transparency": "mask|blend|transp|smask|alpha", "font": "font|glyph|type1|type3|cff|truetype|cid|cmap", "annotation/form": "annot|form|widget|acro"} +print(" by name (pages <0.5% far from poppler / pages):") +for c, rx in cats.items(): + sel = [i for i, x in enumerate(res["hayro"]) if re.search(rx, x[0][0].lower())] + if sel: + print(f" {c}: hayro {sum(1 for i in sel if res['hayro'][i][2] < .005)}/{len(sel)}, pdf.js {sum(1 for i in sel if res['pdfjs'][i][2] < .005)}/{len(sel)}") + +# Time. +for n in ("hayro", "pdfjs", "poppler"): + ms = np.array([r[n]["ms"] for r in pages.values() if n in r]) + print(f" render ms per page, {n}: median {np.median(ms):.0f}, p90 {np.percentile(ms, 90):.0f}, p99 {np.percentile(ms, 99):.0f}, max {ms.max():.0f}, total {ms.sum() / 1000:.0f} s over {len(ms)} pages") +rss = [r["rss_kb"] for rs in logs["hayro"].values() for r in rs if r["page"] == -1 and r.get("rss_kb")] +print(f" hayro process peak RSS: median {np.median(rss) / 1024:.0f} MB, p99 {np.percentile(rss, 99) / 1024:.0f} MB, max {max(rss) / 1024:.0f} MB") +worst = sorted(per.items(), key=lambda kv: -kv[1]["hayro"][1])[:8] +print(" hayro's worst against poppler (hayro bad / pdf.js bad):") +for (pdf, page), v in worst: + print(f" {pdf} p{page}: {v['hayro'][1] * 100:.1f}% / {v['pdfjs'][1] * 100:.1f}%") +worst = sorted(per.items(), key=lambda kv: -kv[1]["pdfjs"][1])[:8] +print(" pdf.js's worst against poppler (pdf.js bad / hayro bad):") +for (pdf, page), v in worst: + print(f" {pdf} p{page}: {v['pdfjs'][1] * 100:.1f}% / {v['hayro'][1] * 100:.1f}%") +json.dump({f"{k[0]}:{k[1]}": v for k, v in per.items()}, open(f"{out}/compare3.json", "w")) diff --git a/scripts/pdf-compare/hayro-eval/Cargo.toml b/scripts/pdf-compare/hayro-eval/Cargo.toml new file mode 100644 index 0000000..75708a0 --- /dev/null +++ b/scripts/pdf-compare/hayro-eval/Cargo.toml @@ -0,0 +1,13 @@ +# Not part of the workspace: a harness (see ../README.md), with its own lock and target directory. +[package] +name = "hayro-eval" +version = "0.0.0" +edition = "2021" +publish = false + +[workspace] + +[dependencies] +hayro = "=0.8.0" +hayro-interpret = "=0.8.0" +hayro-syntax = "=0.8.0" diff --git a/scripts/pdf-compare/hayro-eval/src/main.rs b/scripts/pdf-compare/hayro-eval/src/main.rs new file mode 100644 index 0000000..904fe2a --- /dev/null +++ b/scripts/pdf-compare/hayro-eval/src/main.rs @@ -0,0 +1,54 @@ +// hayro-eval PDF OUTDIR MAXPAGES: renders the first MAXPAGES pages of PDF at scale 1 (one point to +// one pixel, as pdf.js's viewport at scale 1) on white, writes OUTDIR/-.png and prints +// one JSON line per page: ms to render, size, or the failure. +use hayro::{render, RenderCache, RenderSettings, PixmapSettings}; +use hayro_interpret::InterpreterSettings; +use hayro_syntax::Pdf; +use std::time::Instant; + +fn json(s: &str) -> String { + s.chars().flat_map(|c| match c { + '"' => vec!['\\', '"'], + '\\' => vec!['\\', '\\'], + c if (c as u32) < 0x20 => vec![' '], + c => vec![c], + }).collect() +} + +fn main() { + let a: Vec = std::env::args().collect(); + let (path, out, max) = (&a[1], &a[2], a[3].parse::().unwrap()); + let stem = std::path::Path::new(path).file_stem().unwrap().to_string_lossy().to_string(); + let data = std::fs::read(path).unwrap(); + let t0 = Instant::now(); + let pdf = match Pdf::new(data) { + Ok(p) => p, + Err(e) => { + println!("{{\"pdf\":\"{}\",\"page\":0,\"status\":\"load: {}\"}}", json(&stem), json(&format!("{e:?}"))); + return; + } + }; + let load_ms = t0.elapsed().as_secs_f64() * 1000.0; + let pages = pdf.pages(); + let cache = RenderCache::new(); + let settings = InterpreterSettings::default(); + let render_settings = RenderSettings::default(); + for (i, page) in pages.iter().enumerate().take(max) { + let t = Instant::now(); + let pix = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + let ps = PixmapSettings { bg_color: hayro::vello_cpu::color::palette::css::WHITE, ..PixmapSettings::default() }; + render(page, &cache, &settings, &render_settings, &ps) + })); + let ms = t.elapsed().as_secs_f64() * 1000.0; + match pix { + Ok(p) => { + let (w, h) = (p.width(), p.height()); + let png = p.into_png().unwrap_or_default(); + let file = format!("{out}/{stem}-{}.png", i + 1); + std::fs::write(&file, &png).unwrap(); + println!("{{\"pdf\":\"{}\",\"page\":{},\"pages\":{},\"w\":{w},\"h\":{h},\"ms\":{ms:.1},\"load_ms\":{load_ms:.1},\"status\":\"ok\"}}", json(&stem), i + 1, pages.len()); + } + Err(_) => println!("{{\"pdf\":\"{}\",\"page\":{},\"status\":\"panic\"}}", json(&stem), i + 1), + } + } +} diff --git a/scripts/pdf-compare/hayro-wasm.mjs b/scripts/pdf-compare/hayro-wasm.mjs new file mode 100644 index 0000000..af1ba44 --- /dev/null +++ b/scripts/pdf-compare/hayro-wasm.mjs @@ -0,0 +1,77 @@ +// node hayro-wasm.mjs LIST MAXPAGES: hayro compiled to wasm (renderPage), run in Chromium over the first +// MAXPAGES pages of each PDF named in LIST; one JSON line per page: ms, size, wasm memory after, or failure. +import fs from "node:fs"; +import http from "node:http"; +import path from "node:path"; +import { createRequire } from "node:module"; + +const root = process.env.EXAV_VIEWER_DIR ?? path.resolve(import.meta.dirname, "../../crates/exav-viewer"); +const require = createRequire(root + "/package.json"); +const { chromium } = require("playwright"); +// wasm-bindgen's --target web output of hayro-wasm, with hayro_wasm_bg.opt.wasm made by wasm-opt. +const pkg = process.env.HAYRO_WASM_PKG ?? path.resolve(import.meta.dirname, "hayro-wasm/pkg"); +const [list, maxArg] = process.argv.slice(2); +const max = Number(maxArg); +const files = fs.readFileSync(list, "utf8").split("\n").filter(Boolean); + +const server = http.createServer((req, res) => { + const url = decodeURIComponent(req.url.split("?")[0]); + let file; + if (url === "/") { + res.setHeader("content-type", "text/html"); + return res.end(""); + } + if (url.startsWith("/pkg/")) file = path.join(pkg, url.slice(5)); + else if (url.startsWith("/file/")) file = files[Number(url.slice(6))]; + else return res.writeHead(404).end(); + fs.readFile(file, (e, d) => { + if (e) return res.writeHead(404).end(); + res.setHeader("content-type", file.endsWith(".js") ? "text/javascript" : file.endsWith(".wasm") ? "application/wasm" : "application/octet-stream"); + res.end(d); + }); +}); +await new Promise((r) => server.listen(0, "127.0.0.1", r)); +const base = `http://127.0.0.1:${server.address().port}`; +const browser = await chromium.launch(); +for (let n = 0; n < files.length; n++) { + const stem = path.basename(files[n], path.extname(files[n])); + const page = await (await browser.newContext()).newPage(); + const timeout = setTimeout(() => page.close().catch(() => {}), 150000); + try { + await page.goto(base + "/"); + const results = await page.evaluate( + async ({ base, n, max }) => { + const m = await import(base + "/pkg/hayro_wasm.js"); + const wasm = await m.default({ module_or_path: base + "/pkg/hayro_wasm_bg.opt.wasm" }); + const buf = new Uint8Array(await (await fetch(base + "/file/" + n)).arrayBuffer()); + let count; + try { + count = m.pageCount(buf); + } catch (e) { + return [{ page: 0, status: "load: " + String(e && e.message ? e.message : e) }]; + } + const out = []; + for (let i = 0; i < Math.min(max, count); i++) { + const t = performance.now(); + try { + const r = m.renderPage(buf, i); + const v = new DataView(r.buffer, r.byteOffset); + out.push({ page: i + 1, pages: count, w: v.getUint32(0, true), h: v.getUint32(4, true), ms: +(performance.now() - t).toFixed(1), mem: wasm.memory.buffer.byteLength, status: "ok" }); + } catch (e) { + out.push({ page: i + 1, status: "render: " + String(e && e.message ? e.message : e).slice(0, 100) }); + break; + } + } + return out; + }, + { base, n, max }, + ); + for (const r of results) console.log(JSON.stringify({ pdf: stem, ...r })); + } catch (e) { + console.log(JSON.stringify({ pdf: stem, page: 0, status: "harness: " + String(e.message).slice(0, 120) })); + } + clearTimeout(timeout); + await page.context().close().catch(() => {}); +} +await browser.close(); +server.close(); diff --git a/scripts/pdf-compare/hayro-wasm/Cargo.toml b/scripts/pdf-compare/hayro-wasm/Cargo.toml new file mode 100644 index 0000000..87d2628 --- /dev/null +++ b/scripts/pdf-compare/hayro-wasm/Cargo.toml @@ -0,0 +1,24 @@ +# Not part of the workspace: a harness (see ../README.md), with its own lock and target directory. +[package] +name = "hayro-wasm" +version = "0.0.0" +edition = "2021" +publish = false + +[workspace] + +[lib] +crate-type = ["cdylib"] + +[dependencies] +hayro = "=0.8.0" +hayro-interpret = "=0.8.0" +hayro-syntax = "=0.8.0" +wasm-bindgen = "=0.2.129" + +[profile.release] +opt-level = "z" +lto = true +codegen-units = 1 +panic = "abort" +strip = true diff --git a/scripts/pdf-compare/hayro-wasm/src/lib.rs b/scripts/pdf-compare/hayro-wasm/src/lib.rs new file mode 100644 index 0000000..7d2ec45 --- /dev/null +++ b/scripts/pdf-compare/hayro-wasm/src/lib.rs @@ -0,0 +1,27 @@ +use hayro::{render, PixmapSettings, RenderCache, RenderSettings}; +use hayro_interpret::InterpreterSettings; +use hayro_syntax::Pdf; +use wasm_bindgen::prelude::*; + +/// Page `index` (0-based) of `data` at scale 1 on white: width and height as two u32 (LE), then RGBA. +#[wasm_bindgen(js_name = renderPage)] +pub fn render_page(data: &[u8], index: u32) -> Result, JsError> { + let pdf = Pdf::new(data.to_vec()).map_err(|e| JsError::new(&format!("{e:?}")))?; + let pages = pdf.pages(); + let page = pages.get(index as usize).ok_or_else(|| JsError::new("no such page"))?; + let cache = RenderCache::new(); + let ps = PixmapSettings { bg_color: hayro::vello_cpu::color::palette::css::WHITE, ..PixmapSettings::default() }; + let pix = render(page, &cache, &InterpreterSettings::default(), &RenderSettings::default(), &ps); + let (w, h) = (pix.width() as u32, pix.height() as u32); + let mut out = Vec::with_capacity(8 + (w * h * 4) as usize); + out.extend_from_slice(&w.to_le_bytes()); + out.extend_from_slice(&h.to_le_bytes()); + out.extend_from_slice(pix.data_as_u8_slice()); + Ok(out) +} + +#[wasm_bindgen(js_name = pageCount)] +pub fn page_count(data: &[u8]) -> Result { + let pdf = Pdf::new(data.to_vec()).map_err(|e| JsError::new(&format!("{e:?}")))?; + Ok(pdf.pages().len() as u32) +} diff --git a/scripts/pdf-compare/pdfjs.mjs b/scripts/pdf-compare/pdfjs.mjs new file mode 100644 index 0000000..28bc200 --- /dev/null +++ b/scripts/pdf-compare/pdfjs.mjs @@ -0,0 +1,100 @@ +// node pdfjs.mjs LIST OUTDIR MAXPAGES: renders the first MAXPAGES pages of each PDF named in LIST +// (one path a line) at scale 1 on white in headless Chromium with the pdfjs-dist of the viewer, writes +// OUTDIR/-.png, prints one JSON line per page: ms to render, size, or the failure. +import fs from "node:fs"; +import http from "node:http"; +import path from "node:path"; +import { createRequire } from "node:module"; + +// The viewer's node_modules (playwright, pdfjs-dist), a Linux install of it. +const root = process.env.EXAV_VIEWER_DIR ?? path.resolve(import.meta.dirname, "../../crates/exav-viewer"); +const require = createRequire(root + "/package.json"); +const { chromium } = require("playwright"); +const pdfjs = path.join(root, "node_modules", "pdfjs-dist"); + +const [list, out, maxArg] = process.argv.slice(2); +const max = Number(maxArg); +const files = fs.readFileSync(list, "utf8").split("\n").filter(Boolean); + +const server = http.createServer((req, res) => { + const url = decodeURIComponent(req.url.split("?")[0]); + let file; + if (url === "/") { + res.setHeader("content-type", "text/html"); + return res.end(""); + } + if (url.startsWith("/pdfjs/")) file = path.join(pdfjs, url.slice(7)); + else if (url.startsWith("/file/")) file = files[Number(url.slice(6))]; + else return res.writeHead(404).end(); + fs.readFile(file, (e, d) => { + if (e) return res.writeHead(404).end(); + res.setHeader("content-type", file.endsWith(".mjs") ? "text/javascript" : "application/octet-stream"); + res.end(d); + }); +}); +await new Promise((r) => server.listen(0, "127.0.0.1", r)); +const base = `http://127.0.0.1:${server.address().port}`; + +const browser = await chromium.launch(); +for (let n = 0; n < files.length; n++) { + const stem = path.basename(files[n], path.extname(files[n])); + const page = await (await browser.newContext({ deviceScaleFactor: 1 })).newPage(); + const timeout = setTimeout(() => page.close().catch(() => {}), 120000); + try { + await page.goto(base + "/"); + const results = await page.evaluate( + async ({ base, n, max }) => { + const pdfjs = await import(base + "/pdfjs/build/pdf.mjs"); + pdfjs.GlobalWorkerOptions.workerSrc = base + "/pdfjs/build/pdf.worker.mjs"; + const out = []; + const t0 = performance.now(); + let doc; + try { + const buf = await (await fetch(base + "/file/" + n)).arrayBuffer(); + doc = await pdfjs.getDocument({ + data: new Uint8Array(buf), + cMapUrl: base + "/pdfjs/cmaps/", + cMapPacked: true, + standardFontDataUrl: base + "/pdfjs/standard_fonts/", + iccUrl: base + "/pdfjs/iccs/", + wasmUrl: base + "/pdfjs/wasm/", + isEvalSupported: false, + }).promise; + } catch (e) { + return [{ page: 0, status: "load: " + String(e && e.message ? e.message : e) }]; + } + const loadMs = performance.now() - t0; + for (let i = 1; i <= Math.min(max, doc.numPages); i++) { + try { + const p = await doc.getPage(i); + const vp = p.getViewport({ scale: 1 }); + const canvas = document.createElement("canvas"); + canvas.width = Math.ceil(vp.width); + canvas.height = Math.ceil(vp.height); + const ctx = canvas.getContext("2d"); + ctx.fillStyle = "white"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + const t = performance.now(); + await p.render({ canvasContext: ctx, viewport: vp }).promise; + out.push({ page: i, pages: doc.numPages, w: canvas.width, h: canvas.height, ms: +(performance.now() - t).toFixed(1), load_ms: +loadMs.toFixed(1), status: "ok", png: canvas.toDataURL("image/png").split(",")[1] }); + } catch (e) { + out.push({ page: i, status: "render: " + String(e && e.message ? e.message : e) }); + } + } + return out; + }, + { base, n, max }, + ); + for (const r of results) { + const { png, ...line } = r; + if (png) fs.writeFileSync(`${out}/${stem}-${r.page}.png`, Buffer.from(png, "base64")); + console.log(JSON.stringify({ pdf: stem, ...line })); + } + } catch (e) { + console.log(JSON.stringify({ pdf: stem, page: 0, status: "harness: " + String(e.message).slice(0, 200) })); + } + clearTimeout(timeout); + await page.context().close().catch(() => {}); +} +await browser.close(); +server.close(); diff --git a/scripts/pdf-compare/run_hayro.py b/scripts/pdf-compare/run_hayro.py new file mode 100644 index 0000000..7e1f89e --- /dev/null +++ b/scripts/pdf-compare/run_hayro.py @@ -0,0 +1,48 @@ +"""python3 -I run_hayro.py CORPUS OUT MAXPAGES: hayro-eval on every PDF of CORPUS, 60 s and one process each. + +Writes OUT/hayro.jsonl (the file is rewritten whole every 25 PDFs): a line per page, and per PDF a line with +the peak RSS and the wall time of the process, or "timeout" / "crash". +""" +import json, os, subprocess, sys, time + +corpus, out, maxpages = sys.argv[1], sys.argv[2], sys.argv[3] +os.makedirs(out + "/png-hayro", exist_ok=True) +exe = os.environ.get("HAYRO_EVAL") or os.path.join(os.path.dirname(os.path.abspath(__file__)), "hayro-eval/target/release/hayro-eval") +files = sorted(f for f in os.listdir(corpus) if f.endswith(".pdf")) +lines = [] + +def flush(): + tmp = out + "/hayro.jsonl.tmp" + with open(tmp, "w") as f: + f.write("\n".join(json.dumps(l) for l in lines) + "\n") + os.replace(tmp, out + "/hayro.jsonl") + +for n, name in enumerate(files): + stem = os.path.splitext(name)[0] + t = time.time() + try: + p = subprocess.run(["/usr/bin/time", "-f", "RSS %M", exe, f"{corpus}/{name}", out + "/png-hayro", maxpages], + capture_output=True, text=True, timeout=60) + wall = time.time() - t + rss = 0 + for l in p.stderr.splitlines(): + if l.startswith("RSS "): + rss = int(l.split()[1]) + got = 0 + for l in p.stdout.splitlines(): + if l.startswith("{"): + try: + lines.append(json.loads(l)); got += 1 + except Exception: + pass + if p.returncode != 0 or got == 0: + tail = p.stderr.strip().splitlines()[-2:] if p.stderr else [] + lines.append({"pdf": stem, "page": 0, "status": f"crash({p.returncode}): " + " | ".join(tail)[:160]}) + lines.append({"pdf": stem, "page": -1, "status": "proc", "rss_kb": rss, "wall_s": round(wall, 2)}) + except subprocess.TimeoutExpired: + lines.append({"pdf": stem, "page": 0, "status": "timeout"}) + lines.append({"pdf": stem, "page": -1, "status": "proc", "rss_kb": 0, "wall_s": 60}) + if n % 25 == 24: + flush() +flush() +print("done", len(files)) diff --git a/scripts/pdf-compare/run_poppler.py b/scripts/pdf-compare/run_poppler.py new file mode 100644 index 0000000..82006c0 --- /dev/null +++ b/scripts/pdf-compare/run_poppler.py @@ -0,0 +1,38 @@ +"""python3 -I run_poppler.py CORPUS OUT MAXPAGES: pdftoppm (poppler) on every PDF, 72 dpi, white page. + +Writes OUT/poppler.jsonl and OUT/png-poppler/-.png; one line per page, and per PDF a line with +the wall time of the process (page -1). +""" +import glob, json, os, subprocess, sys, time +from PIL import Image + +Image.MAX_IMAGE_PIXELS = None +corpus, out, maxpages = sys.argv[1], sys.argv[2], sys.argv[3] +os.makedirs(out + "/png-poppler", exist_ok=True) +lines = [] +files = sorted(f for f in os.listdir(corpus) if f.endswith(".pdf")) +for n, name in enumerate(files): + stem = os.path.splitext(name)[0] + prefix = f"{out}/png-poppler/{stem}" + t = time.time() + try: + p = subprocess.run(["pdftoppm", "-r", "72", "-f", "1", "-l", maxpages, "-png", f"{corpus}/{name}", prefix], + capture_output=True, text=True, timeout=60) + wall = time.time() - t + pngs = sorted(glob.glob(prefix + "-*.png")) + for f in pngs: + page = int(f.rsplit("-", 1)[1].split(".")[0]) + # pdftoppm pads the page number to the width of the page count. + os.replace(f, f"{prefix}-{page}.png") if f != f"{prefix}-{page}.png" else None + with Image.open(f"{prefix}-{page}.png") as im: + w, h = im.size + lines.append({"pdf": stem, "page": page, "w": w, "h": h, "ms": round(1000 * wall / max(1, len(pngs)), 1), "status": "ok"}) + if not pngs: + lines.append({"pdf": stem, "page": 0, "status": f"fail({p.returncode}): " + (p.stderr.strip().splitlines() or [""])[0][:120]}) + lines.append({"pdf": stem, "page": -1, "status": "proc", "wall_s": round(wall, 2)}) + except subprocess.TimeoutExpired: + lines.append({"pdf": stem, "page": 0, "status": "timeout"}) + if n % 50 == 49: + open(out + "/poppler.jsonl", "w").write("\n".join(json.dumps(l) for l in lines) + "\n") +open(out + "/poppler.jsonl", "w").write("\n".join(json.dumps(l) for l in lines) + "\n") +print("done", len(files)) diff --git a/scripts/release.sh b/scripts/release.sh index 508db27..c72cb7b 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -85,7 +85,8 @@ $CARGO clippy --all-targets --features exav-core/http -- -D warnings || fail "cl $CARGO clippy -p exav-core --all-targets --features unstable-internals -- -D warnings || fail "clippy (unstable-internals)" # exav-render's drawing and model readers sit behind features no other crate turns on. $CARGO clippy -p exav-render --all-targets --features dwg -- -D warnings || fail "clippy (exav-render dwg)" -$CARGO clippy -p exav-render --all-targets --no-default-features --features ifc,stl -- -D warnings || fail "clippy (exav-render ifc,stl)" +$CARGO clippy -p exav-render --all-targets --no-default-features --features ifc,stl,obj,ply,gltf -- -D warnings || fail "clippy (exav-render ifc,stl,obj,ply,gltf)" +$CARGO clippy -p exav-render --all-targets --no-default-features --features office,office-test-util -- -D warnings || fail "clippy (exav-render office)" step "Tests" # The native matrix; `make test` additionally needs wasmtime and node. diff --git a/scripts/test-www.sh b/scripts/test-www.sh index a08a6e1..b42c7c3 100755 --- a/scripts/test-www.sh +++ b/scripts/test-www.sh @@ -23,6 +23,9 @@ if ! command -v node >/dev/null 2>&1; then exit 1 fi +# The format registry against the code, and the pages generated from it. +node "$REPO/scripts/formats.mjs" check + if [ ! -d node_modules ]; then npm ci || npm install fi diff --git a/www/astro.config.mjs b/www/astro.config.mjs index a6f1ea0..4147452 100644 --- a/www/astro.config.mjs +++ b/www/astro.config.mjs @@ -3,10 +3,12 @@ import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; import starlightSidebarTopics from 'starlight-sidebar-topics'; +const SITE = 'https://exav.org'; const GITHUB_REPO = 'https://github.com/sylvinus/exav'; +const OG_ALT = 'exav: Memory-safe tools for untrusted files.'; export default defineConfig({ - site: 'https://exav.org', + site: SITE, redirects: { // Folded into Design principles; keep old links working. '/concepts/never-silent/': '/scanner/concepts/design-principles/#never-a-silent-clean', @@ -97,6 +99,22 @@ export default defineConfig({ alt: '', }, favicon: '/favicon.svg', + // Starlight already writes the description, canonical link, og:title, + // og:description, og:type, og:url, og:site_name, og:locale and + // twitter:card (summary_large_image) of every page, and the `lang` + // attribute. What it does not: the preview image (public/og.png, drawn + // by scripts/make-og-image.py) and the browser's theme colour, which is + // the dark theme's background (the site is dark only). + head: [ + { tag: 'meta', attrs: { property: 'og:image', content: `${SITE}/og.png` } }, + { tag: 'meta', attrs: { property: 'og:image:type', content: 'image/png' } }, + { tag: 'meta', attrs: { property: 'og:image:width', content: '1200' } }, + { tag: 'meta', attrs: { property: 'og:image:height', content: '630' } }, + { tag: 'meta', attrs: { property: 'og:image:alt', content: OG_ALT } }, + { tag: 'meta', attrs: { name: 'twitter:image', content: `${SITE}/og.png` } }, + { tag: 'meta', attrs: { name: 'twitter:image:alt', content: OG_ALT } }, + { tag: 'meta', attrs: { name: 'theme-color', content: '#17181c' } }, + ], social: [ { icon: 'github', label: 'GitHub', href: GITHUB_REPO }, ], @@ -199,6 +217,7 @@ export default defineConfig({ { label: 'React UI', slug: 'viewer/react' }, { label: 'Core API', slug: 'viewer/api' }, { label: 'Security', slug: 'viewer/security' }, + { label: 'Example files', slug: 'viewer/examples' }, { label: 'Live demo', link: '/viewer/demo/', attrs: { target: '_blank' } }, ], }, @@ -233,6 +252,7 @@ export default defineConfig({ icon: 'open-book', items: [ { label: 'Technical architecture', slug: 'project/architecture' }, + { label: 'Format matrix', slug: 'project/formats' }, { label: 'Roadmap', slug: 'project/roadmap' }, { label: 'Contributing', slug: 'project/contributing' }, { label: 'Security', slug: 'project/security' }, diff --git a/www/package-lock.json b/www/package-lock.json index 9e34adb..728851f 100644 --- a/www/package-lock.json +++ b/www/package-lock.json @@ -8,96 +8,90 @@ "name": "exav-www", "version": "0.1.0", "dependencies": { - "@astrojs/starlight": "^0.41.4", - "astro": "^7.1.3", - "sharp": "^0.35.3", - "starlight-sidebar-topics": "0.8.0" + "@astrojs/starlight": "^0.42.7", + "astro": "^7.4.2", + "sharp": "^0.35.5", + "starlight-sidebar-topics": "0.9.0" }, "devDependencies": { - "@astrojs/check": "^0.9.9", + "@astrojs/check": "^0.9.12", "typescript": "^6.0.3" } }, - "node_modules/@astrojs/check": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.9.tgz", - "integrity": "sha512-A5UW8uIuErLWEoRQvzgXpO1gTjUFtK8r7nU2Z7GewAMxUb7bPvpk11qaKKgxqXlHJWlAvaaxy+Xg28A6bmQ1Tg==", + "node_modules/@astrojs/astro2tsx": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@astrojs/astro2tsx/-/astro2tsx-0.1.3.tgz", + "integrity": "sha512-GMDC7Eo0myBUA/QLBl0u+OcegJ8LiBhccmNZR34KmprQNP8gQUJlWlOOZWUsxNA2rNS6GuPYcGDyLoPnjmn4/Q==", "dev": true, "license": "MIT", "dependencies": { - "@astrojs/language-server": "^2.16.7", - "chokidar": "^4.0.3", - "kleur": "^4.1.5", - "yargs": "^17.7.2" - }, - "bin": { - "astro-check": "bin/astro-check.js" + "@emnapi/core": "1.11.3", + "@napi-rs/wasm-runtime": "1.2.4" }, - "peerDependencies": { - "typescript": "^5.0.0 || ^6.0.0" + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@astrojs/check/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "node_modules/@astrojs/check": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.12.tgz", + "integrity": "sha512-hazpqxIfZWj2VhyPyR0pOEQ/IhFDM/2nIApL96zMXABdD8NrUKYDmhxTy7h+drTDl9MQG/Sd1ET/4amadVJUUA==", "dev": true, "license": "MIT", "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" + "@astrojs/language-server": "^2.17.3", + "chokidar": "^5.0.0", + "kleur": "^4.1.5", + "yargs": "^18.2.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@astrojs/check/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" + "bin": { + "astro-check": "bin/astro-check.js" }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "typescript": "^5.0.0 || ^6.0.0" } }, - "node_modules/@astrojs/compiler": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.1.tgz", - "integrity": "sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==", - "dev": true, - "license": "MIT" - }, "node_modules/@astrojs/compiler-binding": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding/-/compiler-binding-0.3.1.tgz", - "integrity": "sha512-DaAUj29AIBU2XdJ8uwcab8lW5O2pk9pY8AXkcMw0sw77nVa3oeTYRcO+Dvbbpoexf6ThMc0FMWYCQ/wN1/T7oQ==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding/-/compiler-binding-0.5.2.tgz", + "integrity": "sha512-lEn76+0JcMQ5RDXU0wSMWJg2ZppiZvSULpghC29cfv4o9bhvWFDbQjsCtvjjXN9iVLFQ7fL3wTR2L2UU13mP8g==", "license": "MIT", "engines": { "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@astrojs/compiler-binding-darwin-arm64": "0.3.1", - "@astrojs/compiler-binding-darwin-x64": "0.3.1", - "@astrojs/compiler-binding-linux-arm64-gnu": "0.3.1", - "@astrojs/compiler-binding-linux-arm64-musl": "0.3.1", - "@astrojs/compiler-binding-linux-x64-gnu": "0.3.1", - "@astrojs/compiler-binding-linux-x64-musl": "0.3.1", - "@astrojs/compiler-binding-wasm32-wasi": "0.3.1", - "@astrojs/compiler-binding-win32-arm64-msvc": "0.3.1", - "@astrojs/compiler-binding-win32-x64-msvc": "0.3.1" + "@astrojs/compiler-binding-android-arm64": "0.5.2", + "@astrojs/compiler-binding-darwin-arm64": "0.5.2", + "@astrojs/compiler-binding-darwin-x64": "0.5.2", + "@astrojs/compiler-binding-linux-arm64-gnu": "0.5.2", + "@astrojs/compiler-binding-linux-arm64-musl": "0.5.2", + "@astrojs/compiler-binding-linux-x64-gnu": "0.5.2", + "@astrojs/compiler-binding-linux-x64-musl": "0.5.2", + "@astrojs/compiler-binding-wasm32-wasi": "0.5.2", + "@astrojs/compiler-binding-win32-arm64-msvc": "0.5.2", + "@astrojs/compiler-binding-win32-x64-msvc": "0.5.2" + } + }, + "node_modules/@astrojs/compiler-binding-android-arm64": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-android-arm64/-/compiler-binding-android-arm64-0.5.2.tgz", + "integrity": "sha512-kckIxon6Rm/Bxzh9mGPYpRRqUbToUQoHptCmpMmE+Yt0Xumq8CqrKUidyYhrBsrHVO7bxuRzzWUUqvpf+iYceQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@astrojs/compiler-binding-darwin-arm64": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-arm64/-/compiler-binding-darwin-arm64-0.3.1.tgz", - "integrity": "sha512-IEmEF2fUIlTHtpeE/isyEGVOB14cEyh/LZOFYt6wn3jNyVpdC8aR5OZ+RzFUR/f+8ZDM1LaMwZKvoA7eMyJeFw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-arm64/-/compiler-binding-darwin-arm64-0.5.2.tgz", + "integrity": "sha512-1ZG5Ar3dD8HtodX9XH1mRmE0qBXZlvjYXSFfpgFwocqfWnvhFuqtGUNseL8wgfImiRMztIjpQqlogQFQQtgiag==", "cpu": [ "arm64" ], @@ -111,9 +105,9 @@ } }, "node_modules/@astrojs/compiler-binding-darwin-x64": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-x64/-/compiler-binding-darwin-x64-0.3.1.tgz", - "integrity": "sha512-GF2kIxjpPDLsn94zbZNMsxEmkU828QqnmM7kiQJnaooS3jmI+I7kk6+oI6EpwOsK3femCMdcm+wmOsEqtGrmjQ==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-x64/-/compiler-binding-darwin-x64-0.5.2.tgz", + "integrity": "sha512-+kl35S7hiHJ2cb7eujwEsPFYYuSgE11uEE2Z20lAJ+undpgulMcW+weQqFPOSSZccEKHOiLIY+kQHkb4e4092w==", "cpu": [ "x64" ], @@ -127,9 +121,9 @@ } }, "node_modules/@astrojs/compiler-binding-linux-arm64-gnu": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-gnu/-/compiler-binding-linux-arm64-gnu-0.3.1.tgz", - "integrity": "sha512-XJL3SDmOtVrqFhCirNcHwE91+IesJqlgNo23I4qW9QUYfwzm/TBZuH61fgqsb1ttgR1mMYz6ooPWs0JDhwMqpQ==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-gnu/-/compiler-binding-linux-arm64-gnu-0.5.2.tgz", + "integrity": "sha512-BqlR0EHNQLPLwgL9+xogjsAc7zGf0cHho2CPdhv0P1yqbVMwGVaGAqrANP6VYAXCqSC43AF4Czcxc2n+oqdesg==", "cpu": [ "arm64" ], @@ -146,9 +140,9 @@ } }, "node_modules/@astrojs/compiler-binding-linux-arm64-musl": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-musl/-/compiler-binding-linux-arm64-musl-0.3.1.tgz", - "integrity": "sha512-xqE8BVbDoBueK/B47w30PtkVofUWJKGkwoMVE+EOMLf11rnoANxIAdA9FPqY+rng4oNI5ndHGsri1yPj2k8vZQ==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-musl/-/compiler-binding-linux-arm64-musl-0.5.2.tgz", + "integrity": "sha512-GRGyby3AZWw5d6JQzidyxPyvGgHWsSusrpgKyFVpDTKctABF7L3Pd5V1cRJbV36/rcu+Eh292/wL7pF7MkmGkQ==", "cpu": [ "arm64" ], @@ -165,9 +159,9 @@ } }, "node_modules/@astrojs/compiler-binding-linux-x64-gnu": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-gnu/-/compiler-binding-linux-x64-gnu-0.3.1.tgz", - "integrity": "sha512-1y0StU1qiCuDFH3rmbRJXcxdfHxFPrES1Rd+RLffosvUR7I2cH5SF5SFnBN9vXpzpkmyElZm3Yr47iJBPN7vVA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-gnu/-/compiler-binding-linux-x64-gnu-0.5.2.tgz", + "integrity": "sha512-9XAqGTMQAtIslMsjK3xdyY6OI9d59OZqcLBB6pvD/DcoR0daYswfrKx2azdDERDY4AqAnWPC7odVM1BmxYv3Vw==", "cpu": [ "x64" ], @@ -184,9 +178,9 @@ } }, "node_modules/@astrojs/compiler-binding-linux-x64-musl": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-musl/-/compiler-binding-linux-x64-musl-0.3.1.tgz", - "integrity": "sha512-16q0fYf7kpbmdObZEeZJEup8hQv/whgNwVjrSvT8umrKwLDSnNIWiQpm09lQQu6bweZB0XyIvHwlPitvJhC+hg==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-musl/-/compiler-binding-linux-x64-musl-0.5.2.tgz", + "integrity": "sha512-jOViewGeTh9bSfS8vK72ECxoy2yvmA+Pd/ZcEvBI5c7+7IcfHwZ5qA4L9fRYuOhSrAifvQ2dV4vm1XAtloaWBw==", "cpu": [ "x64" ], @@ -203,25 +197,48 @@ } }, "node_modules/@astrojs/compiler-binding-wasm32-wasi": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-wasm32-wasi/-/compiler-binding-wasm32-wasi-0.3.1.tgz", - "integrity": "sha512-cB456shIwDv/PrVT+2QG7LFndpHkVge5HjqADKZgGaAc9JHVktCtjSrcdkRQ+3tbkPazNKaTLRjXLIiz2NIx9g==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-wasm32-wasi/-/compiler-binding-wasm32-wasi-0.5.2.tgz", + "integrity": "sha512-Z7p64doar1uvR5C9Xs6j1CV9lGlPVQX7OQ2aAtZ/xKC5aGS6GB13nyc2UfQXTQLvZrvVwsyaflTQy6ziY5Bekw==", "cpu": [ "wasm32" ], "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^1.1.6" + "@emnapi/core": "1.11.3", + "@emnapi/runtime": "1.11.3", + "@napi-rs/wasm-runtime": "^1.2.5" }, "engines": { - "node": ">=14.0.0" + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.5.tgz", + "integrity": "sha512-HshSvXzmBxNzqejd3k/KemgQ3hdREUYFRRrgxOZ+gPljDIsO2SDZrVZMd4Z/HsxudQbE62OVyVFE8z9BCurfjA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" } }, "node_modules/@astrojs/compiler-binding-win32-arm64-msvc": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-arm64-msvc/-/compiler-binding-win32-arm64-msvc-0.3.1.tgz", - "integrity": "sha512-ur/9+If/yTE69mmeX5MqSZndL0HOyx67GeNZUy3N7wVdWpLz9UTJXwyWS4UR2PUQHitghjsM5xoX0Ge56WRVQQ==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-arm64-msvc/-/compiler-binding-win32-arm64-msvc-0.5.2.tgz", + "integrity": "sha512-Tr13bh+ahTWsjXjzctK7pFpWV+dUU4FtBfETlR7gO+ueex0F+RDch7eRr0YfKysaRhk9tWm14lsCJ5uWyFPNHQ==", "cpu": [ "arm64" ], @@ -235,9 +252,9 @@ } }, "node_modules/@astrojs/compiler-binding-win32-x64-msvc": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-x64-msvc/-/compiler-binding-win32-x64-msvc-0.3.1.tgz", - "integrity": "sha512-k0W+kDBzDkNZOqu4kElDvCOIbKw5Ut9S1WZ1Krj3KTgNuBERNKXsMMsRLLcbgfdMdbe7bTekQLshZrrvmYpmwA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-x64-msvc/-/compiler-binding-win32-x64-msvc-0.5.2.tgz", + "integrity": "sha512-SfKkI+jOQYLh6wojPvVPV0lFfQnxisweN9B+qCzRvZp7DHAuGif8Y0WcC5PUgN4jb8VKy57LggQDtggR46Du1g==", "cpu": [ "x64" ], @@ -251,49 +268,48 @@ } }, "node_modules/@astrojs/compiler-rs": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-rs/-/compiler-rs-0.3.1.tgz", - "integrity": "sha512-aT7xkgsbNoS6nriY5qKpbihK43slFHO41iqgHCTdOvn1ifaQxLCc5yXy+6GzAtiafoaC1zA7OwVXCXMsvUZOkg==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-rs/-/compiler-rs-0.5.2.tgz", + "integrity": "sha512-IvwYLB8t1M86rKO4oPdBi9GP4gzXcgrVlNgocjwos1jeeUuEIV8d9Crn1PvYD/5IKteWOxpIHomf7e8iYlkE+Q==", "license": "MIT", "dependencies": { - "@astrojs/compiler-binding": "0.3.1" + "@astrojs/compiler-binding": "0.5.2" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@astrojs/internal-helpers": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.10.1.tgz", - "integrity": "sha512-5phcroT/vmOOrYuuAxtkbPixy5hePtlz9i8K4OeDv3dNK6/UQRuXPOSRTxIOBbUY5Sonw2UaxjbuVc43Mcir6Q==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.13.0.tgz", + "integrity": "sha512-20jxQqnSmpskcGyad7N5l6Xf1gz0UCa6lNde44bEBdaXGpncEYfAZJ142r2ZgzBaG4dUyzGmhqZWv1INU2eiHQ==", "license": "MIT", "dependencies": { - "@types/hast": "^3.0.4", + "@types/hast": "^3.0.5", "@types/mdast": "^4.0.4", - "js-yaml": "^4.1.1", - "picomatch": "^4.0.4", + "picomatch": "^4.0.7", "retext-smartypants": "^6.2.0", - "shiki": "^4.0.2", - "smol-toml": "^1.6.0", - "unified": "^11.0.5" + "shiki": "^4.5.0", + "smol-toml": "^1.9.1", + "unified": "^11.0.5", + "yaml": "^2.9.1" } }, "node_modules/@astrojs/language-server": { - "version": "2.16.13", - "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.16.13.tgz", - "integrity": "sha512-ekOa+CYprEq5n4EJC1qTIAhLk49HZIUQuFwrEuF+3JK/pdMaYnWoREFUI2A0KEPOJiFA2kamBzKzbYljDvUxLg==", + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.17.3.tgz", + "integrity": "sha512-QIAFu1e/4quJMTPdmBOm+ZPXc5NDGZE4/YQjgR3EgjhGLl/tdidaWJDr5WmO2lesVc+BW1qN/xNBURmuePDG2A==", "dev": true, "license": "MIT", "dependencies": { - "@astrojs/compiler": "^2.13.1", + "@astrojs/astro2tsx": "^0.1.2", "@astrojs/yaml2ts": "^0.2.4", - "@jridgewell/sourcemap-codec": "^1.5.5", "@volar/kit": "~2.4.28", "@volar/language-core": "~2.4.28", "@volar/language-server": "~2.4.28", "@volar/language-service": "~2.4.28", "muggle-string": "^0.4.1", - "tinyglobby": "^0.2.16", + "tinyglobby": "^0.2.17", "volar-service-css": "0.0.71", "volar-service-emmet": "0.0.71", "volar-service-html": "0.0.71", @@ -302,7 +318,7 @@ "volar-service-typescript-twoslash-queries": "0.0.71", "volar-service-yaml": "0.0.71", "vscode-html-languageservice": "^5.6.2", - "vscode-uri": "^3.1.0" + "vscode-uri": "^3.2.0" }, "bin": { "astro-ls": "bin/nodeServer.js" @@ -320,88 +336,52 @@ } } }, - "node_modules/@astrojs/markdown-remark": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.2.1.tgz", - "integrity": "sha512-jPVNIqTvk+yKviikszv/Y1U4jGUSKpp/Nw48QZV4qjWgp70j4Lkq3lhSDRbWwCfgKvEyO9GHuVbV1dM2WYXy1w==", - "license": "MIT", - "dependencies": { - "@astrojs/internal-helpers": "0.10.1", - "@astrojs/prism": "4.0.2", - "github-slugger": "^2.0.0", - "hast-util-from-html": "^2.0.3", - "hast-util-to-text": "^4.0.2", - "mdast-util-definitions": "^6.0.0", - "rehype-raw": "^7.0.0", - "rehype-stringify": "^10.0.1", - "remark-gfm": "^4.0.1", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.1.2", - "remark-smartypants": "^3.0.2", - "unified": "^11.0.5", - "unist-util-remove-position": "^5.0.0", - "unist-util-visit": "^5.1.0", - "unist-util-visit-parents": "^6.0.2", - "vfile": "^6.0.3" - } - }, "node_modules/@astrojs/markdown-satteri": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.3.4.tgz", - "integrity": "sha512-6Lvt/bQZEBW+zzdhPblvfZEy5PGEYJaUsUqaCgwHeRPxZJL1gc9I+DRLKWJjjYTWDzVUTzXlMq4WwSK+X34CVw==", + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.4.5.tgz", + "integrity": "sha512-0IeGdoFbv0f+442KJhYS44Wg8F3MuHmRsxIEYuFyqkjRubc6dPBFZ7azor5t4AeXLQoT5A5h9HyViKpd70Dl9w==", "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.10.1", - "@astrojs/prism": "4.0.2", + "@astrojs/internal-helpers": "0.13.0", + "@astrojs/prism": "4.1.1", "github-slugger": "^2.0.0", - "hast-util-from-html": "^2.0.3", - "satteri": "^0.9.1" + "satteri": "^0.10.5" } }, "node_modules/@astrojs/mdx": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-7.0.3.tgz", - "integrity": "sha512-RxyIwU0uFam5ftwqKOjpIdhnFxZ/kEikeimLyQy3eGXbHT8WgRGzzesOIHVU8+m9TY8ag5WVOyvV24/GyqPdPQ==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-8.1.1.tgz", + "integrity": "sha512-jEJUJsO2KqmKfBXaKeDHDCCj+Kerj1Fj+XndHznF9wxahvs+1onYCBeKmieM28N2+uA6mW57DOQQw5YaDLdBnA==", "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.10.1", - "@astrojs/markdown-remark": "7.2.1", - "@mdx-js/mdx": "^3.1.1", - "acorn": "^8.16.0", - "es-module-lexer": "^2.0.0", - "estree-util-visit": "^2.0.0", - "hast-util-to-html": "^9.0.5", - "piccolore": "^0.1.3", - "rehype-raw": "^7.0.0", - "remark-gfm": "^4.0.1", - "remark-smartypants": "^3.0.2", - "source-map": "^0.7.6", - "unist-util-visit": "^5.1.0", - "vfile": "^6.0.3" + "@astrojs/internal-helpers": "0.13.0", + "@astrojs/markdown-satteri": "0.4.5", + "es-module-lexer": "^3.0.3" }, "engines": { - "node": ">=22.12.0" + "node": ">=22.23.4" }, "peerDependencies": { - "@astrojs/markdown-satteri": "^0.3.1", - "astro": "^7.0.0" + "@astrojs/markdown-remark": "^7.3.0", + "@astrojs/markdown-satteri": "^0.4.0", + "astro": "^7.2.10" }, "peerDependenciesMeta": { - "@astrojs/markdown-satteri": { + "@astrojs/markdown-remark": { "optional": true } } }, "node_modules/@astrojs/prism": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.0.2.tgz", - "integrity": "sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.1.1.tgz", + "integrity": "sha512-sXlAXJX6t4QfuLg+CuCDzpg7NoxWcyb4paFprgtFppLeisCBmh935h+tJ5CWXfsXEoW2IDy/ihbRMtiu28Chjw==", "license": "MIT", "dependencies": { "prismjs": "^1.30.0" }, "engines": { - "node": ">=22.12.0" + "node": ">=22.23.4" } }, "node_modules/@astrojs/sitemap": { @@ -416,44 +396,43 @@ } }, "node_modules/@astrojs/starlight": { - "version": "0.41.4", - "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.41.4.tgz", - "integrity": "sha512-cRCKZhM2BKYViCakBiN68aVwPn5qj/XtMMq//G54xOWdXXcvic1gMMEI+veNlIKOqqC4QmIjcjk4jiFtlZ3mMg==", + "version": "0.42.7", + "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.42.7.tgz", + "integrity": "sha512-mlbit5iRjLx5eIcLf84Q2CwkrrsEgZrQwKKBK+vRf+ZGiSrwy1UGdT1hUfAIaHrMfcvkDpL+gw3aua7HobiKFg==", "license": "MIT", "dependencies": { - "@astrojs/markdown-satteri": "^0.3.2", - "@astrojs/mdx": "^7.0.0", - "@astrojs/sitemap": "^3.7.2", + "@astrojs/markdown-satteri": "^0.4.0", + "@astrojs/mdx": "^8.0.0", + "@astrojs/sitemap": "^3.7.3", "@pagefind/default-ui": "^1.3.0", - "@types/hast": "^3.0.4", + "@types/hast": "^3.0.5", "@types/js-yaml": "^4.0.9", "@types/mdast": "^4.0.4", "astro-expressive-code": "^0.44.0", "bcp-47": "^2.1.0", - "hast-util-from-html": "^2.0.3", + "hast-util-format": "^1.1.0", "hast-util-select": "^6.0.4", + "hast-util-to-html": "^9.0.5", "hast-util-to-string": "^3.0.1", "hastscript": "^9.0.1", "i18next": "^26.0.7", "js-yaml": "^4.1.1", "klona": "^2.0.6", - "magic-string": "^0.30.21", + "magic-string": "^1.2.3", "mdast-util-directive": "^3.1.0", "mdast-util-to-markdown": "^2.1.2", "mdast-util-to-string": "^4.0.0", "pagefind": "^1.5.2", - "rehype": "^13.0.2", - "rehype-format": "^5.0.1", "remark-directive": "^4.0.0", - "satteri": "^0.9.1", + "satteri": "^0.10.3", "ultrahtml": "^1.6.0", "unified": "^11.0.5", "unist-util-visit": "^5.1.0", "vfile": "^6.0.3" }, "peerDependencies": { - "@astrojs/markdown-remark": "^7.2.0", - "astro": "^7.0.2" + "@astrojs/markdown-remark": "^7.3.0", + "astro": "^7.2.10" }, "peerDependenciesMeta": { "@astrojs/markdown-remark": { @@ -462,18 +441,18 @@ } }, "node_modules/@astrojs/telemetry": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.3.tgz", - "integrity": "sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.4.1.tgz", + "integrity": "sha512-SMkvMsGOpM0FMAoT5pzhgI3LZC0JSPWf7Evwop+fZ3N6UkusPM7lI+sOJjMNI5OJrVoiei1/AGo1cY7sikTc5A==", "license": "MIT", "dependencies": { "ci-info": "^4.4.0", "dset": "^3.1.4", "is-docker": "^4.0.0", - "package-manager-detector": "^1.6.0" + "package-manager-detector": "^1.9.0" }, "engines": { - "node": "18.20.8 || ^20.3.0 || >=22.0.0" + "node": ">=22.23.4" } }, "node_modules/@astrojs/yaml2ts": { @@ -505,12 +484,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", - "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "version": "7.29.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.29.7" + "@babel/types": "^7.29.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -520,9 +499,9 @@ } }, "node_modules/@babel/types": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", - "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.29.7", @@ -533,9 +512,9 @@ } }, "node_modules/@bruits/satteri-darwin-arm64": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-arm64/-/satteri-darwin-arm64-0.9.5.tgz", - "integrity": "sha512-iw4nZgx9v30lWo/MTngQqi1pI78KI0DnkSm+lVJGYdmPLgAyDNJigVhpG42/Iq55A6c1Ll8q66ljyyRiQUxwow==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-arm64/-/satteri-darwin-arm64-0.10.5.tgz", + "integrity": "sha512-27KTVl4TJkVahMy/ohyA7qd4938G5UNneFUz/PsScYfpIhj0IVAS23mpcJXdPF44sa6nva198lmV/cKIb2YPyA==", "cpu": [ "arm64" ], @@ -546,9 +525,9 @@ ] }, "node_modules/@bruits/satteri-darwin-x64": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-x64/-/satteri-darwin-x64-0.9.5.tgz", - "integrity": "sha512-6T26Z5Kf3cFW2PSlk9p7zT7yVxvuBSiJvYyz9u8KjYwMTqZyIDOj2wDyNpxKV4+6yUVG7rddq2QwvG/8LJA2+Q==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-x64/-/satteri-darwin-x64-0.10.5.tgz", + "integrity": "sha512-IjnLe3nKspq6qaeqGgjT7MT8VrTV74yWRlaag7ZdNsI8TDAYZ0iPxMCo+9KQZHUk5EyVB+reBI/PFWL5KuFw9Q==", "cpu": [ "x64" ], @@ -559,9 +538,9 @@ ] }, "node_modules/@bruits/satteri-linux-arm64-gnu": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-gnu/-/satteri-linux-arm64-gnu-0.9.5.tgz", - "integrity": "sha512-u51id17uJwNEMK9nBlICsq6U31c+XVqQueVBkwRIzZG+gMpS8TOJctt5h5Wz33Z8xnMdTd+adtACVz0yHgGuOA==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-gnu/-/satteri-linux-arm64-gnu-0.10.5.tgz", + "integrity": "sha512-glkYXZCJywjP13v67eAyAMSJdF+ncvEbYvgi/wOtffL9tQ27lr/zsyzUfgs+ovjJ9d8JNQKiXeiArJcX8PJL9w==", "cpu": [ "arm64" ], @@ -575,9 +554,9 @@ ] }, "node_modules/@bruits/satteri-linux-arm64-musl": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-musl/-/satteri-linux-arm64-musl-0.9.5.tgz", - "integrity": "sha512-v39HxiwGC5Rqm01HksP6+5Y+xKLPlsuVFgIgpEAo+SiQ22c+mJVhS3u7Z6ePAKdhL5NJoK1xq70kLz3L13AhpQ==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-musl/-/satteri-linux-arm64-musl-0.10.5.tgz", + "integrity": "sha512-yWdgG1g17Nh2QyGVlFUxGRa3FEFwiMcpZEyMNWkbM3deC94cmVc+/i9OuyFpdKuWo3GkgoCtYVOoxk1uCnCZIA==", "cpu": [ "arm64" ], @@ -591,9 +570,9 @@ ] }, "node_modules/@bruits/satteri-linux-x64-gnu": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-gnu/-/satteri-linux-x64-gnu-0.9.5.tgz", - "integrity": "sha512-F3uO8uFp3pAP5ZGXttwvh57GS7s0lL953tnNdyI2gRyP4kOOkp6pyGojNJzCjkDvWI2Cvb9iNrKok3aqQPauAw==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-gnu/-/satteri-linux-x64-gnu-0.10.5.tgz", + "integrity": "sha512-FVaLoPT1fBgGl0J+AYebyyXJYBachGl8Oyyrf1lye4RTqCB4S0Gwkj1uM9RJyThUOvx5VUmAT1CnNh1SFHA+kw==", "cpu": [ "x64" ], @@ -607,9 +586,9 @@ ] }, "node_modules/@bruits/satteri-linux-x64-musl": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-musl/-/satteri-linux-x64-musl-0.9.5.tgz", - "integrity": "sha512-bicEqglLlz++mWyADaZoP0JY20s4vDfLjaPYgQqC+NI4zZLTOOg1T4GB8aqtc822Pqji8SQBmSrTb7CrP8i08Q==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-musl/-/satteri-linux-x64-musl-0.10.5.tgz", + "integrity": "sha512-EHpVAx2bqW3GINHTKkljtxVfQmVDGWIuwOYOP5YghTj+0PkBa2o8oKPRtQ9Kbsr1Fye8jtUcDjhwj2jMNugZKg==", "cpu": [ "x64" ], @@ -623,9 +602,9 @@ ] }, "node_modules/@bruits/satteri-wasm32-wasi": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@bruits/satteri-wasm32-wasi/-/satteri-wasm32-wasi-0.9.5.tgz", - "integrity": "sha512-zauAuMwfPnKPUkd4AFixRFpXdgKwP2mKgxrIIo2gJzW0/ZneF9dbHnLkojSpaBnCCp7VUL1hIi5WWZvB1CqmAQ==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-wasm32-wasi/-/satteri-wasm32-wasi-0.10.5.tgz", + "integrity": "sha512-ypz8c/Zmipxp4IoeDa228Gstv6TLzVmNs3yC6wKCoNSOjx1iwpgzu87Y3hTkXFdwChVGU85qeUDuOIarGUZQLw==", "cpu": [ "wasm32" ], @@ -634,7 +613,7 @@ "dependencies": { "@emnapi/core": "1.11.1", "@emnapi/runtime": "1.11.1", - "@napi-rs/wasm-runtime": "^1.1.6" + "@napi-rs/wasm-runtime": "^1.2.3" }, "engines": { "node": ">=14.0.0" @@ -672,9 +651,9 @@ } }, "node_modules/@bruits/satteri-win32-arm64-msvc": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-arm64-msvc/-/satteri-win32-arm64-msvc-0.9.5.tgz", - "integrity": "sha512-SrfE7NEsgZjBvU3c+RR6oQRu0ToXY5uVJEbieXEF0YTctIV2zAVlbaMjWLts074QCgh3a+XHWkR/lWh2VH2LUg==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-arm64-msvc/-/satteri-win32-arm64-msvc-0.10.5.tgz", + "integrity": "sha512-siTV88nb0LRqNpkL2gXboqCwVdq95sLtzMHS1/3eONV2gLbB3NAK46wmSMvCO/yquBvI2lvaFIfd8P12ecsxBw==", "cpu": [ "arm64" ], @@ -685,9 +664,9 @@ ] }, "node_modules/@bruits/satteri-win32-x64-msvc": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-x64-msvc/-/satteri-win32-x64-msvc-0.9.5.tgz", - "integrity": "sha512-5Kw9ZAtTGS8WHizyn+CJhjjfIQrw+7jcZodpmpXJjefnO15M8UexIi6JR2E5thyvsmHyhL6ZDDMUNR4bKJPd4g==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-x64-msvc/-/satteri-win32-x64-msvc-0.10.5.tgz", + "integrity": "sha512-C3IfPvfvMXmlzBxaMPKFS1XiuV9pu2mC7YqkPk7PSvTgPZ8gbdASIpHpztDLvTTQjqZ0z1Ol8tK5X+V6XXC0wQ==", "cpu": [ "x64" ], @@ -710,9 +689,9 @@ } }, "node_modules/@clack/core": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.4.3.tgz", - "integrity": "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.5.1.tgz", + "integrity": "sha512-iHTrHA8MtVuLl2TfZySmcKv1qO2PoyC9Z7pfSDozEuV5vtY3/wcOPKJXlqJ5Oq2Cx5DDGQGAMVx6HZfRRoVEbQ==", "license": "MIT", "dependencies": { "fast-wrap-ansi": "^0.2.0", @@ -723,12 +702,12 @@ } }, "node_modules/@clack/prompts": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.7.0.tgz", - "integrity": "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.8.1.tgz", + "integrity": "sha512-dlT1m5e/0yUL0kRNcQn7yGLVThkgbB0Ga/1AmfDDC/8ik6AIiSf2QLQO2zPYvefsHP0aFgxO93cVLCCfDp7kzQ==", "license": "MIT", "dependencies": { - "@clack/core": "1.4.3", + "@clack/core": "1.5.1", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" @@ -812,9 +791,8 @@ "version": "1.11.3", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz", "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==", + "devOptional": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "@emnapi/wasi-threads": "1.2.3", "tslib": "^2.4.0" @@ -824,8 +802,8 @@ "version": "1.11.3", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "devOptional": true, "license": "MIT", - "optional": true, "dependencies": { "tslib": "^2.4.0" } @@ -834,646 +812,229 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz", "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==", + "devOptional": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "tslib": "^2.4.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", - "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", - "cpu": [ - "ppc64" - ], + "node_modules/@expressive-code/core": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.44.1.tgz", + "integrity": "sha512-3dDo9N8D7hYrLNNMMWFovg3+aDUtnQm7c7z0GZc1c0LEFVBc0Q6lKG+tVT28gDadOvsgOANfCn35fgpe97Pmgg==", "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@ctrl/tinycolor": "^4.0.4", + "hast-util-select": "^6.0.2", + "hast-util-to-html": "^9.0.1", + "hast-util-to-text": "^4.0.1", + "hastscript": "^9.0.0", + "postcss": "^8.4.38", + "postcss-nested": "^6.0.1", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.1" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", - "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", - "cpu": [ - "arm" - ], + "node_modules/@expressive-code/plugin-frames": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.44.1.tgz", + "integrity": "sha512-HC/bdRao9225ApcgO/e3jn8ZOhldKO7ob1O/Tcipvtv7Vb5nMphZhMtD9uuywpvxkPYBHJi3504WhrKg05Dwqg==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@expressive-code/core": "^0.44.1" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", - "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", - "cpu": [ - "arm64" - ], + "node_modules/@expressive-code/plugin-shiki": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.44.1.tgz", + "integrity": "sha512-YApiZt3buUzBwL5tqj8G+sYC5NjMjRCHgQwr9bmGl69rtcHy6fE9dooWUeKYB978fJT2BuxT5FeHcF47rA3SEg==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@expressive-code/core": "^0.44.1", + "shiki": "^4.0.2" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", - "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", - "cpu": [ - "x64" - ], + "node_modules/@expressive-code/plugin-text-markers": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.44.1.tgz", + "integrity": "sha512-B3BsJoJ8CFMlcIX9f+X9tcI3C4zPDO601+YuLi9GheSTNro7ZfqSjLptMQKBHOWZvxnAtY5zvIX7iO/qtBhNBg==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.44.1" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", - "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.5.tgz", + "integrity": "sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==", "cpu": [ "arm64" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=18" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.4" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", - "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.5.tgz", + "integrity": "sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==", "cpu": [ "x64" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=18" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.4" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.5.tgz", + "integrity": "sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", - "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.4.tgz", + "integrity": "sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==", "cpu": [ "arm64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "freebsd" + "darwin" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", - "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.4.tgz", + "integrity": "sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==", "cpu": [ "x64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "freebsd" + "darwin" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", - "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.4.tgz", + "integrity": "sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==", "cpu": [ "arm" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", - "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.4.tgz", + "integrity": "sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==", "cpu": [ "arm64" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", - "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.4.tgz", + "integrity": "sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==", "cpu": [ - "ia32" + "ppc64" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", - "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.4.tgz", + "integrity": "sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==", "cpu": [ - "loong64" + "riscv64" ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", - "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", - "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", - "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", - "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", - "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", - "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", - "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", - "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", - "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", - "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", - "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", - "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", - "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", - "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@expressive-code/core": { - "version": "0.44.1", - "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.44.1.tgz", - "integrity": "sha512-3dDo9N8D7hYrLNNMMWFovg3+aDUtnQm7c7z0GZc1c0LEFVBc0Q6lKG+tVT28gDadOvsgOANfCn35fgpe97Pmgg==", - "license": "MIT", - "dependencies": { - "@ctrl/tinycolor": "^4.0.4", - "hast-util-select": "^6.0.2", - "hast-util-to-html": "^9.0.1", - "hast-util-to-text": "^4.0.1", - "hastscript": "^9.0.0", - "postcss": "^8.4.38", - "postcss-nested": "^6.0.1", - "unist-util-visit": "^5.0.0", - "unist-util-visit-parents": "^6.0.1" - } - }, - "node_modules/@expressive-code/plugin-frames": { - "version": "0.44.1", - "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.44.1.tgz", - "integrity": "sha512-HC/bdRao9225ApcgO/e3jn8ZOhldKO7ob1O/Tcipvtv7Vb5nMphZhMtD9uuywpvxkPYBHJi3504WhrKg05Dwqg==", - "license": "MIT", - "dependencies": { - "@expressive-code/core": "^0.44.1" - } - }, - "node_modules/@expressive-code/plugin-shiki": { - "version": "0.44.1", - "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.44.1.tgz", - "integrity": "sha512-YApiZt3buUzBwL5tqj8G+sYC5NjMjRCHgQwr9bmGl69rtcHy6fE9dooWUeKYB978fJT2BuxT5FeHcF47rA3SEg==", - "license": "MIT", - "dependencies": { - "@expressive-code/core": "^0.44.1", - "shiki": "^4.0.2" - } - }, - "node_modules/@expressive-code/plugin-text-markers": { - "version": "0.44.1", - "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.44.1.tgz", - "integrity": "sha512-B3BsJoJ8CFMlcIX9f+X9tcI3C4zPDO601+YuLi9GheSTNro7ZfqSjLptMQKBHOWZvxnAtY5zvIX7iO/qtBhNBg==", - "license": "MIT", - "dependencies": { - "@expressive-code/core": "^0.44.1" - } - }, - "node_modules/@img/colour": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", - "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", - "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.3.2" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", - "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.3.2" - } - }, - "node_modules/@img/sharp-freebsd-wasm32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", - "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", - "license": "Apache-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "dependencies": { - "@img/sharp-wasm32": "0.35.3" - }, - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", - "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", - "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", - "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", - "cpu": [ - "arm" - ], - "libc": [ - "glibc" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", - "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", - "cpu": [ - "arm64" - ], - "libc": [ - "glibc" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", - "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", - "cpu": [ - "ppc64" - ], - "libc": [ - "glibc" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", - "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", - "cpu": [ - "riscv64" - ], - "libc": [ - "glibc" - ], - "license": "LGPL-3.0-or-later", + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -1483,9 +1044,9 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", - "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.4.tgz", + "integrity": "sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==", "cpu": [ "s390x" ], @@ -1502,9 +1063,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", - "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.4.tgz", + "integrity": "sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==", "cpu": [ "x64" ], @@ -1521,9 +1082,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", - "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.4.tgz", + "integrity": "sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==", "cpu": [ "arm64" ], @@ -1540,9 +1101,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", - "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.4.tgz", + "integrity": "sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==", "cpu": [ "x64" ], @@ -1559,9 +1120,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", - "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.5.tgz", + "integrity": "sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==", "cpu": [ "arm" ], @@ -1580,13 +1141,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.3.2" + "@img/sharp-libvips-linux-arm": "1.3.4" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", - "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.5.tgz", + "integrity": "sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==", "cpu": [ "arm64" ], @@ -1605,13 +1166,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.3.2" + "@img/sharp-libvips-linux-arm64": "1.3.4" } }, "node_modules/@img/sharp-linux-ppc64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", - "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.5.tgz", + "integrity": "sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==", "cpu": [ "ppc64" ], @@ -1630,13 +1191,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.3.2" + "@img/sharp-libvips-linux-ppc64": "1.3.4" } }, "node_modules/@img/sharp-linux-riscv64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", - "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.5.tgz", + "integrity": "sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==", "cpu": [ "riscv64" ], @@ -1655,13 +1216,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.3.2" + "@img/sharp-libvips-linux-riscv64": "1.3.4" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", - "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.5.tgz", + "integrity": "sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==", "cpu": [ "s390x" ], @@ -1680,13 +1241,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.3.2" + "@img/sharp-libvips-linux-s390x": "1.3.4" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", - "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.5.tgz", + "integrity": "sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==", "cpu": [ "x64" ], @@ -1705,13 +1266,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.3.2" + "@img/sharp-libvips-linux-x64": "1.3.4" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", - "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.5.tgz", + "integrity": "sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==", "cpu": [ "arm64" ], @@ -1730,13 +1291,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + "@img/sharp-libvips-linuxmusl-arm64": "1.3.4" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", - "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.5.tgz", + "integrity": "sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==", "cpu": [ "x64" ], @@ -1755,17 +1316,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.3.2" + "@img/sharp-libvips-linuxmusl-x64": "1.3.4" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", - "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.5.tgz", + "integrity": "sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==", "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.11.1" + "@emnapi/runtime": "^1.11.3" }, "engines": { "node": ">=20.9.0" @@ -1775,16 +1336,16 @@ } }, "node_modules/@img/sharp-webcontainers-wasm32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", - "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.5.tgz", + "integrity": "sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==", "cpu": [ "wasm32" ], "license": "Apache-2.0", "optional": true, "dependencies": { - "@img/sharp-wasm32": "0.35.3" + "@img/sharp-wasm32": "0.35.5" }, "engines": { "node": ">=20.9.0" @@ -1794,9 +1355,9 @@ } }, "node_modules/@img/sharp-win32-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", - "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.5.tgz", + "integrity": "sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==", "cpu": [ "arm64" ], @@ -1813,9 +1374,9 @@ } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", - "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.5.tgz", + "integrity": "sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==", "cpu": [ "ia32" ], @@ -1832,9 +1393,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", - "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.5.tgz", + "integrity": "sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==", "cpu": [ "x64" ], @@ -1851,64 +1412,30 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "license": "MIT" }, - "node_modules/@mdx-js/mdx": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", - "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdx": "^2.0.0", - "acorn": "^8.0.0", - "collapse-white-space": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-util-scope": "^1.0.0", - "estree-walker": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "markdown-extensions": "^2.0.0", - "recma-build-jsx": "^1.0.0", - "recma-jsx": "^1.0.0", - "recma-stringify": "^1.0.0", - "rehype-recma": "^1.0.0", - "remark-mdx": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "source-map": "^0.7.0", - "unified": "^11.0.0", - "unist-util-position-from-estree": "^2.0.0", - "unist-util-stringify-position": "^4.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", - "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.4.tgz", + "integrity": "sha512-AJxoUD2/15ESHbvpcyjU274nsAPLuOtPHCk0vKJM5pj//Fg/B1FXNWjPnXTT9PymCYYiHo4zPj0ZomXBKhoy7g==", + "devOptional": true, "license": "MIT", - "optional": true, "dependencies": { "@tybys/wasm-util": "^0.10.3" }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, "funding": { "type": "github", "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" } }, "node_modules/@oslojs/encoding": { @@ -1918,12 +1445,12 @@ "license": "MIT" }, "node_modules/@oxc-project/types": { - "version": "0.139.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", - "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", + "version": "0.155.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.155.0.tgz", + "integrity": "sha512-SeE8JPwW1xs1tHeNycjUtUBdhorRa8o4jlvjwk49R7/Z291i+4DQa7JJIgOm/TaYQZx+QrPQbVJ/9c8dMIZN8Q==", "license": "MIT", "funding": { - "url": "https://github.com/sponsors/Boshen" + "url": "https://github.com/sponsors/oxc-project" } }, "node_modules/@pagefind/darwin-arm64": { @@ -2023,10 +1550,26 @@ "win32" ] }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.15.tgz", + "integrity": "sha512-aLcgK9gIJ3YRvrrtfSBbRa27F5WrpiTaPulnFpsHPxpUHgFlSgnU4854MHwoRGEBhfRJDWCS2WQ7lIjskE9Olw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", - "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.15.tgz", + "integrity": "sha512-xD7DdZCrbThKuxNg7ooQmvp07ys4J/pnSEMTG3/OdOWl6daC67m/Q4fL78sRHMxTH/N4fGUbYhcPM0MF5WFHkg==", "cpu": [ "arm64" ], @@ -2040,9 +1583,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", - "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.15.tgz", + "integrity": "sha512-m2WuQ6r0B4OTYxyPpNLtXaMRbRDUbG8YQV2Q3KTdSSK8Th6KHCnC8jVCJt8bvYeSB5WivkkNbc85mKadaSdOxA==", "cpu": [ "arm64" ], @@ -2056,9 +1599,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", - "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.15.tgz", + "integrity": "sha512-5RtnsHM36nodM9WbMy+zip0LGS/G+y5wro5RHrpOlr4ac24+1zSi9kiV2MP1myZeZ/ifEHfulQcWjnAXzc2C2A==", "cpu": [ "x64" ], @@ -2072,9 +1615,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", - "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.15.tgz", + "integrity": "sha512-g3l09pyFqhu+135JKkbkwiKGQmwU5hUMUPJ4VdBADvuqR8d33L6H578rh8m7rtxbdp+VmX/+nzI7nvhSZlzpUQ==", "cpu": [ "x64" ], @@ -2088,9 +1631,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", - "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.15.tgz", + "integrity": "sha512-nIe3VugI97nGQtspPxDqA4sXMUpeiocKIP/CqpY/u/vgbT+alX+cVxu1C/oVBPKg4feNTmYovE91v4DgXvXNwQ==", "cpu": [ "arm" ], @@ -2104,9 +1647,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", - "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.15.tgz", + "integrity": "sha512-iTBjXx+B5QSvgI89lJfmqh4wTh8NabR1YZIIN3hNx4zSG0EVfVqkOvLulNpG4251pbd6/IAmZ/LefVk1Y4rPhw==", "cpu": [ "arm64" ], @@ -2123,9 +1666,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", - "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.15.tgz", + "integrity": "sha512-uN26XOnVR7rqQupG3V9oAG2EGGatWjcJHOeDOHUFCh4TBWmP2tHTFoVN13aYbwfm0aHqJAEmcwhAu6sooIjfqQ==", "cpu": [ "arm64" ], @@ -2142,9 +1685,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", - "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.15.tgz", + "integrity": "sha512-9nWkcdd+H+XhaA3fQIwpHnKIrfx/PQ6rO0pivr78Og07tXlUlctBBJoEYLPfhTmCR/QxEVdn6uPjHV5SymPhdw==", "cpu": [ "ppc64" ], @@ -2161,9 +1704,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", - "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.15.tgz", + "integrity": "sha512-Ggh0ciFjLwIusLSLz7LZYEaGdxOAUJXI+Qu5JCbhPJJHEt8vP+IjRATTJheiJsdzzTYgUiHUiw3X1Ea3ZpMBdA==", "cpu": [ "s390x" ], @@ -2180,9 +1723,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", - "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.15.tgz", + "integrity": "sha512-FHg60rS6DBePAYZ9X9F67x+JObFdmgn6tupA1C/a3B+CufFmTD4mX+e8M75tCiAO3foR/6xwVBI0KQiI7sn/rw==", "cpu": [ "x64" ], @@ -2199,9 +1742,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", - "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.15.tgz", + "integrity": "sha512-/cvV/7v5VGz/moiz0XKRj2dE8DzsKyhIu1KpOvJGPjRywg3yscON889UGvAe8zfiJLHup7VLjBduoGWi3HusWQ==", "cpu": [ "x64" ], @@ -2218,9 +1761,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", - "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.15.tgz", + "integrity": "sha512-MyzC5Hrv/sm+Z7TSGKP/j8001RO2xQm1zOpCNVL4j0cY/VhBZviludA2YFQ7i4lH6ZAXxQm0lcMdBzM+99mE7w==", "cpu": [ "arm64" ], @@ -2233,59 +1776,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", - "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", - "cpu": [ - "wasm32" - ], - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.11.1", - "@emnapi/runtime": "1.11.1", - "@napi-rs/wasm-runtime": "^1.1.6" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", - "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.2", - "tslib": "^2.4.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", - "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", - "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", - "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.15.tgz", + "integrity": "sha512-+PgYiS+AH5omy6L45ZLxybasauJaj3M8buoT83D+nzPmCayXlxUV9hydhciCKVyIg0B/v0BtXPDE1uGqNwCPpg==", "cpu": [ "arm64" ], @@ -2299,9 +1793,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", - "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.15.tgz", + "integrity": "sha512-HFZd2QNQYn1JbIi+Hpd7H+r/lkWxcfIu28nirZ6eCn2LafuvmExMlb/P96Sfx5tf7pPArw39IdhmCF8vmV+NhQ==", "cpu": [ "x64" ], @@ -2320,44 +1814,16 @@ "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", "license": "MIT" }, - "node_modules/@rollup/pluginutils": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", - "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "license": "MIT" - }, "node_modules/@shikijs/core": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.3.1.tgz", - "integrity": "sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.5.0.tgz", + "integrity": "sha512-6CIgwq+bt2JZ3OSjb/nBkkwEf/CfpHcbam+Mg5Pllco7HAGRQ2/EFhZrrJtbyNTgKwknfVS+llsXGygiDGwJWw==", "license": "MIT", "dependencies": { - "@shikijs/primitive": "4.3.1", - "@shikijs/types": "4.3.1", + "@shikijs/primitive": "4.5.0", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4", + "@types/hast": "^3.0.5", "hast-util-to-html": "^9.0.5" }, "engines": { @@ -2365,12 +1831,12 @@ } }, "node_modules/@shikijs/engine-javascript": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.3.1.tgz", - "integrity": "sha512-JBItcnPuYq7jVJdZo/vMj94r+szT7XEjHFX+mvFDGSEIbVAXAGyHAHzhbWzpGOwYidCZrErJLLgn2PVeiokHnQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.5.0.tgz", + "integrity": "sha512-Ed6UdEj84LyYkwnxM5CvSMWAD+id9ExTYri0/+x41U9zrgNifPSS9lZm0JqBP0VfYI8yr8tY5nbNq9+p9R0kFA==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.3.1", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" }, @@ -2379,12 +1845,12 @@ } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.3.1.tgz", - "integrity": "sha512-OXyNMzg0pews+msMj4cHeqT4xiYKKvbnn6VbdAXxfoFl3SSx4fJTc8FadECuc5/H9p3BzhNAoAUXKwAu9rWYhg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.5.0.tgz", + "integrity": "sha512-dKVmbJecVdB9recl8a/CU4jdpNXyjJQrIcesIkpS70s5HS02ohpnCSpMUbotPnEUzbAcLQ+S4hwZYbkBBiTcJw==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.3.1", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2" }, "engines": { @@ -2392,68 +1858,68 @@ } }, "node_modules/@shikijs/langs": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.3.1.tgz", - "integrity": "sha512-m0l9nsDqgBHvbZbk7A0/kXz/impK3uB/c6rAn6Gpg/uPtdZRQ+alsN/17MU5thb68XTj/4DxkZAotrM0GGSpDQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.5.0.tgz", + "integrity": "sha512-wwBTqwduXSz0X4v9Qa2EWeFaYJEw1clCncWjoRNQRbVDu3SPRTRWucnouYapKj3b8Q+sk/41Vbc4B5c8nuYzLA==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.3.1" + "@shikijs/types": "4.5.0" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/primitive": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.3.1.tgz", - "integrity": "sha512-CXQRQOYy1leqQ8ceTeJdmXv/bsUY++6QyLpXJ94LZAAYj5X2SKRdc5ipguv4NPyGVKItB2PPwUpRNe0Sjh5S1A==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.5.0.tgz", + "integrity": "sha512-UM7ShlA8oz0OWxLLO8BmO9Ip6fVqdkt8yF0EH7nOCqHfrx1eEAzF0ZUVK7L+I8NEgeu1PEWSRlxaiPPeCb4iDg==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.3.1", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@types/hast": "^3.0.5" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/themes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.3.1.tgz", - "integrity": "sha512-dgpoJ4WqNi2yTmizQHBJ5zcX6j2lE6icN/0yt4l1kkf16jrY/pwPLoTb1ETsWMz0OBLf9ZNvwmxft+cH+N9qSA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.5.0.tgz", + "integrity": "sha512-zGb87H3UBbpuI4yoh5UguB1XbU+2BDU3kflM7UfZ+Cy2hWo9lBtqjSVK20gmLY6ukYl040hAypGXMgud9vul8Q==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.3.1" + "@shikijs/types": "4.5.0" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/types": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.3.1.tgz", - "integrity": "sha512-CHFxE0jztBIZRHH6gxXE7DXUCFXjReEGxZ/j0rfSLGKZuwp2xBYycEP14875DSa9KLL/6700oxIq6oO6ef9K2g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.5.0.tgz", + "integrity": "sha512-drtPrtD8N0DENyD2cyt6Ajy+IWsiCLgMxODwLTpvH1UsN6a9jf90tNTPjqwHvA+0Lzu9e0txk8DjfqH1p9UJRw==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@types/hast": "^3.0.5" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.1.0.tgz", + "integrity": "sha512-cVBuhDQjBZaNMTwBquYfPydrUP+E3hE6oYGasx8h6ZrODIM7/r+gxLDXdd66oszbrggZHEntdE6j+5gYIVyMWQ==", "license": "MIT" }, "node_modules/@tybys/wasm-util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "devOptional": true, "license": "MIT", - "optional": true, "dependencies": { "tslib": "^2.4.0" } @@ -2506,12 +1972,6 @@ "@types/unist": "*" } }, - "node_modules/@types/mdx": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.14.tgz", - "integrity": "sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==", - "license": "MIT" - }, "node_modules/@types/ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", @@ -2558,80 +2018,105 @@ "license": "ISC" }, "node_modules/@volar/kit": { - "version": "2.4.28", - "resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.28.tgz", - "integrity": "sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg==", + "version": "2.4.30", + "resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.30.tgz", + "integrity": "sha512-VocLtumfXnqnPQEWc9Yx7uC1uOh9gyjVNlrn2+6Zx/z9aM6yTLhPK8lSqM9Ilu81XRa48I00lcYJWLi2BLxx8Q==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-service": "2.4.28", - "@volar/typescript": "2.4.28", + "@volar/language-service": "2.4.30", + "@volar/typescript": "2.4.30", "typesafe-path": "^0.2.2", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" }, "peerDependencies": { - "typescript": "*" + "typescript": "<7" } }, "node_modules/@volar/language-core": { - "version": "2.4.28", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz", - "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", + "version": "2.4.30", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.30.tgz", + "integrity": "sha512-73fjwEV8wat6aOZ6U/y/hqtE30ocrIWECg67b0txGczOMNw+MffLmvJ5fnFfN9drVUEYZzLdaNo6VAy6G6avMw==", "dev": true, "license": "MIT", "dependencies": { - "@volar/source-map": "2.4.28" + "@volar/source-map": "2.4.30" } }, "node_modules/@volar/language-server": { - "version": "2.4.28", - "resolved": "https://registry.npmjs.org/@volar/language-server/-/language-server-2.4.28.tgz", - "integrity": "sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw==", + "version": "2.4.30", + "resolved": "https://registry.npmjs.org/@volar/language-server/-/language-server-2.4.30.tgz", + "integrity": "sha512-tcP9fzzUBbsLIFHhgnRU4ncQjMn9G9Vax0ffkQmdCrXVEYqRroUepmyC5AVgiju5bCiLD6a55qen5iOTQHkb3g==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.28", - "@volar/language-service": "2.4.28", - "@volar/typescript": "2.4.28", + "@volar/language-core": "2.4.30", + "@volar/language-service": "2.4.30", + "@volar/typescript": "2.4.30", "path-browserify": "^1.0.1", "request-light": "^0.7.0", "vscode-languageserver": "^9.0.1", "vscode-languageserver-protocol": "^3.17.5", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "typescript": "<7" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@volar/language-service": { - "version": "2.4.28", - "resolved": "https://registry.npmjs.org/@volar/language-service/-/language-service-2.4.28.tgz", - "integrity": "sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw==", + "version": "2.4.30", + "resolved": "https://registry.npmjs.org/@volar/language-service/-/language-service-2.4.30.tgz", + "integrity": "sha512-w/xDsASiqC71ggCOm7sTDXDNk/l72XEptodeRC68tgZ0e5QM4hM3zAqBGC7mBctvhrpYwKfMG+t9xcUo2hEFtA==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.28", + "@volar/language-core": "2.4.30", "vscode-languageserver-protocol": "^3.17.5", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "typescript": "<7" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@volar/source-map": { - "version": "2.4.28", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz", - "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "version": "2.4.30", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.30.tgz", + "integrity": "sha512-zym1ob/KwDDyN+0jGVtxwbxJSRRnUvv5HspCtz3yEfVVdCG4/dzxJktMGPAgemqRuVs81O0o/y0q3qOUErR8kg==", "dev": true, "license": "MIT" }, "node_modules/@volar/typescript": { - "version": "2.4.28", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz", - "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", + "version": "2.4.30", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.30.tgz", + "integrity": "sha512-/DgA5tgYFPfrLFuSjIMXMGHk1LQv2+P8eny6+BhGNzFJELWIW7UZlc56ZLIRFhLsPpMfIFxM8/HvOPBggrjTZg==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.28", + "@volar/language-core": "2.4.30", + "@volar/language-service": "2.4.30", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "typescript": "<7" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@vscode/emmet-helper": { @@ -2662,27 +2147,6 @@ "dev": true, "license": "MIT" }, - "node_modules/acorn": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", - "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, "node_modules/ajv": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", @@ -2726,9 +2190,9 @@ } }, "node_modules/am-i-vibing": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/am-i-vibing/-/am-i-vibing-0.4.0.tgz", - "integrity": "sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/am-i-vibing/-/am-i-vibing-0.5.0.tgz", + "integrity": "sha512-KLcsDhqf1XRrJmJr+9I/C0EX2K+sGrAGZFgkmd84c8TJO9zJBu+/kFInjazu1KfJWFhWDKdRWkpBzEs7s35DVA==", "license": "MIT", "dependencies": { "process-ancestry": "^0.1.0" @@ -2738,26 +2202,26 @@ } }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.4.0.tgz", + "integrity": "sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -2809,90 +2273,70 @@ "node": ">= 0.4" } }, - "node_modules/array-iterate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", - "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/astring": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", - "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", - "license": "MIT", - "bin": { - "astring": "bin/astring" - } - }, "node_modules/astro": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/astro/-/astro-7.1.3.tgz", - "integrity": "sha512-4dhPyAAXthf3xLEYnG8SeL7yr/nTPPABfY7e9YF0yuO+vK9Xp+8Q5j4xzsmL3GueukQv4oNwGNTBepLOiDGeJA==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/astro/-/astro-7.4.2.tgz", + "integrity": "sha512-FAH4cdDlFaVnQGjazLTEIC5vJqGlo5XANc1wIbzQHIqAjJTll/RWTUs+SPNW1JdezG4YGxMZllaE5A41T2kzhA==", "license": "MIT", "dependencies": { - "@astrojs/compiler-rs": "^0.3.1", - "@astrojs/internal-helpers": "0.10.1", - "@astrojs/markdown-satteri": "0.3.4", - "@astrojs/telemetry": "3.3.3", - "@capsizecss/unpack": "^4.0.0", - "@clack/prompts": "^1.1.0", + "@astrojs/compiler-rs": "^0.5.1", + "@astrojs/internal-helpers": "0.13.0", + "@astrojs/markdown-satteri": "0.4.5", + "@astrojs/telemetry": "3.4.1", + "@capsizecss/unpack": "^4.0.1", + "@clack/prompts": "^1.8.1", "@oslojs/encoding": "^1.1.0", - "@rollup/pluginutils": "^5.3.0", - "am-i-vibing": "^0.4.0", + "am-i-vibing": "^0.5.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "ci-info": "^4.4.0", "clsx": "^2.1.1", "common-ancestor-path": "^2.0.0", "cookie": "^2.0.1", - "devalue": "^5.8.1", - "diff": "^8.0.3", + "devalue": "^6.0.2", + "diff": "^9.0.0", "dset": "^3.1.4", - "es-module-lexer": "^2.0.0", - "esbuild": "^0.28.0", + "es-module-lexer": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.4.1", - "get-tsconfig": "5.0.0-beta.4", + "get-tsconfig": "5.0.0-beta.6", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", - "http-cache-semantics": "^4.2.0", - "js-yaml": "^4.1.1", + "http-cache-semantics": "^4.3.0", "jsonc-parser": "^3.3.1", - "magic-string": "^0.30.21", - "magicast": "^0.5.2", + "magic-string": "^1.4.3", + "magicast": "^0.5.5", "mrmime": "^2.0.1", "neotraverse": "^1.0.1", - "obug": "^2.1.1", - "p-limit": "^7.3.0", - "p-queue": "^9.1.0", - "package-manager-detector": "^1.6.0", + "obug": "^3.0.0", + "p-limit": "^7.3.3", + "p-queue": "^9.3.5", + "package-manager-detector": "^1.9.0", "piccolore": "^0.1.3", - "picomatch": "^4.0.4", - "semver": "^7.7.4", - "shiki": "^4.0.2", - "smol-toml": "^1.6.0", - "svgo": "^4.0.1", - "tinyclip": "^0.1.12", - "tinyexec": "^1.0.4", - "tinyglobby": "^0.2.15", - "ultrahtml": "^1.6.0", - "unifont": "~0.7.4", + "picomatch": "^4.0.7", + "rolldown": "^1.2.13", + "shiki": "^4.5.0", + "smol-toml": "^1.9.1", + "svgo": "^4.1.0", + "tinyclip": "^1.0.3", + "tinyexec": "^1.3.1", + "tinyglobby": "^0.2.17", + "tinyps": "^0.5.0", + "ultrahtml": "^1.7.0", + "unifont": "^1.0.3", "unstorage": "^1.17.5", - "vite": "^8.0.13", - "vitefu": "^1.1.2", + "verkit": "^0.5.0", + "vite": "^8.3.4", + "vitefu": "^1.1.3", "xxhash-wasm": "^1.1.0", "yargs-parser": "^22.0.0", - "zod": "^4.3.6" + "zod": "^4.6.6" }, "bin": { "astro": "bin/astro.mjs" }, "engines": { - "node": ">=22.12.0", + "node": ">=22.23.4", "npm": ">=9.6.5", "pnpm": ">=7.1.0" }, @@ -2901,10 +2345,10 @@ "url": "https://opencollective.com/astrodotbuild" }, "optionalDependencies": { - "sharp": "^0.34.0 || ^0.35.0" + "sharp": "^0.35.4" }, "peerDependencies": { - "@astrojs/markdown-remark": "7.2.1" + "@astrojs/markdown-remark": "^7.3.0" }, "peerDependenciesMeta": { "@astrojs/markdown-remark": { @@ -3056,59 +2500,47 @@ } }, "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "dev": true, "license": "ISC", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=12" + "node": ">=20" } }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "node_modules/cliui/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">=6" - } - }, - "node_modules/collapse-white-space": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", - "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", - "license": "MIT", + "node": ">=18" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=6" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -3166,16 +2598,16 @@ } }, "node_modules/css-select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", - "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-6.0.0.tgz", + "integrity": "sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==", "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" + "css-what": "^7.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "nth-check": "^2.1.1" }, "funding": { "url": "https://github.com/sponsors/fb55" @@ -3211,9 +2643,9 @@ } }, "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-7.0.0.tgz", + "integrity": "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==", "license": "BSD-2-Clause", "engines": { "node": ">= 6" @@ -3328,10 +2760,13 @@ } }, "node_modules/devalue": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.8.2.tgz", - "integrity": "sha512-DObPPAfdtFbXjxLqK8s2Xk9ZuWz5+ZoFEhC7J76es4GU/rEiXwHTmbImoCdyoCOcBH1UF3+Cz6Z2sYD4hyl5TA==", - "license": "MIT" + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-6.0.3.tgz", + "integrity": "sha512-3woMEITftG1wKeO/4d/QXH1DVKctTSZg3jNGPpjp9hNr5Hos8MCFF5McTML5ZtgKDObm2R591B0spRp2IVernA==", + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/devlop": { "version": "1.1.0", @@ -3347,9 +2782,9 @@ } }, "node_modules/diff": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", - "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", + "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -3382,18 +2817,6 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -3462,16 +2885,16 @@ } }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, "license": "MIT" }, "node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -3481,84 +2904,11 @@ } }, "node_modules/es-module-lexer": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", - "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-3.0.4.tgz", + "integrity": "sha512-BldNY5mwkVu+cQ5Ymn3e6hB9Sx8XHx4ZevWbiUyZbfKxJxYO27Hf0wfzkxIaD5CAJMaGl3YspKELj0ff/7nCMA==", "license": "MIT" }, - "node_modules/esast-util-from-estree": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", - "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-visit": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/esast-util-from-js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", - "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "acorn": "^8.0.0", - "esast-util-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/esbuild": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", - "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.1", - "@esbuild/android-arm": "0.28.1", - "@esbuild/android-arm64": "0.28.1", - "@esbuild/android-x64": "0.28.1", - "@esbuild/darwin-arm64": "0.28.1", - "@esbuild/darwin-x64": "0.28.1", - "@esbuild/freebsd-arm64": "0.28.1", - "@esbuild/freebsd-x64": "0.28.1", - "@esbuild/linux-arm": "0.28.1", - "@esbuild/linux-arm64": "0.28.1", - "@esbuild/linux-ia32": "0.28.1", - "@esbuild/linux-loong64": "0.28.1", - "@esbuild/linux-mips64el": "0.28.1", - "@esbuild/linux-ppc64": "0.28.1", - "@esbuild/linux-riscv64": "0.28.1", - "@esbuild/linux-s390x": "0.28.1", - "@esbuild/linux-x64": "0.28.1", - "@esbuild/netbsd-arm64": "0.28.1", - "@esbuild/netbsd-x64": "0.28.1", - "@esbuild/openbsd-arm64": "0.28.1", - "@esbuild/openbsd-x64": "0.28.1", - "@esbuild/openharmony-arm64": "0.28.1", - "@esbuild/sunos-x64": "0.28.1", - "@esbuild/win32-arm64": "0.28.1", - "@esbuild/win32-ia32": "0.28.1", - "@esbuild/win32-x64": "0.28.1" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -3569,109 +2919,6 @@ "node": ">=6" } }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/estree-util-attach-comments": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", - "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-build-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", - "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-walker": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-is-identifier-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", - "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-scope": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", - "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-to-js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", - "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "astring": "^1.8.0", - "source-map": "^0.7.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-visit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", - "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/eventemitter3": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", @@ -3719,9 +2966,9 @@ } }, "node_modules/fast-uri": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", - "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.9.tgz", + "integrity": "sha512-hS/0Wt3Ya043oKXs0sIxrMpKQITXhMLIrVAKKXi4gozGC9v7YRWVnXIZzjNPTO02M9BdxLCWqK1yRXgNziVyJQ==", "dev": true, "funding": [ { @@ -3770,6 +3017,12 @@ "node": ">=8" } }, + "node_modules/fnv1a-64": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/fnv1a-64/-/fnv1a-64-0.1.2.tgz", + "integrity": "sha512-mJbcILTPybAR1jdOwt/lVv8N2cffeJFFP+gVbSAwLEx1ujXH27RpPd8Rokec/KX9c76UYIB6Co+H4lQzxPnJfA==", + "license": "MIT" + }, "node_modules/fontace": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz", @@ -3815,10 +3068,23 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.7.0.tgz", + "integrity": "sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-tsconfig": { - "version": "5.0.0-beta.4", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-5.0.0-beta.4.tgz", - "integrity": "sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ==", + "version": "5.0.0-beta.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-5.0.0-beta.6.tgz", + "integrity": "sha512-X6fBC0pmImC70gvX2zm56go9hx0MyoGVdG0tUCkg/D+Xnh5TJsOZ7iDbOdI3PvmtrDxnu1YdDufpK2QJX1Meqw==", "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -3879,45 +3145,7 @@ "hast-util-phrasing": "^3.0.0", "hast-util-whitespace": "^3.0.0", "html-whitespace-sensitive-tag-names": "^3.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-html": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", - "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "devlop": "^1.1.0", - "hast-util-from-parse5": "^8.0.0", - "parse5": "^7.0.0", - "vfile": "^6.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-parse5": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", - "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "hastscript": "^9.0.0", - "property-information": "^7.0.0", - "vfile": "^6.0.0", - "vfile-location": "^5.0.0", - "web-namespaces": "^2.0.0" + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", @@ -4010,31 +3238,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-raw": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", - "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-from-parse5": "^8.0.0", - "hast-util-to-parse5": "^8.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "parse5": "^7.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/hast-util-select": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz", @@ -4062,34 +3265,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-to-estree": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", - "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-attach-comments": "^3.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/hast-util-to-html": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", @@ -4113,52 +3288,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", - "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-parse5": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", - "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/hast-util-to-string": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", @@ -4245,9 +3374,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.3.0.tgz", + "integrity": "sha512-M5t5LlJpS1UHMjvwRQVdFHvPISGeLAxNcrWuJkeGh0KxsqCHZ1O3NXZU/8x7cD0BDcGW8kapxMKTvwlqrNkHkA==", "license": "BSD-2-Clause" }, "node_modules/i18next": { @@ -4278,12 +3407,6 @@ } } }, - "node_modules/inline-style-parser": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", - "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", - "license": "MIT" - }, "node_modules/iron-webcrypto": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", @@ -4342,16 +3465,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-hexadecimal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", @@ -4669,335 +3782,104 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", - "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/lru-cache": { - "version": "11.5.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", - "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/magicast": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz", - "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.3", - "@babel/types": "^7.29.0", - "source-map-js": "^1.2.1" - } - }, - "node_modules/markdown-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", - "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/markdown-table": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", - "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-definitions": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", - "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-directive": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz", - "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", - "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", - "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", - "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", - "license": "MIT", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", - "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-find-and-replace": "^3.0.0", - "micromark-util-character": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", - "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", - "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/mdast-util-mdx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", - "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/magic-string": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.3.tgz", + "integrity": "sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==", "license": "MIT", "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "@jridgewell/sourcemap-codec": "^1.6.0" } }, - "node_modules/mdast-util-mdx-expression": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", - "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "node_modules/magicast": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.5.tgz", + "integrity": "sha512-UicdXN8zQ3JHlxVq+28afMXPr1z7WNY6+7EJnzTdQWkTAlMLF5fNCCKxJHBQwGaNGR11581EiQmQzx73+MvszA==", "license": "MIT", "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "source-map-js": "^1.2.1" } }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", - "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "node_modules/mdast-util-directive": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz", + "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==", "license": "MIT", "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", - "devlop": "^1.1.0", + "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", "license": "MIT", "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", @@ -5155,235 +4037,12 @@ "license": "MIT", "dependencies": { "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "parse-entities": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "license": "MIT", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdx-expression": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", - "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-mdx-expression": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-mdx-jsx": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", - "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "micromark-factory-mdx-expression": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdx-md": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", - "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdxjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", - "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", - "license": "MIT", - "dependencies": { - "acorn": "^8.0.0", - "acorn-jsx": "^5.0.0", - "micromark-extension-mdx-expression": "^3.0.0", - "micromark-extension-mdx-jsx": "^3.0.0", - "micromark-extension-mdx-md": "^2.0.0", - "micromark-extension-mdxjs-esm": "^3.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdxjs-esm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", - "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" + "parse-entities": "^4.0.0" }, "funding": { "type": "opencollective", @@ -5433,33 +4092,6 @@ "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-factory-mdx-expression": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", - "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" - } - }, "node_modules/micromark-factory-space": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", @@ -5661,31 +4293,6 @@ ], "license": "MIT" }, - "node_modules/micromark-util-events-to-acorn": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", - "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "estree-util-visit": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "vfile-message": "^4.0.0" - } - }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", @@ -5838,9 +4445,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", - "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "version": "3.3.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", "funding": [ { "type": "github", @@ -5911,9 +4518,9 @@ } }, "node_modules/obug": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", - "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/obug/-/obug-3.0.0.tgz", + "integrity": "sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==", "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" @@ -5934,12 +4541,6 @@ "ufo": "^1.6.1" } }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", - "license": "MIT" - }, "node_modules/oniguruma-parser": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", @@ -5958,9 +4559,9 @@ } }, "node_modules/p-limit": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.1.tgz", - "integrity": "sha512-0trZaiG7Y7kN/Egy9a8j47t9osC0Tch4PaIWd9yGF6bvmlk7muExRvGNYb8sXBwEKMoNKsbNN9P8EefuQekE4Q==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.3.tgz", + "integrity": "sha512-SKgVvDU5TNIxQ4r30U75BNLC6a+6GOEjngrk/ysM5+Zu3oJuk1SC5ApzIzY/7PjCEjoVPMWJ0zho/4QUiEB7TQ==", "license": "MIT", "dependencies": { "yocto-queue": "^1.2.1" @@ -5973,9 +4574,9 @@ } }, "node_modules/p-queue": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.3.tgz", - "integrity": "sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA==", + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.5.tgz", + "integrity": "sha512-Lki/zhXFVmDhesBUn/yHRLW9Bte7mE7xoFHzTR8sIomV7a2z+LxYAPkGvdfidNiu4fKSfjtawixxSHcZci5QcQ==", "license": "MIT", "dependencies": { "eventemitter3": "^5.0.4", @@ -5989,9 +4590,9 @@ } }, "node_modules/p-timeout": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", - "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.2.tgz", + "integrity": "sha512-prbX4Z3YszrFNgH+MW5Zoeq3baXrMtP/MQnFeET90UB/GtGcGDQ5Usg9OCy6ETjTTntOw1SL2z9fMPUppN3Guw==", "license": "MIT", "engines": { "node": ">=20" @@ -6001,9 +4602,9 @@ } }, "node_modules/package-manager-detector": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.8.0.tgz", - "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.9.0.tgz", + "integrity": "sha512-zAMfbta9nPA8AKkA4WdmNAT8R8s6Dk0/xwPsqNnRidMFcLo1YkLuPDTgs2f64XdzS8vbLNnoJ+uUIkgbz7oRHA==", "license": "MIT" }, "node_modules/pagefind": { @@ -6049,36 +4650,6 @@ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, - "node_modules/parse-latin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", - "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", - "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0", - "@types/unist": "^3.0.0", - "nlcst-to-string": "^4.0.0", - "unist-util-modify-children": "^4.0.0", - "unist-util-visit-children": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -6099,9 +4670,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "license": "MIT", "engines": { "node": ">=12" @@ -6111,9 +4682,9 @@ } }, "node_modules/postcss": { - "version": "8.5.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", - "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "version": "8.5.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz", + "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==", "funding": [ { "type": "opencollective", @@ -6130,9 +4701,9 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.16", + "nanoid": "^3.3.20", "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "source-map-js": "^1.2.2" }, "engines": { "node": "^10 || ^12 || >=14" @@ -6177,9 +4748,9 @@ } }, "node_modules/prettier": { - "version": "3.9.6", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", - "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.10.tgz", + "integrity": "sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==", "dev": true, "license": "MIT", "bin": { @@ -6204,335 +4775,83 @@ "node_modules/process-ancestry": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/process-ancestry/-/process-ancestry-0.1.0.tgz", - "integrity": "sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/property-information": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", - "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/radix3": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", - "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", - "license": "MIT" - }, - "node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/recma-build-jsx": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", - "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-util-build-jsx": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/recma-jsx": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", - "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", - "license": "MIT", - "dependencies": { - "acorn-jsx": "^5.0.0", - "estree-util-to-js": "^2.0.0", - "recma-parse": "^1.0.0", - "recma-stringify": "^1.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/recma-parse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", - "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "esast-util-from-js": "^2.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/recma-stringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", - "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-util-to-js": "^2.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", - "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", - "license": "MIT", - "dependencies": { - "regex-utilities": "^2.3.0" - } - }, - "node_modules/regex-recursion": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", - "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", - "license": "MIT", - "dependencies": { - "regex-utilities": "^2.3.0" - } - }, - "node_modules/regex-utilities": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", - "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", - "license": "MIT" - }, - "node_modules/rehype": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", - "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "rehype-parse": "^9.0.0", - "rehype-stringify": "^10.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-expressive-code": { - "version": "0.44.1", - "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.44.1.tgz", - "integrity": "sha512-+VZgs7Evw4LXRN3owpoBNSTpYuW6GeOdjqcUT1TuY8o/4MGPtbd0EU7Bgrju7X8KrQ6SslOBAuGWJ5fV5TriJQ==", - "license": "MIT", - "dependencies": { - "expressive-code": "^0.44.1" - } - }, - "node_modules/rehype-format": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/rehype-format/-/rehype-format-5.0.1.tgz", - "integrity": "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-format": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-parse": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", - "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-from-html": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-raw": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", - "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-raw": "^9.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-recma": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", - "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "hast-util-to-estree": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-stringify": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", - "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-to-html": "^9.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-directive": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-4.0.0.tgz", - "integrity": "sha512-7sxn4RfF1o3izevPV1DheyGDD6X4c9hrGpfdUpm7uC++dqrnJxIZVkk7CoKqcLm0VUMAuOol7Mno3m6g8cfMuA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-directive": "^3.0.0", - "micromark-extension-directive": "^4.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "integrity": "sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" } }, - "node_modules/remark-gfm": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", - "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "node_modules/property-information": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-gfm": "^3.0.0", - "micromark-extension-gfm": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "unified": "^11.0.0" - }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/remark-mdx": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", - "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", "license": "MIT", - "dependencies": { - "mdast-util-mdx": "^3.0.0", - "micromark-extension-mdxjs": "^3.0.0" + "engines": { + "node": ">= 20.19.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "regex-utilities": "^2.3.0" } }, - "node_modules/remark-rehype": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", - "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "regex-utilities": "^2.3.0" } }, - "node_modules/remark-smartypants": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.3.tgz", - "integrity": "sha512-gCaK+ndZ0hYezlqFegHFCVh2CQemsi0Npdh1qVM9bxlUFknjkbP6VmojWhddOCrbK0PbbacmYLWfTULRiT1eWA==", + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "license": "MIT" + }, + "node_modules/rehype-expressive-code": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.44.1.tgz", + "integrity": "sha512-+VZgs7Evw4LXRN3owpoBNSTpYuW6GeOdjqcUT1TuY8o/4MGPtbd0EU7Bgrju7X8KrQ6SslOBAuGWJ5fV5TriJQ==", "license": "MIT", "dependencies": { - "retext": "^9.0.0", - "retext-smartypants": "^6.0.0", - "unified": "^11.0.4", - "unist-util-visit": "^5.0.0" - }, - "engines": { - "node": ">=16.0.0" + "expressive-code": "^0.44.1" } }, - "node_modules/remark-stringify": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "node_modules/remark-directive": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-4.0.0.tgz", + "integrity": "sha512-7sxn4RfF1o3izevPV1DheyGDD6X4c9hrGpfdUpm7uC++dqrnJxIZVkk7CoKqcLm0VUMAuOol7Mno3m6g8cfMuA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", - "mdast-util-to-markdown": "^2.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^4.0.0", "unified": "^11.0.0" }, "funding": { @@ -6547,16 +4866,6 @@ "dev": true, "license": "MIT" }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -6576,37 +4885,6 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/retext": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", - "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", - "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0", - "retext-latin": "^4.0.0", - "retext-stringify": "^4.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-latin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", - "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", - "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0", - "parse-latin": "^7.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/retext-smartypants": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", @@ -6622,28 +4900,13 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/retext-stringify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", - "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", - "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0", - "nlcst-to-string": "^4.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/rolldown": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", - "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.15.tgz", + "integrity": "sha512-6odND+fel5zVw3I4Yc2e69gvguDnX0CAAGiNDZSq4ik5WUcaLrkD2GLuog0XcODbor31hZ5ayEMgVDno+KPV5g==", "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.139.0", + "@oxc-project/types": "=0.155.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -6653,44 +4916,44 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.1.5", - "@rolldown/binding-darwin-arm64": "1.1.5", - "@rolldown/binding-darwin-x64": "1.1.5", - "@rolldown/binding-freebsd-x64": "1.1.5", - "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", - "@rolldown/binding-linux-arm64-gnu": "1.1.5", - "@rolldown/binding-linux-arm64-musl": "1.1.5", - "@rolldown/binding-linux-ppc64-gnu": "1.1.5", - "@rolldown/binding-linux-s390x-gnu": "1.1.5", - "@rolldown/binding-linux-x64-gnu": "1.1.5", - "@rolldown/binding-linux-x64-musl": "1.1.5", - "@rolldown/binding-openharmony-arm64": "1.1.5", - "@rolldown/binding-wasm32-wasi": "1.1.5", - "@rolldown/binding-win32-arm64-msvc": "1.1.5", - "@rolldown/binding-win32-x64-msvc": "1.1.5" + "@rolldown/binding-android-arm-eabi": "1.2.15", + "@rolldown/binding-android-arm64": "1.2.15", + "@rolldown/binding-darwin-arm64": "1.2.15", + "@rolldown/binding-darwin-x64": "1.2.15", + "@rolldown/binding-freebsd-x64": "1.2.15", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.15", + "@rolldown/binding-linux-arm64-gnu": "1.2.15", + "@rolldown/binding-linux-arm64-musl": "1.2.15", + "@rolldown/binding-linux-ppc64-gnu": "1.2.15", + "@rolldown/binding-linux-s390x-gnu": "1.2.15", + "@rolldown/binding-linux-x64-gnu": "1.2.15", + "@rolldown/binding-linux-x64-musl": "1.2.15", + "@rolldown/binding-openharmony-arm64": "1.2.15", + "@rolldown/binding-win32-arm64-msvc": "1.2.15", + "@rolldown/binding-win32-x64-msvc": "1.2.15" } }, "node_modules/satteri": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/satteri/-/satteri-0.9.5.tgz", - "integrity": "sha512-ZuWVl+vnM64y+/TtX8Kosv2c00W+hLQiiwnEL6H0UKVVrxFqMw4D2CJHHQaouVd89OAhtBBfjWLqhKi3TVUV4w==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/satteri/-/satteri-0.10.5.tgz", + "integrity": "sha512-Ao1LKpAEa9Wdg0otgbVKViZHEq9ebdXe4DMrp3s9vQAU0HNIuHnFEuMuOcm0ZIXyV0Yzxj91NvhLpvXZJO/5ZQ==", "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.5", - "@types/hast": "^3.0.4", + "@types/hast": "^3.0.5", "@types/mdast": "^4.0.4", "@types/unist": "^3.0.3" }, "optionalDependencies": { - "@bruits/satteri-darwin-arm64": "0.9.5", - "@bruits/satteri-darwin-x64": "0.9.5", - "@bruits/satteri-linux-arm64-gnu": "0.9.5", - "@bruits/satteri-linux-arm64-musl": "0.9.5", - "@bruits/satteri-linux-x64-gnu": "0.9.5", - "@bruits/satteri-linux-x64-musl": "0.9.5", - "@bruits/satteri-wasm32-wasi": "0.9.5", - "@bruits/satteri-win32-arm64-msvc": "0.9.5", - "@bruits/satteri-win32-x64-msvc": "0.9.5" + "@bruits/satteri-darwin-arm64": "0.10.5", + "@bruits/satteri-darwin-x64": "0.10.5", + "@bruits/satteri-linux-arm64-gnu": "0.10.5", + "@bruits/satteri-linux-arm64-musl": "0.10.5", + "@bruits/satteri-linux-x64-gnu": "0.10.5", + "@bruits/satteri-linux-x64-musl": "0.10.5", + "@bruits/satteri-wasm32-wasi": "0.10.5", + "@bruits/satteri-win32-arm64-msvc": "0.10.5", + "@bruits/satteri-win32-x64-msvc": "0.10.5" } }, "node_modules/sax": { @@ -6715,9 +4978,9 @@ } }, "node_modules/sharp": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", - "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.5.tgz", + "integrity": "sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==", "license": "Apache-2.0", "dependencies": { "@img/colour": "^1.1.0", @@ -6731,31 +4994,31 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.35.3", - "@img/sharp-darwin-x64": "0.35.3", - "@img/sharp-freebsd-wasm32": "0.35.3", - "@img/sharp-libvips-darwin-arm64": "1.3.2", - "@img/sharp-libvips-darwin-x64": "1.3.2", - "@img/sharp-libvips-linux-arm": "1.3.2", - "@img/sharp-libvips-linux-arm64": "1.3.2", - "@img/sharp-libvips-linux-ppc64": "1.3.2", - "@img/sharp-libvips-linux-riscv64": "1.3.2", - "@img/sharp-libvips-linux-s390x": "1.3.2", - "@img/sharp-libvips-linux-x64": "1.3.2", - "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", - "@img/sharp-libvips-linuxmusl-x64": "1.3.2", - "@img/sharp-linux-arm": "0.35.3", - "@img/sharp-linux-arm64": "0.35.3", - "@img/sharp-linux-ppc64": "0.35.3", - "@img/sharp-linux-riscv64": "0.35.3", - "@img/sharp-linux-s390x": "0.35.3", - "@img/sharp-linux-x64": "0.35.3", - "@img/sharp-linuxmusl-arm64": "0.35.3", - "@img/sharp-linuxmusl-x64": "0.35.3", - "@img/sharp-webcontainers-wasm32": "0.35.3", - "@img/sharp-win32-arm64": "0.35.3", - "@img/sharp-win32-ia32": "0.35.3", - "@img/sharp-win32-x64": "0.35.3" + "@img/sharp-darwin-arm64": "0.35.5", + "@img/sharp-darwin-x64": "0.35.5", + "@img/sharp-freebsd-wasm32": "0.35.5", + "@img/sharp-libvips-darwin-arm64": "1.3.4", + "@img/sharp-libvips-darwin-x64": "1.3.4", + "@img/sharp-libvips-linux-arm": "1.3.4", + "@img/sharp-libvips-linux-arm64": "1.3.4", + "@img/sharp-libvips-linux-ppc64": "1.3.4", + "@img/sharp-libvips-linux-riscv64": "1.3.4", + "@img/sharp-libvips-linux-s390x": "1.3.4", + "@img/sharp-libvips-linux-x64": "1.3.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.4", + "@img/sharp-libvips-linuxmusl-x64": "1.3.4", + "@img/sharp-linux-arm": "0.35.5", + "@img/sharp-linux-arm64": "0.35.5", + "@img/sharp-linux-ppc64": "0.35.5", + "@img/sharp-linux-riscv64": "0.35.5", + "@img/sharp-linux-s390x": "0.35.5", + "@img/sharp-linux-x64": "0.35.5", + "@img/sharp-linuxmusl-arm64": "0.35.5", + "@img/sharp-linuxmusl-x64": "0.35.5", + "@img/sharp-webcontainers-wasm32": "0.35.5", + "@img/sharp-win32-arm64": "0.35.5", + "@img/sharp-win32-ia32": "0.35.5", + "@img/sharp-win32-x64": "0.35.5" }, "peerDependenciesMeta": { "@types/node": { @@ -6764,19 +5027,19 @@ } }, "node_modules/shiki": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.3.1.tgz", - "integrity": "sha512-oR+qDVi2OjX1tmDpyv+3KviX01KzO6Af+0NNnKnsp9491UEGz2YpxTuJboS/6VhYpTdqzmuJBuiTlrAWWJAssw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.5.0.tgz", + "integrity": "sha512-OcRW72ngQvc+MSVWBRIovC/BTW589iUE/Vxav7VeM4RcY9MUjqB+IR6ILG1k9nuW6LiG/nct9uma4/MBtnZbmQ==", "license": "MIT", "dependencies": { - "@shikijs/core": "4.3.1", - "@shikijs/engine-javascript": "4.3.1", - "@shikijs/engine-oniguruma": "4.3.1", - "@shikijs/langs": "4.3.1", - "@shikijs/themes": "4.3.1", - "@shikijs/types": "4.3.1", + "@shikijs/core": "4.5.0", + "@shikijs/engine-javascript": "4.5.0", + "@shikijs/engine-oniguruma": "4.5.0", + "@shikijs/langs": "4.5.0", + "@shikijs/themes": "4.5.0", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@types/hast": "^3.0.5" }, "engines": { "node": ">=20" @@ -6808,9 +5071,9 @@ } }, "node_modules/smol-toml": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.7.0.tgz", - "integrity": "sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.9.1.tgz", + "integrity": "sha512-j7WyPdf0CJoutMzMoPLF/bVXHtKZIT9Rb4eGeEbWw8X2t5oirjPgpL+OpaENZrILYaXqYwnVH+qgUwVbl+pUJQ==", "license": "BSD-3-Clause", "engines": { "node": ">= 18" @@ -6819,19 +5082,10 @@ "url": "https://github.com/sponsors/cyyynthia" } }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -6848,9 +5102,9 @@ } }, "node_modules/starlight-sidebar-topics": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/starlight-sidebar-topics/-/starlight-sidebar-topics-0.8.0.tgz", - "integrity": "sha512-hE8+w2vNL13h6cq3UJGl05milJQ3+1BSlhaV5V4a993YzYczU6uLAj6jfUDKQ2mmgkdVWp8/UNDF4Je/rQXNQw==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/starlight-sidebar-topics/-/starlight-sidebar-topics-0.9.0.tgz", + "integrity": "sha512-xFwMAAtTVyqsO5DZ8Ldk0vN+2QoPdtjtDi8fbrzvQATIJvIvfaBLL9JzfXAjNHI9vMkj35VMWMd8tTICeO6RIA==", "license": "MIT", "dependencies": { "picomatch": "^4.0.3" @@ -6859,9 +5113,16 @@ "node": ">=22.12.0" }, "peerDependencies": { - "@astrojs/starlight": ">=0.38.0" + "@astrojs/starlight": ">=0.42.0", + "astro": "^7.2.10" } }, + "node_modules/std-env": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.3.0.tgz", + "integrity": "sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==", + "license": "MIT" + }, "node_modules/stream-replace-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz", @@ -6869,18 +5130,20 @@ "license": "MIT" }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.3.0.tgz", + "integrity": "sha512-ZbmZM0JCihQN91dWnxoipT2KOEyHqEyfRXUyjuRhW8b/xnqPDoq4gWEVApTVa9db2wN8mmoikgFBbjh71+cGeQ==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" }, "engines": { - "node": ">=8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/stringify-entities": { @@ -6898,49 +5161,34 @@ } }, "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.2.2" }, "engines": { - "node": ">=8" - } - }, - "node_modules/style-to-js": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", - "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", - "license": "MIT", - "dependencies": { - "style-to-object": "1.0.14" - } - }, - "node_modules/style-to-object": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", - "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", - "license": "MIT", - "dependencies": { - "inline-style-parser": "0.2.7" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/svgo": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.2.tgz", - "integrity": "sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.1.0.tgz", + "integrity": "sha512-bkxnTg1kSU0guhIBmibA6UUhrQmPVA1XsQLN+ylCd+UWzbnLkySOcXpyk1mrl05f+pcaCx2eHb+sp6BgMZWX+Q==", "license": "MIT", "dependencies": { "commander": "^11.1.0", - "css-select": "^5.1.0", + "css-select": "^6.0.0", "css-tree": "^3.0.1", - "css-what": "^6.1.0", + "css-what": "^7.0.0", "csso": "^5.0.5", "picocolors": "^1.1.1", - "sax": "^1.5.0" + "sax": "1.6.1" }, "bin": { "svgo": "bin/svgo.js" @@ -6960,18 +5208,18 @@ "license": "MIT" }, "node_modules/tinyclip": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-0.1.15.tgz", - "integrity": "sha512-uo33abH+Ays0xYaDysoBt494Hb3hsEczMpcC0MwFl773pazORx4fmvKhclhR1wonUbB6vvpRsvVMwnhfqeMc+A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-1.0.3.tgz", + "integrity": "sha512-nTv2raKFMzGG6JJp0lpNDsRPdfFE6UHlu2rVEjXo8vkx1ZS3LW2CVXqIaLu8xZlu+6tbFs9V58Qc/Jmk/Ii7wA==", "license": "MIT", "engines": { "node": "^16.14.0 || >= 17.3.0" } }, "node_modules/tinyexec": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", - "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.1.tgz", + "integrity": "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==", "license": "MIT", "engines": { "node": ">=18" @@ -6993,6 +5241,12 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tinyps": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/tinyps/-/tinyps-0.5.1.tgz", + "integrity": "sha512-B6Ykif5HflC3AdDkS4Zst/2muYVfeXoVMy+KorqH80s/1x4vunIORpNySH681X7fjj+dFM9MDKD6/Hsccjb87Q==", + "license": "MIT" + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -7017,8 +5271,8 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "optional": true + "devOptional": true, + "license": "0BSD" }, "node_modules/typesafe-path": { "version": "0.2.2", @@ -7069,6 +5323,15 @@ "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", "license": "MIT" }, + "node_modules/undici": { + "version": "8.12.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.12.3.tgz", + "integrity": "sha512-+fdndUTwBP86cVjihTp21hZHo7d6oj1c/47XPA3lL8mM0XHs+C4EkcjmgRsFnFk2f/UONGDy9ItBItmXsLOQHw==", + "license": "MIT", + "engines": { + "node": ">=22.19.0" + } + }, "node_modules/undici-types": { "version": "7.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", @@ -7095,14 +5358,15 @@ } }, "node_modules/unifont": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.4.tgz", - "integrity": "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-1.0.3.tgz", + "integrity": "sha512-XGnEwj5sWdCbiBX01mWLSBncS0yMRjnLygau3IfdOlfjMacNIQvTGW4VH7pWBq+gGWArfSef/CensMLjMmIr/A==", "license": "MIT", "dependencies": { "css-tree": "^3.1.0", - "ofetch": "^1.5.1", - "ohash": "^2.0.11" + "fnv1a-64": "^0.1.2", + "std-env": "^4.2.0", + "undici": "^8.0.0" } }, "node_modules/unist-util-find-after": { @@ -7132,20 +5396,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-modify-children": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", - "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "array-iterate": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/unist-util-position": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", @@ -7159,33 +5409,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-position-from-estree": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", - "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-remove-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", - "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", @@ -7214,19 +5437,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-visit-children": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", - "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/unist-util-visit-parents": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", @@ -7355,28 +5565,26 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "node_modules/verkit": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/verkit/-/verkit-0.5.0.tgz", + "integrity": "sha512-u4J1hr6Y+C/hit34GwL3eIcUf3wngT8TlYUjK7tk0jxydKLAq3sYvifjdTDA6U3KCKRcQCQDGf/srjxfZF3l7g==", "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" + "engines": { + "node": ">=18.12.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sxzz" } }, - "node_modules/vfile-location": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", - "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", - "vfile": "^6.0.0" + "vfile-message": "^4.0.0" }, "funding": { "type": "opencollective", @@ -7398,15 +5606,15 @@ } }, "node_modules/vite": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz", - "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.5.tgz", + "integrity": "sha512-z1YpjieJ9g0ebTmQpLBv/oq9E3F9EIlOe+7LahW8SrE3LTiG3udBRUXQOlYXP9b+IC2q2phHeVxj9xGlw34OEQ==", "license": "MIT", "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.5", - "postcss": "^8.5.17", - "rolldown": "~1.1.5", + "lightningcss": "^1.33.0", + "picomatch": "^4.0.7", + "postcss": "^8.5.30", + "rolldown": "~1.2.14", "tinyglobby": "^0.2.17" }, "bin": { @@ -7423,7 +5631,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.3.0", + "@vitejs/devtools": "^0.7.1 || ^0.8.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -7687,13 +5895,13 @@ } }, "node_modules/vscode-jsonrpc": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-9.0.1.tgz", - "integrity": "sha512-rfuA6T75H6m5EkbhtEPzre9pT0HPcDI2MMy4+nPFIBks5J8JBAUHD4tRYSgaBOijIEC7SRkC1kKyXTLqbmh9jw==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-10.0.0.tgz", + "integrity": "sha512-USSfxg0vDIpTQqlQBGxF3mBARyoS8cU7LHLpbYNh6dOJt32dlskxPWB0Irrh5TllTmyf7oNLAvqDqzklbwwnpA==", "dev": true, "license": "MIT", "engines": { - "node": ">=14.0.0" + "node": ">=14.17.0" } }, "node_modules/vscode-languageserver": { @@ -7710,27 +5918,27 @@ } }, "node_modules/vscode-languageserver-protocol": { - "version": "3.18.2", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.18.2.tgz", - "integrity": "sha512-XRyDbT0Pp3sSNti3JmxVEUMySWCSi1hhM+/KUlCy1hV1zmrqpM1OwO12EAki8blhmLuIMpaJrYbo0OzGVfK2Qg==", + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.18.5.tgz", + "integrity": "sha512-FW4fBMzZ99N8xeob4py0l050wgCoRgTpEq5Xcsb9lM1bc29UKGR/wSV+4knaqFxssFHajy7OzNiKP/m3U1ZEuA==", "dev": true, "license": "MIT", "dependencies": { - "vscode-jsonrpc": "9.0.1", - "vscode-languageserver-types": "3.18.0" + "vscode-jsonrpc": "10.0.0", + "vscode-languageserver-types": "3.18.5" } }, "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", - "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.16.tgz", + "integrity": "sha512-qeNEuOi9a3qkqRf7Gfez2WL2VwlBTLCNekHBGO9kxPVUp9XuY15yfTJ9jwvOwKI0I2MhUUfZq95NSp+LK1CLQg==", "dev": true, "license": "MIT" }, "node_modules/vscode-languageserver-types": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.0.tgz", - "integrity": "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g==", + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.5.tgz", + "integrity": "sha512-kPd6+JQNz3HMJvjKlqUxERSlZHAntl/aGpsk7ImwIh0ewDKDcjgAEyVSYciPiOJD3ftbK9IrfiqUeTZLSbCizw==", "dev": true, "license": "MIT" }, @@ -7770,38 +5978,46 @@ "license": "MIT" }, "node_modules/vscode-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", - "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.2.0.tgz", + "integrity": "sha512-m2gXo3bn0G1kT9InzMf07fTbqMbGtyckj3bH5ktLO+1Ssv+yiATZ4dhwaQv9UZWxJh6E9IFGnQyjgWVDWVBDrg==", "dev": true, "license": "MIT" }, - "node_modules/web-namespaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/xxhash-wasm": { @@ -7821,10 +6037,9 @@ } }, "node_modules/yaml": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", - "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", - "devOptional": true, + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", + "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -7884,22 +6099,21 @@ } }, "node_modules/yargs": { - "version": "17.7.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", - "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.2.0.tgz", + "integrity": "sha512-9OpKOLeaoNFecEp7P6iYbzze/5CqWoH7N3SMs/6y1XF4nMvFMspEGZzJ6uFi9MmQwXhyzqYoSEKO3tvA3Z/o2w==", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^8.0.1", + "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", + "string-width": "^8.2.1", "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "yargs-parser": "^22.0.0" }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs-parser": { @@ -7911,16 +6125,6 @@ "node": "^20.19.0 || ^22.12.0 || >=23" } }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/yocto-queue": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", @@ -7934,9 +6138,9 @@ } }, "node_modules/zod": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", - "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", + "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/www/package.json b/www/package.json index 066657d..c374322 100644 --- a/www/package.json +++ b/www/package.json @@ -12,13 +12,13 @@ "check": "astro check" }, "dependencies": { - "@astrojs/starlight": "^0.41.4", - "astro": "^7.1.3", - "sharp": "^0.35.3", - "starlight-sidebar-topics": "0.8.0" + "@astrojs/starlight": "^0.42.7", + "astro": "^7.4.2", + "sharp": "^0.35.5", + "starlight-sidebar-topics": "0.9.0" }, "devDependencies": { - "@astrojs/check": "^0.9.9", + "@astrojs/check": "^0.9.12", "typescript": "^6.0.3" } } diff --git a/www/public/og.png b/www/public/og.png new file mode 100644 index 0000000..579a11e Binary files /dev/null and b/www/public/og.png differ diff --git a/www/public/robots.txt b/www/public/robots.txt new file mode 100644 index 0000000..3fa0764 --- /dev/null +++ b/www/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://exav.org/sitemap-index.xml diff --git a/www/scripts/make-og-image.py b/www/scripts/make-og-image.py new file mode 100644 index 0000000..a359d16 --- /dev/null +++ b/www/scripts/make-og-image.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +"""Draws www/public/og.png, the picture that link previews show for exav.org. + + python3 -I www/scripts/make-og-image.py + +The picture is 1200 x 630 pixels: the site's mark (the teal shield with the +2x2 "exav" monogram of src/assets/logo.svg, drawn again here), the name and the +tagline, on the site's dark background. Everything is drawn from nothing by +this script, with Pillow; no photograph, logo or other asset is read. + +Licence: the picture and this script are dedicated to the public domain under +CC0-1.0 (https://creativecommons.org/publicdomain/zero/1.0/). The text is set +in DejaVu Sans, a free font (Bitstream Vera licence with public domain +additions) whose licence lets its rendered text be used freely. + +The output does not depend on the date or the machine beyond Pillow's +rasteriser, so running the script again on the same version gives the same +file. +""" +import os +import sys + +from PIL import Image, ImageDraw, ImageFont +from PIL.PngImagePlugin import PngInfo + +WIDTH, HEIGHT = 1200, 630 +SCALE = 3 # drawn this many times larger, then reduced, for smooth edges + +BACKGROUND = (0x17, 0x18, 0x1C) # Starlight's dark --sl-color-black +TEAL = (0x0F, 0x9E, 0x8E) # --sl-color-accent in src/styles/custom.css +WHITE = (0xFF, 0xFF, 0xFF) +TEXT = (0xED, 0xEE, 0xF3) # --sl-color-white +MUTED = (0xC1, 0xC3, 0xC8) # --sl-color-gray-2 + +NAME = "exav" +TAGLINE = ["Memory-safe tools", "for untrusted files."] +ADDRESS = "exav.org" + +FONT_DIRS = ["/usr/share/fonts/truetype/dejavu", "/usr/share/fonts/dejavu", "/usr/share/fonts/TTF"] + + +def font(name, size): + for directory in FONT_DIRS: + path = os.path.join(directory, name) + if os.path.exists(path): + return ImageFont.truetype(path, size) + sys.exit(f"{name} not found in {', '.join(FONT_DIRS)}: install DejaVu Sans (fonts-dejavu-core)") + + +def cubic(p0, p1, p2, p3, steps=24): + """Points of a cubic Bezier curve, the start left out.""" + out = [] + for i in range(1, steps + 1): + t = i / steps + u = 1 - t + out.append( + ( + u**3 * p0[0] + 3 * u * u * t * p1[0] + 3 * u * t * t * p2[0] + t**3 * p3[0], + u**3 * p0[1] + 3 * u * u * t * p1[1] + 3 * u * t * t * p2[1] + t**3 * p3[1], + ) + ) + return out + + +def shield(): + """The shield of logo.svg, in its 32 x 32 units: + M16 3.4 26 6.6v12.1c0 4.9-4.1 8.1-10 10-5.9-1.9-10-5.1-10-10V6.6Z""" + points = [(16, 3.4), (26, 6.6), (26, 18.7)] + points += cubic((26, 18.7), (26, 23.6), (21.9, 26.8), (16, 28.7)) + points += cubic((16, 28.7), (10.1, 26.8), (6, 23.6), (6, 18.7)) + points += [(6, 6.6)] + return points + + +def draw_mark(draw, left, top, size): + """The mark with its top left corner at (left, top), `size` pixels wide.""" + k = size / 32 + + def at(x, y): + return (left + x * k, top + y * k) + + draw.rounded_rectangle([left, top, left + size, top + size], radius=8 * k, fill=TEAL) + draw.polygon([at(x, y) for x, y in shield()], fill=WHITE) + letters = font("DejaVuSans-Bold.ttf", round(10 * k)) + for letter, x, y in (("e", 12.6, 15.3), ("x", 19.4, 15.3), ("a", 12.6, 22.9), ("v", 19.4, 22.9)): + draw.text(at(x, y), letter, font=letters, fill=TEAL, anchor="ms") + + +def main(): + image = Image.new("RGB", (WIDTH * SCALE, HEIGHT * SCALE), BACKGROUND) + draw = ImageDraw.Draw(image) + + mark = 330 + draw_mark(draw, 120 * SCALE, (HEIGHT - mark) // 2 * SCALE, mark * SCALE) + + left = 520 * SCALE + draw.text((left, 292 * SCALE), NAME, font=font("DejaVuSans-Bold.ttf", 170 * SCALE), fill=TEXT, anchor="ls") + tagline = font("DejaVuSans.ttf", 46 * SCALE) + for i, line in enumerate(TAGLINE): + draw.text((left, (362 + i * 62) * SCALE), line, font=tagline, fill=MUTED, anchor="ls") + draw.text((left, 520 * SCALE), ADDRESS, font=font("DejaVuSansMono-Bold.ttf", 34 * SCALE), fill=TEAL, anchor="ls") + + image = image.resize((WIDTH, HEIGHT), Image.LANCZOS) + + info = PngInfo() + info.add_text("Title", "exav: Memory-safe tools for untrusted files.") + info.add_text("Copyright", "CC0-1.0: https://creativecommons.org/publicdomain/zero/1.0/") + out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "public", "og.png") + image.save(out, optimize=True, pnginfo=info) + print(f"wrote {os.path.normpath(out)}") + + +if __name__ == "__main__": + main() diff --git a/www/src/content/docs/index.mdx b/www/src/content/docs/index.mdx index 62edcfa..0e315a9 100644 --- a/www/src/content/docs/index.mdx +++ b/www/src/content/docs/index.mdx @@ -2,6 +2,9 @@ title: exav description: Memory-safe tools for untrusted files, written in Rust. A malware scanner compatible with ClamAV's signatures and protocols, an archive extractor, and a file viewer for the browser. template: splash +head: + - tag: title + content: "exav: Memory-safe tools for untrusted files" hero: tagline: Memory-safe tools for untrusted files. Scan them for malware, unpack them, and view them in the browser. image: @@ -49,9 +52,9 @@ Each tool is usable on its own. [Start here](/unpack/) - `@exav/viewer` shows PDF, images, DWG and DXF, Office documents, IFC and - STL models, media and archives in the browser, and can open each file in - a sandboxed frame of its own. + `@exav/viewer` shows PDF, images, DWG and DXF, Office documents (the old + formats too), IFC, STL, OBJ, PLY and glTF models, media and archives in + the browser, and can open each file in a sandboxed frame of its own. ```sh npm install @exav/viewer diff --git a/www/src/content/docs/project/architecture.md b/www/src/content/docs/project/architecture.md index adbe776..b91d897 100644 --- a/www/src/content/docs/project/architecture.md +++ b/www/src/content/docs/project/architecture.md @@ -13,14 +13,30 @@ does in [How extraction works](/unpack/how-it-works/). The CLI (which is also the daemon) drives the scanning engine, `exav-core`, which also builds its own WASI binary, `exav-wasm` (feature `wasi-bin`). Two -front ends use only the extractor, `exav-unpack`: the archive grep and +front ends use the extractor, `exav-unpack`: the archive grep and `@exav/unpack-wasm`. `@exav/viewer`'s wasm modules use only `exav-render`. `exav-core` hashes images through `exav-imagehash` (the `image-hash` feature), which decodes them with `exav-render`. exav-render reads DWG and DXF -with exav-unpack's drawing parsers (its `dwg` feature); the scanner draws -nothing. `exav-update`, behind the `http-update` feature (part of `http`), -sits to the side, feeding fresh signatures out of band. +with exav-unpack's drawing parsers (its `dwg` feature), and its text layer +reads HTML and the XML parts of documents with exav-unpack's (its `text` +feature). That layer, the text a reader sees in a document, is also what the +scanner (`exav-core`'s `visible-text` feature) and the archive grep (its +`text` feature) read documents through; the scanner draws nothing. +`exav-update`, behind the `http-update` feature (part of `http`), sits to the +side, feeding fresh signatures out of band. + +`exav-render` is one crate, with the office converters in it as modules: +spreadsheets (`sheets`) to XLSX, presentations and drawings (`slides`) to +PPTX and text documents (`docs`) to DOCX, each behind a feature +(`office-sheets`, `office-slides`, `office-docs`, or `office` for the three), +and a `common` module they share (ZIP packages, ODF's XML, code pages, +compound files, iWork archives) that is not public. None is in the default +feature set. Under the office features the crate adds `zip`, `quick-xml`, +`encoding_rs`, `md-5` and `sha1` to its dependencies (`flate2`, which they use +too, is already there for the image decoders). The scanner links all of them +already, through exav-unpack, so `visible-text-office` adds code but no crate. +The viewer builds `sheets`, `slides` and `docs` into one wasm module each. Every arrow points down: nothing calls anything above it, which is what lets the extraction, decoding and hashing crates be taken on their own. Dashed @@ -34,11 +50,14 @@ labelled with. half of @exav/viewer), exav-grep and exav-unpack-wasm. exav depends on exav-core, and on exav-update behind the http-update feature. exav-core also builds exav-wasm, its wasm32-wasip1 binary. exav-core depends on - exav-imagehash behind the image-hash feature, on exav-unpack, and on exav-x86 - for the bytecode disassembly API. exav-imagehash and exav-viewer depend on - exav-render, which depends on exav-unpack behind its dwg feature. exav-grep - and exav-unpack-wasm depend on exav-unpack, which depends on exav-pe-emu - behind its pe-emu feature, which depends on exav-x86. + exav-imagehash behind the image-hash feature, on exav-render behind the + visible-text feature, on exav-unpack, and on exav-x86 for the bytecode + disassembly API. exav-imagehash and exav-viewer depend on exav-render, and + exav-grep does behind its text feature. exav-render, which holds the image + decoders, the DWG, DXF, IFC, STL, OBJ, PLY and glTF readers, the office converters and the + text layer, depends on exav-unpack behind its dwg and text features. + exav-grep and exav-unpack-wasm depend on exav-unpack, which depends on + exav-pe-emu behind its pe-emu feature, which depends on exav-x86. @@ -52,8 +71,8 @@ labelled with. - - + + @@ -65,7 +84,7 @@ labelled with. exav-unpack-wasm exav-update exav-core - exav-imagehash + exav-imagehash exav-render exav-unpack exav-pe-emu @@ -84,9 +103,10 @@ labelled with. typing · patterns · hashes YARA · .cbc VM + exav-wasm (WASI binary) - image hashes - image decoders - DWG · DXF · IFC · STL + image hashes + image decoders · DWG · DXF + IFC · STL · OBJ · PLY · glTF + office converters · text layer archives · disk images · documents packed executables packer stub emulator @@ -94,25 +114,29 @@ labelled with. http-update - image-hash - dwg + image-hash + visible-text + text + dwg · text pe-emu bytecode disasm - + - + - - + + + + diff --git a/www/src/content/docs/project/contributing.md b/www/src/content/docs/project/contributing.md index cd364a9..3143082 100644 --- a/www/src/content/docs/project/contributing.md +++ b/www/src/content/docs/project/contributing.md @@ -10,7 +10,7 @@ targets. For a vulnerability, do not open a public issue: see [Security](/project/security/#reporting-a-vulnerability). Contributors follow the [code of conduct](https://github.com/sylvinus/exav/blob/main/CODE_OF_CONDUCT.md). -To start, install Rust 1.92 or newer and a C compiler (the `http` build links +To start, install Rust 1.95 or newer and a C compiler (the `http` build links `ring`), clone the repository and run `make test-native`. The rest of `make test` also needs `wasmtime`, Node.js and `wasm-pack` ([below](#before-submitting)). @@ -99,9 +99,10 @@ make lint # CI's clippy passes (-D warnings) and cargo fmt --check | target | what it covers | needs | | --- | --- | --- | -| `make test-native` | the workspace under every feature pass: default, `http`, `exav-unpack` with `checksums`, `--no-default-features`, `unstable-internals`, `testing-faults` | a C compiler | +| `make test-native` | the workspace under every feature pass: default, `http`, `exav-unpack` with `checksums`, `--no-default-features`, `unstable-internals`, `testing-faults`, and exav-render's `office-*`, `markdown`, `text-pdf` and `text-office` passes | a C compiler | | `make test-wasm` | the extractor and core unit tests on 32-bit `wasm32-wasip1` | `wasmtime` | | `make test-js` | the WASM bindings' vitest units and Playwright browser tests | Node.js, `wasm-pack`, python3; downloads Chromium | +| `make test-viewer` | `@exav/viewer`: its wasm modules rebuilt from the current source, vitest units, the package as `npm publish` would upload it, the sink and wasm-import gates, and the demo driven in headless browsers under its Content-Security-Policy | Node.js, `wasm-bindgen-cli` at the version the viewer pins; downloads browsers | | `make test-www` | `astro check`, a docs build (frontmatter, sidebar entries, rendering) and a check that every internal link and anchor resolves | Node.js | Not in `make test`: @@ -123,7 +124,7 @@ reports green having checked nothing. Run `make test` before you push. CI runs, on every pull request and push to `main`: the `make lint` checks, `make test-native`, the MSRV check (`make msrv`), `make test-yara-diff`, the WASM -builds with `make test-wasm` and `make test-js`, `make test-www`, `cargo audit`, +builds with `make test-wasm` and `make test-js`, `make test-viewer`, `make test-www`, `cargo audit`, `cargo deny check`, and a `cargo-fuzz` smoke run of every target. Add a line to the `[Unreleased]` section of `CHANGELOG.md` for any change a user diff --git a/www/src/content/docs/project/dependencies.md b/www/src/content/docs/project/dependencies.md index c01ade6..c6e4f16 100644 --- a/www/src/content/docs/project/dependencies.md +++ b/www/src/content/docs/project/dependencies.md @@ -28,8 +28,8 @@ dependency policy behind these choices is in the repository's the parsers a hostile client reaches first are exav's own. - **`unsafe` in dependencies.** Many dependencies use `unsafe` internally: SIMD byte search and hashing, OS syscalls (the daemon), and buffer handling in some - decoders that read scanned bytes (`lzfse_rust`, `ruzstd`, `zip`, `tar`, - `delharc`, `goblin`). exav's own crates contain none outside the daemon's + decoders that read scanned bytes (`ruzstd`, `zip`, `tar`, `delharc`, + `goblin`). exav's own crates contain none outside the daemon's `libc` calls. The tables give a count per crate, and reducing it is on the [roadmap](/project/roadmap/). - **Feature-gated capability.** Optional features (`http-scan`, `http-update`, @@ -71,8 +71,8 @@ code, not a dependency. | [`regex`](https://crates.io/crates/regex) | Linear-time regex (PCRE subsignatures, phishing allowlists) | MIT OR Apache-2.0 | 1 | | [`regex-automata`](https://crates.io/crates/regex-automata) / [`regex-syntax`](https://crates.io/crates/regex-syntax) | Linear-time (DoS-safe) regex engine + parser (YARA regexes, the atom prefilter's required literals) | MIT OR Apache-2.0 | 55 / **none** (`forbid`) | | [`bit-set`](https://crates.io/crates/bit-set) | For the backtracking regex engine vendored in exav-core (below) | Apache-2.0 OR MIT | 2 | -| [`goblin`](https://crates.io/crates/goblin) | PE / ELF / Mach-O executable parsing | MIT | 34 | -| [`md-5`](https://crates.io/crates/md-5) / [`sha1`](https://crates.io/crates/sha1) / [`sha2`](https://crates.io/crates/sha2) | Hash signatures (whole-file / section digests), and key derivation in `decrypt` | MIT OR Apache-2.0 | 1 / 7 / 50 (CPU-feature detection, SIMD) | +| [`goblin`](https://crates.io/crates/goblin) | PE / ELF executable parsing, built without its Mach-O, `ar` and TE parsers | MIT | 34 | +| [`md-5`](https://crates.io/crates/md-5) / [`sha1`](https://crates.io/crates/sha1) / [`sha2`](https://crates.io/crates/sha2) | Hash signatures (whole-file / section digests), key derivation in `decrypt`, and, for `md-5` and `sha1`, the opening of an XLS encrypted with Excel's default password in exav-render's `office-sheets` and `office-slides` features | MIT OR Apache-2.0 | 1 / 7 / 50 (CPU-feature detection, SIMD) | | [`crc32fast`](https://crates.io/crates/crc32fast) | CRC-32 (the `.exavdb` trailer, YARA's `hash` module, archive CRCs) | MIT OR Apache-2.0 | 15 (SIMD) | | [`base64`](https://crates.io/crates/base64) | Base64 decode (YARA `base64` modifiers; uuencode, email, XDP and embedded payloads in `exav-unpack`) | MIT OR Apache-2.0 | **none** (`forbid`) | | [`yara-x-parser`](https://crates.io/crates/yara-x-parser) | YARA grammar/AST parser (the native engine's front end) | BSD-3-Clause | 5 | @@ -80,7 +80,11 @@ code, not a dependency. | [`zune-jpeg`](https://crates.io/crates/zune-jpeg) / [`zune-core`](https://crates.io/crates/zune-core) | JPEG decoding for fuzzy image hashing (0.5.8, and 0.4.21 for JPEG-compressed TIFF), built without its SIMD features, which hold all of its `unsafe` | MIT OR Apache-2.0 OR Zlib | **none** (`forbid`) / **none** (two versions of each resolve) | | [`png`](https://crates.io/crates/png) / [`gif`](https://crates.io/crates/gif) | `image`'s PNG and GIF decoders, required at the versions libclamav links (as are the JPEG and TIFF ones), which `cargo install` would not otherwise hold | MIT OR Apache-2.0 | **none** (`forbid`) / **none** (`forbid`) | | [`hayro-jpeg2000`](https://crates.io/crates/hayro-jpeg2000) / [`hayro-jbig2`](https://crates.io/crates/hayro-jbig2) | JPEG 2000 and JBIG2 decoding for fuzzy image hashing, in [exav-render](/subprojects/exav-render/), built without their `simd` feature (fearless_simd); `hayro-ccitt`, below, is hayro-jbig2's | Apache-2.0 OR MIT | **none** (`forbid`) / **none** (`forbid`) | -| [`fax`](https://crates.io/crates/fax) / [`weezl`](https://crates.io/crates/weezl) / [`half`](https://crates.io/crates/half) / [`quick-error`](https://crates.io/crates/quick-error) / [`bytemuck`](https://crates.io/crates/bytemuck) | The vendored TIFF decoder's: CCITT fax, LZW, 16-bit floats, error types, byte casts | MIT / MIT OR Apache-2.0 / MIT OR Apache-2.0 / MIT OR Apache-2.0 / Zlib OR Apache-2.0 OR MIT | **none** / **none** (`forbid`) / 84 / **none** / 323 | +| [`zenjxl-decoder`](https://crates.io/crates/zenjxl-decoder) with `zenjxl-decoder-simd` and `zenjxl-decoder-macros` | JPEG XL decoding in `@exav/viewer`'s image module (exav-render's `jxl` feature, not a default): a fork of the libjxl team's jxl-rs with limits on pixels and memory, built without its SIMD and without `threads`; the viewer only | BSD-3-Clause | **none** (`forbid`; its `allow-unsafe` feature is off) / **none** (`forbid`) / **none** (`forbid`) | +| [`fax`](https://crates.io/crates/fax) / [`weezl`](https://crates.io/crates/weezl) / [`quick-error`](https://crates.io/crates/quick-error) / [`bytemuck`](https://crates.io/crates/bytemuck) | The vendored TIFF decoder's: CCITT fax, LZW, error types, byte casts | MIT / MIT OR Apache-2.0 / MIT OR Apache-2.0 / Zlib OR Apache-2.0 OR MIT | **none** / **none** (`forbid`) / **none** / 323 | +| [`pulldown-cmark`](https://crates.io/crates/pulldown-cmark) | Markdown (CommonMark, tables, strikethrough) read as events, into a tree of data in `@exav/viewer`'s text module and into the text a reader sees for the scanner's `visible-text` feature (on by default) and `exav-grep --text` (exav-render's `markdown` feature); without its `html` and `simd` features, so no markup is made and the crate is `forbid(unsafe_code)`. It was measured linear on 35 hostile 1 MB inputs (worst 8 ms) and without advisories | MIT | **none** (`forbid`; the 4 uses are its SIMD feature, off) | +| [`html5gum`](https://crates.io/crates/html5gum) | HTML visible text (`visible-text`, on by default; `exav-grep --text`): a spec-compliant tokenizer alone (it passes the html5lib tokenizer tests), pulled token by token, keeping the words and where each link leads. No tree is built. Without its default `jetscii` feature it has no dependency | MIT | **none** (`forbid`) | +| [`hayro-interpret`](https://crates.io/crates/hayro-interpret) / [`hayro-syntax`](https://crates.io/crates/hayro-syntax) | PDF visible text (`visible-text-pdf` / `text-pdf`, **not a default**): hayro interprets each page and hands over its glyphs with their Unicode (`ToUnicode`, else glyph names). It is by the author of the JPEG 2000 and JBIG2 decoders exav-render already uses, and shares them. hayro puts no bound on what a stream decompresses to (a 1 MB PDF took 2.1 GB), so exav reads a PDF with it only after its own reader has taken every stream within the budget; a panic in it is contained. Built without the predefined CJK CMaps (`embed-cmaps`, which brings `brotli`). **Why it is off by default:** `hayro-interpret` turns on `hayro-syntax`'s `unsafe` feature itself, which switches every `flate2` in the build to `zlib-rs` (damaged streams then give back other bytes: two of exav-unpack's tests fail with it) and adds SIMD to the image decoders | Apache-2.0 OR MIT | **none** (`forbid`) / 11 (a lifetime `transmute`; with its `unsafe` feature, which is on, `flate2` and SIMD) | | [`tlsh2`](https://crates.io/crates/tlsh2) | TLSH fuzzy hashing | Apache-2.0 OR BSD-3-Clause | **none** | | [`rmp-serde`](https://crates.io/crates/rmp-serde) / [`rmp`](https://crates.io/crates/rmp) / [`serde`](https://crates.io/crates/serde) | MessagePack encoding of the prebuilt `.exavdb` | MIT / MIT / MIT OR Apache-2.0 | **none** (`forbid`) / 1 / 2 | | [`rustc-hash`](https://crates.io/crates/rustc-hash) | Fast hashing for internal maps (also in `exav-pe-emu`) | Apache-2.0 OR MIT | **none** | @@ -97,7 +101,8 @@ Some of exav is vendored source instead of dependencies, under its crates' - [exav-render](/subprojects/exav-render/)'s `src/image_codecs/`, which exav-imagehash decodes through: `image` 0.25.9's JPEG and TIFF decoders and the decoder of `tiff` 0.10.3 (MIT), so that zune-jpeg is built without its - SIMD code, which `image` and `tiff` cannot turn off. + SIMD code, which `image` and `tiff` cannot turn off. It holds 16-bit float + samples as their bits, which keeps `half` and `zerocopy` out. - exav-imagehash's `src/pillow.rs`: Pillow 12.3.0's resampler and grey conversions (MIT-CMU), ported for its imagehash preset. - exav-imagehash's `src/dct.rs`: rustdct 0.7.1's DCT-II for power-of-two @@ -109,13 +114,36 @@ Some of exav is vendored source instead of dependencies, under its crates' [`exav-x86`](/subprojects/exav-x86/) only, the oracle its differential tests, table generator and fuzz target check against. +### The office converters (`exav-render`) + +[exav-render](/subprojects/exav-render/#office-documents)'s `office-sheets`, +`office-slides` and `office-docs` features (`office` for the three; none is a +default) read ZIP packages and compound files and write XLSX, PPTX and DOCX. +They add five crates to its dependencies, all in the tables on this page: +`zip` (without default features, deflate through `flate2`), `quick-xml`, +`encoding_rs`, and `md-5` and `sha1` (for an XLS encrypted with Excel's +default password). `flate2` is already there for the image decoders, and the +compound file reader, the iWork (protobuf and Snappy) readers and the OfficeArt +reader are exav-render's own code. + +Counted as above, `cargo tree -p exav-render -e no-dev --prefix none | sort -u +| wc -l` gives 37 packages by default and 59 with `--features office` on +Linux (56 for `wasm32-unknown-unknown`), the crate itself included. The scanner +links every one of them already, through exav-unpack, so its +`visible-text-office` feature adds code and no crate. + ## Extraction & decompression (`exav-unpack`) Also `#![forbid(unsafe_code)]`. The decoders are pure-Rust; there is no C compression library in the tree. Most of these read scanned bytes. The bzip2 decoder is not a dependency: it is vendored from `bzip2-rs` into `formats/bzip2_rs`, with a fix for incompressible blocks, and is as -`unsafe`-free as the rest of the crate. +`unsafe`-free as the rest of the crate. Nor is the InstallShield `.z` reader: +its table of contents is read as the `unshield` crate reads it, and its PKWARE +DCL members are decoded in `formats/dcl_explode.rs`, ported from the +`explode` crate and Mark Adler's `blast.c`. The LZFSE and LZVN decoder of +DMG runs is `formats/lzfse.rs`, ported from Apple's reference implementation +(BSD-3-Clause) and checked against it, damaged streams included. | Crate | Purpose | License | `unsafe` uses | |---|---|---|---| @@ -123,23 +151,21 @@ decoder is not a dependency: it is vendored from `bzip2-rs` into | [`deflate64`](https://crates.io/crates/deflate64) | Deflate64 (ZIP method 9) | MIT | **none** (`forbid`) | | [`xz4rust`](https://crates.io/crates/xz4rust) | XZ (`.xz`, ZIP method 95, DMG) | MIT | 3 | | [`lzma-rust2`](https://crates.io/crates/lzma-rust2) | LZMA / LZMA2 (7z, lzip, ZIP method 14, SWF, NSIS, UPX, EGG) | Apache-2.0 | 14 | -| [`ruzstd`](https://crates.io/crates/ruzstd) | Zstandard (pure Rust) | MIT | 39 | +| [`ruzstd`](https://crates.io/crates/ruzstd) | Zstandard (pure Rust), without its `hash` feature: exav does not check the content checksum | MIT | 39 | | [`lzxd`](https://crates.io/crates/lzxd) | LZX (CAB) | MIT OR Apache-2.0 | **none** | -| [`lzfse_rust`](https://crates.io/crates/lzfse_rust) | LZFSE / LZVN (DMG) | MIT OR Apache-2.0 | 435 | | [`delharc`](https://crates.io/crates/delharc) | LHA / LZH | MIT OR Apache-2.0 | 19 | | [`bitstream-io`](https://crates.io/crates/bitstream-io) | Bit-level readers for decoders | MIT OR Apache-2.0 | **none** (`forbid`) | | [`tar`](https://crates.io/crates/tar) | tar archives (`xattr` disabled, which drops its syscall crates) | MIT OR Apache-2.0 | 26 | -| [`zip`](https://crates.io/crates/zip) | ZIP container parsing | MIT | 32 | +| [`zip`](https://crates.io/crates/zip) | ZIP container parsing; also the packages the office converters of [exav-render](/subprojects/exav-render/#office-documents) read and write (built without default features, deflate through `flate2`) | MIT | 25 | | [`cfb`](https://crates.io/crates/cfb) | OLE2 / Compound File Binary (Office) | MIT | **none** | -| [`encoding_rs`](https://crates.io/crates/encoding_rs) | the code pages of DXF and DWG drawings before 2007, Asian double-byte ones included (features `dxf`, `dwg`), built without `simd-accel` | (Apache-2.0 OR MIT) AND BSD-3-Clause | 193 | -| [`quick-xml`](https://crates.io/crates/quick-xml) | OOXML / XML parsing | MIT | **none** (`forbid`) | +| [`encoding_rs`](https://crates.io/crates/encoding_rs) | the code pages of DXF and DWG drawings before 2007, Asian double-byte ones included (features `dxf`, `dwg`), and of the text of the legacy office formats (exav-render's `office-*` features), built without `simd-accel` | (Apache-2.0 OR MIT) AND BSD-3-Clause | 180 | +| [`quick-xml`](https://crates.io/crates/quick-xml) | OOXML / XML parsing; also the OpenDocument, Visio and Word 2003 XML the office converters read and the XML they write | MIT | **none** (`forbid`) | | [`mail-parser`](https://crates.io/crates/mail-parser) | MIME / email parsing | Apache-2.0 OR MIT | **none** (`forbid`) | | [`apfs`](https://crates.io/crates/apfs) / [`hfsplus`](https://crates.io/crates/hfsplus) | DMG filesystem parsing | MIT | **none** | | [`ext4-view`](https://crates.io/crates/ext4-view) | ext2/3/4 filesystem walking (virtual disks) | MIT OR Apache-2.0 | **none** (`forbid`) | | [`fatfs`](https://crates.io/crates/fatfs) | FAT12/16/32 cluster-chain walking | MIT | 11 | | [`lznt1`](https://crates.io/crates/lznt1) | LZNT1 (NTFS compressed streams) | MIT | **none** (`forbid`) | | [`salzweg`](https://crates.io/crates/salzweg) | LZW (ZOO, Unix `compress`) | MIT | **none** | -| [`unshield`](https://crates.io/crates/unshield) | InstallShield `.z` archives | MIT | **none** | | [`tinyvec`](https://crates.io/crates/tinyvec) | Inline vectors for the vendored bzip2 decoder | Zlib OR Apache-2.0 OR MIT | **none** (`forbid`) | | [`byteorder`](https://crates.io/crates/byteorder) | Byte-order reads | Unlicense OR MIT | 40 | @@ -196,8 +222,7 @@ The `unsafe` column counts occurrences of the `unsafe` keyword in each crate's shipped `src/` (comments stripped; tests, benches and examples excluded) at the version resolved when the table was written. Read it as surface to review, not as risk. Most of it is in `hashbrown` and `bytemuck`, neither of which parses -scanned bytes, and in `zerocopy` (with its derive macro), which `half` pulls -in, and `moxcms`, which `image` does. There are +scanned bytes, and in `moxcms`, which `image` pulls in. There are no raw-syscall binding crates: `rustix` and `linux-raw-sys` are kept out by [writing the spill file in-tree](#cli--runtime-exav) and by building `tar` without `xattr`. Reproduce the counts with `cargo geiger`, or per crate with: @@ -215,17 +240,19 @@ find ~/.cargo/registry/src/*/-/src -name '*.rs' -print0 \ | [`anstyle`](https://crates.io/crates/anstyle) | MIT OR Apache-2.0 | 1 | `clap` | | [`anstyle-parse`](https://crates.io/crates/anstyle-parse) | MIT OR Apache-2.0 | 3 | `clap` | | [`anstyle-query`](https://crates.io/crates/anstyle-query) | MIT OR Apache-2.0 | 1 | `clap` | -| [`arraydeque`](https://crates.io/crates/arraydeque) | MIT/Apache-2.0 | 77 | `unshield` | +| [`aligned-vec`](https://crates.io/crates/aligned-vec) | MIT | 56 (the aligned allocation of the decoder's buffers) | `zenjxl-decoder` | +| [`array-init`](https://crates.io/crates/array-init) | MIT OR Apache-2.0 | 4 | `zenjxl-decoder` | | [`ascii_tree`](https://crates.io/crates/ascii_tree) | MIT | **none** | `yara-x-parser` | +| [`atomic_refcell`](https://crates.io/crates/atomic_refcell) | Apache-2.0 OR MIT | 14 | `zenjxl-decoder` | | [`beef`](https://crates.io/crates/beef) | MIT OR Apache-2.0 | 26 | `yara-x-parser` | | [`bit-vec`](https://crates.io/crates/bit-vec) | Apache-2.0 OR MIT | 4 | `bit-set` | | [`autocfg`](https://crates.io/crates/autocfg) | Apache-2.0 OR MIT | **none** | build-time: `num-traits` and its users | -| [`bitflags`](https://crates.io/crates/bitflags) | MIT OR Apache-2.0 | 21 (two versions resolve: 19 + 2) | `delharc`, `ext4-view`, `fatfs`, `image`, `png`, `yara-x-parser` | +| [`bitflags`](https://crates.io/crates/bitflags) | MIT OR Apache-2.0 | 21 (two versions resolve: 19 + 2) | `delharc`, `ext4-view`, `fatfs`, `image`, `png`, `pulldown-cmark`, `yara-x-parser` | | [`block-buffer`](https://crates.io/crates/block-buffer) | MIT OR Apache-2.0 | 21 | `digest`, `hmac`, `md-5`, `pbkdf2`, `sha1`, `sha2` | | [`block-padding`](https://crates.io/crates/block-padding) | MIT OR Apache-2.0 | **none** | `aes`, `cbc`, `des` | | [`bstr`](https://crates.io/crates/bstr) | MIT OR Apache-2.0 | 39 | `yara-x-parser` | | [`byteorder-lite`](https://crates.io/crates/byteorder-lite) | Unlicense OR MIT | 1 | `image` | -| [`cfg-if`](https://crates.io/crates/cfg-if) | MIT OR Apache-2.0 | **none** | `crc32fast`, `flate2`, `half`, `image`, `md-5`, `png`, `sha1`, `sha2`, `tar`, `zip` | +| [`cfg-if`](https://crates.io/crates/cfg-if) | MIT OR Apache-2.0 | **none** | `crc32fast`, `flate2`, `image`, `md-5`, `png`, `sha1`, `sha2`, `tar`, `zip` | | [`chrono`](https://crates.io/crates/chrono) | MIT OR Apache-2.0 | 11 | `delharc` | | [`cipher`](https://crates.io/crates/cipher) | MIT OR Apache-2.0 | **none** (`forbid`) | `aes`, `cbc`, `des` | | [`clap_builder`](https://crates.io/crates/clap_builder) | MIT OR Apache-2.0 | **none** (`forbid`) | `clap` | @@ -235,6 +262,7 @@ find ~/.cargo/registry/src/*/-/src -name '*.rs' -print0 \ | [`color_quant`](https://crates.io/crates/color_quant) | MIT | **none** | `gif`, `image` | | [`colorchoice`](https://crates.io/crates/colorchoice) | MIT OR Apache-2.0 | **none** | `clap` | | [`const-oid`](https://crates.io/crates/const-oid) | Apache-2.0 OR MIT | 1 | `digest`, `hmac`, `md-5`, `pbkdf2`, `sha1`, `sha2` | +| [`core_detect`](https://crates.io/crates/core_detect) | MIT/Apache-2.0 | 7 | `encoding_rs`, on x86 and x86-64 | | [`countme`](https://crates.io/crates/countme) | MIT OR Apache-2.0 | 1 | `yara-x-parser` | | [`cpubits`](https://crates.io/crates/cpubits) | MIT OR Apache-2.0 | **none** | `aes` | | [`cpufeatures`](https://crates.io/crates/cpufeatures) | MIT OR Apache-2.0 | 11 | `aes`, `sha1`, `sha2` | @@ -243,8 +271,8 @@ find ~/.cargo/registry/src/*/-/src -name '*.rs' -print0 \ | [`crypto-common`](https://crates.io/crates/crypto-common) | MIT OR Apache-2.0 | **none** (`forbid`) | `aes`, `cbc`, `des`, `digest`, `hmac`, `md-5`, `pbkdf2`, `sha1`, `sha2` | | [`ctutils`](https://crates.io/crates/ctutils) | Apache-2.0 OR MIT | **none** (`forbid`) | `digest`, `hmac`, `md-5`, `pbkdf2`, `sha1`, `sha2` | | [`either`](https://crates.io/crates/either) | MIT OR Apache-2.0 | 2 | `yara-x-parser` | +| [`enough`](https://crates.io/crates/enough) | MIT OR Apache-2.0 | **none** (`forbid`) | `zenjxl-decoder` | | [`equivalent`](https://crates.io/crates/equivalent) | Apache-2.0 OR MIT | **none** | `mail-parser`, `yara-x-parser`, `zip` | -| [`explode`](https://crates.io/crates/explode) | MIT | 5 | `unshield` | | [`fax_derive`](https://crates.io/crates/fax_derive) | MIT | **none** | `fax` | | [`fdeflate`](https://crates.io/crates/fdeflate) | MIT OR Apache-2.0 | **none** (`forbid`) | `image`, `png` | | [`filetime`](https://crates.io/crates/filetime) | MIT/Apache-2.0 | 9 | `tar` | @@ -268,40 +296,51 @@ find ~/.cargo/registry/src/*/-/src -name '*.rs' -print0 \ | [`logos-derive`](https://crates.io/crates/logos-derive) | MIT OR Apache-2.0 | **none** | `yara-x-parser` | | [`miniz_oxide`](https://crates.io/crates/miniz_oxide) | MIT OR Zlib OR Apache-2.0 | **none** (`forbid`; two versions resolve) | `flate2`, `image`, `png`, `zip` | | [`moxcms`](https://crates.io/crates/moxcms) | BSD-3-Clause OR Apache-2.0 | 344 | `image` | +| [`multiversion_no_op`](https://crates.io/crates/multiversion_no_op) | Apache-2.0 OR MIT | **none** | `encoding_rs` | | [`no_std_io2`](https://crates.io/crates/no_std_io2) | Apache-2.0 OR MIT | 11 | `bitstream-io`, `zip` | +| [`num-derive`](https://crates.io/crates/num-derive) / [`paste`](https://crates.io/crates/paste) | MIT OR Apache-2.0 | **none** / **none** | `zenjxl-decoder` | | [`num-traits`](https://crates.io/crates/num-traits) | MIT OR Apache-2.0 | 1 | `delharc`, `image`, `rmp`, `rmp-serde`, `yara-x-parser` | | [`plain`](https://crates.io/crates/plain) | MIT/Apache-2.0 | 23 | `goblin` | -| [`proc-macro2`](https://crates.io/crates/proc-macro2) | MIT OR Apache-2.0 | 6 | `apfs`, `clap`, `fax`, `goblin`, `half`, `hfsplus`, `lznt1`, `mail-parser`, `rmp-serde`, `serde`, `thiserror`, `yara-x-parser` | +| [`proc-macro2`](https://crates.io/crates/proc-macro2) | MIT OR Apache-2.0 | 6 | `apfs`, `clap`, `fax`, `goblin`, `hfsplus`, `lznt1`, `mail-parser`, `rmp-serde`, `serde`, `thiserror`, `yara-x-parser` | | [`pxfm`](https://crates.io/crates/pxfm) | BSD-3-Clause OR Apache-2.0 | 224 | `image` | | [`qoi`](https://crates.io/crates/qoi) | MIT/Apache-2.0 | **none** (`forbid`) | `image` | -| [`quote`](https://crates.io/crates/quote) | MIT OR Apache-2.0 | **none** | `apfs`, `clap`, `fax`, `goblin`, `half`, `hfsplus`, `lznt1`, `mail-parser`, `rmp-serde`, `serde`, `thiserror`, `yara-x-parser` | +| [`quote`](https://crates.io/crates/quote) | MIT OR Apache-2.0 | **none** | `apfs`, `clap`, `fax`, `goblin`, `hfsplus`, `lznt1`, `mail-parser`, `rmp-serde`, `serde`, `thiserror`, `yara-x-parser` | | [`rowan`](https://crates.io/crates/rowan) | MIT OR Apache-2.0 | 55 | `yara-x-parser` | | [`rustc-hash`](https://crates.io/crates/rustc-hash) | Apache-2.0 OR MIT | **none** | a second version (1.x) for `yara-x-parser` | | [`rustc_version`](https://crates.io/crates/rustc_version) | MIT OR Apache-2.0 | **none** | build-time: `yara-x-parser` | +| [`rustversion`](https://crates.io/crates/rustversion) | MIT OR Apache-2.0 | 1 | build-time: `encoding_rs` | | [`same-file`](https://crates.io/crates/same-file) | Unlicense/MIT | 3 | `walkdir` | +| [`scopeguard`](https://crates.io/crates/scopeguard) | MIT OR Apache-2.0 | 3 | `encoding_rs` | | [`scroll`](https://crates.io/crates/scroll) | MIT | 7 | `goblin` | | [`scroll_derive`](https://crates.io/crates/scroll_derive) | MIT | 1 | `goblin` | | [`semver`](https://crates.io/crates/semver) | MIT OR Apache-2.0 | 47 | build-time: `yara-x-parser` | | [`serde_core`](https://crates.io/crates/serde_core) | MIT OR Apache-2.0 | 2 | `rmp-serde`, `serde`, `serde_json` | | [`serde_derive`](https://crates.io/crates/serde_derive) | MIT OR Apache-2.0 | **none** | `rmp-serde`, `serde` | | [`simd-adler32`](https://crates.io/crates/simd-adler32) | MIT | 36 | `flate2`, `image`, `png`, `zip` | +| [`simdutf8`](https://crates.io/crates/simdutf8) | MIT OR Apache-2.0 | 135 (SIMD UTF-8 validation, on x86, x86-64, aarch64 and wasm32 with `simd128`) | `encoding_rs` | | [`strsim`](https://crates.io/crates/strsim) | MIT | **none** (`forbid`) | `clap` | -| [`syn`](https://crates.io/crates/syn) | MIT OR Apache-2.0 | 152 (two versions resolve: 71 + 81) | `apfs`, `clap`, `fax`, `goblin`, `half`, `hfsplus`, `lznt1`, `mail-parser`, `rmp-serde`, `serde`, `thiserror`, `yara-x-parser` | +| [`syn`](https://crates.io/crates/syn) | MIT OR Apache-2.0 | 152 (two versions resolve: 71 + 81) | `apfs`, `clap`, `fax`, `goblin`, `hfsplus`, `lznt1`, `mail-parser`, `rmp-serde`, `serde`, `thiserror`, `yara-x-parser` | | [`text-size`](https://crates.io/crates/text-size) | MIT OR Apache-2.0 | **none** (`forbid`) | `yara-x-parser` | | [`thiserror-impl`](https://crates.io/crates/thiserror-impl) | MIT OR Apache-2.0 | 1 | `apfs`, `hfsplus`, `lznt1`, `thiserror` | -| [`twox-hash`](https://crates.io/crates/twox-hash) | MIT | 72 | `ruzstd` | | [`typed-path`](https://crates.io/crates/typed-path) | MIT OR Apache-2.0 | 32 | `zip` | | [`typenum`](https://crates.io/crates/typenum) | MIT OR Apache-2.0 | **none** (`forbid`) | `aes`, `cbc`, `des`, `digest`, `hmac`, `md-5`, `pbkdf2`, `sha1`, `sha2` | +| [`unicase`](https://crates.io/crates/unicase) | MIT OR Apache-2.0 | **none** | `pulldown-cmark` | | [`unicode-bidi`](https://crates.io/crates/unicode-bidi) | MIT OR Apache-2.0 | 1 | `stringprep` | -| [`unicode-ident`](https://crates.io/crates/unicode-ident) | (MIT OR Apache-2.0) AND Unicode-3.0 | 2 | `apfs`, `clap`, `fax`, `goblin`, `half`, `hfsplus`, `lznt1`, `mail-parser`, `rmp-serde`, `serde`, `thiserror`, `yara-x-parser` | +| [`unicode-ident`](https://crates.io/crates/unicode-ident) | (MIT OR Apache-2.0) AND Unicode-3.0 | 2 | `apfs`, `clap`, `fax`, `goblin`, `hfsplus`, `lznt1`, `mail-parser`, `rmp-serde`, `serde`, `thiserror`, `yara-x-parser` | | [`unicode-normalization`](https://crates.io/crates/unicode-normalization) | MIT OR Apache-2.0 | 5 | `stringprep` | | [`unicode-properties`](https://crates.io/crates/unicode-properties) | MIT/Apache-2.0 | **none** | `stringprep` | | [`utf8parse`](https://crates.io/crates/utf8parse) | Apache-2.0 OR MIT | 1 | `clap` | | [`uuid`](https://crates.io/crates/uuid) | Apache-2.0 OR MIT | 15 | `cfb` | | [`web-time`](https://crates.io/crates/web-time) | MIT OR Apache-2.0 | **none** | `cfb` | -| [`zerocopy`](https://crates.io/crates/zerocopy) | BSD-2-Clause OR Apache-2.0 OR MIT | 482 | `half` | -| [`zerocopy-derive`](https://crates.io/crates/zerocopy-derive) | BSD-2-Clause OR Apache-2.0 OR MIT | 807 | `half` | | [`zmij`](https://crates.io/crates/zmij) | MIT | 70 | `serde_json` | +| [`phf`](https://crates.io/crates/phf) / `phf_shared` (two versions of each resolve) | MIT | **none** / 1 | `hayro-interpret` | +| [`smallvec`](https://crates.io/crates/smallvec) | MIT OR Apache-2.0 | 80 | `hayro-syntax`, `hayro-interpret`, `kurbo` | +| [`hayro-cmap`](https://crates.io/crates/hayro-cmap) / [`hayro-postscript`](https://crates.io/crates/hayro-postscript) | Apache-2.0 OR MIT | **none** (`forbid`) / **none** (`forbid`) | `hayro-interpret` | +| [`kurbo`](https://crates.io/crates/kurbo) / `polycool` / [`arrayvec`](https://crates.io/crates/arrayvec) | Apache-2.0 OR MIT / MIT OR Apache-2.0 / MIT OR Apache-2.0 | **none** / **none** / 52 | `hayro-interpret` | +| [`skrifa`](https://crates.io/crates/skrifa) / `read-fonts` | MIT OR Apache-2.0 | **none** (`forbid`) / **none** (`forbid`) | `hayro-interpret` (reads the PDF's embedded fonts) | +| [`font-types`](https://crates.io/crates/font-types) / `bytemuck_derive` | MIT OR Apache-2.0 / Zlib OR Apache-2.0 OR MIT | 3 / 7 | `read-fonts` | +| [`yoke`](https://crates.io/crates/yoke) / `yoke-derive` / `zerofrom` / `zerofrom-derive` / `stable_deref_trait` | Unicode-3.0 (and MIT OR Apache-2.0) | 91 / 11 / **none** / **none** / 28 | `read-fonts`, `skrifa` | +| [`fastrand`](https://crates.io/crates/fastrand) | Apache-2.0 OR MIT | **none** (`forbid`) | `phf_generator` (build time) | ## Verifying this yourself diff --git a/www/src/content/docs/project/formats.md b/www/src/content/docs/project/formats.md new file mode 100644 index 0000000..210a430 --- /dev/null +++ b/www/src/content/docs/project/formats.md @@ -0,0 +1,184 @@ +--- +title: Format matrix +description: Which of exav's tools reads each file format, the scanner, the extractor or the viewer, and whether the extractor streams it or reads it whole. +--- + + + +One table for "can exav handle my file": for each format, what the +[scanner](/scanner/reference/formats/) does with it, whether the +[extractor](/unpack/formats/) streams it or reads it whole (a format read +whole is held in memory up to the buffer limit), and which plugin of the +[viewer](/viewer/) opens it. The pages of each tool have the detail: +codecs, encryption, limits. + +- **Scanner.** opened, and every member scanned; recognised and reported UNSCANNABLE or PASSWORD-PROTECTED, not opened; scanned through a text view as well as its bytes; typed by its content, its signatures applied; no type of its own. +- **Extractor.** *Streamed*: the members are decoded as they are read, at any size. *Read whole*: the container is read into memory first; *members streamed* says the members then come out one at a time. *Recognised, reported*: the format is told apart and the file is reported as not examined, never clean. +- **Viewer.** The plugin, as `@exav/viewer` names it. *No*: the viewer does not open it. + +## Archives and compressed streams + +| Format | Extensions | Scanner | Extractor | Viewer | +|---|---|---|---|---| +| ZIP | `.zip` | Opened, members scanned | Streamed | `archive` | +| Packages that are ZIP files (JAR, APK, IPA, wheel, NuGet, VSIX, MSIX...) | `.jar` `.war` `.ear` `.apk` `.apks` `.xapk` `.aab` `.ipa` `.xpi` `.whl` `.nupkg` `.vsix` `.kmz` `.appx` `.appxbundle` `.msix` `.msixbundle` | Opened, members scanned | Streamed | `archive` | +| Comic book archives (CBZ, CBR, CB7, CBT) | `.cbz` `.cbr` `.cb7` `.cbt` | Opened, members scanned | Streamed | `archive` | +| gzip | `.gz` `.tgz` | Opened, members scanned | Streamed | `archive` | +| bzip2 | `.bz2` `.tbz` `.tbz2` | Opened, members scanned | Streamed | `archive` | +| xz | `.xz` `.txz` | Opened, members scanned | Streamed | `archive` | +| Zstandard | `.zst` `.tzst` | Opened, members scanned | Streamed | `archive` | +| LZ4 | `.lz4` | Opened, members scanned | Streamed | `archive` | +| lzip | `.lz` `.tlz` | Opened, members scanned | Streamed | `archive` | +| Unix compress (.Z) | `.z` `.taz` | Opened, members scanned | Streamed | `archive` | +| tar | `.tar` | Opened, members scanned | Streamed | `archive` | +| 7z | `.7z` | Opened, members scanned | Read whole, members streamed | `archive` | +| RAR (RAR3 and RAR5) | `.rar` | Opened, members scanned | Read whole | `archive` | +| Cabinet (CAB) | `.cab` | Opened, members scanned | Streamed | `archive` | +| Compiled HTML Help (CHM) | `.chm` | Opened, members scanned | Read whole | `archive` | +| LHA / LZH | `.lzh` `.lha` | Opened, members scanned | Streamed | `archive` | +| ARJ | `.arj` | Opened, members scanned | Read whole | `archive` | +| ar (static libraries, Debian packages) | `.ar` `.a` `.deb` `.udeb` | Opened, members scanned | Streamed | `archive` | +| cpio (RPM payloads, initramfs) | `.cpio` | Opened, members scanned | Streamed | `archive` | +| xar (macOS packages) | `.xar` `.pkg` `.xip` | Opened, members scanned | Read whole | `archive` | +| ZOO | `.zoo` | Opened, members scanned | Read whole | `archive` | +| ARC / PKARC / PAK | `.arc` | Opened, members scanned | Read whole | `archive` | +| ALZ | `.alz` | Opened, members scanned | Read whole | `archive` | +| EGG | `.egg` | Opened, members scanned | Read whole | `archive` | +| InstallShield .z | | Opened, members scanned | Read whole | No | +| MS-Compress (SZDD, KWAJ) | | Opened, members scanned | Streamed | No | +| ACE | `.ace` | Reported, not opened | Recognised, reported | No | +| StuffIt and StuffIt X | `.sit` `.sitx` | Reported, not opened | Recognised, reported | No | +| InstallShield InstallScript cabinet | | Reported, not opened | Recognised, reported | No | +| CryptFF | | Reported, not opened | Recognised, reported | No | +| lrzip | `.lrz` | Reported, not opened | Recognised, reported | No | +| AppleSingle and AppleDouble | | Reported, not opened | Recognised, reported | No | + +## Disk images and filesystems + +| Format | Extensions | Scanner | Extractor | Viewer | +|---|---|---|---|---| +| ISO 9660 and UDF | `.iso` | Opened, members scanned | Streamed | `archive` | +| Apple disk image (DMG) | `.dmg` | Opened, members scanned | Streamed | `archive` | +| VHD | `.vhd` | Opened, members scanned | Streamed | `archive` | +| VHDX | `.vhdx` | Opened, members scanned | Streamed | `archive` | +| VMDK (and OVA) | `.vmdk` `.ova` | Opened, members scanned | Streamed | `archive` | +| QCOW2 | `.qcow2` | Opened, members scanned | Streamed | `archive` | +| Windows imaging (WIM, ESD) | `.wim` `.esd` | Opened, members scanned | Read whole | `archive` | +| Partition maps (GPT, APM, MBR) and raw disk images | `.img` | Opened, members scanned | Streamed | `archive` | +| FAT12, FAT16, FAT32 | | Opened, members scanned | Streamed | No | +| NTFS | | Opened, members scanned | Streamed | No | +| ext2, ext3, ext4 | | Opened, members scanned | Read whole | No | + +## Installers, self-extractors and packers + +| Format | Extensions | Scanner | Extractor | Viewer | +|---|---|---|---|---| +| InstallShield MSI | | Reported, not opened | Recognised, reported | No | +| NSIS installer | | Opened, members scanned | Read whole | No | +| Inno Setup installer | | Reported, not opened | Recognised, reported | No | +| Self-extracting archives | | Opened, members scanned | Streamed | No | +| AutoIt compiled scripts | | Opened, members scanned | Read whole | No | +| UPX-packed executables | | Opened, members scanned | Read whole | No | +| Other packed PE executables | | Opened, members scanned | Read whole | No | +| Mach-O universal binaries | | Opened, members scanned | Streamed | No | + +## Documents + +| Format | Extensions | Scanner | Extractor | Viewer | +|---|---|---|---|---| +| OLE2 compound files (legacy Office, MSI) | | Opened, members scanned | Read whole | No | +| PDF | `.pdf` | Opened, members scanned | Read whole | `pdf` | +| Word (DOCX) | `.docx` `.docm` `.dotx` | Opened, members scanned | Streamed | `docx` | +| Excel (XLSX) | `.xlsx` `.xlsm` | Opened, members scanned | Streamed | `xlsx` | +| PowerPoint (PPTX) | `.pptx` `.pptm` `.ppsx` `.potx` | Opened, members scanned | Streamed | `pptx` | +| Word 6 to 2003 (DOC) | `.doc` `.dot` | Scanned with its text | Read whole | `doc` | +| Excel 4 to 2003 (XLS) | `.xls` `.xlt` | Scanned with its text | Read whole | `xls` | +| PowerPoint 95 to 2003 (PPT) | `.ppt` `.pps` `.pot` | Scanned with its text | Read whole | `ppt` | +| RTF | `.rtf` | Scanned with its text | Read whole | `rtf` | +| OpenDocument text (ODT) | `.odt` `.ott` `.fodt` | Scanned with its text | Streamed | `odt` | +| OpenDocument spreadsheet (ODS) | `.ods` `.ots` `.fods` | Scanned with its text | Streamed | `ods` | +| OpenDocument presentation (ODP) | `.odp` `.otp` `.fodp` | Scanned with its text | Streamed | `odp` | +| Keynote | `.key` | Scanned with its text | Streamed | `keynote` | +| Numbers | `.numbers` | Scanned with its text | Streamed | `numbers` | +| Pages | `.pages` | Scanned with its text | Streamed | No | +| CSV and TSV | `.csv` `.tsv` | Scanned with its text | No | `csv` | +| Visio | `.vsd` `.vst` `.vdx` `.vtx` `.vsdx` `.vsdm` `.vstx` `.vstm` | Bytes only | No | `visio` | +| CorelDRAW | `.cdr` `.cmx` | Bytes only | No | `coreldraw` | +| Publisher | `.pub` | Opened, members scanned | Read whole | `publisher` | +| PageMaker 6 to 7 | `.pmd` `.pm6` `.p65` | Bytes only | No | `pagemaker` | +| FreeHand 3 to 11 | `.fh` `.fh3` `.fh4` `.fh5` `.fh7` `.fh8` `.fh9` `.fh10` `.fh11` | Bytes only | No | `freehand` | +| QuarkXPress 3.1 to 4.1 | `.qxd` `.qxt` | Bytes only | No | `quarkxpress` | +| Zoner Draw 4 and 5 | `.zmf` | Bytes only | No | `zonerdraw` | +| WordPerfect Graphics 1 and 2 | `.wpg` | Bytes only | No | `wpg` | +| Hangul Word Processor 3 (HWP3) | `.hwp` | Opened, members scanned | Read whole | No | +| OneNote | `.one` | Opened, members scanned | Streamed | No | +| Adobe XDP | `.xdp` | Opened, members scanned | Read whole | No | + +## Mail and encodings + +| Format | Extensions | Scanner | Extractor | Viewer | +|---|---|---|---|---| +| TNEF (winmail.dat) | `winmail.dat` `.tnef` | Opened, members scanned | Streamed | `archive` | +| Email (MIME) and MHTML | `.eml` `.mht` `.mhtml` | Opened, members scanned | Read whole | No | +| BinHex | `.hqx` | Opened, members scanned | Read whole | No | +| uuencode | `.uu` | Opened, members scanned | Read whole | No | + +## Images + +| Format | Extensions | Scanner | Extractor | Viewer | +|---|---|---|---|---| +| PNG, JPEG, GIF, WebP and SVG | `.png` `.jpg` `.jpeg` `.webp` `.gif` `.svg` | Typed, signatures applied | No | `image` | +| TIFF | `.tif` `.tiff` | Typed, signatures applied | No | `image` | +| BMP | `.bmp` | Typed, signatures applied | No | `image` | +| ICO, PNM, QOI, DDS, farbfeld, Radiance HDR | `.ico` `.pbm` `.pgm` `.ppm` `.pnm` `.pam` `.qoi` `.dds` `.ff` `.hdr` | Typed, signatures applied | No | `image` | +| JPEG 2000 | `.jp2` `.jpf` `.jpx` `.j2k` `.j2c` | Typed, signatures applied | No | `image` | +| JBIG2 | `.jb2` `.jbig2` | Typed, signatures applied | No | `image` | +| JPEG XL | `.jxl` | Typed, signatures applied | No | `image` | +| Camera RAW (DNG, CR2, CR3, NEF, ARW, ORF, RW2, RAF, PEF...) | `.dng` `.gpr` `.cr2` `.cr3` `.crw` `.nef` `.nrw` `.arw` `.sr2` `.srf` `.orf` `.ori` `.rw2` `.rwl` `.raw` `.raf` `.pef` `.srw` `.3fr` `.fff` `.iiq` `.x3f` `.mrw` `.dcr` `.kdc` `.erf` `.mef` `.mos` | Typed, signatures applied | No | `image` | +| HEIC and HEIF | `.heic` `.heif` | Typed, signatures applied | No | No | + +## Drawings and 3D models + +| Format | Extensions | Scanner | Extractor | Viewer | +|---|---|---|---|---| +| OpenDocument drawing (ODG) | `.odg` `.otg` `.fodg` | Scanned with its text | Streamed | `odg` | +| AutoCAD DWG | `.dwg` | Opened, members scanned | Read whole | `dwg` | +| AutoCAD DXF | `.dxf` | Opened, members scanned | Read whole | `dxf` | +| IFC | `.ifc` | Bytes only | No | `ifc` | +| STL | `.stl` | Bytes only | No | `stl` | +| Wavefront OBJ | `.obj` | Bytes only | No | `obj` | +| Stanford PLY | `.ply` | Bytes only | No | `ply` | +| glTF 2.0 (GLTF, GLB) | `.gltf` `.glb` | Bytes only | No | `gltf` | + +## Video and audio + +| Format | Extensions | Scanner | Extractor | Viewer | +|---|---|---|---|---| +| Video (MP4, MOV, WebM, Ogg) | `.mp4` `.m4v` `.mov` `.webm` `.ogv` | Bytes only | No | `video` | +| Audio (MP3, M4A, AAC, WAV, Ogg, Opus, FLAC) | `.mp3` `.m4a` `.aac` `.wav` `.ogg` `.oga` `.opus` `.flac` | Bytes only | No | `audio` | + +## Text and code + +| Format | Extensions | Scanner | Extractor | Viewer | +|---|---|---|---|---| +| Markdown | `.md` `.markdown` | Scanned with its text | No | `text` | +| JSON | `.json` `.geojson` | Typed, signatures applied | No | `text` | +| XML (and RSS, KML, GPX, plist...) | `.xml` `.xsd` `.xsl` `.xslt` `.rss` `.atom` `.kml` `.gpx` `.rdf` `.wsdl` `.plist` | Typed, signatures applied | No | `text` | +| HTML | `.html` `.htm` `.xhtml` | Scanned with its text | No | `text` | +| Diffs and patches | `.diff` `.patch` | Typed, signatures applied | No | `text` | +| Plain text, logs, configuration, subtitles | `.txt` `.text` `.log` `.jsonl` `.ndjson` `.srt` `.vtt` `.yaml` `.yml` `.toml` `.ini` `.cfg` `.conf` `.properties` | Typed, signatures applied | No | `text` | +| Source code | `.js` `.mjs` `.cjs` `.jsx` `.ts` `.tsx` `.mts` `.cts` `.css` `.scss` `.py` `.sh` `.bash` `.zsh` `.bat` `.ps1` `.c` `.h` `.cc` `.cpp` `.hpp` `.cs` `.rs` `.go` `.java` `.kt` `.swift` `.rb` `.php` `.pl` `.lua` `.sql` | Typed, signatures applied | No | `text` | + +## Executables and other carriers + +| Format | Extensions | Scanner | Extractor | Viewer | +|---|---|---|---|---| +| Windows executables (PE) | `.exe` `.dll` `.sys` | Typed, signatures applied | No | No | +| ELF | | Typed, signatures applied | No | No | +| Mach-O | | Typed, signatures applied | No | No | +| Windows shortcuts (LNK) | `.lnk` | Opened, members scanned | Read whole | No | +| Python bytecode (.pyc) | `.pyc` | Opened, members scanned | Streamed | No | +| Java class files | `.class` | Opened, members scanned | Read whole | No | +| SWF (Flash) | `.swf` | Opened, members scanned | Streamed | No | +| AI models (pickle, safetensors) | `.pkl` `.safetensors` | Opened, members scanned | Read whole | No | +| Microsoft Script Encoder | `.vbe` `.jse` | Opened, members scanned | Read whole | No | diff --git a/www/src/content/docs/project/license.md b/www/src/content/docs/project/license.md index b30d5a0..5bc9843 100644 --- a/www/src/content/docs/project/license.md +++ b/www/src/content/docs/project/license.md @@ -25,6 +25,14 @@ primitives and the `webpki-roots` certificate store. Among the rest: - exav also contains code ported or derived from permissively licensed projects (RAR, AZO, CAB, DMG, PPMd and bzip2 decoders among them, the HWP3 layout, and `iced-x86`'s generated decoder tables), each attributed in `NOTICE`. +- exav-render's office converters (spreadsheets, presentations, text + documents) are written from published specifications, among them + Microsoft's Open Specifications and the OASIS OpenDocument standard, and + from what other converters do with sample files, used as a black box. No code + of another office application is in them. The specifications, the tables and + message layouts taken from MIT-licensed projects (numbers-parser and + keynote-parser), and the test fixtures are listed in + [`crates/exav-render/NOTICE`](https://github.com/sylvinus/exav/blob/main/crates/exav-render/NOTICE). - The WASM sandbox runs exav under a WASI runtime you provide, under its own license; exav does not bundle it. See the [WASM sandbox guide](/scanner/guides/wasm-sandbox/). diff --git a/www/src/content/docs/project/roadmap.md b/www/src/content/docs/project/roadmap.md index 5c13661..b6b415c 100644 --- a/www/src/content/docs/project/roadmap.md +++ b/www/src/content/docs/project/roadmap.md @@ -1,6 +1,6 @@ --- title: Roadmap -description: What's next for exav, from signature-matching performance and one read pass for large files to broader bytecode coverage, streaming RAR, multi-volume archives, JPEG XL in the viewer and less dependency unsafe. +description: What's next for exav, from signature-matching performance and one read pass for large files to broader bytecode coverage, streaming RAR, multi-volume archives, the viewer's Office converters, document text search and less dependency unsafe. --- exav is beta and `0.0.x`: any release may change behaviour or APIs. What has @@ -71,20 +71,15 @@ bounded object, so streaming it would save little memory; raising counted, so the list of what to add is measured. - Verifying Authenticode signatures cryptographically. Parsing, digest checks and `.crb` matching exist today. -- **Joining format-aware volume sets**: RAR `.partN`/`.rNN`, ZIP `.zNN`, and - multi-cabinet CAB. Byte-split sets (`x.7z.001`, `x.7z.002`, ...) are already - joined when their parts arrive together (see - [split archives](/scanner/guides/daemon/#split-archives)). A format-aware volume - carries its own headers and a member's data resumes past the next volume's - header, so the join belongs in the format's decoder. ClamAV does not join - them either; exav reports the split member and scans the part in the volume - it was given. Sibling volumes will only be looked for next to the scanned - file, under names generated from its own, as regular files (no symlinks). A - cabinet names its successor inside the file, so that name will be matched - against the directory listing and never opened as a path. +- **Volume sets met inside a container.** RAR, ZIP and CAB volume sets are + joined when their volumes sit next to each other on disk, or arrive together + at the daemon (see [split archives](/scanner/guides/daemon/#split-archives)), + but not when the volumes are members of another archive: each is then scanned + on its own and the member continued in another volume is reported. - The unimplemented `Target:` values (internal, other, and ClamAV's reserved - slot 8), `EP` and section offsets on ELF and Mach-O files, and the unloaded - database extensions (`.cat`, `.ioc`, and the legacy `.sdb`/`.zmd`/`.rmd`). + slot 8), `EP` on Mach-O files (clamscan does not resolve it either), and the + unloaded database extensions (`.cat`, `.ioc`, and the legacy + `.sdb`/`.zmd`/`.rmd`). None appears in a stock official database; all matter for third-party feeds. See [Targets](/scanner/reference/comparison-with-clamav/#targets). @@ -93,28 +88,44 @@ bounded object, so streaming it would save little memory; raising - QEMU/KVM dynamic detonation: a separate, heavyweight feature, only if there is demand. -## File viewer: JPEG XL, after 0.0.2 - -The viewer does not open JPEG XL yet. The decoder to build on is -[`jxl`](https://crates.io/crates/jxl) (jxl-rs, the libjxl team's own, -BSD-3-Clause), forked as a crate of exav's so that it can be -`#![forbid(unsafe_code)]` like the other decoders the viewer runs: - -- **Without SIMD.** Its SIMD (347 `unsafe` sites) is behind features, and the - WebAssembly build does without it. -- **Without the rest of its `unsafe`**, about 80 sites that no feature turns - off. Most are in the image buffers: allocation by hand, buffers - reinterpreted as another number type, rows sliced from raw pointers. They - become typed vectors. The others are unchecked indexing in the modular - predictor and the entropy decoder, a small-vector type and a few casts. Its - `array-init` and `byteorder` dependencies give way to the standard library. -- **Checked** against libjxl's `djxl` on its conformance files, and fuzzed. -- **In the viewer only,** in its WebAssembly image module: the scanner's image - hashing gains nothing from it, since ClamAV's image signatures do not cover - the format. - -The cost is speed (no SIMD, bounds checks), and following upstream, which -releases about monthly, by hand. +## Documents, search and the viewer + +The viewer opens JPEG XL (a fork of the libjxl team's jxl-rs, `forbid(unsafe_code)` +and built without SIMD), camera RAW previews, and converts the old Office +formats in the browser. What is not done: + +- **The text-document converter is a prototype.** On the project's test files, + 32% of the pages of DOC files come out close to a reference rendering, + against 50% for DOCX drawn natively. Open decisions: falling back to the + external converter for what it reports unsupported (Pages '09, Word 1 and + 2), making it the default even where an external converter is set, keeping + tracked changes in DOC, and Pages tables, pictures and headers. +- **Presentations.** PowerPoint 2, 3 and 4 are recognised and reported + unsupported. PowerPoint 95 pictures, freeforms and arcs are left out. The + first slide could be drawn while the rest converts. Binary Visio, CorelDRAW, + Publisher and the other page layout formats are read only by an + [external converter](/viewer/integration/#the-external-converter). +- **Searching documents.** `exav-grep --text` and the scanner's text view read + Markdown, HTML, the XML parts of Office and OpenDocument files, DXF and DWG, + and, behind opt-in features, PDF and the legacy and flat office formats. + Still to do: IFC names and property values, an email's headers, the + hyperlinks of OOXML files (apart from their labels), PDF link annotations, + the speaker notes of presentations, and matches located by page and by + drawing entity. PDF text and the office readers are not defaults because of + hayro's `unsafe` and the size of the readers. OCR for images and scanned + pages, and QR codes for the scanner, are proposed. +- **Drawings and models.** DWG before R13 is reported unsupported. Large + drawings have no level of detail, annotative objects, external references + and linked images are not resolved, and 3D is out of scope. IFC geometry has + [known gaps](/subprojects/exav-render/#ifc-and-stl-models). glTF with Draco + or meshopt, and PLY point clouds, are not drawn. +- **Camera RAW.** The sensor data is never decoded, so a file with no preview + (most phones' DNG, Minolta MRW, CR3 whose preview is HEIF) shows an error. +- **Other viewer gaps.** Replacing a document in a sandboxed frame starts the + zoom and position over. Archives left out on purpose: email, OLE + containers, OpenDocument and EPUB, packers and installers. Text previews + have no line numbers, tree view or search. The browser's own JPEG XL decoder + could spare the module's size where it exists. ## Hardening: less dependency `unsafe` @@ -128,10 +139,11 @@ ongoing goal: - **Audit** each dependency's `unsafe` by reachability from a hostile-input scan path (the per-crate counts are done). - **Drop** dependencies exav does not need (done for `tar`'s `xattr`, which was - the largest source of syscall `unsafe`). + the largest source of syscall `unsafe`, for `half` and `zerocopy`, and for + zstd's checksum, `twox-hash`). - **Make safe** what can be: portable builds without SIMD where the speed cost is - acceptable, and vendoring then removing `unsafe` (the RAR PPMd decoder has - none). + acceptable, and vendoring then removing `unsafe` (the RAR PPMd, LZFSE and + InstallShield Z decoders have none). - **Reuse exav's own safe code** where it duplicates an `unsafe` dependency. - **Verify** the rest with `cargo-fuzz` and Miri (`make miri`), and document the containment (panic isolation, the prefork process boundary, the WASM build). diff --git a/www/src/content/docs/scanner/concepts/how-it-works.md b/www/src/content/docs/scanner/concepts/how-it-works.md index fdf8b79..9ccc0b7 100644 --- a/www/src/content/docs/scanner/concepts/how-it-works.md +++ b/www/src/content/docs/scanner/concepts/how-it-works.md @@ -86,6 +86,13 @@ File type comes from the content, not the extension: an executable renamed `.jpg` is still scanned as an executable. The budgets every extraction runs under are in [How extraction works](/unpack/how-it-works/). +A document is matched twice: as its bytes, and as the text a reader sees, a +second view of the same object with its markup, escapes and run boundaries +gone and each link followed by where it goes. That view is made by the +`visible-text` feature, on by default; which documents it reads, and what +happens when one cannot be read, is in +[Supported formats](/scanner/reference/formats/#the-text-a-reader-sees). + ## Signature types and runtime structures Different ClamAV signature types compile to different runtime structures rather diff --git a/www/src/content/docs/scanner/concepts/quirks.md b/www/src/content/docs/scanner/concepts/quirks.md index 028966e..382d957 100644 --- a/www/src/content/docs/scanner/concepts/quirks.md +++ b/www/src/content/docs/scanner/concepts/quirks.md @@ -354,7 +354,10 @@ Which signatures meet which rendering follows clamscan, probed one signature at a time: `Target:3` and `Target:7` signatures match only the HTML and text renderings, never raw bytes; an HTML file has the HTML rendering and a text file the text one, not the other; `Target:4` (mail) signatures match a mail's raw -bytes. An HTML signature on plain JavaScript is a match clamscan cannot make, +bytes. The exception is the [visible text](/scanner/reference/feature-flags/) of +a document (the `visible-text` feature, off under `--clamav-compat`): the words +of an HTML page, a Markdown file or an Office part are also a text view, which +`Target:7` signatures see. An HTML signature on plain JavaScript is a match clamscan cannot make, and one did fire on obfuscated npm code before. Java signatures (`Target:12`) are gated on the `cafebabe` magic because one fired on APK members, and the targets exav cannot positively identify are skipped (see diff --git a/www/src/content/docs/scanner/getting-started/installation.mdx b/www/src/content/docs/scanner/getting-started/installation.mdx index 5a2c477..a8c3675 100644 --- a/www/src/content/docs/scanner/getting-started/installation.mdx +++ b/www/src/content/docs/scanner/getting-started/installation.mdx @@ -39,7 +39,7 @@ and [exav-imagehash](/subprojects/exav-imagehash/). ## From crates.io -Building needs Rust 1.92 or newer (`rustc --version`; `rustup update` to +Building needs Rust 1.95 or newer (`rustc --version`; `rustup update` to upgrade). ```sh @@ -61,7 +61,7 @@ See [Feature flags](/scanner/reference/feature-flags/) for all build options. -1. Install a Rust toolchain (1.92 or newer) via [rustup](https://rustup.rs/). +1. Install a Rust toolchain (1.95 or newer) via [rustup](https://rustup.rs/). 2. Clone and build: diff --git a/www/src/content/docs/scanner/guides/daemon.mdx b/www/src/content/docs/scanner/guides/daemon.mdx index 8a2278b..de39f7e 100644 --- a/www/src/content/docs/scanner/guides/daemon.mdx +++ b/www/src/content/docs/scanner/guides/daemon.mdx @@ -48,8 +48,9 @@ or a daemon running as another user. `-` (stdin) is always sent as contents. A directory names its whole tree in all three modes, as it does for `clamdscan`. The client walks it and sends one request per file, so `--exclude` / `--include` -apply to the tree and each request has one reply. The parts of a byte-split -archive (`x.001`, `x.002`, ...) are sent together so the daemon can rejoin them +apply to the tree and each request has one reply. The parts of a split archive +(`x.001`, `x.002`, ...; a RAR's `x.part1.rar` or `x.r00`; a ZIP's `x.z01` +and `x.zip`) are sent together so the daemon can rejoin them (see [split archives](#split-archives)). By path, a directory holding such parts goes as one `CONTSCAN`, and the client's filters and `--no-recursive` do not apply to it; with `contents` or `fd`, the parts of each directory go in one @@ -158,9 +159,15 @@ daemon could not hold in full has what it held scanned and is answered scanned. The reply carries `"truncated": true` when the request ended before its terminator, so some files never arrived. -RAR `.partN` and ZIP `.zNN` volumes are not rejoined this way: each carries its -own headers, so concatenating them produces garbage that still looks like an -archive. Each is scanned on its own. +Volumes that carry their own headers are rejoined too, by the format's own +join and not by concatenation (which would produce garbage that still looks like +an archive): a RAR set (`x.part1.rar`, `x.part2.rar`, ..., or `x.rar`, `x.r00`, +...), a ZIP set (`x.z01`, ..., and the `x.zip` that ends it) and a set of +cabinets, found from the names their headers give one another. A set with a +volume missing, or whose volumes do not fit together, is `PARTIAL`, never +clean. The client sends a directory as one request when it holds a byte-split, +RAR or ZIP part by name, with its `.zip` and `.cab` files; a directory of +cabinets alone is rejoined when the daemon scans it by path (`CONTSCAN`). ## Size over the wire diff --git a/www/src/content/docs/scanner/reference/cli.md b/www/src/content/docs/scanner/reference/cli.md index b31dc6f..6b8ce66 100644 --- a/www/src/content/docs/scanner/reference/cli.md +++ b/www/src/content/docs/scanner/reference/cli.md @@ -388,8 +388,9 @@ paths, which the daemon opens itself; `--send-as` sends the file instead: `fd` is the cheapest (no copy) and needs a Unix socket; asking for it over TCP is refused rather than falling back to the path. `contents` works anywhere. Both -send the parts of a byte-split archive together (`EXINSTREAM MULTI`) so the -archive is scanned whole; by path, the same job is a `CONTSCAN` of the directory. +send the parts of a split archive (byte-split, RAR or ZIP volumes) together +(`EXINSTREAM MULTI`) so the archive is scanned whole; by path, the same job is a +`CONTSCAN` of the directory. A client walks a directory itself in every mode and sends one request per file, so `--exclude`, `--exclude-dir`, `--include`, `--files-from` and `--no-recursive` diff --git a/www/src/content/docs/scanner/reference/comparison-with-clamav.md b/www/src/content/docs/scanner/reference/comparison-with-clamav.md index 39112ba..3e78538 100644 --- a/www/src/content/docs/scanner/reference/comparison-with-clamav.md +++ b/www/src/content/docs/scanner/reference/comparison-with-clamav.md @@ -186,8 +186,8 @@ recursive extraction the scanner uses. exav is younger than ClamAV and does not match it everywhere. Most gaps below show up as `UNSCANNABLE`, `LIMITS-EXCEEDED` or a counted skip: a gap costs coverage, not a false all-clear. The exceptions are detections exav does not -implement (the [heuristics](#heuristic-alerts), and the `Target:` values and -ELF and Mach-O offsets [below](#targets)): there +implement (the [heuristics](#heuristic-alerts), and the `Target:` values +[below](#targets)): there a file gets `OK` where ClamAV would alert. A signature with a constraint exav cannot evaluate is refused rather than loaded without it, since that would make it fire more broadly than the format allows. See the [roadmap](/project/roadmap/) @@ -306,10 +306,10 @@ positives (observed: a Java CVE signature firing on APK members). | 3 | HTML | Supported (restricted to HTML and RTF) | | 4 | Mail | Supported | | 5 | Graphics | Supported: an object that reads as an image, or one a `HandlerType:CL_TYPE_GRAPHICS` signature re-typed | -| 6 | ELF | Supported, but `EP` and section offsets do not resolve (see below) | +| 6 | ELF | Supported, with `EP` and section offsets (see below) | | 7 | ASCII text | Supported | | 8 | *(unused)* | Not implemented; a reserved slot in ClamAV too | -| 9 | Mach-O | Supported, but `EP` and section offsets do not resolve (see below) | +| 9 | Mach-O | Supported, with section offsets; `EP` does not resolve, as in clamscan (see below) | | 10 | PDF | Supported | | 11 | Flash / SWF | Supported (`FWS` uncompressed, `CWS`/`ZWS` compressed) | | 12 | Java class | Supported (gated on the `cafebabe` magic) | @@ -325,11 +325,16 @@ reads: it hashes as the same pixels do in a PNG. A build without the is matched against them whatever its target. The hash is ClamAV's to the bit ([exav-imagehash](/subprojects/exav-imagehash/)). -The entry point and sections are read from a PE only. ClamAV also resolves -`EP`, `Sn`, `SL` and `SEn` offsets on ELF and Mach-O files; in exav a -subsignature anchored that way on one never matches, and the file can come -back `OK` where ClamAV alerts. None of the 5,767 ELF and Mach-O signatures in -`daily` 28140 (October 2026) uses such an offset. +The entry point and sections are read from the headers of a PE, an ELF or a +Mach-O. On an ELF, `EP` is the entry point's file offset, found through the +loadable segment that maps it (the memory past the segment's bytes included), +and `Sn`, `SL` and `SEn` are the section headers' file ranges, counted from the +null section; on a Mach-O, `Sn`, `SL` and `SEn` count the sections of every +segment in load order. Each was measured against clamscan 1.4.3 with a +signature at the offset and a control three bytes off. `EP` on a Mach-O is not +resolved, by exav or by clamscan (neither `LC_MAIN` nor `LC_UNIXTHREAD`, in +32 and 64 bits). None of the 5,767 ELF and Mach-O signatures in `daily` 28140 +(October 2026) uses such an offset. ### Signature-format coverage diff --git a/www/src/content/docs/scanner/reference/feature-flags.md b/www/src/content/docs/scanner/reference/feature-flags.md index dbc1b6c..27b9f40 100644 --- a/www/src/content/docs/scanner/reference/feature-flags.md +++ b/www/src/content/docs/scanner/reference/feature-flags.md @@ -16,7 +16,7 @@ pages: [exav-core](/subprojects/exav-core/#features), ## Default features ```toml -default = ["yara", "all-formats", "decrypt", "dlp", "phishing", "icap", "image-hash"] +default = ["yara", "all-formats", "decrypt", "dlp", "phishing", "icap", "image-hash", "visible-text"] ``` The default build is pure Rust and links no TLS stack; HTTP is opt-in. @@ -31,6 +31,9 @@ The default build is pure Rust and links no TLS stack; HTTP is opt-in. | `dlp` | yes | The structured-data leak heuristics (`--dlp-credit-cards` / `--dlp-ssns`). | | `phishing` | yes | The phishing heuristic `--detect phishing` runs, and the `.pdb`/`.gdb`/`.wdb` URL lists it reads. | | `image-hash` | yes | `fuzzy_img#` subsignatures, through [exav-imagehash](/subprojects/exav-imagehash/) and its image decoders. Without it those signatures load as unsupported (counted, with the reason), and no image is ever decoded. | +| `visible-text` | yes | A document is matched through the text a reader sees as well as its bytes: its words without the marks, tags, escapes or run boundaries, entities decoded, and each link followed by where it goes (`label (target)`, whatever the target), as a text view that `Target:0` and `Target:7` signatures see. Markdown (`.md`, `.markdown`), HTML (pages and fragments), the XML parts of Word, PowerPoint, Excel and OpenDocument files (by their path in the package), and AutoCAD drawings (DXF, DWG), as the input or as a member. With `--detect phishing`, each link whose label names one site and whose target another is judged as an HTML anchor is. Not under `--clamav-compat`. Read by [exav-render](/subprojects/exav-render/#text)'s `text`: pulldown-cmark, html5gum's tokenizer and quick-xml. A document past `--max-object-bytes` is not read and the scan is reported incomplete. | +| `visible-text-pdf` | **no** | And PDF's, read by hayro. Off by default because `hayro-interpret` turns on `hayro-syntax`'s `unsafe` feature, which switches every `flate2` in the build to zlib-rs (a damaged stream then gives back other bytes) and adds SIMD to the image decoders, and because it adds some 40 crates. hayro puts no bound on what a stream decompresses to, so a PDF is given to it only after exav's own reader has taken every stream within the limits. | +| `visible-text-office` | **no** | And the legacy and flat office formats the XML parts do not reach: DOC, XLS, PPT, RTF, Word 2003 XML, SpreadsheetML 2003, SYLK, FODT, FODS, FODP, FODG, Numbers, Pages and Keynote, with the same text view, link handling and `--detect phishing` judging. Read by [exav-render](/subprojects/exav-render/#text)'s `text-office`, from what its office converters read. Safe Rust and within the scan's limits, but the largest readers of the scan, so not a default. A document of those formats whose text cannot be taken out (encrypted, past a limit, damaged) marks the scan incomplete (`PARTIAL`), never clean; its bytes are still scanned. A compound file is read as an office document only by its extension (`.doc`, `.dot`, `.xls`, `.xlt`, `.xlw`, `.ppt`, `.pps`, `.pot`), so that an installer is not read whole to find out. Speaker notes and the text of animations are not in the view. | | `icap` | yes | The [ICAP (RFC 3507) server](/scanner/guides/icap/) and its `--icap-*` flags. Pure Rust, no extra dependencies; binds nothing unless an `icap://` address is given. | | `http` | **no** | HTTP(S) support: both halves below, and the only thing that links a TLS stack (`ureq` → `rustls` → `ring`). In `exav-core`, `http` is only the range-request backend (`dep:ureq`); in `exav` it is `http = ["http-scan", "http-update"]`. | | `http-scan` | no | Scanning an `http(s)://` argument, and the daemon's `SCANURL` command. Both also need `--allow-http-scan` at run time. | diff --git a/www/src/content/docs/scanner/reference/formats.md b/www/src/content/docs/scanner/reference/formats.md index 0a4e256..02bff4a 100644 --- a/www/src/content/docs/scanner/reference/formats.md +++ b/www/src/content/docs/scanner/reference/formats.md @@ -12,7 +12,9 @@ reported `UNSCANNABLE`, `PASSWORD-PROTECTED` or `LIMITS-EXCEEDED`, never Containers are opened by the extractor, [exav-unpack](/unpack/). Its [Supported formats](/unpack/formats/) page has the codec-level detail; this -page is what the scanner does with each kind of file. +page is what the scanner does with each kind of file, and the +[format matrix](/project/formats/) has every format, with what the extractor +and the viewer do with it. ## File types @@ -23,8 +25,8 @@ rules. On top of that: | Type | What the scanner does with it | Signatures that apply to it alone | |---|---|---| | PE (Windows executables and DLLs) | Reads the entry point, sections, imports, icons, version information and Authenticode signer; unpacks a packed file ([below](#packed-executables)) | `Target:1`; `EP`, section and `VI` offsets; section hashes (`.mdb`, `.msb`), import hashes (`.imp`), icons (`.idb`), signer block list (`.crb`); YARA `pe` and `dotnet` | -| ELF | Scanned as it is; a UPX-packed one is unpacked | `Target:6`; YARA `elf`. `EP` and section offsets do not resolve ([gap](/scanner/reference/comparison-with-clamav/#targets)) | -| Mach-O | A universal binary is split per architecture; each is scanned as it is, and a UPX-packed one unpacked | `Target:9`, with the same offset gap | +| ELF | Scanned as it is; a UPX-packed one is unpacked | `Target:6`, with `EP` and section offsets ([how](/scanner/reference/comparison-with-clamav/#targets)); YARA `elf` | +| Mach-O | A universal binary is split per architecture; each is scanned as it is, and a UPX-packed one unpacked | `Target:9`, with section offsets (`EP` does not resolve, as in clamscan) | | OLE2 (legacy Office, MSI) | Every stream; VBA macros decompressed, Excel 4.0 (XLM) macros, `Ole10Native` payloads; encrypted Excel decrypted | `Target:2` | | OOXML (`.docx`, `.xlsx`, `.pptx`) | Opened as the ZIP it is; told apart as Word, Excel or PowerPoint for `Container:`; encrypted documents decrypted | as for its members | | PDF | Streams decoded through their filters (Flate, LZW, ASCII85, ASCIIHex, RunLength), JavaScript and URI and launch targets collected, the document decrypted. Image streams (DCT, JBIG2, JPX, CCITT) are matched as stored | `Target:10` | @@ -41,6 +43,25 @@ not run. `HandlerType:` re-types an object and scans it again as the new type, as in ClamAV. [Comparison with ClamAV](/scanner/reference/comparison-with-clamav/#targets) covers the targets in detail. +### The text a reader sees + +Beside its bytes, a document is matched through its visible text: the words +without the marks, tags, escapes or run boundaries, entities decoded, and each +link followed by where it goes (`label (target)`). That text is one more view, +which `Target:0` and `Target:7` signatures see, and `--detect phishing` judges +its links. It is the `visible-text` [feature](/scanner/reference/feature-flags/), +off under `--clamav-compat`. + +| Read in the default build | Read with an opt-in feature | +|---|---| +| Markdown (`.md`, `.markdown`), HTML, the XML parts of Word, PowerPoint, Excel and OpenDocument files, DXF and DWG drawings | PDF (`visible-text-pdf`); DOC, XLS, PPT, RTF, Word 2003 XML, SpreadsheetML 2003, SYLK, flat OpenDocument (FODT, FODS, FODP, FODG), Numbers, Pages and Keynote (`visible-text-office`) | + +A document of a kind that has such a text, whose text cannot be taken out +(encrypted, past a limit, damaged), is still scanned as bytes, and the scan is +`PARTIAL`, never `OK`. A compound file (`.doc`, `.xls`, `.ppt` and their +templates) is read as an office document by its extension only, so that an +installer is not read whole to find out. + ## Containers Every format exav-unpack opens is opened when scanning, and its members @@ -63,8 +84,13 @@ scanned in turn: (their embedded objects and preview images; a drawing is not rendered). A set split into byte-numbered parts (`x.7z.001`, `x.7z.002`, ...) and met -inside one container is joined and scanned whole. RAR and ZIP volume sets are -not joined; a member continued in another volume is reported. +inside one container is joined and scanned whole. RAR, ZIP and CAB volume sets +met there are not joined; a member continued in another volume is reported. +Next to each other on disk, or sent together to the daemon, they are: a RAR set +(`x.part1.rar`, `x.r00`), a ZIP set (`x.z01`, ..., `x.zip`) and a CAB set (each +cabinet's header names the next). Scanning one volume of such a set by name +scans the archive its siblings make as well, looked for in the same directory +among regular files (a symbolic link is not a sibling). ### Found inside other files diff --git a/www/src/content/docs/subprojects/exav-core.md b/www/src/content/docs/subprojects/exav-core.md index acce730..9c2a961 100644 --- a/www/src/content/docs/subprojects/exav-core.md +++ b/www/src/content/docs/subprojects/exav-core.md @@ -39,6 +39,10 @@ scan. - **The native [YARA engine](/scanner/guides/yara/)** and a step-capped [bytecode interpreter](/scanner/concepts/bytecode-sandbox/) for `.cbc` programs, both without runtime code generation. +- **A text view of documents** (`visible-text`): a document's words as a + reader sees them, with each link followed by where it goes, are matched + beside its bytes, through [exav-render](/subprojects/exav-render/#text). A + document whose text cannot be taken out marks the scan incomplete. - **Content-based file typing**, PE parsing, fuzzy and similarity scoring, the prebuilt-`.exavdb` builder, and an HTTP range-reader backend (`http` feature) that scans a large remote file through the block cache instead of @@ -223,7 +227,10 @@ names. | Feature | What it does | |---|---| -| default | `yara`, `all-formats`, `decrypt`, `dlp`, `phishing`, `image-hash`: the `exav` binary's defaults minus its `icap` | +| default | `yara`, `all-formats`, `decrypt`, `dlp`, `phishing`, `image-hash`, `visible-text`: the `exav` binary's defaults minus its `icap` | +| `visible-text` | A document's visible text (Markdown, HTML, Office and OpenDocument XML parts, DXF and DWG drawings) is matched as a text view, and each link as its label then its target (see [feature flags](/scanner/reference/feature-flags/)) | +| `visible-text-pdf` | And PDF's, through hayro; not a default (see [feature flags](/scanner/reference/feature-flags/)) | +| `visible-text-office` | And the legacy and flat office formats: DOC, XLS, PPT, RTF, Word 2003 XML, SpreadsheetML 2003, SYLK, FODT, FODS, FODP, FODG, Numbers, Pages and Keynote, through exav-render's office converters; not a default. A document of those formats whose text cannot be taken out (encrypted, past a limit, damaged) marks the scan incomplete (see [feature flags](/scanner/reference/feature-flags/)) | | `http` | The HTTP range-request reader (`dep:ureq`) | | `checksums` | Lets `ScanOptions::verify_checksums` make a container checksum mismatch an error | | `unstable-internals` | Makes the engine internals (`engine`, `bytecode`, `pe`, …) public, for tools; no stability promise | diff --git a/www/src/content/docs/subprojects/exav-grep.md b/www/src/content/docs/subprojects/exav-grep.md index 1df8292..1d2071a 100644 --- a/www/src/content/docs/subprojects/exav-grep.md +++ b/www/src/content/docs/subprojects/exav-grep.md @@ -78,6 +78,7 @@ needs: | `--max-members ` | Cap on members visited inside each input file | | `--max-unpack-depth ` | Cap on archive-within-archive nesting | | `--quiet-unreadable` | Suppress unreadable-member reports | +| `--text` | Search the text a reader sees rather than the bytes, for the files that have one ([below](#searching-the-text)). Needs the `text` feature, which is a default. A text cut at its size limit is reported unreadable (exit `3`) | The limits are the scanner's decompression-bomb budget, spelled as [`exav`](/scanner/reference/cli/#scan-limits) spells them, so pointing it at a hostile @@ -85,6 +86,47 @@ archive is safe. Each input file is read whole into memory, so one larger than `--max-object-bytes` is reported unreadable (exit `3`) rather than read; raise the flag to search it. +## Searching the text + +`--text` searches the words a reader sees instead of the bytes of the file, +for the kinds of file that have some, in an archive too: + +- Markdown (`.md`, `.markdown`), HTML, the XML parts of Word, PowerPoint, + Excel and OpenDocument files, and DXF and DWG drawings, in the default + build; +- PDF, with the `text-pdf` feature, which is not a default; +- with the `text-office` feature, which is not a default either, the legacy + and flat office formats: DOC, XLS, PPT, RTF, Word 2003 XML, SpreadsheetML + 2003, SYLK, FODT, FODS, FODP, FODG, Numbers, Pages and Keynote. + +Entities are decoded, and each link is followed by where it goes, +`label (target)`. Matches are reported under `file!text`, with the text's line +numbers. A workbook or a presentation is searched sheet by sheet and slide by +slide, and a match says which: + +```text +$ exav-grep --text -F "Second sheet" book.xls +book.xls!text/sheet "Notes":2:Second sheet 1 +$ exav-grep --text -F "Second slide" deck.ppt +deck.ppt!text/slide 2:2:Second slide text +$ exav-grep --text -F costs report.doc +report.doc!text:2:Revenue grew by twelve percent over the quarter, while costs stayed flat. +``` + +A document that is also a container (a PDF, a drawing) is walked for its +members as before. A compound file is read as an office document only by its +extension (`.doc`, `.dot`, `.xls`, `.xlt`, `.xlw`, `.ppt`, `.pps`, `.pot`), so +that an installer is not read whole to find out. + +A document of those kinds whose text cannot be taken out (encrypted, past a +limit, damaged) is reported unreadable, with the reason, and its bytes are +searched instead. With no match the exit code is `3`, never `1`: finding +nothing in a document it could not read is not a clean answer. + +```bash +cargo install exav-grep --features text-office +``` + ## What it searches Everything [exav-unpack](/unpack/) opens: zip, rar, 7z, tar, diff --git a/www/src/content/docs/subprojects/exav-render.md b/www/src/content/docs/subprojects/exav-render.md index 16de5c8..9703baf 100644 --- a/www/src/content/docs/subprojects/exav-render.md +++ b/www/src/content/docs/subprojects/exav-render.md @@ -1,6 +1,6 @@ --- title: exav-render -description: Memory-safe decoders that turn a file into something to draw, raster images into pixels, DWG and DXF drawings and IFC and STL models into GPU-ready buffers, behind @exav/viewer and exav-imagehash. +description: Memory-safe decoders that turn a file into something to draw, raster images into pixels, DWG and DXF drawings and IFC, STL, OBJ, PLY and glTF models into GPU-ready buffers, and spreadsheets, presentations and text documents into XLSX, PPTX and DOCX, behind @exav/viewer and exav-imagehash. --- **Memory-safe decoders that turn a file into something to draw.** The Rust @@ -14,6 +14,7 @@ so is the DWG reader it vendors. exav-render = "0.0.2" # images exav-render = { version = "0.0.2", features = ["dwg"] } # and drawings exav-render = { version = "0.0.2", features = ["ifc", "stl"] } # and models +exav-render = { version = "0.0.2", features = ["office"] } # and office documents ``` ## Images @@ -55,6 +56,281 @@ exav-imagehash hashes them like the other formats, so a `fuzzy_img#` signature made from a PNG matches the same picture stored as JPEG 2000 or JBIG2. +JPEG XL (feature `jxl`, not a default: libclamav does not decode it and it is +the largest decoder here) is decoded by +[zenjxl-decoder](https://crates.io/crates/zenjxl-decoder) (BSD-3-Clause), a +fork of the libjxl team's jxl-rs that is `forbid(unsafe_code)` unless its +`allow-unsafe` feature is on, and is built without its SIMD. The first frame +comes back as 8-bit grey with alpha or RGBA, in sRGB, a codestream or a +container alike. The caller's budget is the decoder's: its pixel and memory +limits are set from it, so a file declaring more than the budget is refused +from its header. `@exav/viewer`'s image module has it. + +## Camera RAW + +Feature `raw`, a default. A RAW file holds the sensor data and, beside it, +JPEG previews of several sizes, sometimes an uncompressed RGB one. The reader +(`exav_render::image::raw`) finds them and `decode_any` shows the largest the +budget allows, as 8-bit pixels with the Exif orientation applied (the JPEG's +own, else the file's). The sensor data is never decoded: a file with no +preview, such as most phones' DNG, is `Error::NoPreview`, not a blank. + +```rust +use exav_render::image::{decode_any, raw, DECODE_MAX}; + +let bytes = std::fs::read("IMG_0001.CR3")?; +assert_eq!(raw::detect(&bytes), Some(raw::Kind::Cr3)); +let pixels = decode_any(&bytes, DECODE_MAX)?; +# Ok::<(), Box>(()) +``` + +| Family | Read as | +|---|---| +| DNG (and the Leica, Ricoh, Pentax, GoPro and phone files that are DNG), Canon CR2, Phase One IIQ | TIFF directories | +| Olympus ORF (`IIRO`, `IIRS`, `MMOR`), Panasonic RW2, RAW and Leica RWL (`IIU`) | TIFF directories with the makers' own magic numbers | +| Nikon NEF and NRW, Sony ARW, SR2 and SRF, Pentax PEF, Samsung SRW, Hasselblad 3FR, Kodak, Epson, Mamiya, Leaf | TIFF/EP directories: told from a plain TIFF by sensor data in the file (a colour filter array, a maker's compression, the DNG tags), or by a camera maker's name beside a SubIFD or a thumbnail | +| Canon CR3 | an ISO base media file (`ftyp` brand `crx `); the orientation is in its metadata boxes | +| Fujifilm RAF, Sigma X3F, Canon CRW | a signature, then a search for the JPEG streams | +| Minolta MRW | a signature; it holds no JPEG, so it is `NoPreview` | + +Detection is by the first bytes and, for a TIFF-structured file, its +directories, never the name. A plain TIFF, even one that kept a camera's Make +tag, is not claimed: `Format::detect` and `decode` read every TIFF as TIFF +(which is what exav-imagehash must do), and only `decode_any` and +`raw::decode` try a RAW file first. + +The previews of a TIFF-structured file are listed from the tags the +specifications give them: JPEGInterchangeFormat, and strips of JPEG or of +8 or 16-bit RGB or grey (taken by their high byte), in every directory the +chain, the SubIFDs and the Exif pointer reach. Every file is also searched for +JPEG streams, which is where the makers keep theirs (maker notes, boxes, +sections): a stream counts when its marker segments are well formed up to a +first scan, with a baseline, extended sequential or progressive frame of +8 bits. Lossless JPEG, which is what sensor data is compressed with, is not +read, and neither is the baseline JPEG of a lossy DNG's linear raw data, which +the directory that holds it tells apart. The reader takes the largest, tries +the next when one does not decode, and counts each as the RGBA the page holds +(four bytes a pixel, six when it must be turned) against the budget, so a +preview over it gives way to a smaller one. + +Every offset and count in the file is checked against the data. A directory is +read once, at most 64 are read, nested at most 3 deep, with at most 1,024 +entries and 65,536 strips each; at most 512 JPEG start markers are tried and +64 streams kept, each walked once. A file that panics a decoder is +`Undecodable`. The `raw_preview` fuzz target runs all of it. + +## Markdown + +Feature `markdown`, not a default. CommonMark with tables and strikethrough is +read by [pulldown-cmark](https://crates.io/crates/pulldown-cmark) (MIT), built +without its `html` and `simd` features so that no markup is made and the crate +is `forbid(unsafe_code)`, and folded into a tree of `Block`s and `Inline`s +with no step that recurses on the input. + +```rust +use exav_render::markdown::{parse, Block}; + +let doc = parse("# Title\n\nSome *text* and [a link](https://example.com)."); +assert!(matches!(doc.blocks[0], Block::Heading { level: 1, .. })); +let json = doc.to_json(); // the shape @exav/viewer's page reads +``` + +Raw HTML is text (a `