diff --git a/.github/workflows/mkdocs.yml b/.github/workflows/mkdocs.yml deleted file mode 100644 index 72816cd..0000000 --- a/.github/workflows/mkdocs.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Run mkdocs -on: - push: - branches: - - main -permissions: - contents: write -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Set up Python runtime - uses: actions/setup-python@v4 - with: - python-version: 3.x - - - name: Install Python dependencies - run: pip install mkdocs-monorepo-plugin mkdocs-redirects mkdocs-with-pdf weasyprint mkdocs-git-authors-plugin mkdocs-git-revision-date-localized-plugin mkdocs-git-committers-plugin-2 setuptools - - - name: Set up build cache - uses: actions/cache@v2 - with: - key: ${{ github.ref }} - path: .cache - - - name: Install Insiders build - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - run: pip install git+https://${GH_TOKEN}@github.com/squidfunk/mkdocs-material-insiders.git - - run: mkdocs gh-deploy --force diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..eb89841 --- /dev/null +++ b/404.html @@ -0,0 +1,1513 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ +

404 - Not found

+ +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index d1ba585..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,20 +0,0 @@ -# How to Contribute - -Thank you so *much* for offering to help out. We truly appreciate it. - -If you'd like to contribute, start by searching through the [issues](https://github.com/sparkfun/SparkFun_Micro_OLED_Arduino_Library/issues) and [pull requests](https://github.com/sparkfun/SparkFun_Micro_OLED_Arduino_Library/pulls) to see whether someone else has raised a similar idea or question. -Please check the [closed issues](https://github.com/sparkfun/SparkFun_Micro_OLED_Arduino_Library/issues?q=is%3Aissue+is%3Aclosed) -and [closed pull requests](https://github.com/sparkfun/SparkFun_Micro_OLED_Arduino_Library/pulls?q=is%3Apr+is%3Aclosed) too - you may find that your issue or feature has already been discussed. - -If you decide to add a feature to this library, please create a PR and follow these best practices: - -* Change as little as possible. Do not submit a PR that changes 100 lines of whitespace. Break up into multiple PRs if necessary. -* If you've added a new feature document it with a simple example sketch. This serves both as a test of your PR and as a quick way for users to quickly learn how to use your new feature. -* If you add new functions also add them to _keywords.txt_ so that they are properly highlighted in Arduino. [Read more](https://www.arduino.cc/en/Hacking/libraryTutorial). -* **Important:** Please submit your PR using the [release_candidate branch](https://github.com/sparkfun/SparkFun_Micro_OLED_Arduino_Library/tree/release_candidate). That way, we can merge and test your PR quickly without changing the _master_ branch - -![Contributing.JPG](./img/Contributing.JPG) - -## Style guide - -Please read and follow the [Arduino API style guide](https://www.arduino.cc/en/Reference/APIStyleGuide). Also read and consider the [Arduino style guide](https://www.arduino.cc/en/Reference/StyleGuide). diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 8203c34..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,55 +0,0 @@ -SparkFun License Information -============================ - -SparkFun uses two different licenses for our files — one for hardware and one for code. - -Hardware ---------- - -**SparkFun hardware is released under [Creative Commons Share-alike 4.0 International](http://creativecommons.org/licenses/by-sa/4.0/).** - -Note: This is a human-readable summary of (and not a substitute for) the [license](http://creativecommons.org/licenses/by-sa/4.0/legalcode). - -You are free to: - -Share — copy and redistribute the material in any medium or format -Adapt — remix, transform, and build upon the material -for any purpose, even commercially. -The licensor cannot revoke these freedoms as long as you follow the license terms. -Under the following terms: - -Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. -ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. -No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. -Notices: - -You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. -No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. - - -Code --------- - -**SparkFun code, firmware, and software is released under the [MIT License](http://opensource.org/licenses/MIT).** - -The MIT License (MIT) - -Copyright (c) 2015 SparkFun Electronics - -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. diff --git a/README.md b/README.md deleted file mode 100644 index b75fa7a..0000000 --- a/README.md +++ /dev/null @@ -1,80 +0,0 @@ -![SparkFun Qwiic OLED Arduino Library](https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library/blob/main/docs/img/OLEDLibBanner.png "SparkFun Qwiic OLED Arduino Library") - -# SparkFun Qwiic OLED Arduino Library -

- - - - - - follow on Twitter - - -

- - - - - - - - - - - - - - - - -
SparkFun Micro OLED Breakout (Qwiic)
[LCD-14532]
SparkFun Qwiic OLED Display (0.91 in, 128x32)
[LCD-24606]
smôl OLED Display (0.91 in, 128x32)
[SPX-18996]
SparkFun Transparent Graphical OLED Breakout (Qwiic)
[LCD-15173]
SparkFun Qwiic OLED - (1.3in., 128x64)
[LCD-23453]
- - -The SparkFun Qwiic OLED Arduino Library is a single graphics module that supports all SparkFun OLED boards based on the SSD1306 from Solomon Systech. Prior to this library, three different libraries were used to support our four different OLED boards. - -The SparkFun Qwiic OLED Library delivers a common implementation for all our Qwiic OLED products, delivering a unified, fast, and efficient solution that implements a familiar and easy to understand user experience. - -## Key Features -* Implements common graphics capabilities: pixel, line, rectangle, filled rectangle, circle, filled circle, bitmap, text and raster operators (i.e. XOR). -* Smart data transfer to the device – only sends _dirty_ regions of the graphics buffer to the OLED device, not the entire buffer. -* High performance – 2x faster than our previous OLED library, often much higher. -* Efficient memory usage. No dynamic memory utilized. Static resources are loaded once, and only on explicit declaration. -* Implements a familiar interface, making migration from older libraries straight forward - -## Documentation -A full library use overview, API reference guide and key example walk through are available on this repositories github page - [sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library](https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/) - -## How much faster? - -The SparkFun Qwiic OLED Library is between 40% and 450% faster. The original [Micro OLED library](https://github.com/sparkfun/SparkFun_Micro_OLED_Arduino_Library) had a max output of ~75 frames per second. This library automatically only updates *what changed* we can reach more than 300 frames per second. What does that look like? - -https://user-images.githubusercontent.com/117102/160000377-b2de6d3f-a90f-42da-bd95-2a301c817c80.mp4 - -Above, the OLED on the right is running the original Micro OLED library at 75fps. On the left the display is more than 348 frames per second. In real life it's quite smooth; the camera is not able to keep up. This is at 400kHz I2C. - -https://user-images.githubusercontent.com/117102/160000390-47a318ac-4158-4988-8831-44f7b9d32f01.mp4 - -Above, the OLED on the right is running the original Micro OLED library at 75fps. On the left the display is more than 107 frames per second because the clock takes up a lot of the display, but not all of it. This is at 400kHz I2C. - -## Supported Products - -* [LCD-22495](https://www.sparkfun.com/products/22495) - SparkFun Micro OLED Breakout (Qwiic) -* [LCD-14532](https://www.sparkfun.com/products/14532) - SparkFun Micro OLED Breakout (Qwiic) -* [LCD-13003](https://www.sparkfun.com/products/13003) - SparkFun Micro OLED Breakout -* [LCD-24606](https://www.sparkfun.com/products/24606) - SparkFun Qwiic OLED Display (0.91 in, 128x32) -* [LCD-17153](https://www.sparkfun.com/products/17153) - SparkFun Qwiic OLED Display (0.91 in, 128x32) -* [SPX-18996](https://www.sparkfun.com/products/18996) - smôl OLED Display (0.91 in, 128x32) -* [LCD-15173](https://www.sparkfun.com/products/15173) - SparkFun Transparent Graphical OLED Breakout (Qwiic) -* [LCD-23453](https://www.sparkfun.com/products/23453) - SparkFun Qwiic OLED (1.3 in., 128x64) - -### Supported Microcontrollers - Arduino Environment - -* [Artemis](https://www.sparkfun.com/products/15574) -* [SAMD51](https://www.sparkfun.com/products/14713) -* [ESP32](https://www.sparkfun.com/products/15663) -* [STM32](https://www.sparkfun.com/products/17712) -* [SAMD21](https://www.sparkfun.com/products/14812) -* [nrf5280](https://www.sparkfun.com/products/15025) -* [Teensy](https://www.sparkfun.com/products/16402) -* [ATMega328](https://www.sparkfun.com/products/18158) diff --git a/api_arduino/index.html b/api_arduino/index.html new file mode 100644 index 0000000..968e4fa --- /dev/null +++ b/api_arduino/index.html @@ -0,0 +1,1852 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Arduino Print - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Arduino Print

+

Methods used to support Arduino Print functionality.

+

setCursor()

+

This method is called set the "cursor" position in the device. The library supports the Arduino Print interface, enabling the use of a print() and println() methods. The set cursor position defines where to start text output for this functionality.

+
void setCursor(uint8_t x, uint8_t y)
+
+ + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
xuint8_tThe X coordinate of the cursor
yuint8_tThe Y coordinate of the cursor
+

setColor()

+

This method is called to set the current color of the system. This is used by the Arduino Print interface functionality

+
void setColor(uint8_t clr)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
clruint8_tThe color to set. 0 = black, > 0 = white
+

getColor()

+

This method is called to get the current color of the system. This is used by the Arduino Print interface functionality

+
uint8_t getColor(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valueuint8_tThe current color
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api_device/index.html b/api_device/index.html new file mode 100644 index 0000000..6c079a1 --- /dev/null +++ b/api_device/index.html @@ -0,0 +1,2204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Device - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Device Operations

+

Methods to setup the device, get device information and change display options.

+

Initialization

+

begin()

+

This method is called to initialize the OLED library and connection to the OLED device. This method must be called before calling any graphics methods.

+
bool begin(TwoWire &wirePort, uint8_t address)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
wirePortTwoWireoptional. The Wire port. If not provided, the default port is used
addressuint8_toptional. I2C Address. If not provided, the default address is used.
return valuebooltrue on success, false on startup failure
+

reset()

+

When called, this method reset the library state and OLED device to their intial state. Helpful to reset the OLED after waking up a system from a sleep state.

+
void reset()
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valuebooltrue on success, false on startup failure
+

Geometry

+

getWidth()

+

This method returns the width, in pixels, of the connected OLED device

+
uint8_t getWidth(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valueuint8_tThe width in pixels of the connected OLED device
+

getHeight()

+

This method returns the height, in pixels, of the connected OLED device

+
uint8_t getHeight(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valueuint8_tThe height in pixels of the connected OLED device
+

Display Modes

+

invert()

+

This method inverts the current graphics on the display. This results of this command happen immediatly.

+
void invert(bool bInvert)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
bInvertbooltrue - the screen is inverted. false - the screen is set to normal
+

flipVertical()

+

When called, the screen contents are flipped vertically if the flip parameter is true, or restored to normal display if the flip parameter is false.

+
void flipVertical(bool bFlip)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
bFlipbooltrue - the screen is flipped vertically. false - the screen is set to normal
+

flipHorizontal()

+

When called, the screen contents are flipped horizontally if the flip parameter is true, or restored to normal display if the flip parameter is false.

+
void flipHorizontal(bool bFlip)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
bFlipbooltrue - the screen is flipped horizontally. false - the screen is set to normal
+

displayPower()

+

Used to turn the OLED display on or off.

+
void displayPower(bool bEnable)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
bEnablebooltrue - the OLED display is powered on (default). false - the OLED dsiplay is powered off.
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api_draw/index.html b/api_draw/index.html new file mode 100644 index 0000000..9aefa70 --- /dev/null +++ b/api_draw/index.html @@ -0,0 +1,2163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Drawing State - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Drawing Settings/State

+

Methods for setting the drawing state of the library.

+

setFont()

+

This method is called to set the current font in the library. The current font is used when calling the text() method on this device.

+

The default font for the device is 5x7.

+
void setFont(QwiicFont& theFont)
+void setFont(const QwiicFont * theFont)
+
+ + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
theFontQwiicFontThe font to set as current in the device
theFontQwiicFont*Pointer to the font to set as current in the device.
+

For the library, fonts are added to your program by including them via include files which are part of this library.

+

The following fonts are included:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FontInclude FileFont VariableDescription
5x7<res/qw_fnt_5x7.h>QW_FONT_5X7A full, 5 x 7 font
31x48<res/qw_fnt_31x48.h>QW_FONT_31X48A full, 31 x 48 font
Seven Segment<res/qw_fnt_7segment.h>QW_FONT_7SEGMENTNumbers only
8x16<res/qw_fnt_8x16.h>QW_FONT_8X16A full, 8 x 16 font
Large Numbers<res/qw_fnt_largenum.h>QW_FONT_LARGENUMNumbers only
+

For each font, the font variables are objects with the following attributes:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeValue
widthThe font width in pixels
heightThe font height in pixels
startThe font start character offset
n_charsThe number of characters
map_widthThe width of the font map
+

Example use of a font object attribute: +

#include <res/qw_fnt_31x48.h>
+
+int myFontWidth = QW_FONT_31X48.width;
+

+

getFont()

+

This method returns the current font for the device.

+
QwiicFont * getFont(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valueQwiicFont*A pointer to the current font. See setFont() for font object details.
+

getFontName()

+

This method returns the height in pixels of a provided String based on the current device font.

+
String getFontName(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valueStringThe name of the current font.
+

getStringWidth()

+

This method returns the width in pixels of a provided String based on the current device font.

+
unsigned int getStringWidth(String text)
+
+ + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
textStringThe string used to determine width
return valueunsigned intThe width of the provide string, as determined using the current font.
+

getStringHeight()

+

This method returns the height in pixels of a provided String based on the current device font.

+
unsigned int getStringHeight(String text)
+
+ + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
textStringThe string used to determine height
return valueunsigned intThe height of the provide string, as determined using the current font.
+

setDrawMode()

+

This method sets the current draw mode for the library. The draw mode determines how pixels are set on the screen during drawing operations.

+
void setDrawMode(grRasterOp_t rop)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
ropgrRasterOp_tThe raster operation (ROP) to set the graphics system to.
+

Raster operations device how source (pixels to draw) are represented on the destination device. The available Raster Operation (ROP) codes are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ROP CodeDescription
grROPCopydefault Drawn pixel values are copied to the device screen
grROPNotCopyA not operation is applied to the source value before copying to screen
grROPNotA not operation is applied to the destination (screen) value
grROPXORA XOR operation is performed between the source and destination values
grROPBlackA value of 0, or black is drawn to the destination
grROPWhiteA value of 1, or black is drawn to the destination
+

getDrawMode()

+

This method returns the current draw mode for the library. The draw mode determines how pixels are set on the screen during drawing operations.

+
grRasterOp_t getDrawMode(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valuegrRasterOp_tThe current aster operation (ROP) of the graphics system.
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api_graphics/index.html b/api_graphics/index.html new file mode 100644 index 0000000..e45c922 --- /dev/null +++ b/api_graphics/index.html @@ -0,0 +1,2446 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Graphics - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Graphics Methods

+

Methods used to draw and display graphics.

+

display()

+

When called, any pending display updates are sent to the connected OLED device. This includes drawn graphics and erase commands.

+
void display(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
NONE
+

erase()

+

Erases all graphics on the device, placing the display in a blank state. The erase update isn't sent to the device until the next display() call on the device.

+
void erase(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
NONE
+

pixel()

+

Set the value of a pixel on the screen.

+
void pixel(uint8_t x, uint8_t y, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
xuint8_tThe X coordinate of the pixel to set
yuint8_tThe Y coordinate of the pixel to set
clruint8_toptional The color value to set the pixel. This defaults to white (1).
+

line()

+

Draw a line on the screen.

+

Note: If a line is horizontal (y0 = y1) or vertical (x0 = x1), optimized draw algorithms are used by the library.

+
void line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe start X coordinate of the line
y0uint8_tThe start Y coordinate of the line
x1uint8_tThe end X coordinate of the line
y1uint8_tThe end Y coordinate of the line
clruint8_toptional The color value to draw the line. This defaults to white (1).
+

rectangle()

+

Draw a rectangle on the screen.

+
void rectangle(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe start X coordinate of the rectangle - upper left corner
y0uint8_tThe start Y coordinate of the rectangle - upper left corner
widthuint8_tThe width of the rectangle
heightuint8_tThe height of the rectangle
clruint8_toptional The color value to draw the line. This defaults to white (1).
+

rectangleFill()

+

Draw a filled rectangle on the screen.

+
void rectangleFill(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe start X coordinate of the rectangle - upper left corner
y0uint8_tThe start Y coordinate of the rectangle - upper left corner
widthuint8_tThe width of the rectangle
heightuint8_tThe height of the rectangle
clruint8_toptional The color value to draw the line. This defaults to white (1).
+

circle()

+

Draw a circle on the screen.

+
void circle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate of the circle center
y0uint8_tThe Y coordinate of the circle center
radiusuint8_tThe radius of the circle
clruint8_toptional The color value to draw the circle. This defaults to white (1).
+

circleFill()

+

Draw a filled circle on the screen.

+
void circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate of the circle center
y0uint8_tThe Y coordinate of the circle center
radiusuint8_tThe radius of the circle
clruint8_toptional The color value to draw the circle. This defaults to white (1).
+

bitmap()

+

Draws a bitmap on the screen.

+

The bitmap should be 8 bit encoded - each pixel contains 8 y values.

+
void bitmap(uint8_t x0, uint8_t y0, uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height )
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate to place the bitmap - upper left corner
y0uint8_tThe Y coordinate to place the bitmap - upper left corner
pBitmapuint8_t *A pointer to the bitmap array
bmp_widthuint8_tThe width of the bitmap
bmp_heightuint8_tThe height of the bitmap
+

bitmap()

+

Draws a bitmap on the screen.

+

The bitmap should be 8 bit encoded - each pixel contains 8 y values.

+

The coordinate [x1,y1] allows for only a portion of bitmap to be drawn.

+
void bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, 
+                uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height )
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate to place the bitmap - upper left corner
y0uint8_tThe Y coordinate to place the bitmap - upper left corner
x1uint8_tThe end X coordinate of the bitmap - lower right corner
y1uint8_tThe end Y coordinate of the bitmap - lower right corner
pBitmapuint8_t *A pointer to the bitmap array
bmp_widthuint8_tThe width of the bitmap
bmp_heightuint8_tThe height of the bitmap
+

bitmap()

+

Draws a bitmap on the screen using a Bitmap object for the bitmap data.

+
void bitmap(uint8_t x0, uint8_t y0, QwiicBitmap& bitmap)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate to place the bitmap - upper left corner
y0uint8_tThe Y coordinate to place the bitmap - upper left corner
BitmapQwiicBitmapA bitmap object
+

text()

+

Draws a string using the current font on the screen.

+
void text(uint8_t x0, uint8_t y0, const char * text, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate to start drawing the text
y0uint8_tThe Y coordinate to start drawing the text
textconst char*The string to draw on the screen
textStringThe Arduino string to draw on the screen
clruint8_toptional The color value to draw the circle. This defaults to white (1).
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api_scroll/index.html b/api_scroll/index.html new file mode 100644 index 0000000..687b77d --- /dev/null +++ b/api_scroll/index.html @@ -0,0 +1,2026 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scrolling - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Scrolling

+

Methods for device scrolling

+

scrollStop()

+

If the device is in a scrolling mode, calling this method stops the scroll, and restores the device to normal display operation. This action is performed immediately.

+
void scrollStop(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
NONE
+

scrollRight()

+

This method is called to start the device scrolling the displayed graphics to the right. This action is performed immediately.

+

The screen will scroll until the scrollStop() method is called.

+
void scrollRight(uint8_t start, uint8_t stop, uint8_t interval)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
startuint8_tThe start page address of the scroll - valid values are 0 thru 7
stopuint8_tThe stop/end page address of the scroll - valid values are 0 thru 7
intervaluint8_tThe time interval between scroll step - values listed below
+

Defined values for the interval parameter:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Defined SymbolTime Interval Between Steps
SCROLL_INTERVAL_2_FRAMES2
SCROLL_INTERVAL_3_FRAMES3
SCROLL_INTERVAL_4_FRAMES4
SCROLL_INTERVAL_5_FRAMES5
SCROLL_INTERVAL_25_FRAMES25
SCROLL_INTERVAL_64_FRAMES64
SCROLL_INTERVAL_128_FRAMES128
SCROLL_INTERVAL_256_FRAMES256
+

scrollVertRight()

+

This method is called to start the device scrolling the displayed graphics vertically and to the right. This action is performed immediately.

+

The screen will scroll until the scrollStop() method is called.

+
void scrolVertlRight(uint8_t start, uint8_t stop, uint8_t interval)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
startuint8_tThe start page address of the scroll - valid values are 0 thru 7
stopuint8_tThe stop/end page address of the scroll - valid values are 0 thru 7
intervaluint8_tThe time interval between scroll step - values listed in scrollRight
+

scrollLeft()

+

This method is called start to the device scrolling the displayed graphics to the left. This action is performed immediately.

+

The screen will scroll until the scrollStop() method is called.

+
void scrollLeft(uint8_t start, uint8_t stop, uint8_t interval)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
startuint8_tThe start page address of the scroll - valid values are 0 thru 7
stopuint8_tThe stop/end page address of the scroll - valid values are 0 thru 7
intervaluint8_tThe time interval between scroll step - values listed in scrollRight
+

scrollVertLeft()

+

This method is called to start the device scrolling the displayed graphics vertically and to the left. This action is performed immediately.

+

The screen will scroll until the scrollStop() method is called.

+
void scrolVertlLeft(uint8_t start, uint8_t stop, uint8_t interval)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
startuint8_tThe start page address of the scroll - valid values are 0 thru 7
stopuint8_tThe stop/end page address of the scroll - valid values are 0 thru 7
intervaluint8_tThe time interval between scroll step - values listed in scrollRight
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/assets/MicroMod-logo-updated.png b/assets/MicroMod-logo-updated.png similarity index 100% rename from docs/assets/MicroMod-logo-updated.png rename to assets/MicroMod-logo-updated.png diff --git a/docs/assets/Qwiic-registered-updated.png b/assets/Qwiic-registered-updated.png similarity index 100% rename from docs/assets/Qwiic-registered-updated.png rename to assets/Qwiic-registered-updated.png diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000..1cf13b9 Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/javascripts/bundle.5a789024.min.js b/assets/javascripts/bundle.5a789024.min.js new file mode 100644 index 0000000..3e1321c --- /dev/null +++ b/assets/javascripts/bundle.5a789024.min.js @@ -0,0 +1,3 @@ +"use strict";(()=>{var Zi=Object.create;var _r=Object.defineProperty;var ea=Object.getOwnPropertyDescriptor;var ta=Object.getOwnPropertyNames,Gt=Object.getOwnPropertySymbols,ra=Object.getPrototypeOf,Ar=Object.prototype.hasOwnProperty,bo=Object.prototype.propertyIsEnumerable;var ho=(e,t,r)=>t in e?_r(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,R=(e,t)=>{for(var r in t||(t={}))Ar.call(t,r)&&ho(e,r,t[r]);if(Gt)for(var r of Gt(t))bo.call(t,r)&&ho(e,r,t[r]);return e};var vo=(e,t)=>{var r={};for(var o in e)Ar.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o]);if(e!=null&&Gt)for(var o of Gt(e))t.indexOf(o)<0&&bo.call(e,o)&&(r[o]=e[o]);return r};var Cr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var oa=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of ta(t))!Ar.call(e,n)&&n!==r&&_r(e,n,{get:()=>t[n],enumerable:!(o=ea(t,n))||o.enumerable});return e};var Rt=(e,t,r)=>(r=e!=null?Zi(ra(e)):{},oa(t||!e||!e.__esModule?_r(r,"default",{value:e,enumerable:!0}):r,e));var go=(e,t,r)=>new Promise((o,n)=>{var i=c=>{try{a(r.next(c))}catch(p){n(p)}},s=c=>{try{a(r.throw(c))}catch(p){n(p)}},a=c=>c.done?o(c.value):Promise.resolve(c.value).then(i,s);a((r=r.apply(e,t)).next())});var xo=Cr((kr,yo)=>{(function(e,t){typeof kr=="object"&&typeof yo!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(kr,function(){"use strict";function e(r){var o=!0,n=!1,i=null,s={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function a(k){return!!(k&&k!==document&&k.nodeName!=="HTML"&&k.nodeName!=="BODY"&&"classList"in k&&"contains"in k.classList)}function c(k){var ut=k.type,je=k.tagName;return!!(je==="INPUT"&&s[ut]&&!k.readOnly||je==="TEXTAREA"&&!k.readOnly||k.isContentEditable)}function p(k){k.classList.contains("focus-visible")||(k.classList.add("focus-visible"),k.setAttribute("data-focus-visible-added",""))}function l(k){k.hasAttribute("data-focus-visible-added")&&(k.classList.remove("focus-visible"),k.removeAttribute("data-focus-visible-added"))}function f(k){k.metaKey||k.altKey||k.ctrlKey||(a(r.activeElement)&&p(r.activeElement),o=!0)}function u(k){o=!1}function d(k){a(k.target)&&(o||c(k.target))&&p(k.target)}function v(k){a(k.target)&&(k.target.classList.contains("focus-visible")||k.target.hasAttribute("data-focus-visible-added"))&&(n=!0,window.clearTimeout(i),i=window.setTimeout(function(){n=!1},100),l(k.target))}function S(k){document.visibilityState==="hidden"&&(n&&(o=!0),X())}function X(){document.addEventListener("mousemove",ee),document.addEventListener("mousedown",ee),document.addEventListener("mouseup",ee),document.addEventListener("pointermove",ee),document.addEventListener("pointerdown",ee),document.addEventListener("pointerup",ee),document.addEventListener("touchmove",ee),document.addEventListener("touchstart",ee),document.addEventListener("touchend",ee)}function re(){document.removeEventListener("mousemove",ee),document.removeEventListener("mousedown",ee),document.removeEventListener("mouseup",ee),document.removeEventListener("pointermove",ee),document.removeEventListener("pointerdown",ee),document.removeEventListener("pointerup",ee),document.removeEventListener("touchmove",ee),document.removeEventListener("touchstart",ee),document.removeEventListener("touchend",ee)}function ee(k){k.target.nodeName&&k.target.nodeName.toLowerCase()==="html"||(o=!1,re())}document.addEventListener("keydown",f,!0),document.addEventListener("mousedown",u,!0),document.addEventListener("pointerdown",u,!0),document.addEventListener("touchstart",u,!0),document.addEventListener("visibilitychange",S,!0),X(),r.addEventListener("focus",d,!0),r.addEventListener("blur",v,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var ro=Cr((Uy,Pn)=>{"use strict";var qa=/["'&<>]/;Pn.exports=Ka;function Ka(e){var t=""+e,r=qa.exec(t);if(!r)return t;var o,n="",i=0,s=0;for(i=r.index;i{(function(t,r){typeof zt=="object"&&typeof io=="object"?io.exports=r():typeof define=="function"&&define.amd?define([],r):typeof zt=="object"?zt.ClipboardJS=r():t.ClipboardJS=r()})(zt,function(){return function(){var e={686:function(o,n,i){"use strict";i.d(n,{default:function(){return Xi}});var s=i(279),a=i.n(s),c=i(370),p=i.n(c),l=i(817),f=i.n(l);function u(q){try{return document.execCommand(q)}catch(C){return!1}}var d=function(C){var _=f()(C);return u("cut"),_},v=d;function S(q){var C=document.documentElement.getAttribute("dir")==="rtl",_=document.createElement("textarea");_.style.fontSize="12pt",_.style.border="0",_.style.padding="0",_.style.margin="0",_.style.position="absolute",_.style[C?"right":"left"]="-9999px";var D=window.pageYOffset||document.documentElement.scrollTop;return _.style.top="".concat(D,"px"),_.setAttribute("readonly",""),_.value=q,_}var X=function(C,_){var D=S(C);_.container.appendChild(D);var N=f()(D);return u("copy"),D.remove(),N},re=function(C){var _=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},D="";return typeof C=="string"?D=X(C,_):C instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(C==null?void 0:C.type)?D=X(C.value,_):(D=f()(C),u("copy")),D},ee=re;function k(q){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?k=function(_){return typeof _}:k=function(_){return _&&typeof Symbol=="function"&&_.constructor===Symbol&&_!==Symbol.prototype?"symbol":typeof _},k(q)}var ut=function(){var C=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},_=C.action,D=_===void 0?"copy":_,N=C.container,G=C.target,We=C.text;if(D!=="copy"&&D!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(G!==void 0)if(G&&k(G)==="object"&&G.nodeType===1){if(D==="copy"&&G.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(D==="cut"&&(G.hasAttribute("readonly")||G.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(We)return ee(We,{container:N});if(G)return D==="cut"?v(G):ee(G,{container:N})},je=ut;function P(q){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?P=function(_){return typeof _}:P=function(_){return _&&typeof Symbol=="function"&&_.constructor===Symbol&&_!==Symbol.prototype?"symbol":typeof _},P(q)}function se(q,C){if(!(q instanceof C))throw new TypeError("Cannot call a class as a function")}function ce(q,C){for(var _=0;_0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof N.action=="function"?N.action:this.defaultAction,this.target=typeof N.target=="function"?N.target:this.defaultTarget,this.text=typeof N.text=="function"?N.text:this.defaultText,this.container=P(N.container)==="object"?N.container:document.body}},{key:"listenClick",value:function(N){var G=this;this.listener=p()(N,"click",function(We){return G.onClick(We)})}},{key:"onClick",value:function(N){var G=N.delegateTarget||N.currentTarget,We=this.action(G)||"copy",Bt=je({action:We,container:this.container,target:this.target(G),text:this.text(G)});this.emit(Bt?"success":"error",{action:We,text:Bt,trigger:G,clearSelection:function(){G&&G.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(N){return Mr("action",N)}},{key:"defaultTarget",value:function(N){var G=Mr("target",N);if(G)return document.querySelector(G)}},{key:"defaultText",value:function(N){return Mr("text",N)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(N){var G=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return ee(N,G)}},{key:"cut",value:function(N){return v(N)}},{key:"isSupported",value:function(){var N=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],G=typeof N=="string"?[N]:N,We=!!document.queryCommandSupported;return G.forEach(function(Bt){We=We&&!!document.queryCommandSupported(Bt)}),We}}]),_}(a()),Xi=Ji},828:function(o){var n=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function s(a,c){for(;a&&a.nodeType!==n;){if(typeof a.matches=="function"&&a.matches(c))return a;a=a.parentNode}}o.exports=s},438:function(o,n,i){var s=i(828);function a(l,f,u,d,v){var S=p.apply(this,arguments);return l.addEventListener(u,S,v),{destroy:function(){l.removeEventListener(u,S,v)}}}function c(l,f,u,d,v){return typeof l.addEventListener=="function"?a.apply(null,arguments):typeof u=="function"?a.bind(null,document).apply(null,arguments):(typeof l=="string"&&(l=document.querySelectorAll(l)),Array.prototype.map.call(l,function(S){return a(S,f,u,d,v)}))}function p(l,f,u,d){return function(v){v.delegateTarget=s(v.target,f),v.delegateTarget&&d.call(l,v)}}o.exports=c},879:function(o,n){n.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},n.nodeList=function(i){var s=Object.prototype.toString.call(i);return i!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in i&&(i.length===0||n.node(i[0]))},n.string=function(i){return typeof i=="string"||i instanceof String},n.fn=function(i){var s=Object.prototype.toString.call(i);return s==="[object Function]"}},370:function(o,n,i){var s=i(879),a=i(438);function c(u,d,v){if(!u&&!d&&!v)throw new Error("Missing required arguments");if(!s.string(d))throw new TypeError("Second argument must be a String");if(!s.fn(v))throw new TypeError("Third argument must be a Function");if(s.node(u))return p(u,d,v);if(s.nodeList(u))return l(u,d,v);if(s.string(u))return f(u,d,v);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function p(u,d,v){return u.addEventListener(d,v),{destroy:function(){u.removeEventListener(d,v)}}}function l(u,d,v){return Array.prototype.forEach.call(u,function(S){S.addEventListener(d,v)}),{destroy:function(){Array.prototype.forEach.call(u,function(S){S.removeEventListener(d,v)})}}}function f(u,d,v){return a(document.body,u,d,v)}o.exports=c},817:function(o){function n(i){var s;if(i.nodeName==="SELECT")i.focus(),s=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var a=i.hasAttribute("readonly");a||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),a||i.removeAttribute("readonly"),s=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var c=window.getSelection(),p=document.createRange();p.selectNodeContents(i),c.removeAllRanges(),c.addRange(p),s=c.toString()}return s}o.exports=n},279:function(o){function n(){}n.prototype={on:function(i,s,a){var c=this.e||(this.e={});return(c[i]||(c[i]=[])).push({fn:s,ctx:a}),this},once:function(i,s,a){var c=this;function p(){c.off(i,p),s.apply(a,arguments)}return p._=s,this.on(i,p,a)},emit:function(i){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[i]||[]).slice(),c=0,p=a.length;for(c;c0&&i[i.length-1])&&(p[0]===6||p[0]===2)){r=0;continue}if(p[0]===3&&(!i||p[1]>i[0]&&p[1]=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function K(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var o=r.call(e),n,i=[],s;try{for(;(t===void 0||t-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(a){s={error:a}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(s)throw s.error}}return i}function B(e,t,r){if(r||arguments.length===2)for(var o=0,n=t.length,i;o1||c(d,S)})},v&&(n[d]=v(n[d])))}function c(d,v){try{p(o[d](v))}catch(S){u(i[0][3],S)}}function p(d){d.value instanceof dt?Promise.resolve(d.value.v).then(l,f):u(i[0][2],d)}function l(d){c("next",d)}function f(d){c("throw",d)}function u(d,v){d(v),i.shift(),i.length&&c(i[0][0],i[0][1])}}function To(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof Oe=="function"?Oe(e):e[Symbol.iterator](),r={},o("next"),o("throw"),o("return"),r[Symbol.asyncIterator]=function(){return this},r);function o(i){r[i]=e[i]&&function(s){return new Promise(function(a,c){s=e[i](s),n(a,c,s.done,s.value)})}}function n(i,s,a,c){Promise.resolve(c).then(function(p){i({value:p,done:a})},s)}}function I(e){return typeof e=="function"}function yt(e){var t=function(o){Error.call(o),o.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var Xt=yt(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(o,n){return n+1+") "+o.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Ze(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var qe=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,o,n,i;if(!this.closed){this.closed=!0;var s=this._parentage;if(s)if(this._parentage=null,Array.isArray(s))try{for(var a=Oe(s),c=a.next();!c.done;c=a.next()){var p=c.value;p.remove(this)}}catch(S){t={error:S}}finally{try{c&&!c.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}else s.remove(this);var l=this.initialTeardown;if(I(l))try{l()}catch(S){i=S instanceof Xt?S.errors:[S]}var f=this._finalizers;if(f){this._finalizers=null;try{for(var u=Oe(f),d=u.next();!d.done;d=u.next()){var v=d.value;try{So(v)}catch(S){i=i!=null?i:[],S instanceof Xt?i=B(B([],K(i)),K(S.errors)):i.push(S)}}}catch(S){o={error:S}}finally{try{d&&!d.done&&(n=u.return)&&n.call(u)}finally{if(o)throw o.error}}}if(i)throw new Xt(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)So(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Ze(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Ze(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var $r=qe.EMPTY;function Zt(e){return e instanceof qe||e&&"closed"in e&&I(e.remove)&&I(e.add)&&I(e.unsubscribe)}function So(e){I(e)?e():e.unsubscribe()}var De={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var xt={setTimeout:function(e,t){for(var r=[],o=2;o0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var o=this,n=this,i=n.hasError,s=n.isStopped,a=n.observers;return i||s?$r:(this.currentObservers=null,a.push(r),new qe(function(){o.currentObservers=null,Ze(a,r)}))},t.prototype._checkFinalizedStatuses=function(r){var o=this,n=o.hasError,i=o.thrownError,s=o.isStopped;n?r.error(i):s&&r.complete()},t.prototype.asObservable=function(){var r=new F;return r.source=this,r},t.create=function(r,o){return new Ho(r,o)},t}(F);var Ho=function(e){ie(t,e);function t(r,o){var n=e.call(this)||this;return n.destination=r,n.source=o,n}return t.prototype.next=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.next)===null||n===void 0||n.call(o,r)},t.prototype.error=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.error)===null||n===void 0||n.call(o,r)},t.prototype.complete=function(){var r,o;(o=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||o===void 0||o.call(r)},t.prototype._subscribe=function(r){var o,n;return(n=(o=this.source)===null||o===void 0?void 0:o.subscribe(r))!==null&&n!==void 0?n:$r},t}(T);var jr=function(e){ie(t,e);function t(r){var o=e.call(this)||this;return o._value=r,o}return Object.defineProperty(t.prototype,"value",{get:function(){return this.getValue()},enumerable:!1,configurable:!0}),t.prototype._subscribe=function(r){var o=e.prototype._subscribe.call(this,r);return!o.closed&&r.next(this._value),o},t.prototype.getValue=function(){var r=this,o=r.hasError,n=r.thrownError,i=r._value;if(o)throw n;return this._throwIfClosed(),i},t.prototype.next=function(r){e.prototype.next.call(this,this._value=r)},t}(T);var It={now:function(){return(It.delegate||Date).now()},delegate:void 0};var Ft=function(e){ie(t,e);function t(r,o,n){r===void 0&&(r=1/0),o===void 0&&(o=1/0),n===void 0&&(n=It);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=o,i._timestampProvider=n,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=o===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,o),i}return t.prototype.next=function(r){var o=this,n=o.isStopped,i=o._buffer,s=o._infiniteTimeWindow,a=o._timestampProvider,c=o._windowTime;n||(i.push(r),!s&&i.push(a.now()+c)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var o=this._innerSubscribe(r),n=this,i=n._infiniteTimeWindow,s=n._buffer,a=s.slice(),c=0;c0?e.prototype.schedule.call(this,r,o):(this.delay=o,this.state=r,this.scheduler.flush(this),this)},t.prototype.execute=function(r,o){return o>0||this.closed?e.prototype.execute.call(this,r,o):this._execute(r,o)},t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!=null&&n>0||n==null&&this.delay>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.flush(this),0)},t}(St);var Po=function(e){ie(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t}(Ot);var Dr=new Po(Ro);var Io=function(e){ie(t,e);function t(r,o){var n=e.call(this,r,o)||this;return n.scheduler=r,n.work=o,n}return t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!==null&&n>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.actions.push(this),r._scheduled||(r._scheduled=Tt.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,o,n){var i;if(n===void 0&&(n=0),n!=null?n>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,o,n);var s=r.actions;o!=null&&((i=s[s.length-1])===null||i===void 0?void 0:i.id)!==o&&(Tt.cancelAnimationFrame(o),r._scheduled=void 0)},t}(St);var Fo=function(e){ie(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var o=this._scheduled;this._scheduled=void 0;var n=this.actions,i;r=r||n.shift();do if(i=r.execute(r.state,r.delay))break;while((r=n[0])&&r.id===o&&n.shift());if(this._active=!1,i){for(;(r=n[0])&&r.id===o&&n.shift();)r.unsubscribe();throw i}},t}(Ot);var ye=new Fo(Io);var y=new F(function(e){return e.complete()});function rr(e){return e&&I(e.schedule)}function Vr(e){return e[e.length-1]}function pt(e){return I(Vr(e))?e.pop():void 0}function Fe(e){return rr(Vr(e))?e.pop():void 0}function or(e,t){return typeof Vr(e)=="number"?e.pop():t}var Lt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function nr(e){return I(e==null?void 0:e.then)}function ir(e){return I(e[wt])}function ar(e){return Symbol.asyncIterator&&I(e==null?void 0:e[Symbol.asyncIterator])}function sr(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function fa(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var cr=fa();function pr(e){return I(e==null?void 0:e[cr])}function lr(e){return wo(this,arguments,function(){var r,o,n,i;return Jt(this,function(s){switch(s.label){case 0:r=e.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,dt(r.read())];case 3:return o=s.sent(),n=o.value,i=o.done,i?[4,dt(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,dt(n)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function mr(e){return I(e==null?void 0:e.getReader)}function U(e){if(e instanceof F)return e;if(e!=null){if(ir(e))return ua(e);if(Lt(e))return da(e);if(nr(e))return ha(e);if(ar(e))return jo(e);if(pr(e))return ba(e);if(mr(e))return va(e)}throw sr(e)}function ua(e){return new F(function(t){var r=e[wt]();if(I(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function da(e){return new F(function(t){for(var r=0;r=2;return function(o){return o.pipe(e?g(function(n,i){return e(n,i,o)}):be,Ee(1),r?Qe(t):tn(function(){return new ur}))}}function Yr(e){return e<=0?function(){return y}:E(function(t,r){var o=[];t.subscribe(w(r,function(n){o.push(n),e=2,!0))}function le(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new T}:t,o=e.resetOnError,n=o===void 0?!0:o,i=e.resetOnComplete,s=i===void 0?!0:i,a=e.resetOnRefCountZero,c=a===void 0?!0:a;return function(p){var l,f,u,d=0,v=!1,S=!1,X=function(){f==null||f.unsubscribe(),f=void 0},re=function(){X(),l=u=void 0,v=S=!1},ee=function(){var k=l;re(),k==null||k.unsubscribe()};return E(function(k,ut){d++,!S&&!v&&X();var je=u=u!=null?u:r();ut.add(function(){d--,d===0&&!S&&!v&&(f=Br(ee,c))}),je.subscribe(ut),!l&&d>0&&(l=new bt({next:function(P){return je.next(P)},error:function(P){S=!0,X(),f=Br(re,n,P),je.error(P)},complete:function(){v=!0,X(),f=Br(re,s),je.complete()}}),U(k).subscribe(l))})(p)}}function Br(e,t){for(var r=[],o=2;oe.next(document)),e}function M(e,t=document){return Array.from(t.querySelectorAll(e))}function j(e,t=document){let r=ue(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function ue(e,t=document){return t.querySelector(e)||void 0}function Ne(){var e,t,r,o;return(o=(r=(t=(e=document.activeElement)==null?void 0:e.shadowRoot)==null?void 0:t.activeElement)!=null?r:document.activeElement)!=null?o:void 0}var Pa=L(h(document.body,"focusin"),h(document.body,"focusout")).pipe(Ae(1),Q(void 0),m(()=>Ne()||document.body),Z(1));function Ye(e){return Pa.pipe(m(t=>e.contains(t)),Y())}function it(e,t){return H(()=>L(h(e,"mouseenter").pipe(m(()=>!0)),h(e,"mouseleave").pipe(m(()=>!1))).pipe(t?Ut(r=>He(+!r*t)):be,Q(e.matches(":hover"))))}function sn(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)sn(e,r)}function x(e,t,...r){let o=document.createElement(e);if(t)for(let n of Object.keys(t))typeof t[n]!="undefined"&&(typeof t[n]!="boolean"?o.setAttribute(n,t[n]):o.setAttribute(n,""));for(let n of r)sn(o,n);return o}function br(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function At(e){let t=x("script",{src:e});return H(()=>(document.head.appendChild(t),L(h(t,"load"),h(t,"error").pipe(b(()=>Nr(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(m(()=>{}),A(()=>document.head.removeChild(t)),Ee(1))))}var cn=new T,Ia=H(()=>typeof ResizeObserver=="undefined"?At("https://unpkg.com/resize-observer-polyfill"):$(void 0)).pipe(m(()=>new ResizeObserver(e=>e.forEach(t=>cn.next(t)))),b(e=>L(tt,$(e)).pipe(A(()=>e.disconnect()))),Z(1));function de(e){return{width:e.offsetWidth,height:e.offsetHeight}}function Le(e){let t=e;for(;t.clientWidth===0&&t.parentElement;)t=t.parentElement;return Ia.pipe(O(r=>r.observe(t)),b(r=>cn.pipe(g(o=>o.target===t),A(()=>r.unobserve(t)))),m(()=>de(e)),Q(de(e)))}function Ct(e){return{width:e.scrollWidth,height:e.scrollHeight}}function vr(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}function pn(e){let t=[],r=e.parentElement;for(;r;)(e.clientWidth>r.clientWidth||e.clientHeight>r.clientHeight)&&t.push(r),r=(e=r).parentElement;return t.length===0&&t.push(document.documentElement),t}function Be(e){return{x:e.offsetLeft,y:e.offsetTop}}function ln(e){let t=e.getBoundingClientRect();return{x:t.x+window.scrollX,y:t.y+window.scrollY}}function mn(e){return L(h(window,"load"),h(window,"resize")).pipe($e(0,ye),m(()=>Be(e)),Q(Be(e)))}function gr(e){return{x:e.scrollLeft,y:e.scrollTop}}function Ge(e){return L(h(e,"scroll"),h(window,"scroll"),h(window,"resize")).pipe($e(0,ye),m(()=>gr(e)),Q(gr(e)))}var fn=new T,Fa=H(()=>$(new IntersectionObserver(e=>{for(let t of e)fn.next(t)},{threshold:0}))).pipe(b(e=>L(tt,$(e)).pipe(A(()=>e.disconnect()))),Z(1));function mt(e){return Fa.pipe(O(t=>t.observe(e)),b(t=>fn.pipe(g(({target:r})=>r===e),A(()=>t.unobserve(e)),m(({isIntersecting:r})=>r))))}function un(e,t=16){return Ge(e).pipe(m(({y:r})=>{let o=de(e),n=Ct(e);return r>=n.height-o.height-t}),Y())}var yr={drawer:j("[data-md-toggle=drawer]"),search:j("[data-md-toggle=search]")};function dn(e){return yr[e].checked}function at(e,t){yr[e].checked!==t&&yr[e].click()}function Je(e){let t=yr[e];return h(t,"change").pipe(m(()=>t.checked),Q(t.checked))}function ja(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ua(){return L(h(window,"compositionstart").pipe(m(()=>!0)),h(window,"compositionend").pipe(m(()=>!1))).pipe(Q(!1))}function hn(){let e=h(window,"keydown").pipe(g(t=>!(t.metaKey||t.ctrlKey)),m(t=>({mode:dn("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),g(({mode:t,type:r})=>{if(t==="global"){let o=Ne();if(typeof o!="undefined")return!ja(o,r)}return!0}),le());return Ua().pipe(b(t=>t?y:e))}function we(){return new URL(location.href)}function st(e,t=!1){if(V("navigation.instant")&&!t){let r=x("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function bn(){return new T}function vn(){return location.hash.slice(1)}function gn(e){let t=x("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Zr(e){return L(h(window,"hashchange"),e).pipe(m(vn),Q(vn()),g(t=>t.length>0),Z(1))}function yn(e){return Zr(e).pipe(m(t=>ue(`[id="${t}"]`)),g(t=>typeof t!="undefined"))}function Dt(e){let t=matchMedia(e);return dr(r=>t.addListener(()=>r(t.matches))).pipe(Q(t.matches))}function xn(){let e=matchMedia("print");return L(h(window,"beforeprint").pipe(m(()=>!0)),h(window,"afterprint").pipe(m(()=>!1))).pipe(Q(e.matches))}function eo(e,t){return e.pipe(b(r=>r?t():y))}function to(e,t){return new F(r=>{let o=new XMLHttpRequest;return o.open("GET",`${e}`),o.responseType="blob",o.addEventListener("load",()=>{o.status>=200&&o.status<300?(r.next(o.response),r.complete()):r.error(new Error(o.statusText))}),o.addEventListener("error",()=>{r.error(new Error("Network error"))}),o.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(o.addEventListener("progress",n=>{var i;if(n.lengthComputable)t.progress$.next(n.loaded/n.total*100);else{let s=(i=o.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(n.loaded/+s*100)}}),t.progress$.next(5)),o.send(),()=>o.abort()})}function ze(e,t){return to(e,t).pipe(b(r=>r.text()),m(r=>JSON.parse(r)),Z(1))}function xr(e,t){let r=new DOMParser;return to(e,t).pipe(b(o=>o.text()),m(o=>r.parseFromString(o,"text/html")),Z(1))}function En(e,t){let r=new DOMParser;return to(e,t).pipe(b(o=>o.text()),m(o=>r.parseFromString(o,"text/xml")),Z(1))}function wn(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function Tn(){return L(h(window,"scroll",{passive:!0}),h(window,"resize",{passive:!0})).pipe(m(wn),Q(wn()))}function Sn(){return{width:innerWidth,height:innerHeight}}function On(){return h(window,"resize",{passive:!0}).pipe(m(Sn),Q(Sn()))}function Ln(){return z([Tn(),On()]).pipe(m(([e,t])=>({offset:e,size:t})),Z(1))}function Er(e,{viewport$:t,header$:r}){let o=t.pipe(ne("size")),n=z([o,r]).pipe(m(()=>Be(e)));return z([r,t,n]).pipe(m(([{height:i},{offset:s,size:a},{x:c,y:p}])=>({offset:{x:s.x-c,y:s.y-p+i},size:a})))}function Wa(e){return h(e,"message",t=>t.data)}function Da(e){let t=new T;return t.subscribe(r=>e.postMessage(r)),t}function Mn(e,t=new Worker(e)){let r=Wa(t),o=Da(t),n=new T;n.subscribe(o);let i=o.pipe(oe(),ae(!0));return n.pipe(oe(),Ve(r.pipe(W(i))),le())}var Va=j("#__config"),kt=JSON.parse(Va.textContent);kt.base=`${new URL(kt.base,we())}`;function Te(){return kt}function V(e){return kt.features.includes(e)}function Me(e,t){return typeof t!="undefined"?kt.translations[e].replace("#",t.toString()):kt.translations[e]}function Ce(e,t=document){return j(`[data-md-component=${e}]`,t)}function me(e,t=document){return M(`[data-md-component=${e}]`,t)}function Na(e){let t=j(".md-typeset > :first-child",e);return h(t,"click",{once:!0}).pipe(m(()=>j(".md-typeset",e)),m(r=>({hash:__md_hash(r.innerHTML)})))}function _n(e){if(!V("announce.dismiss")||!e.childElementCount)return y;if(!e.hidden){let t=j(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return H(()=>{let t=new T;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),Na(e).pipe(O(r=>t.next(r)),A(()=>t.complete()),m(r=>R({ref:e},r)))})}function za(e,{target$:t}){return t.pipe(m(r=>({hidden:r!==e})))}function An(e,t){let r=new T;return r.subscribe(({hidden:o})=>{e.hidden=o}),za(e,t).pipe(O(o=>r.next(o)),A(()=>r.complete()),m(o=>R({ref:e},o)))}function Vt(e,t){return t==="inline"?x("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"})):x("div",{class:"md-tooltip",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"}))}function wr(...e){return x("div",{class:"md-tooltip2",role:"dialog"},x("div",{class:"md-tooltip2__inner md-typeset"},e))}function Cn(...e){return x("div",{class:"md-tooltip2",role:"tooltip"},x("div",{class:"md-tooltip2__inner md-typeset"},e))}function kn(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return x("aside",{class:"md-annotation",tabIndex:0},Vt(t),x("a",{href:r,class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}else return x("aside",{class:"md-annotation",tabIndex:0},Vt(t),x("span",{class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}function Hn(e){return x("button",{class:"md-code__button",title:Me("clipboard.copy"),"data-clipboard-target":`#${e} > code`,"data-md-type":"copy"})}function $n(){return x("button",{class:"md-code__button",title:"Toggle line selection","data-md-type":"select"})}function Rn(){return x("nav",{class:"md-code__nav"})}var In=Rt(ro());function oo(e,t){let r=t&2,o=t&1,n=Object.keys(e.terms).filter(c=>!e.terms[c]).reduce((c,p)=>[...c,x("del",null,(0,In.default)(p))," "],[]).slice(0,-1),i=Te(),s=new URL(e.location,i.base);V("search.highlight")&&s.searchParams.set("h",Object.entries(e.terms).filter(([,c])=>c).reduce((c,[p])=>`${c} ${p}`.trim(),""));let{tags:a}=Te();return x("a",{href:`${s}`,class:"md-search-result__link",tabIndex:-1},x("article",{class:"md-search-result__article md-typeset","data-md-score":e.score.toFixed(2)},r>0&&x("div",{class:"md-search-result__icon md-icon"}),r>0&&x("h1",null,e.title),r<=0&&x("h2",null,e.title),o>0&&e.text.length>0&&e.text,e.tags&&x("nav",{class:"md-tags"},e.tags.map(c=>{let p=a?c in a?`md-tag-icon md-tag--${a[c]}`:"md-tag-icon":"";return x("span",{class:`md-tag ${p}`},c)})),o>0&&n.length>0&&x("p",{class:"md-search-result__terms"},Me("search.result.term.missing"),": ",...n)))}function Fn(e){let t=e[0].score,r=[...e],o=Te(),n=r.findIndex(l=>!`${new URL(l.location,o.base)}`.includes("#")),[i]=r.splice(n,1),s=r.findIndex(l=>l.scoreoo(l,1)),...c.length?[x("details",{class:"md-search-result__more"},x("summary",{tabIndex:-1},x("div",null,c.length>0&&c.length===1?Me("search.result.more.one"):Me("search.result.more.other",c.length))),...c.map(l=>oo(l,1)))]:[]];return x("li",{class:"md-search-result__item"},p)}function jn(e){return x("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>x("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?br(r):r)))}function no(e){let t=`tabbed-control tabbed-control--${e}`;return x("div",{class:t,hidden:!0},x("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function Un(e){return x("div",{class:"md-typeset__scrollwrap"},x("div",{class:"md-typeset__table"},e))}function Qa(e){var o;let t=Te(),r=new URL(`../${e.version}/`,t.base);return x("li",{class:"md-version__item"},x("a",{href:`${r}`,class:"md-version__link"},e.title,((o=t.version)==null?void 0:o.alias)&&e.aliases.length>0&&x("span",{class:"md-version__alias"},e.aliases[0])))}function Wn(e,t){var o;let r=Te();return e=e.filter(n=>{var i;return!((i=n.properties)!=null&&i.hidden)}),x("div",{class:"md-version"},x("button",{class:"md-version__current","aria-label":Me("select.version")},t.title,((o=r.version)==null?void 0:o.alias)&&t.aliases.length>0&&x("span",{class:"md-version__alias"},t.aliases[0])),x("ul",{class:"md-version__list"},e.map(Qa)))}var Ya=0;function Ba(e,t=250){let r=z([Ye(e),it(e,t)]).pipe(m(([n,i])=>n||i),Y()),o=H(()=>pn(e)).pipe(J(Ge),gt(1),Re(r),m(()=>ln(e)));return r.pipe(Pe(n=>n),b(()=>z([r,o])),m(([n,i])=>({active:n,offset:i})),le())}function Nt(e,t,r=250){let{content$:o,viewport$:n}=t,i=`__tooltip2_${Ya++}`;return H(()=>{let s=new T,a=new jr(!1);s.pipe(oe(),ae(!1)).subscribe(a);let c=a.pipe(Ut(l=>He(+!l*250,Dr)),Y(),b(l=>l?o:y),O(l=>l.id=i),le());z([s.pipe(m(({active:l})=>l)),c.pipe(b(l=>it(l,250)),Q(!1))]).pipe(m(l=>l.some(f=>f))).subscribe(a);let p=a.pipe(g(l=>l),te(c,n),m(([l,f,{size:u}])=>{let d=e.getBoundingClientRect(),v=d.width/2;if(f.role==="tooltip")return{x:v,y:8+d.height};if(d.y>=u.height/2){let{height:S}=de(f);return{x:v,y:-16-S}}else return{x:v,y:16+d.height}}));return z([c,s,p]).subscribe(([l,{offset:f},u])=>{l.style.setProperty("--md-tooltip-host-x",`${f.x}px`),l.style.setProperty("--md-tooltip-host-y",`${f.y}px`),l.style.setProperty("--md-tooltip-x",`${u.x}px`),l.style.setProperty("--md-tooltip-y",`${u.y}px`),l.classList.toggle("md-tooltip2--top",u.y<0),l.classList.toggle("md-tooltip2--bottom",u.y>=0)}),a.pipe(g(l=>l),te(c,(l,f)=>f),g(l=>l.role==="tooltip")).subscribe(l=>{let f=de(j(":scope > *",l));l.style.setProperty("--md-tooltip-width",`${f.width}px`),l.style.setProperty("--md-tooltip-tail","0px")}),a.pipe(Y(),xe(ye),te(c)).subscribe(([l,f])=>{f.classList.toggle("md-tooltip2--active",l)}),z([a.pipe(g(l=>l)),c]).subscribe(([l,f])=>{f.role==="dialog"?(e.setAttribute("aria-controls",i),e.setAttribute("aria-haspopup","dialog")):e.setAttribute("aria-describedby",i)}),a.pipe(g(l=>!l)).subscribe(()=>{e.removeAttribute("aria-controls"),e.removeAttribute("aria-describedby"),e.removeAttribute("aria-haspopup")}),Ba(e,r).pipe(O(l=>s.next(l)),A(()=>s.complete()),m(l=>R({ref:e},l)))})}function Xe(e,{viewport$:t},r=document.body){return Nt(e,{content$:new F(o=>{let n=e.title,i=Cn(n);return o.next(i),e.removeAttribute("title"),r.append(i),()=>{i.remove(),e.setAttribute("title",n)}}),viewport$:t},0)}function Ga(e,t){let r=H(()=>z([mn(e),Ge(t)])).pipe(m(([{x:o,y:n},i])=>{let{width:s,height:a}=de(e);return{x:o-i.x+s/2,y:n-i.y+a/2}}));return Ye(e).pipe(b(o=>r.pipe(m(n=>({active:o,offset:n})),Ee(+!o||1/0))))}function Dn(e,t,{target$:r}){let[o,n]=Array.from(e.children);return H(()=>{let i=new T,s=i.pipe(oe(),ae(!0));return i.subscribe({next({offset:a}){e.style.setProperty("--md-tooltip-x",`${a.x}px`),e.style.setProperty("--md-tooltip-y",`${a.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),mt(e).pipe(W(s)).subscribe(a=>{e.toggleAttribute("data-md-visible",a)}),L(i.pipe(g(({active:a})=>a)),i.pipe(Ae(250),g(({active:a})=>!a))).subscribe({next({active:a}){a?e.prepend(o):o.remove()},complete(){e.prepend(o)}}),i.pipe($e(16,ye)).subscribe(({active:a})=>{o.classList.toggle("md-tooltip--active",a)}),i.pipe(gt(125,ye),g(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:a})=>a)).subscribe({next(a){a?e.style.setProperty("--md-tooltip-0",`${-a}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),h(n,"click").pipe(W(s),g(a=>!(a.metaKey||a.ctrlKey))).subscribe(a=>{a.stopPropagation(),a.preventDefault()}),h(n,"mousedown").pipe(W(s),te(i)).subscribe(([a,{active:c}])=>{var p;if(a.button!==0||a.metaKey||a.ctrlKey)a.preventDefault();else if(c){a.preventDefault();let l=e.parentElement.closest(".md-annotation");l instanceof HTMLElement?l.focus():(p=Ne())==null||p.blur()}}),r.pipe(W(s),g(a=>a===o),nt(125)).subscribe(()=>e.focus()),Ga(e,t).pipe(O(a=>i.next(a)),A(()=>i.complete()),m(a=>R({ref:e},a)))})}function Ja(e){let t=Te();if(e.tagName!=="CODE")return[e];let r=[".c",".c1",".cm"];if(typeof t.annotate!="undefined"){let o=e.closest("[class|=language]");if(o)for(let n of Array.from(o.classList)){if(!n.startsWith("language-"))continue;let[,i]=n.split("-");i in t.annotate&&r.push(...t.annotate[i])}}return M(r.join(", "),e)}function Xa(e){let t=[];for(let r of Ja(e)){let o=[],n=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=n.nextNode();i;i=n.nextNode())o.push(i);for(let i of o){let s;for(;s=/(\(\d+\))(!)?/.exec(i.textContent);){let[,a,c]=s;if(typeof c=="undefined"){let p=i.splitText(s.index);i=p.splitText(a.length),t.push(p)}else{i.textContent=a,t.push(i);break}}}}return t}function Vn(e,t){t.append(...Array.from(e.childNodes))}function Tr(e,t,{target$:r,print$:o}){let n=t.closest("[id]"),i=n==null?void 0:n.id,s=new Map;for(let a of Xa(t)){let[,c]=a.textContent.match(/\((\d+)\)/);ue(`:scope > li:nth-child(${c})`,e)&&(s.set(c,kn(c,i)),a.replaceWith(s.get(c)))}return s.size===0?y:H(()=>{let a=new T,c=a.pipe(oe(),ae(!0)),p=[];for(let[l,f]of s)p.push([j(".md-typeset",f),j(`:scope > li:nth-child(${l})`,e)]);return o.pipe(W(c)).subscribe(l=>{e.hidden=!l,e.classList.toggle("md-annotation-list",l);for(let[f,u]of p)l?Vn(f,u):Vn(u,f)}),L(...[...s].map(([,l])=>Dn(l,t,{target$:r}))).pipe(A(()=>a.complete()),le())})}function Nn(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return Nn(t)}}function zn(e,t){return H(()=>{let r=Nn(e);return typeof r!="undefined"?Tr(r,e,t):y})}var Kn=Rt(ao());var Za=0,qn=L(h(window,"keydown").pipe(m(()=>!0)),L(h(window,"keyup"),h(window,"contextmenu")).pipe(m(()=>!1))).pipe(Q(!1),Z(1));function Qn(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return Qn(t)}}function es(e){return Le(e).pipe(m(({width:t})=>({scrollable:Ct(e).width>t})),ne("scrollable"))}function Yn(e,t){let{matches:r}=matchMedia("(hover)"),o=H(()=>{let n=new T,i=n.pipe(Yr(1));n.subscribe(({scrollable:d})=>{d&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let s=[],a=e.closest("pre"),c=a.closest("[id]"),p=c?c.id:Za++;a.id=`__code_${p}`;let l=[],f=e.closest(".highlight");if(f instanceof HTMLElement){let d=Qn(f);if(typeof d!="undefined"&&(f.classList.contains("annotate")||V("content.code.annotate"))){let v=Tr(d,e,t);l.push(Le(f).pipe(W(i),m(({width:S,height:X})=>S&&X),Y(),b(S=>S?v:y)))}}let u=M(":scope > span[id]",e);if(u.length&&(e.classList.add("md-code__content"),e.closest(".select")||V("content.code.select")&&!e.closest(".no-select"))){let d=+u[0].id.split("-").pop(),v=$n();s.push(v),V("content.tooltips")&&l.push(Xe(v,{viewport$}));let S=h(v,"click").pipe(Wt(P=>!P,!1),O(()=>v.blur()),le());S.subscribe(P=>{v.classList.toggle("md-code__button--active",P)});let X=fe(u).pipe(J(P=>it(P).pipe(m(se=>[P,se]))));S.pipe(b(P=>P?X:y)).subscribe(([P,se])=>{let ce=ue(".hll.select",P);if(ce&&!se)ce.replaceWith(...Array.from(ce.childNodes));else if(!ce&&se){let he=document.createElement("span");he.className="hll select",he.append(...Array.from(P.childNodes).slice(1)),P.append(he)}});let re=fe(u).pipe(J(P=>h(P,"mousedown").pipe(O(se=>se.preventDefault()),m(()=>P)))),ee=S.pipe(b(P=>P?re:y),te(qn),m(([P,se])=>{var he;let ce=u.indexOf(P)+d;if(se===!1)return[ce,ce];{let Se=M(".hll",e).map(Ue=>u.indexOf(Ue.parentElement)+d);return(he=window.getSelection())==null||he.removeAllRanges(),[Math.min(ce,...Se),Math.max(ce,...Se)]}})),k=Zr(y).pipe(g(P=>P.startsWith(`__codelineno-${p}-`)));k.subscribe(P=>{let[,,se]=P.split("-"),ce=se.split(":").map(Se=>+Se-d+1);ce.length===1&&ce.push(ce[0]);for(let Se of M(".hll:not(.select)",e))Se.replaceWith(...Array.from(Se.childNodes));let he=u.slice(ce[0]-1,ce[1]);for(let Se of he){let Ue=document.createElement("span");Ue.className="hll",Ue.append(...Array.from(Se.childNodes).slice(1)),Se.append(Ue)}}),k.pipe(Ee(1),xe(pe)).subscribe(P=>{if(P.includes(":")){let se=document.getElementById(P.split(":")[0]);se&&setTimeout(()=>{let ce=se,he=-64;for(;ce!==document.body;)he+=ce.offsetTop,ce=ce.offsetParent;window.scrollTo({top:he})},1)}});let je=fe(M('a[href^="#__codelineno"]',f)).pipe(J(P=>h(P,"click").pipe(O(se=>se.preventDefault()),m(()=>P)))).pipe(W(i),te(qn),m(([P,se])=>{let he=+j(`[id="${P.hash.slice(1)}"]`).parentElement.id.split("-").pop();if(se===!1)return[he,he];{let Se=M(".hll",e).map(Ue=>+Ue.parentElement.id.split("-").pop());return[Math.min(he,...Se),Math.max(he,...Se)]}}));L(ee,je).subscribe(P=>{let se=`#__codelineno-${p}-`;P[0]===P[1]?se+=P[0]:se+=`${P[0]}:${P[1]}`,history.replaceState({},"",se),window.dispatchEvent(new HashChangeEvent("hashchange",{newURL:window.location.origin+window.location.pathname+se,oldURL:window.location.href}))})}if(Kn.default.isSupported()&&(e.closest(".copy")||V("content.code.copy")&&!e.closest(".no-copy"))){let d=Hn(a.id);s.push(d),V("content.tooltips")&&l.push(Xe(d,{viewport$}))}if(s.length){let d=Rn();d.append(...s),a.insertBefore(d,e)}return es(e).pipe(O(d=>n.next(d)),A(()=>n.complete()),m(d=>R({ref:e},d)),Ve(L(...l).pipe(W(i))))});return V("content.lazy")?mt(e).pipe(g(n=>n),Ee(1),b(()=>o)):o}function ts(e,{target$:t,print$:r}){let o=!0;return L(t.pipe(m(n=>n.closest("details:not([open])")),g(n=>e===n),m(()=>({action:"open",reveal:!0}))),r.pipe(g(n=>n||!o),O(()=>o=e.open),m(n=>({action:n?"open":"close"}))))}function Bn(e,t){return H(()=>{let r=new T;return r.subscribe(({action:o,reveal:n})=>{e.toggleAttribute("open",o==="open"),n&&e.scrollIntoView()}),ts(e,t).pipe(O(o=>r.next(o)),A(()=>r.complete()),m(o=>R({ref:e},o)))})}var Gn=0;function rs(e){let t=document.createElement("h3");t.innerHTML=e.innerHTML;let r=[t],o=e.nextElementSibling;for(;o&&!(o instanceof HTMLHeadingElement);)r.push(o),o=o.nextElementSibling;return r}function os(e,t){for(let r of M("[href], [src]",e))for(let o of["href","src"]){let n=r.getAttribute(o);if(n&&!/^(?:[a-z]+:)?\/\//i.test(n)){r[o]=new URL(r.getAttribute(o),t).toString();break}}for(let r of M("[name^=__], [for]",e))for(let o of["id","for","name"]){let n=r.getAttribute(o);n&&r.setAttribute(o,`${n}$preview_${Gn}`)}return Gn++,$(e)}function Jn(e,t){let{sitemap$:r}=t;if(!(e instanceof HTMLAnchorElement))return y;if(!(V("navigation.instant.preview")||e.hasAttribute("data-preview")))return y;let o=z([Ye(e),it(e)]).pipe(m(([i,s])=>i||s),Y(),g(i=>i));return rt([r,o]).pipe(b(([i])=>{let s=new URL(e.href);return s.search=s.hash="",i.has(`${s}`)?$(s):y}),b(i=>xr(i).pipe(b(s=>os(s,i)))),b(i=>{let s=e.hash?`article [id="${e.hash.slice(1)}"]`:"article h1",a=ue(s,i);return typeof a=="undefined"?y:$(rs(a))})).pipe(b(i=>{let s=new F(a=>{let c=wr(...i);return a.next(c),document.body.append(c),()=>c.remove()});return Nt(e,R({content$:s},t))}))}var Xn=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.flowchartTitleText{fill:var(--md-mermaid-label-fg-color)}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel p,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel p{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color);stroke-width:.05rem}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}.classDiagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs marker.marker.composition.class path,defs marker.marker.dependency.class path,defs marker.marker.extension.class path{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs marker.marker.aggregation.class path{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}.statediagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}a .nodeLabel{text-decoration:underline}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}.entityTitleText{fill:var(--md-mermaid-label-fg-color)}.attributeBoxEven,.attributeBoxOdd{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityBox{fill:var(--md-mermaid-label-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityLabel{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.relationshipLabelBox{fill:var(--md-mermaid-label-bg-color);fill-opacity:1;background-color:var(--md-mermaid-label-bg-color);opacity:1}.relationshipLabel{fill:var(--md-mermaid-label-fg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs #ONE_OR_MORE_END *,defs #ONE_OR_MORE_START *,defs #ONLY_ONE_END *,defs #ONLY_ONE_START *,defs #ZERO_OR_MORE_END *,defs #ZERO_OR_MORE_START *,defs #ZERO_OR_ONE_END *,defs #ZERO_OR_ONE_START *{stroke:var(--md-mermaid-edge-color)!important}defs #ZERO_OR_MORE_END circle,defs #ZERO_OR_MORE_START circle{fill:var(--md-mermaid-label-bg-color)}text:not([class]):last-child{fill:var(--md-mermaid-label-fg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var so,is=0;function as(){return typeof mermaid=="undefined"||mermaid instanceof Element?At("https://unpkg.com/mermaid@11/dist/mermaid.min.js"):$(void 0)}function Zn(e){return e.classList.remove("mermaid"),so||(so=as().pipe(O(()=>mermaid.initialize({startOnLoad:!1,themeCSS:Xn,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),m(()=>{}),Z(1))),so.subscribe(()=>go(this,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${is++}`,r=x("div",{class:"mermaid"}),o=e.textContent,{svg:n,fn:i}=yield mermaid.render(t,o),s=r.attachShadow({mode:"closed"});s.innerHTML=n,e.replaceWith(r),i==null||i(s)})),so.pipe(m(()=>({ref:e})))}var ei=x("table");function ti(e){return e.replaceWith(ei),ei.replaceWith(Un(e)),$({ref:e})}function ss(e){let t=e.find(r=>r.checked)||e[0];return L(...e.map(r=>h(r,"change").pipe(m(()=>j(`label[for="${r.id}"]`))))).pipe(Q(j(`label[for="${t.id}"]`)),m(r=>({active:r})))}function ri(e,{viewport$:t,target$:r}){let o=j(".tabbed-labels",e),n=M(":scope > input",e),i=no("prev");e.append(i);let s=no("next");return e.append(s),H(()=>{let a=new T,c=a.pipe(oe(),ae(!0));z([a,Le(e),mt(e)]).pipe(W(c),$e(1,ye)).subscribe({next([{active:p},l]){let f=Be(p),{width:u}=de(p);e.style.setProperty("--md-indicator-x",`${f.x}px`),e.style.setProperty("--md-indicator-width",`${u}px`);let d=gr(o);(f.xd.x+l.width)&&o.scrollTo({left:Math.max(0,f.x-16),behavior:"smooth"})},complete(){e.style.removeProperty("--md-indicator-x"),e.style.removeProperty("--md-indicator-width")}}),z([Ge(o),Le(o)]).pipe(W(c)).subscribe(([p,l])=>{let f=Ct(o);i.hidden=p.x<16,s.hidden=p.x>f.width-l.width-16}),L(h(i,"click").pipe(m(()=>-1)),h(s,"click").pipe(m(()=>1))).pipe(W(c)).subscribe(p=>{let{width:l}=de(o);o.scrollBy({left:l*p,behavior:"smooth"})}),r.pipe(W(c),g(p=>n.includes(p))).subscribe(p=>p.click()),o.classList.add("tabbed-labels--linked");for(let p of n){let l=j(`label[for="${p.id}"]`);l.replaceChildren(x("a",{href:`#${l.htmlFor}`,tabIndex:-1},...Array.from(l.childNodes))),h(l.firstElementChild,"click").pipe(W(c),g(f=>!(f.metaKey||f.ctrlKey)),O(f=>{f.preventDefault(),f.stopPropagation()})).subscribe(()=>{history.replaceState({},"",`#${l.htmlFor}`),l.click()})}return V("content.tabs.link")&&a.pipe(Ie(1),te(t)).subscribe(([{active:p},{offset:l}])=>{let f=p.innerText.trim();if(p.hasAttribute("data-md-switching"))p.removeAttribute("data-md-switching");else{let u=e.offsetTop-l.y;for(let v of M("[data-tabs]"))for(let S of M(":scope > input",v)){let X=j(`label[for="${S.id}"]`);if(X!==p&&X.innerText.trim()===f){X.setAttribute("data-md-switching",""),S.click();break}}window.scrollTo({top:e.offsetTop-u});let d=__md_get("__tabs")||[];__md_set("__tabs",[...new Set([f,...d])])}}),a.pipe(W(c)).subscribe(()=>{for(let p of M("audio, video",e))p.pause()}),ss(n).pipe(O(p=>a.next(p)),A(()=>a.complete()),m(p=>R({ref:e},p)))}).pipe(et(pe))}function oi(e,t){let{viewport$:r,target$:o,print$:n}=t;return L(...M(".annotate:not(.highlight)",e).map(i=>zn(i,{target$:o,print$:n})),...M("pre:not(.mermaid) > code",e).map(i=>Yn(i,{target$:o,print$:n})),...M("a:not([title])",e).map(i=>Jn(i,t)),...M("pre.mermaid",e).map(i=>Zn(i)),...M("table:not([class])",e).map(i=>ti(i)),...M("details",e).map(i=>Bn(i,{target$:o,print$:n})),...M("[data-tabs]",e).map(i=>ri(i,{viewport$:r,target$:o})),...M("[title]",e).filter(()=>V("content.tooltips")).map(i=>Xe(i,{viewport$:r})),...M(".footnote-ref",e).filter(()=>V("content.footnote.tooltips")).map(i=>Nt(i,{content$:new F(s=>{let a=new URL(i.href).hash.slice(1),c=Array.from(document.getElementById(a).cloneNode(!0).children),p=wr(...c);return s.next(p),document.body.append(p),()=>p.remove()}),viewport$:r})))}function cs(e,{alert$:t}){return t.pipe(b(r=>L($(!0),$(!1).pipe(nt(2e3))).pipe(m(o=>({message:r,active:o})))))}function ni(e,t){let r=j(".md-typeset",e);return H(()=>{let o=new T;return o.subscribe(({message:n,active:i})=>{e.classList.toggle("md-dialog--active",i),r.textContent=n}),cs(e,t).pipe(O(n=>o.next(n)),A(()=>o.complete()),m(n=>R({ref:e},n)))})}var ps=0;function ls(e,t){document.body.append(e);let{width:r}=de(e);e.style.setProperty("--md-tooltip-width",`${r}px`),e.remove();let o=vr(t),n=typeof o!="undefined"?Ge(o):$({x:0,y:0}),i=L(Ye(t),it(t)).pipe(Y());return z([i,n]).pipe(m(([s,a])=>{let{x:c,y:p}=Be(t),l=de(t),f=t.closest("table");return f&&t.parentElement&&(c+=f.offsetLeft+t.parentElement.offsetLeft,p+=f.offsetTop+t.parentElement.offsetTop),{active:s,offset:{x:c-a.x+l.width/2-r/2,y:p-a.y+l.height+8}}}))}function ii(e){let t=e.title;if(!t.length)return y;let r=`__tooltip_${ps++}`,o=Vt(r,"inline"),n=j(".md-typeset",o);return n.innerHTML=t,H(()=>{let i=new T;return i.subscribe({next({offset:s}){o.style.setProperty("--md-tooltip-x",`${s.x}px`),o.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){o.style.removeProperty("--md-tooltip-x"),o.style.removeProperty("--md-tooltip-y")}}),L(i.pipe(g(({active:s})=>s)),i.pipe(Ae(250),g(({active:s})=>!s))).subscribe({next({active:s}){s?(e.insertAdjacentElement("afterend",o),e.setAttribute("aria-describedby",r),e.removeAttribute("title")):(o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t))},complete(){o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t)}}),i.pipe($e(16,ye)).subscribe(({active:s})=>{o.classList.toggle("md-tooltip--active",s)}),i.pipe(gt(125,ye),g(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:s})=>s)).subscribe({next(s){s?o.style.setProperty("--md-tooltip-0",`${-s}px`):o.style.removeProperty("--md-tooltip-0")},complete(){o.style.removeProperty("--md-tooltip-0")}}),ls(o,e).pipe(O(s=>i.next(s)),A(()=>i.complete()),m(s=>R({ref:e},s)))}).pipe(et(pe))}function ms({viewport$:e}){if(!V("header.autohide"))return $(!1);let t=e.pipe(m(({offset:{y:n}})=>n),ot(2,1),m(([n,i])=>[nMath.abs(i-n.y)>100),m(([,[n]])=>n),Y()),o=Je("search");return z([e,o]).pipe(m(([{offset:n},i])=>n.y>400&&!i),Y(),b(n=>n?r:$(!1)),Q(!1))}function ai(e,t){return H(()=>z([Le(e),ms(t)])).pipe(m(([{height:r},o])=>({height:r,hidden:o})),Y((r,o)=>r.height===o.height&&r.hidden===o.hidden),Z(1))}function si(e,{header$:t,main$:r}){return H(()=>{let o=new T,n=o.pipe(oe(),ae(!0));o.pipe(ne("active"),Re(t)).subscribe(([{active:s},{hidden:a}])=>{e.classList.toggle("md-header--shadow",s&&!a),e.hidden=a});let i=fe(M("[title]",e)).pipe(g(()=>V("content.tooltips")),J(s=>ii(s)));return r.subscribe(o),t.pipe(W(n),m(s=>R({ref:e},s)),Ve(i.pipe(W(n))))})}function fs(e,{viewport$:t,header$:r}){return Er(e,{viewport$:t,header$:r}).pipe(m(({offset:{y:o}})=>{let{height:n}=de(e);return{active:o>=n}}),ne("active"))}function ci(e,t){return H(()=>{let r=new T;r.subscribe({next({active:n}){e.classList.toggle("md-header__title--active",n)},complete(){e.classList.remove("md-header__title--active")}});let o=ue(".md-content h1");return typeof o=="undefined"?y:fs(o,t).pipe(O(n=>r.next(n)),A(()=>r.complete()),m(n=>R({ref:e},n)))})}function pi(e,{viewport$:t,header$:r}){let o=r.pipe(m(({height:i})=>i),Y()),n=o.pipe(b(()=>Le(e).pipe(m(({height:i})=>({top:e.offsetTop,bottom:e.offsetTop+i})),ne("bottom"))));return z([o,n,t]).pipe(m(([i,{top:s,bottom:a},{offset:{y:c},size:{height:p}}])=>(p=Math.max(0,p-Math.max(0,s-c,i)-Math.max(0,p+c-a)),{offset:s-i,height:p,active:s-i<=c})),Y((i,s)=>i.offset===s.offset&&i.height===s.height&&i.active===s.active))}function us(e){let t=__md_get("__palette")||{index:e.findIndex(o=>matchMedia(o.getAttribute("data-md-color-media")).matches)},r=Math.max(0,Math.min(t.index,e.length-1));return $(...e).pipe(J(o=>h(o,"change").pipe(m(()=>o))),Q(e[r]),m(o=>({index:e.indexOf(o),color:{media:o.getAttribute("data-md-color-media"),scheme:o.getAttribute("data-md-color-scheme"),primary:o.getAttribute("data-md-color-primary"),accent:o.getAttribute("data-md-color-accent")}})),Z(1))}function li(e){let t=M("input",e),r=x("meta",{name:"theme-color"});document.head.appendChild(r);let o=x("meta",{name:"color-scheme"});document.head.appendChild(o);let n=Dt("(prefers-color-scheme: light)");return H(()=>{let i=new T;return i.subscribe(s=>{if(document.body.setAttribute("data-md-color-switching",""),s.color.media==="(prefers-color-scheme)"){let a=matchMedia("(prefers-color-scheme: light)"),c=document.querySelector(a.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");s.color.scheme=c.getAttribute("data-md-color-scheme"),s.color.primary=c.getAttribute("data-md-color-primary"),s.color.accent=c.getAttribute("data-md-color-accent")}for(let[a,c]of Object.entries(s.color))document.body.setAttribute(`data-md-color-${a}`,c);for(let a=0;as.key==="Enter"),te(i,(s,a)=>a)).subscribe(({index:s})=>{s=(s+1)%t.length,t[s].click(),t[s].focus()}),i.pipe(m(()=>{let s=Ce("header"),a=window.getComputedStyle(s);return o.content=a.colorScheme,a.backgroundColor.match(/\d+/g).map(c=>(+c).toString(16).padStart(2,"0")).join("")})).subscribe(s=>r.content=`#${s}`),i.pipe(xe(pe)).subscribe(()=>{document.body.removeAttribute("data-md-color-switching")}),us(t).pipe(W(n.pipe(Ie(1))),vt(),O(s=>i.next(s)),A(()=>i.complete()),m(s=>R({ref:e},s)))})}function mi(e,{progress$:t}){return H(()=>{let r=new T;return r.subscribe(({value:o})=>{e.style.setProperty("--md-progress-value",`${o}`)}),t.pipe(O(o=>r.next({value:o})),A(()=>r.complete()),m(o=>({ref:e,value:o})))})}function fi(e,t){return e.protocol=t.protocol,e.hostname=t.hostname,e}function ds(e,t){let r=new Map;for(let o of M("url",e)){let n=j("loc",o),i=[fi(new URL(n.textContent),t)];r.set(`${i[0]}`,i);for(let s of M("[rel=alternate]",o)){let a=s.getAttribute("href");a!=null&&i.push(fi(new URL(a),t))}}return r}function Ht(e){return En(new URL("sitemap.xml",e)).pipe(m(t=>ds(t,new URL(e))),ve(()=>$(new Map)),le())}function ui({document$:e}){let t=new Map;e.pipe(b(()=>M("link[rel=alternate]")),m(r=>new URL(r.href)),g(r=>!t.has(r.toString())),J(r=>Ht(r).pipe(m(o=>[r,o]),ve(()=>y)))).subscribe(([r,o])=>{t.set(r.toString().replace(/\/$/,""),o)}),h(document.body,"click").pipe(g(r=>!r.metaKey&&!r.ctrlKey),b(r=>{if(r.target instanceof Element){let o=r.target.closest("a");if(o&&!o.target){let n=[...t].find(([f])=>o.href.startsWith(`${f}/`));if(typeof n=="undefined")return y;let[i,s]=n,a=we();if(a.href.startsWith(i))return y;let c=Te(),p=a.href.replace(c.base,"");p=`${i}/${p}`;let l=s.has(p.split("#")[0])?new URL(p,c.base):new URL(i);return r.preventDefault(),$(l)}}return y})).subscribe(r=>st(r,!0))}var co=Rt(ao());function hs(e){e.setAttribute("data-md-copying","");let t=e.closest("[data-copy]"),r=t?t.getAttribute("data-copy"):e.innerText;return e.removeAttribute("data-md-copying"),r.trimEnd()}function di({alert$:e}){co.default.isSupported()&&new F(t=>{new co.default("[data-clipboard-target], [data-clipboard-text]",{text:r=>r.getAttribute("data-clipboard-text")||hs(j(r.getAttribute("data-clipboard-target")))}).on("success",r=>t.next(r))}).pipe(O(t=>{t.trigger.focus()}),m(()=>Me("clipboard.copied"))).subscribe(e)}function hi(e,t){if(!(e.target instanceof Element))return y;let r=e.target.closest("a");if(r===null)return y;if(r.target||e.metaKey||e.ctrlKey)return y;let o=new URL(r.href);return o.search=o.hash="",t.has(`${o}`)?(e.preventDefault(),$(r)):y}function bi(e){let t=new Map;for(let r of M(":scope > *",e.head))t.set(r.outerHTML,r);return t}function vi(e){for(let t of M("[href], [src]",e))for(let r of["href","src"]){let o=t.getAttribute(r);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){t[r]=t[r];break}}return $(e)}function bs(e){for(let o of["[data-md-component=announce]","[data-md-component=container]","[data-md-component=header-topic]","[data-md-component=outdated]","[data-md-component=logo]","[data-md-component=skip]",...V("navigation.tabs.sticky")?["[data-md-component=tabs]"]:[]]){let n=ue(o),i=ue(o,e);typeof n!="undefined"&&typeof i!="undefined"&&n.replaceWith(i)}let t=bi(document);for(let[o,n]of bi(e))t.has(o)?t.delete(o):document.head.appendChild(n);for(let o of t.values()){let n=o.getAttribute("name");n!=="theme-color"&&n!=="color-scheme"&&o.remove()}let r=Ce("container");return Ke(M("script",r)).pipe(b(o=>{let n=e.createElement("script");if(o.src){for(let i of o.getAttributeNames())n.setAttribute(i,o.getAttribute(i));return o.replaceWith(n),new F(i=>{n.onload=()=>i.complete()})}else return n.textContent=o.textContent,o.replaceWith(n),y}),oe(),ae(document))}function gi({sitemap$:e,location$:t,viewport$:r,progress$:o}){if(location.protocol==="file:")return y;$(document).subscribe(vi);let n=h(document.body,"click").pipe(Re(e),b(([a,c])=>hi(a,c)),m(({href:a})=>new URL(a)),le()),i=h(window,"popstate").pipe(m(we),le());n.pipe(te(r)).subscribe(([a,{offset:c}])=>{history.replaceState(c,""),history.pushState(null,"",a)}),L(n,i).subscribe(t);let s=t.pipe(ne("pathname"),b(a=>xr(a,{progress$:o}).pipe(ve(()=>(st(a,!0),y)))),b(vi),b(bs),le());return L(s.pipe(te(t,(a,c)=>c)),s.pipe(b(()=>t),ne("hash")),t.pipe(Y((a,c)=>a.pathname===c.pathname&&a.hash===c.hash),b(()=>n),O(()=>history.back()))).subscribe(a=>{var c,p;history.state!==null||!a.hash?window.scrollTo(0,(p=(c=history.state)==null?void 0:c.y)!=null?p:0):(history.scrollRestoration="auto",gn(a.hash),history.scrollRestoration="manual")}),t.subscribe(()=>{history.scrollRestoration="manual"}),h(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}),r.pipe(ne("offset"),Ae(100)).subscribe(({offset:a})=>{history.replaceState(a,"")}),V("navigation.instant.prefetch")&&L(h(document.body,"mousemove"),h(document.body,"focusin")).pipe(Re(e),b(([a,c])=>hi(a,c)),Ae(25),Qr(({href:a})=>a),hr(a=>{let c=document.createElement("link");return c.rel="prefetch",c.href=a.toString(),document.head.appendChild(c),h(c,"load").pipe(m(()=>c),Ee(1))})).subscribe(a=>a.remove()),s}var yi=Rt(ro());function xi(e){let t=e.separator.split("|").map(n=>n.replace(/(\(\?[!=<][^)]+\))/g,"").length===0?"\uFFFD":n).join("|"),r=new RegExp(t,"img"),o=(n,i,s)=>`${i}${s}`;return n=>{n=n.replace(/[\s*+\-:~^]+/g," ").trim();let i=new RegExp(`(^|${e.separator}|)(${n.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(r,"|")})`,"img");return s=>(0,yi.default)(s).replace(i,o).replace(/<\/mark>(\s+)]*>/img,"$1")}}function qt(e){return e.type===1}function Sr(e){return e.type===3}function Ei(e,t){let r=Mn(e);return L($(location.protocol!=="file:"),Je("search")).pipe(Pe(o=>o),b(()=>t)).subscribe(({config:o,docs:n})=>r.next({type:0,data:{config:o,docs:n,options:{suggest:V("search.suggest")}}})),r}function wi(e){var l;let{selectedVersionSitemap:t,selectedVersionBaseURL:r,currentLocation:o,currentBaseURL:n}=e,i=(l=po(n))==null?void 0:l.pathname;if(i===void 0)return;let s=ys(o.pathname,i);if(s===void 0)return;let a=Es(t.keys());if(!t.has(a))return;let c=po(s,a);if(!c||!t.has(c.href))return;let p=po(s,r);if(p)return p.hash=o.hash,p.search=o.search,p}function po(e,t){try{return new URL(e,t)}catch(r){return}}function ys(e,t){if(e.startsWith(t))return e.slice(t.length)}function xs(e,t){let r=Math.min(e.length,t.length),o;for(o=0;oy)),o=r.pipe(m(n=>{let[,i]=t.base.match(/([^/]+)\/?$/);return n.find(({version:s,aliases:a})=>s===i||a.includes(i))||n[0]}));r.pipe(m(n=>new Map(n.map(i=>[`${new URL(`../${i.version}/`,t.base)}`,i]))),b(n=>h(document.body,"click").pipe(g(i=>!i.metaKey&&!i.ctrlKey),te(o),b(([i,s])=>{if(i.target instanceof Element){let a=i.target.closest("a");if(a&&!a.target&&n.has(a.href)){let c=a.href;return!i.target.closest(".md-version")&&n.get(c)===s?y:(i.preventDefault(),$(new URL(c)))}}return y}),b(i=>Ht(i).pipe(m(s=>{var a;return(a=wi({selectedVersionSitemap:s,selectedVersionBaseURL:i,currentLocation:we(),currentBaseURL:t.base}))!=null?a:i})))))).subscribe(n=>st(n,!0)),z([r,o]).subscribe(([n,i])=>{j(".md-header__topic").appendChild(Wn(n,i))}),e.pipe(b(()=>o)).subscribe(n=>{var a;let i=new URL(t.base),s=__md_get("__outdated",sessionStorage,i);if(s===null){s=!0;let c=((a=t.version)==null?void 0:a.default)||"latest";Array.isArray(c)||(c=[c]);e:for(let p of c)for(let l of n.aliases.concat(n.version))if(new RegExp(p,"i").test(l)){s=!1;break e}__md_set("__outdated",s,sessionStorage,i)}if(s)for(let c of me("outdated"))c.hidden=!1})}function ws(e,{worker$:t}){let{searchParams:r}=we();r.has("q")&&(at("search",!0),e.value=r.get("q"),e.focus(),Je("search").pipe(Pe(i=>!i)).subscribe(()=>{let i=we();i.searchParams.delete("q"),history.replaceState({},"",`${i}`)}));let o=Ye(e),n=L(t.pipe(Pe(qt)),h(e,"keyup"),o).pipe(m(()=>e.value),Y());return z([n,o]).pipe(m(([i,s])=>({value:i,focus:s})),Z(1))}function Si(e,{worker$:t}){let r=new T,o=r.pipe(oe(),ae(!0));z([t.pipe(Pe(qt)),r],(i,s)=>s).pipe(ne("value")).subscribe(({value:i})=>t.next({type:2,data:i})),r.pipe(ne("focus")).subscribe(({focus:i})=>{i&&at("search",i)}),h(e.form,"reset").pipe(W(o)).subscribe(()=>e.focus());let n=j("header [for=__search]");return h(n,"click").subscribe(()=>e.focus()),ws(e,{worker$:t}).pipe(O(i=>r.next(i)),A(()=>r.complete()),m(i=>R({ref:e},i)),Z(1))}function Oi(e,{worker$:t,query$:r}){let o=new T,n=un(e.parentElement).pipe(g(Boolean)),i=e.parentElement,s=j(":scope > :first-child",e),a=j(":scope > :last-child",e);Je("search").subscribe(l=>a.setAttribute("role",l?"list":"presentation")),o.pipe(te(r),Gr(t.pipe(Pe(qt)))).subscribe(([{items:l},{value:f}])=>{switch(l.length){case 0:s.textContent=f.length?Me("search.result.none"):Me("search.result.placeholder");break;case 1:s.textContent=Me("search.result.one");break;default:let u=br(l.length);s.textContent=Me("search.result.other",u)}});let c=o.pipe(O(()=>a.innerHTML=""),b(({items:l})=>L($(...l.slice(0,10)),$(...l.slice(10)).pipe(ot(4),Xr(n),b(([f])=>f)))),m(Fn),le());return c.subscribe(l=>a.appendChild(l)),c.pipe(J(l=>{let f=ue("details",l);return typeof f=="undefined"?y:h(f,"toggle").pipe(W(o),m(()=>f))})).subscribe(l=>{l.open===!1&&l.offsetTop<=i.scrollTop&&i.scrollTo({top:l.offsetTop})}),t.pipe(g(Sr),m(({data:l})=>l)).pipe(O(l=>o.next(l)),A(()=>o.complete()),m(l=>R({ref:e},l)))}function Ts(e,{query$:t}){return t.pipe(m(({value:r})=>{let o=we();return o.hash="",r=r.replace(/\s+/g,"+").replace(/&/g,"%26").replace(/=/g,"%3D"),o.search=`q=${r}`,{url:o}}))}function Li(e,t){let r=new T,o=r.pipe(oe(),ae(!0));return r.subscribe(({url:n})=>{e.setAttribute("data-clipboard-text",e.href),e.href=`${n}`}),h(e,"click").pipe(W(o)).subscribe(n=>n.preventDefault()),Ts(e,t).pipe(O(n=>r.next(n)),A(()=>r.complete()),m(n=>R({ref:e},n)))}function Mi(e,{worker$:t,keyboard$:r}){let o=new T,n=Ce("search-query"),i=L(h(n,"keydown"),h(n,"focus")).pipe(xe(pe),m(()=>n.value),Y());return o.pipe(Re(i),m(([{suggest:a},c])=>{let p=c.split(/([\s-]+)/);if(a!=null&&a.length&&p[p.length-1]){let l=a[a.length-1];l.startsWith(p[p.length-1])&&(p[p.length-1]=l)}else p.length=0;return p})).subscribe(a=>e.innerHTML=a.join("").replace(/\s/g," ")),r.pipe(g(({mode:a})=>a==="search")).subscribe(a=>{switch(a.type){case"ArrowRight":e.innerText.length&&n.selectionStart===n.value.length&&(n.value=e.innerText);break}}),t.pipe(g(Sr),m(({data:a})=>a)).pipe(O(a=>o.next(a)),A(()=>o.complete()),m(()=>({ref:e})))}function _i(e,{index$:t,keyboard$:r}){let o=Te();try{let n=Ei(o.search,t),i=Ce("search-query",e),s=Ce("search-result",e);h(e,"click").pipe(g(({target:c})=>c instanceof Element&&!!c.closest("a"))).subscribe(()=>at("search",!1)),r.pipe(g(({mode:c})=>c==="search")).subscribe(c=>{let p=Ne();switch(c.type){case"Enter":if(p===i){let l=new Map;for(let f of M(":first-child [href]",s)){let u=f.firstElementChild;l.set(f,parseFloat(u.getAttribute("data-md-score")))}if(l.size){let[[f]]=[...l].sort(([,u],[,d])=>d-u);f.click()}c.claim()}break;case"Escape":case"Tab":at("search",!1),i.blur();break;case"ArrowUp":case"ArrowDown":if(typeof p=="undefined")i.focus();else{let l=[i,...M(":not(details) > [href], summary, details[open] [href]",s)],f=Math.max(0,(Math.max(0,l.indexOf(p))+l.length+(c.type==="ArrowUp"?-1:1))%l.length);l[f].focus()}c.claim();break;default:i!==Ne()&&i.focus()}}),r.pipe(g(({mode:c})=>c==="global")).subscribe(c=>{switch(c.type){case"f":case"s":case"/":i.focus(),i.select(),c.claim();break}});let a=Si(i,{worker$:n});return L(a,Oi(s,{worker$:n,query$:a})).pipe(Ve(...me("search-share",e).map(c=>Li(c,{query$:a})),...me("search-suggest",e).map(c=>Mi(c,{worker$:n,keyboard$:r}))))}catch(n){return e.hidden=!0,tt}}function Ai(e,{index$:t,location$:r}){return z([t,r.pipe(Q(we()),g(o=>!!o.searchParams.get("h")))]).pipe(m(([o,n])=>xi(o.config)(n.searchParams.get("h"))),m(o=>{var s;let n=new Map,i=document.createNodeIterator(e,NodeFilter.SHOW_TEXT);for(let a=i.nextNode();a;a=i.nextNode())if((s=a.parentElement)!=null&&s.offsetHeight){let c=a.textContent,p=o(c);p.length>c.length&&n.set(a,p)}for(let[a,c]of n){let{childNodes:p}=x("span",null,c);a.replaceWith(...Array.from(p))}return{ref:e,nodes:n}}))}function Ss(e,{viewport$:t,main$:r}){let o=e.closest(".md-grid"),n=o.offsetTop-o.parentElement.offsetTop;return z([r,t]).pipe(m(([{offset:i,height:s},{offset:{y:a}}])=>(s=s+Math.min(n,Math.max(0,a-i))-n,{height:s,locked:a>=i+n})),Y((i,s)=>i.height===s.height&&i.locked===s.locked))}function lo(e,o){var n=o,{header$:t}=n,r=vo(n,["header$"]);let i=j(".md-sidebar__scrollwrap",e),{y:s}=Be(i);return H(()=>{let a=new T,c=a.pipe(oe(),ae(!0)),p=a.pipe($e(0,ye));return p.pipe(te(t)).subscribe({next([{height:l},{height:f}]){i.style.height=`${l-2*s}px`,e.style.top=`${f}px`},complete(){i.style.height="",e.style.top=""}}),p.pipe(Pe()).subscribe(()=>{for(let l of M(".md-nav__link--active[href]",e)){if(!l.clientHeight)continue;let f=l.closest(".md-sidebar__scrollwrap");if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=de(f);f.scrollTo({top:u-d/2})}}}),fe(M("label[tabindex]",e)).pipe(J(l=>h(l,"click").pipe(xe(pe),m(()=>l),W(c)))).subscribe(l=>{let f=j(`[id="${l.htmlFor}"]`);j(`[aria-labelledby="${l.id}"]`).setAttribute("aria-expanded",`${f.checked}`)}),V("content.tooltips")&&fe(M("abbr[title]",e)).pipe(J(l=>Xe(l,{viewport$})),W(c)).subscribe(),Ss(e,r).pipe(O(l=>a.next(l)),A(()=>a.complete()),m(l=>R({ref:e},l)))})}function Ci(e,t){if(typeof t!="undefined"){let r=`https://api.github.com/repos/${e}/${t}`;return rt(ze(`${r}/releases/latest`).pipe(ve(()=>y),m(o=>({version:o.tag_name})),Qe({})),ze(r).pipe(ve(()=>y),m(o=>({stars:o.stargazers_count,forks:o.forks_count})),Qe({}))).pipe(m(([o,n])=>R(R({},o),n)))}else{let r=`https://api.github.com/users/${e}`;return ze(r).pipe(m(o=>({repositories:o.public_repos})),Qe({}))}}function ki(e,t){let r=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return rt(ze(`${r}/releases/permalink/latest`).pipe(ve(()=>y),m(({tag_name:o})=>({version:o})),Qe({})),ze(r).pipe(ve(()=>y),m(({star_count:o,forks_count:n})=>({stars:o,forks:n})),Qe({}))).pipe(m(([o,n])=>R(R({},o),n)))}function Hi(e){let t=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);if(t){let[,r,o]=t;return Ci(r,o)}if(t=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i),t){let[,r,o]=t;return ki(r,o)}return y}var Os;function Ls(e){return Os||(Os=H(()=>{let t=__md_get("__source",sessionStorage);if(t)return $(t);if(me("consent").length){let o=__md_get("__consent");if(!(o&&o.github))return y}return Hi(e.href).pipe(O(o=>__md_set("__source",o,sessionStorage)))}).pipe(ve(()=>y),g(t=>Object.keys(t).length>0),m(t=>({facts:t})),Z(1)))}function $i(e){let t=j(":scope > :last-child",e);return H(()=>{let r=new T;return r.subscribe(({facts:o})=>{t.appendChild(jn(o)),t.classList.add("md-source__repository--active")}),Ls(e).pipe(O(o=>r.next(o)),A(()=>r.complete()),m(o=>R({ref:e},o)))})}function Ms(e,{viewport$:t,header$:r}){return Le(document.body).pipe(b(()=>Er(e,{header$:r,viewport$:t})),m(({offset:{y:o}})=>({hidden:o>=10})),ne("hidden"))}function Ri(e,t){return H(()=>{let r=new T;return r.subscribe({next({hidden:o}){e.hidden=o},complete(){e.hidden=!1}}),(V("navigation.tabs.sticky")?$({hidden:!1}):Ms(e,t)).pipe(O(o=>r.next(o)),A(()=>r.complete()),m(o=>R({ref:e},o)))})}function _s(e,{viewport$:t,header$:r}){let o=new Map,n=M(".md-nav__link",e);for(let a of n){let c=decodeURIComponent(a.hash.substring(1)),p=ue(`[id="${c}"]`);typeof p!="undefined"&&o.set(a,p)}let i=r.pipe(ne("height"),m(({height:a})=>{let c=Ce("main"),p=j(":scope > :first-child",c);return a+.8*(p.offsetTop-c.offsetTop)}),le());return Le(document.body).pipe(ne("height"),b(a=>H(()=>{let c=[];return $([...o].reduce((p,[l,f])=>{for(;c.length&&o.get(c[c.length-1]).tagName>=f.tagName;)c.pop();let u=f.offsetTop;for(;!u&&f.parentElement;)f=f.parentElement,u=f.offsetTop;let d=f.offsetParent;for(;d;d=d.offsetParent)u+=d.offsetTop;return p.set([...c=[...c,l]].reverse(),u)},new Map))}).pipe(m(c=>new Map([...c].sort(([,p],[,l])=>p-l))),Re(i),b(([c,p])=>t.pipe(Wt(([l,f],{offset:{y:u},size:d})=>{let v=u+d.height>=Math.floor(a.height);for(;f.length;){let[,S]=f[0];if(S-p=u&&!v)f=[l.pop(),...f];else break}return[l,f]},[[],[...c]]),Y((l,f)=>l[0]===f[0]&&l[1]===f[1])))))).pipe(m(([a,c])=>({prev:a.map(([p])=>p),next:c.map(([p])=>p)})),Q({prev:[],next:[]}),ot(2,1),m(([a,c])=>a.prev.length{let i=new T,s=i.pipe(oe(),ae(!0));if(i.subscribe(({prev:a,next:c})=>{for(let[p]of c)p.classList.remove("md-nav__link--passed"),p.classList.remove("md-nav__link--active");for(let[p,[l]]of a.entries())l.classList.add("md-nav__link--passed"),l.classList.toggle("md-nav__link--active",p===a.length-1)}),V("toc.follow")){let a=L(t.pipe(Ae(1),m(()=>{})),t.pipe(Ae(250),m(()=>"smooth")));i.pipe(g(({prev:c})=>c.length>0),Re(o.pipe(xe(pe))),te(a)).subscribe(([[{prev:c}],p])=>{let[l]=c[c.length-1];if(l.offsetHeight){let f=vr(l);if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=de(f);f.scrollTo({top:u-d/2,behavior:p})}}})}return V("navigation.tracking")&&t.pipe(W(s),ne("offset"),Ae(250),Ie(1),W(n.pipe(Ie(1))),vt({delay:250}),te(i)).subscribe(([,{prev:a}])=>{let c=we(),p=a[a.length-1];if(p&&p.length){let[l]=p,{hash:f}=new URL(l.href);c.hash!==f&&(c.hash=f,history.replaceState({},"",`${c}`))}else c.hash="",history.replaceState({},"",`${c}`)}),_s(e,{viewport$:t,header$:r}).pipe(O(a=>i.next(a)),A(()=>i.complete()),m(a=>R({ref:e},a)))})}function As(e,{viewport$:t,main$:r,target$:o}){let n=t.pipe(m(({offset:{y:s}})=>s),ot(2,1),m(([s,a])=>s>a&&a>0),Y()),i=r.pipe(m(({active:s})=>s));return z([i,n]).pipe(m(([s,a])=>!(s&&a)),Y(),W(o.pipe(Ie(1))),ae(!0),vt({delay:250}),m(s=>({hidden:s})))}function Ii(e,{viewport$:t,header$:r,main$:o,target$:n}){let i=new T,s=i.pipe(oe(),ae(!0));return i.subscribe({next({hidden:a}){e.hidden=a,a?(e.setAttribute("tabindex","-1"),e.blur()):e.removeAttribute("tabindex")},complete(){e.style.top="",e.hidden=!0,e.removeAttribute("tabindex")}}),r.pipe(W(s),ne("height")).subscribe(({height:a})=>{e.style.top=`${a+16}px`}),h(e,"click").subscribe(a=>{a.preventDefault(),window.scrollTo({top:0})}),As(e,{viewport$:t,main$:o,target$:n}).pipe(O(a=>i.next(a)),A(()=>i.complete()),m(a=>R({ref:e},a)))}function Fi({document$:e,viewport$:t}){e.pipe(b(()=>M(".md-ellipsis")),J(r=>mt(r).pipe(W(e.pipe(Ie(1))),g(o=>o),m(()=>r),Ee(1))),g(r=>r.offsetWidth{let o=r.innerText,n=r.closest("a")||r;return n.title=o,V("content.tooltips")?Xe(n,{viewport$:t}).pipe(W(e.pipe(Ie(1))),A(()=>n.removeAttribute("title"))):y})).subscribe(),V("content.tooltips")&&e.pipe(b(()=>M(".md-status")),J(r=>Xe(r,{viewport$:t}))).subscribe()}function ji({document$:e,tablet$:t}){e.pipe(b(()=>M(".md-toggle--indeterminate")),O(r=>{r.indeterminate=!0,r.checked=!1}),J(r=>h(r,"change").pipe(Jr(()=>r.classList.contains("md-toggle--indeterminate")),m(()=>r))),te(t)).subscribe(([r,o])=>{r.classList.remove("md-toggle--indeterminate"),o&&(r.checked=!1)})}function Cs(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}function Ui({document$:e}){e.pipe(b(()=>M("[data-md-scrollfix]")),O(t=>t.removeAttribute("data-md-scrollfix")),g(Cs),J(t=>h(t,"touchstart").pipe(m(()=>t)))).subscribe(t=>{let r=t.scrollTop;r===0?t.scrollTop=1:r+t.offsetHeight===t.scrollHeight&&(t.scrollTop=r-1)})}function Wi({viewport$:e,tablet$:t}){z([Je("search"),t]).pipe(m(([r,o])=>r&&!o),b(r=>$(r).pipe(nt(r?400:100))),te(e)).subscribe(([r,{offset:{y:o}}])=>{if(r)document.body.setAttribute("data-md-scrolllock",""),document.body.style.top=`-${o}px`;else{let n=-1*parseInt(document.body.style.top,10);document.body.removeAttribute("data-md-scrolllock"),document.body.style.top="",n&&window.scrollTo(0,n)}})}Object.entries||(Object.entries=function(e){let t=[];for(let r of Object.keys(e))t.push([r,e[r]]);return t});Object.values||(Object.values=function(e){let t=[];for(let r of Object.keys(e))t.push(e[r]);return t});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(e,t){typeof e=="object"?(this.scrollLeft=e.left,this.scrollTop=e.top):(this.scrollLeft=e,this.scrollTop=t)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...e){let t=this.parentNode;if(t){e.length===0&&t.removeChild(this);for(let r=e.length-1;r>=0;r--){let o=e[r];typeof o=="string"?o=document.createTextNode(o):o.parentNode&&o.parentNode.removeChild(o),r?t.insertBefore(this.previousSibling,o):t.replaceChild(o,this)}}}));function ks(){return location.protocol==="file:"?At(`${new URL("search/search_index.js",Or.base)}`).pipe(m(()=>__index),Z(1)):ze(new URL("search/search_index.json",Or.base))}document.documentElement.classList.remove("no-js");document.documentElement.classList.add("js");var ct=an(),Qt=bn(),$t=yn(Qt),mo=hn(),ke=Ln(),Lr=Dt("(min-width: 960px)"),Vi=Dt("(min-width: 1220px)"),Ni=xn(),Or=Te(),zi=document.forms.namedItem("search")?ks():tt,fo=new T;di({alert$:fo});ui({document$:ct});var uo=new T,qi=Ht(Or.base);V("navigation.instant")&&gi({sitemap$:qi,location$:Qt,viewport$:ke,progress$:uo}).subscribe(ct);var Di;((Di=Or.version)==null?void 0:Di.provider)==="mike"&&Ti({document$:ct});L(Qt,$t).pipe(nt(125)).subscribe(()=>{at("drawer",!1),at("search",!1)});mo.pipe(g(({mode:e})=>e==="global")).subscribe(e=>{switch(e.type){case"p":case",":let t=ue("link[rel=prev]");typeof t!="undefined"&&st(t);break;case"n":case".":let r=ue("link[rel=next]");typeof r!="undefined"&&st(r);break;case"Enter":let o=Ne();o instanceof HTMLLabelElement&&o.click()}});Fi({viewport$:ke,document$:ct});ji({document$:ct,tablet$:Lr});Ui({document$:ct});Wi({viewport$:ke,tablet$:Lr});var ft=ai(Ce("header"),{viewport$:ke}),Kt=ct.pipe(m(()=>Ce("main")),b(e=>pi(e,{viewport$:ke,header$:ft})),Z(1)),Hs=L(...me("consent").map(e=>An(e,{target$:$t})),...me("dialog").map(e=>ni(e,{alert$:fo})),...me("palette").map(e=>li(e)),...me("progress").map(e=>mi(e,{progress$:uo})),...me("search").map(e=>_i(e,{index$:zi,keyboard$:mo})),...me("source").map(e=>$i(e))),$s=H(()=>L(...me("announce").map(e=>_n(e)),...me("content").map(e=>oi(e,{sitemap$:qi,viewport$:ke,target$:$t,print$:Ni})),...me("content").map(e=>V("search.highlight")?Ai(e,{index$:zi,location$:Qt}):y),...me("header").map(e=>si(e,{viewport$:ke,header$:ft,main$:Kt})),...me("header-title").map(e=>ci(e,{viewport$:ke,header$:ft})),...me("sidebar").map(e=>e.getAttribute("data-md-type")==="navigation"?eo(Vi,()=>lo(e,{viewport$:ke,header$:ft,main$:Kt})):eo(Lr,()=>lo(e,{viewport$:ke,header$:ft,main$:Kt}))),...me("tabs").map(e=>Ri(e,{viewport$:ke,header$:ft})),...me("toc").map(e=>Pi(e,{viewport$:ke,header$:ft,main$:Kt,target$:$t})),...me("top").map(e=>Ii(e,{viewport$:ke,header$:ft,main$:Kt,target$:$t})))),Ki=ct.pipe(b(()=>$s),Ve(Hs),Z(1));Ki.subscribe();window.document$=ct;window.location$=Qt;window.target$=$t;window.keyboard$=mo;window.viewport$=ke;window.tablet$=Lr;window.screen$=Vi;window.print$=Ni;window.alert$=fo;window.progress$=uo;window.component$=Ki;})(); diff --git a/assets/javascripts/lunr/min/lunr.ar.min.js b/assets/javascripts/lunr/min/lunr.ar.min.js new file mode 100644 index 0000000..9b06c26 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.ar.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ar=function(){this.pipeline.reset(),this.pipeline.add(e.ar.trimmer,e.ar.stopWordFilter,e.ar.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ar.stemmer))},e.ar.wordCharacters="ء-ٛٱـ",e.ar.trimmer=e.trimmerSupport.generateTrimmer(e.ar.wordCharacters),e.Pipeline.registerFunction(e.ar.trimmer,"trimmer-ar"),e.ar.stemmer=function(){var e=this;return e.result=!1,e.preRemoved=!1,e.sufRemoved=!1,e.pre={pre1:"ف ك ب و س ل ن ا ي ت",pre2:"ال لل",pre3:"بال وال فال تال كال ولل",pre4:"فبال كبال وبال وكال"},e.suf={suf1:"ه ك ت ن ا ي",suf2:"نك نه ها وك يا اه ون ين تن تم نا وا ان كم كن ني نن ما هم هن تك ته ات يه",suf3:"تين كهم نيه نهم ونه وها يهم ونا ونك وني وهم تكم تنا تها تني تهم كما كها ناه نكم هنا تان يها",suf4:"كموه ناها ونني ونهم تكما تموه تكاه كماه ناكم ناهم نيها وننا"},e.patterns=JSON.parse('{"pt43":[{"pt":[{"c":"ا","l":1}]},{"pt":[{"c":"ا,ت,ن,ي","l":0}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"و","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ي","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ا","l":2},{"c":"ل","l":3,"m":3}]},{"pt":[{"c":"م","l":0}]}],"pt53":[{"pt":[{"c":"ت","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":3},{"c":"ل","l":3,"m":4},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":3}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ن","l":4}]},{"pt":[{"c":"ت","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"م","l":0},{"c":"و","l":3}]},{"pt":[{"c":"ا","l":1},{"c":"و","l":3}]},{"pt":[{"c":"و","l":1},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"ا","l":2},{"c":"ن","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":1},{"c":"ا","l":3}]},{"pt":[{"c":"ي,ت,ا,ن","l":0},{"c":"ت","l":1}],"mPt":[{"c":"ف","l":0,"m":2},{"c":"ع","l":1,"m":3},{"c":"ا","l":2},{"c":"ل","l":3,"m":4}]},{"pt":[{"c":"ت,ي,ا,ن","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":2},{"c":"ي","l":3}]},{"pt":[{"c":"ا,ي,ت,ن","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ء","l":4}]}],"pt63":[{"pt":[{"c":"ا","l":0},{"c":"ت","l":2},{"c":"ا","l":4}]},{"pt":[{"c":"ا,ت,ن,ي","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"و","l":3}]},{"pt":[{"c":"م","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ي","l":1},{"c":"ي","l":3},{"c":"ا","l":4},{"c":"ء","l":5}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ا","l":4}]}],"pt54":[{"pt":[{"c":"ت","l":0}]},{"pt":[{"c":"ا,ي,ت,ن","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"م","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":2}]}],"pt64":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":1}]}],"pt73":[{"pt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ا","l":5}]}],"pt75":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":5}]}]}'),e.execArray=["cleanWord","removeDiacritics","cleanAlef","removeStopWords","normalizeHamzaAndAlef","removeStartWaw","removePre432","removeEndTaa","wordCheck"],e.stem=function(){var r=0;for(e.result=!1,e.preRemoved=!1,e.sufRemoved=!1;r=0)return!0},e.normalizeHamzaAndAlef=function(){return e.word=e.word.replace("ؤ","ء"),e.word=e.word.replace("ئ","ء"),e.word=e.word.replace(/([\u0627])\1+/gi,"ا"),!1},e.removeEndTaa=function(){return!(e.word.length>2)||(e.word=e.word.replace(/[\u0627]$/,""),e.word=e.word.replace("ة",""),!1)},e.removeStartWaw=function(){return e.word.length>3&&"و"==e.word[0]&&"و"==e.word[1]&&(e.word=e.word.slice(1)),!1},e.removePre432=function(){var r=e.word;if(e.word.length>=7){var t=new RegExp("^("+e.pre.pre4.split(" ").join("|")+")");e.word=e.word.replace(t,"")}if(e.word==r&&e.word.length>=6){var c=new RegExp("^("+e.pre.pre3.split(" ").join("|")+")");e.word=e.word.replace(c,"")}if(e.word==r&&e.word.length>=5){var l=new RegExp("^("+e.pre.pre2.split(" ").join("|")+")");e.word=e.word.replace(l,"")}return r!=e.word&&(e.preRemoved=!0),!1},e.patternCheck=function(r){for(var t=0;t3){var t=new RegExp("^("+e.pre.pre1.split(" ").join("|")+")");e.word=e.word.replace(t,"")}return r!=e.word&&(e.preRemoved=!0),!1},e.removeSuf1=function(){var r=e.word;if(0==e.sufRemoved&&e.word.length>3){var t=new RegExp("("+e.suf.suf1.split(" ").join("|")+")$");e.word=e.word.replace(t,"")}return r!=e.word&&(e.sufRemoved=!0),!1},e.removeSuf432=function(){var r=e.word;if(e.word.length>=6){var t=new RegExp("("+e.suf.suf4.split(" ").join("|")+")$");e.word=e.word.replace(t,"")}if(e.word==r&&e.word.length>=5){var c=new RegExp("("+e.suf.suf3.split(" ").join("|")+")$");e.word=e.word.replace(c,"")}if(e.word==r&&e.word.length>=4){var l=new RegExp("("+e.suf.suf2.split(" ").join("|")+")$");e.word=e.word.replace(l,"")}return r!=e.word&&(e.sufRemoved=!0),!1},e.wordCheck=function(){for(var r=(e.word,[e.removeSuf432,e.removeSuf1,e.removePre1]),t=0,c=!1;e.word.length>=7&&!e.result&&t=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.de.min.js b/assets/javascripts/lunr/min/lunr.de.min.js new file mode 100644 index 0000000..f3b5c10 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.de.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `German` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.de=function(){this.pipeline.reset(),this.pipeline.add(e.de.trimmer,e.de.stopWordFilter,e.de.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.de.stemmer))},e.de.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.de.trimmer=e.trimmerSupport.generateTrimmer(e.de.wordCharacters),e.Pipeline.registerFunction(e.de.trimmer,"trimmer-de"),e.de.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!v.eq_s(1,e)||(v.ket=v.cursor,!v.in_grouping(p,97,252)))&&(v.slice_from(r),v.cursor=n,!0)}function i(){for(var r,n,i,s,t=v.cursor;;)if(r=v.cursor,v.bra=r,v.eq_s(1,"ß"))v.ket=v.cursor,v.slice_from("ss");else{if(r>=v.limit)break;v.cursor=r+1}for(v.cursor=t;;)for(n=v.cursor;;){if(i=v.cursor,v.in_grouping(p,97,252)){if(s=v.cursor,v.bra=s,e("u","U",i))break;if(v.cursor=s,e("y","Y",i))break}if(i>=v.limit)return void(v.cursor=n);v.cursor=i+1}}function s(){for(;!v.in_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}for(;!v.out_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}return!1}function t(){m=v.limit,l=m;var e=v.cursor+3;0<=e&&e<=v.limit&&(d=e,s()||(m=v.cursor,m=v.limit)return;v.cursor++}}}function c(){return m<=v.cursor}function u(){return l<=v.cursor}function a(){var e,r,n,i,s=v.limit-v.cursor;if(v.ket=v.cursor,(e=v.find_among_b(w,7))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:v.slice_del(),v.ket=v.cursor,v.eq_s_b(1,"s")&&(v.bra=v.cursor,v.eq_s_b(3,"nis")&&v.slice_del());break;case 3:v.in_grouping_b(g,98,116)&&v.slice_del()}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(f,4))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:if(v.in_grouping_b(k,98,116)){var t=v.cursor-3;v.limit_backward<=t&&t<=v.limit&&(v.cursor=t,v.slice_del())}}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(_,8))&&(v.bra=v.cursor,u()))switch(e){case 1:v.slice_del(),v.ket=v.cursor,v.eq_s_b(2,"ig")&&(v.bra=v.cursor,r=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-r,u()&&v.slice_del()));break;case 2:n=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-n,v.slice_del());break;case 3:if(v.slice_del(),v.ket=v.cursor,i=v.limit-v.cursor,!v.eq_s_b(2,"er")&&(v.cursor=v.limit-i,!v.eq_s_b(2,"en")))break;v.bra=v.cursor,c()&&v.slice_del();break;case 4:v.slice_del(),v.ket=v.cursor,e=v.find_among_b(b,2),e&&(v.bra=v.cursor,u()&&1==e&&v.slice_del())}}var d,l,m,h=[new r("",-1,6),new r("U",0,2),new r("Y",0,1),new r("ä",0,3),new r("ö",0,4),new r("ü",0,5)],w=[new r("e",-1,2),new r("em",-1,1),new r("en",-1,2),new r("ern",-1,1),new r("er",-1,1),new r("s",-1,3),new r("es",5,2)],f=[new r("en",-1,1),new r("er",-1,1),new r("st",-1,2),new r("est",2,1)],b=[new r("ig",-1,1),new r("lich",-1,1)],_=[new r("end",-1,1),new r("ig",-1,2),new r("ung",-1,1),new r("lich",-1,3),new r("isch",-1,2),new r("ik",-1,2),new r("heit",-1,3),new r("keit",-1,4)],p=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32,8],g=[117,30,5],k=[117,30,4],v=new n;this.setCurrent=function(e){v.setCurrent(e)},this.getCurrent=function(){return v.getCurrent()},this.stem=function(){var e=v.cursor;return i(),v.cursor=e,t(),v.limit_backward=e,v.cursor=v.limit,a(),v.cursor=v.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.de.stemmer,"stemmer-de"),e.de.stopWordFilter=e.generateStopWordFilter("aber alle allem allen aller alles als also am an ander andere anderem anderen anderer anderes anderm andern anderr anders auch auf aus bei bin bis bist da damit dann das dasselbe dazu daß dein deine deinem deinen deiner deines dem demselben den denn denselben der derer derselbe derselben des desselben dessen dich die dies diese dieselbe dieselben diesem diesen dieser dieses dir doch dort du durch ein eine einem einen einer eines einig einige einigem einigen einiger einiges einmal er es etwas euch euer eure eurem euren eurer eures für gegen gewesen hab habe haben hat hatte hatten hier hin hinter ich ihm ihn ihnen ihr ihre ihrem ihren ihrer ihres im in indem ins ist jede jedem jeden jeder jedes jene jenem jenen jener jenes jetzt kann kein keine keinem keinen keiner keines können könnte machen man manche manchem manchen mancher manches mein meine meinem meinen meiner meines mich mir mit muss musste nach nicht nichts noch nun nur ob oder ohne sehr sein seine seinem seinen seiner seines selbst sich sie sind so solche solchem solchen solcher solches soll sollte sondern sonst um und uns unse unsem unsen unser unses unter viel vom von vor war waren warst was weg weil weiter welche welchem welchen welcher welches wenn werde werden wie wieder will wir wird wirst wo wollen wollte während würde würden zu zum zur zwar zwischen über".split(" ")),e.Pipeline.registerFunction(e.de.stopWordFilter,"stopWordFilter-de")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.du.min.js b/assets/javascripts/lunr/min/lunr.du.min.js new file mode 100644 index 0000000..49a0f3f --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.du.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Dutch` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");console.warn('[Lunr Languages] Please use the "nl" instead of the "du". The "nl" code is the standard code for Dutch language, and "du" will be removed in the next major versions.'),e.du=function(){this.pipeline.reset(),this.pipeline.add(e.du.trimmer,e.du.stopWordFilter,e.du.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.du.stemmer))},e.du.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.du.trimmer=e.trimmerSupport.generateTrimmer(e.du.wordCharacters),e.Pipeline.registerFunction(e.du.trimmer,"trimmer-du"),e.du.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e,r,i,o=C.cursor;;){if(C.bra=C.cursor,e=C.find_among(b,11))switch(C.ket=C.cursor,e){case 1:C.slice_from("a");continue;case 2:C.slice_from("e");continue;case 3:C.slice_from("i");continue;case 4:C.slice_from("o");continue;case 5:C.slice_from("u");continue;case 6:if(C.cursor>=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(r=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=r);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=r;else if(n(r))break}else if(n(r))break}function n(e){return C.cursor=e,e>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,f=_,t()||(_=C.cursor,_<3&&(_=3),t()||(f=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var e;;)if(C.bra=C.cursor,e=C.find_among(p,3))switch(C.ket=C.cursor,e){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return f<=C.cursor}function a(){var e=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-e,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var e;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.slice_del(),w=!0,a())))}function m(){var e;u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.eq_s_b(3,"gem")||(C.cursor=C.limit-e,C.slice_del(),a())))}function d(){var e,r,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,e=C.find_among_b(h,5))switch(C.bra=C.cursor,e){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(z,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(r=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-r,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,e=C.find_among_b(k,6))switch(C.bra=C.cursor,e){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(j,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var f,_,w,b=[new r("",-1,6),new r("á",0,1),new r("ä",0,1),new r("é",0,2),new r("ë",0,2),new r("í",0,3),new r("ï",0,3),new r("ó",0,4),new r("ö",0,4),new r("ú",0,5),new r("ü",0,5)],p=[new r("",-1,3),new r("I",0,2),new r("Y",0,1)],g=[new r("dd",-1,-1),new r("kk",-1,-1),new r("tt",-1,-1)],h=[new r("ene",-1,2),new r("se",-1,3),new r("en",-1,2),new r("heden",2,1),new r("s",-1,3)],k=[new r("end",-1,1),new r("ig",-1,2),new r("ing",-1,1),new r("lijk",-1,3),new r("baar",-1,4),new r("bar",-1,5)],v=[new r("aa",-1,-1),new r("ee",-1,-1),new r("oo",-1,-1),new r("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(e){C.setCurrent(e)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var r=C.cursor;return e(),C.cursor=r,o(),C.limit_backward=r,C.cursor=C.limit,d(),C.cursor=C.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.du.stemmer,"stemmer-du"),e.du.stopWordFilter=e.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),e.Pipeline.registerFunction(e.du.stopWordFilter,"stopWordFilter-du")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.el.min.js b/assets/javascripts/lunr/min/lunr.el.min.js new file mode 100644 index 0000000..ace017b --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.el.min.js @@ -0,0 +1 @@ +!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.el=function(){this.pipeline.reset(),void 0===this.searchPipeline&&this.pipeline.add(e.el.trimmer,e.el.normilizer),this.pipeline.add(e.el.stopWordFilter,e.el.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.el.stemmer))},e.el.wordCharacters="A-Za-zΑαΒβΓγΔδΕεΖζΗηΘθΙιΚκΛλΜμΝνΞξΟοΠπΡρΣσςΤτΥυΦφΧχΨψΩωΆάΈέΉήΊίΌόΎύΏώΪΐΫΰΐΰ",e.el.trimmer=e.trimmerSupport.generateTrimmer(e.el.wordCharacters),e.Pipeline.registerFunction(e.el.trimmer,"trimmer-el"),e.el.stemmer=function(){function e(e){return s.test(e)}function t(e){return/[ΑΕΗΙΟΥΩ]$/.test(e)}function r(e){return/[ΑΕΗΙΟΩ]$/.test(e)}function n(n){var s=n;if(n.length<3)return s;if(!e(n))return s;if(i.indexOf(n)>=0)return s;var u=new RegExp("(.*)("+Object.keys(l).join("|")+")$"),o=u.exec(s);return null!==o&&(s=o[1]+l[o[2]]),null!==(o=/^(.+?)(ΑΔΕΣ|ΑΔΩΝ)$/.exec(s))&&(s=o[1],/(ΟΚ|ΜΑΜ|ΜΑΝ|ΜΠΑΜΠ|ΠΑΤΕΡ|ΓΙΑΓΙ|ΝΤΑΝΤ|ΚΥΡ|ΘΕΙ|ΠΕΘΕΡ|ΜΟΥΣΑΜ|ΚΑΠΛΑΜ|ΠΑΡ|ΨΑΡ|ΤΖΟΥΡ|ΤΑΜΠΟΥΡ|ΓΑΛΑΤ|ΦΑΦΛΑΤ)$/.test(o[1])||(s+="ΑΔ")),null!==(o=/^(.+?)(ΕΔΕΣ|ΕΔΩΝ)$/.exec(s))&&(s=o[1],/(ΟΠ|ΙΠ|ΕΜΠ|ΥΠ|ΓΗΠ|ΔΑΠ|ΚΡΑΣΠ|ΜΙΛ)$/.test(o[1])&&(s+="ΕΔ")),null!==(o=/^(.+?)(ΟΥΔΕΣ|ΟΥΔΩΝ)$/.exec(s))&&(s=o[1],/(ΑΡΚ|ΚΑΛΙΑΚ|ΠΕΤΑΛ|ΛΙΧ|ΠΛΕΞ|ΣΚ|Σ|ΦΛ|ΦΡ|ΒΕΛ|ΛΟΥΛ|ΧΝ|ΣΠ|ΤΡΑΓ|ΦΕ)$/.test(o[1])&&(s+="ΟΥΔ")),null!==(o=/^(.+?)(ΕΩΣ|ΕΩΝ|ΕΑΣ|ΕΑ)$/.exec(s))&&(s=o[1],/^(Θ|Δ|ΕΛ|ΓΑΛ|Ν|Π|ΙΔ|ΠΑΡ|ΣΤΕΡ|ΟΡΦ|ΑΝΔΡ|ΑΝΤΡ)$/.test(o[1])&&(s+="Ε")),null!==(o=/^(.+?)(ΕΙΟ|ΕΙΟΣ|ΕΙΟΙ|ΕΙΑ|ΕΙΑΣ|ΕΙΕΣ|ΕΙΟΥ|ΕΙΟΥΣ|ΕΙΩΝ)$/.exec(s))&&o[1].length>4&&(s=o[1]),null!==(o=/^(.+?)(ΙΟΥΣ|ΙΑΣ|ΙΕΣ|ΙΟΣ|ΙΟΥ|ΙΟΙ|ΙΩΝ|ΙΟΝ|ΙΑ|ΙΟ)$/.exec(s))&&(s=o[1],(t(s)||s.length<2||/^(ΑΓ|ΑΓΓΕΛ|ΑΓΡ|ΑΕΡ|ΑΘΛ|ΑΚΟΥΣ|ΑΞ|ΑΣ|Β|ΒΙΒΛ|ΒΥΤ|Γ|ΓΙΑΓ|ΓΩΝ|Δ|ΔΑΝ|ΔΗΛ|ΔΗΜ|ΔΟΚΙΜ|ΕΛ|ΖΑΧΑΡ|ΗΛ|ΗΠ|ΙΔ|ΙΣΚ|ΙΣΤ|ΙΟΝ|ΙΩΝ|ΚΙΜΩΛ|ΚΟΛΟΝ|ΚΟΡ|ΚΤΗΡ|ΚΥΡ|ΛΑΓ|ΛΟΓ|ΜΑΓ|ΜΠΑΝ|ΜΠΡ|ΝΑΥΤ|ΝΟΤ|ΟΠΑΛ|ΟΞ|ΟΡ|ΟΣ|ΠΑΝΑΓ|ΠΑΤΡ|ΠΗΛ|ΠΗΝ|ΠΛΑΙΣ|ΠΟΝΤ|ΡΑΔ|ΡΟΔ|ΣΚ|ΣΚΟΡΠ|ΣΟΥΝ|ΣΠΑΝ|ΣΤΑΔ|ΣΥΡ|ΤΗΛ|ΤΙΜ|ΤΟΚ|ΤΟΠ|ΤΡΟΧ|ΦΙΛ|ΦΩΤ|Χ|ΧΙΛ|ΧΡΩΜ|ΧΩΡ)$/.test(o[1]))&&(s+="Ι"),/^(ΠΑΛ)$/.test(o[1])&&(s+="ΑΙ")),null!==(o=/^(.+?)(ΙΚΟΣ|ΙΚΟΝ|ΙΚΕΙΣ|ΙΚΟΙ|ΙΚΕΣ|ΙΚΟΥΣ|ΙΚΗ|ΙΚΗΣ|ΙΚΟ|ΙΚΑ|ΙΚΟΥ|ΙΚΩΝ|ΙΚΩΣ)$/.exec(s))&&(s=o[1],(t(s)||/^(ΑΔ|ΑΛ|ΑΜΑΝ|ΑΜΕΡ|ΑΜΜΟΧΑΛ|ΑΝΗΘ|ΑΝΤΙΔ|ΑΠΛ|ΑΤΤ|ΑΦΡ|ΒΑΣ|ΒΡΩΜ|ΓΕΝ|ΓΕΡ|Δ|ΔΙΚΑΝ|ΔΥΤ|ΕΙΔ|ΕΝΔ|ΕΞΩΔ|ΗΘ|ΘΕΤ|ΚΑΛΛΙΝ|ΚΑΛΠ|ΚΑΤΑΔ|ΚΟΥΖΙΝ|ΚΡ|ΚΩΔ|ΛΟΓ|Μ|ΜΕΡ|ΜΟΝΑΔ|ΜΟΥΛ|ΜΟΥΣ|ΜΠΑΓΙΑΤ|ΜΠΑΝ|ΜΠΟΛ|ΜΠΟΣ|ΜΥΣΤ|Ν|ΝΙΤ|ΞΙΚ|ΟΠΤ|ΠΑΝ|ΠΕΤΣ|ΠΙΚΑΝΤ|ΠΙΤΣ|ΠΛΑΣΤ|ΠΛΙΑΤΣ|ΠΟΝΤ|ΠΟΣΤΕΛΝ|ΠΡΩΤΟΔ|ΣΕΡΤ|ΣΗΜΑΝΤ|ΣΤΑΤ|ΣΥΝΑΔ|ΣΥΝΟΜΗΛ|ΤΕΛ|ΤΕΧΝ|ΤΡΟΠ|ΤΣΑΜ|ΥΠΟΔ|Φ|ΦΙΛΟΝ|ΦΥΛΟΔ|ΦΥΣ|ΧΑΣ)$/.test(o[1])||/(ΦΟΙΝ)$/.test(o[1]))&&(s+="ΙΚ")),"ΑΓΑΜΕ"===s&&(s="ΑΓΑΜ"),null!==(o=/^(.+?)(ΑΓΑΜΕ|ΗΣΑΜΕ|ΟΥΣΑΜΕ|ΗΚΑΜΕ|ΗΘΗΚΑΜΕ)$/.exec(s))&&(s=o[1]),null!==(o=/^(.+?)(ΑΜΕ)$/.exec(s))&&(s=o[1],/^(ΑΝΑΠ|ΑΠΟΘ|ΑΠΟΚ|ΑΠΟΣΤ|ΒΟΥΒ|ΞΕΘ|ΟΥΛ|ΠΕΘ|ΠΙΚΡ|ΠΟΤ|ΣΙΧ|Χ)$/.test(o[1])&&(s+="ΑΜ")),null!==(o=/^(.+?)(ΑΓΑΝΕ|ΗΣΑΝΕ|ΟΥΣΑΝΕ|ΙΟΝΤΑΝΕ|ΙΟΤΑΝΕ|ΙΟΥΝΤΑΝΕ|ΟΝΤΑΝΕ|ΟΤΑΝΕ|ΟΥΝΤΑΝΕ|ΗΚΑΝΕ|ΗΘΗΚΑΝΕ)$/.exec(s))&&(s=o[1],/^(ΤΡ|ΤΣ)$/.test(o[1])&&(s+="ΑΓΑΝ")),null!==(o=/^(.+?)(ΑΝΕ)$/.exec(s))&&(s=o[1],(r(s)||/^(ΒΕΤΕΡ|ΒΟΥΛΚ|ΒΡΑΧΜ|Γ|ΔΡΑΔΟΥΜ|Θ|ΚΑΛΠΟΥΖ|ΚΑΣΤΕΛ|ΚΟΡΜΟΡ|ΛΑΟΠΛ|ΜΩΑΜΕΘ|Μ|ΜΟΥΣΟΥΛΜΑΝ|ΟΥΛ|Π|ΠΕΛΕΚ|ΠΛ|ΠΟΛΙΣ|ΠΟΡΤΟΛ|ΣΑΡΑΚΑΤΣ|ΣΟΥΛΤ|ΤΣΑΡΛΑΤ|ΟΡΦ|ΤΣΙΓΓ|ΤΣΟΠ|ΦΩΤΟΣΤΕΦ|Χ|ΨΥΧΟΠΛ|ΑΓ|ΟΡΦ|ΓΑΛ|ΓΕΡ|ΔΕΚ|ΔΙΠΛ|ΑΜΕΡΙΚΑΝ|ΟΥΡ|ΠΙΘ|ΠΟΥΡΙΤ|Σ|ΖΩΝΤ|ΙΚ|ΚΑΣΤ|ΚΟΠ|ΛΙΧ|ΛΟΥΘΗΡ|ΜΑΙΝΤ|ΜΕΛ|ΣΙΓ|ΣΠ|ΣΤΕΓ|ΤΡΑΓ|ΤΣΑΓ|Φ|ΕΡ|ΑΔΑΠ|ΑΘΙΓΓ|ΑΜΗΧ|ΑΝΙΚ|ΑΝΟΡΓ|ΑΠΗΓ|ΑΠΙΘ|ΑΤΣΙΓΓ|ΒΑΣ|ΒΑΣΚ|ΒΑΘΥΓΑΛ|ΒΙΟΜΗΧ|ΒΡΑΧΥΚ|ΔΙΑΤ|ΔΙΑΦ|ΕΝΟΡΓ|ΘΥΣ|ΚΑΠΝΟΒΙΟΜΗΧ|ΚΑΤΑΓΑΛ|ΚΛΙΒ|ΚΟΙΛΑΡΦ|ΛΙΒ|ΜΕΓΛΟΒΙΟΜΗΧ|ΜΙΚΡΟΒΙΟΜΗΧ|ΝΤΑΒ|ΞΗΡΟΚΛΙΒ|ΟΛΙΓΟΔΑΜ|ΟΛΟΓΑΛ|ΠΕΝΤΑΡΦ|ΠΕΡΗΦ|ΠΕΡΙΤΡ|ΠΛΑΤ|ΠΟΛΥΔΑΠ|ΠΟΛΥΜΗΧ|ΣΤΕΦ|ΤΑΒ|ΤΕΤ|ΥΠΕΡΗΦ|ΥΠΟΚΟΠ|ΧΑΜΗΛΟΔΑΠ|ΨΗΛΟΤΑΒ)$/.test(o[1]))&&(s+="ΑΝ")),null!==(o=/^(.+?)(ΗΣΕΤΕ)$/.exec(s))&&(s=o[1]),null!==(o=/^(.+?)(ΕΤΕ)$/.exec(s))&&(s=o[1],(r(s)||/(ΟΔ|ΑΙΡ|ΦΟΡ|ΤΑΘ|ΔΙΑΘ|ΣΧ|ΕΝΔ|ΕΥΡ|ΤΙΘ|ΥΠΕΡΘ|ΡΑΘ|ΕΝΘ|ΡΟΘ|ΣΘ|ΠΥΡ|ΑΙΝ|ΣΥΝΔ|ΣΥΝ|ΣΥΝΘ|ΧΩΡ|ΠΟΝ|ΒΡ|ΚΑΘ|ΕΥΘ|ΕΚΘ|ΝΕΤ|ΡΟΝ|ΑΡΚ|ΒΑΡ|ΒΟΛ|ΩΦΕΛ)$/.test(o[1])||/^(ΑΒΑΡ|ΒΕΝ|ΕΝΑΡ|ΑΒΡ|ΑΔ|ΑΘ|ΑΝ|ΑΠΛ|ΒΑΡΟΝ|ΝΤΡ|ΣΚ|ΚΟΠ|ΜΠΟΡ|ΝΙΦ|ΠΑΓ|ΠΑΡΑΚΑΛ|ΣΕΡΠ|ΣΚΕΛ|ΣΥΡΦ|ΤΟΚ|Υ|Δ|ΕΜ|ΘΑΡΡ|Θ)$/.test(o[1]))&&(s+="ΕΤ")),null!==(o=/^(.+?)(ΟΝΤΑΣ|ΩΝΤΑΣ)$/.exec(s))&&(s=o[1],/^ΑΡΧ$/.test(o[1])&&(s+="ΟΝΤ"),/ΚΡΕ$/.test(o[1])&&(s+="ΩΝΤ")),null!==(o=/^(.+?)(ΟΜΑΣΤΕ|ΙΟΜΑΣΤΕ)$/.exec(s))&&(s=o[1],/^ΟΝ$/.test(o[1])&&(s+="ΟΜΑΣΤ")),null!==(o=/^(.+?)(ΙΕΣΤΕ)$/.exec(s))&&(s=o[1],/^(Π|ΑΠ|ΣΥΜΠ|ΑΣΥΜΠ|ΑΚΑΤΑΠ|ΑΜΕΤΑΜΦ)$/.test(o[1])&&(s+="ΙΕΣΤ")),null!==(o=/^(.+?)(ΕΣΤΕ)$/.exec(s))&&(s=o[1],/^(ΑΛ|ΑΡ|ΕΚΤΕΛ|Ζ|Μ|Ξ|ΠΑΡΑΚΑΛ|ΠΡΟ|ΝΙΣ)$/.test(o[1])&&(s+="ΕΣΤ")),null!==(o=/^(.+?)(ΗΘΗΚΑ|ΗΘΗΚΕΣ|ΗΘΗΚΕ)$/.exec(s))&&(s=o[1]),null!==(o=/^(.+?)(ΗΚΑ|ΗΚΕΣ|ΗΚΕ)$/.exec(s))&&(s=o[1],(/(ΣΚΩΛ|ΣΚΟΥΛ|ΝΑΡΘ|ΣΦ|ΟΘ|ΠΙΘ)$/.test(o[1])||/^(ΔΙΑΘ|Θ|ΠΑΡΑΚΑΤΑΘ|ΠΡΟΣΘ|ΣΥΝΘ)$/.test(o[1]))&&(s+="ΗΚ")),null!==(o=/^(.+?)(ΟΥΣΑ|ΟΥΣΕΣ|ΟΥΣΕ)$/.exec(s))&&(s=o[1],(t(s)||/^(ΦΑΡΜΑΚ|ΧΑΔ|ΑΓΚ|ΑΝΑΡΡ|ΒΡΟΜ|ΕΚΛΙΠ|ΛΑΜΠΙΔ|ΛΕΧ|Μ|ΠΑΤ|Ρ|Λ|ΜΕΔ|ΜΕΣΑΖ|ΥΠΟΤΕΙΝ|ΑΜ|ΑΙΘ|ΑΝΗΚ|ΔΕΣΠΟΖ|ΕΝΔΙΑΦΕΡ)$/.test(o[1])||/(ΠΟΔΑΡ|ΒΛΕΠ|ΠΑΝΤΑΧ|ΦΡΥΔ|ΜΑΝΤΙΛ|ΜΑΛΛ|ΚΥΜΑΤ|ΛΑΧ|ΛΗΓ|ΦΑΓ|ΟΜ|ΠΡΩΤ)$/.test(o[1]))&&(s+="ΟΥΣ")),null!==(o=/^(.+?)(ΑΓΑ|ΑΓΕΣ|ΑΓΕ)$/.exec(s))&&(s=o[1],(/^(ΑΒΑΣΤ|ΠΟΛΥΦ|ΑΔΗΦ|ΠΑΜΦ|Ρ|ΑΣΠ|ΑΦ|ΑΜΑΛ|ΑΜΑΛΛΙ|ΑΝΥΣΤ|ΑΠΕΡ|ΑΣΠΑΡ|ΑΧΑΡ|ΔΕΡΒΕΝ|ΔΡΟΣΟΠ|ΞΕΦ|ΝΕΟΠ|ΝΟΜΟΤ|ΟΛΟΠ|ΟΜΟΤ|ΠΡΟΣΤ|ΠΡΟΣΩΠΟΠ|ΣΥΜΠ|ΣΥΝΤ|Τ|ΥΠΟΤ|ΧΑΡ|ΑΕΙΠ|ΑΙΜΟΣΤ|ΑΝΥΠ|ΑΠΟΤ|ΑΡΤΙΠ|ΔΙΑΤ|ΕΝ|ΕΠΙΤ|ΚΡΟΚΑΛΟΠ|ΣΙΔΗΡΟΠ|Λ|ΝΑΥ|ΟΥΛΑΜ|ΟΥΡ|Π|ΤΡ|Μ)$/.test(o[1])||/(ΟΦ|ΠΕΛ|ΧΟΡΤ|ΛΛ|ΣΦ|ΡΠ|ΦΡ|ΠΡ|ΛΟΧ|ΣΜΗΝ)$/.test(o[1])&&!/^(ΨΟΦ|ΝΑΥΛΟΧ)$/.test(o[1])||/(ΚΟΛΛ)$/.test(o[1]))&&(s+="ΑΓ")),null!==(o=/^(.+?)(ΗΣΕ|ΗΣΟΥ|ΗΣΑ)$/.exec(s))&&(s=o[1],/^(Ν|ΧΕΡΣΟΝ|ΔΩΔΕΚΑΝ|ΕΡΗΜΟΝ|ΜΕΓΑΛΟΝ|ΕΠΤΑΝ|Ι)$/.test(o[1])&&(s+="ΗΣ")),null!==(o=/^(.+?)(ΗΣΤΕ)$/.exec(s))&&(s=o[1],/^(ΑΣΒ|ΣΒ|ΑΧΡ|ΧΡ|ΑΠΛ|ΑΕΙΜΝ|ΔΥΣΧΡ|ΕΥΧΡ|ΚΟΙΝΟΧΡ|ΠΑΛΙΜΨ)$/.test(o[1])&&(s+="ΗΣΤ")),null!==(o=/^(.+?)(ΟΥΝΕ|ΗΣΟΥΝΕ|ΗΘΟΥΝΕ)$/.exec(s))&&(s=o[1],/^(Ν|Ρ|ΣΠΙ|ΣΤΡΑΒΟΜΟΥΤΣ|ΚΑΚΟΜΟΥΤΣ|ΕΞΩΝ)$/.test(o[1])&&(s+="ΟΥΝ")),null!==(o=/^(.+?)(ΟΥΜΕ|ΗΣΟΥΜΕ|ΗΘΟΥΜΕ)$/.exec(s))&&(s=o[1],/^(ΠΑΡΑΣΟΥΣ|Φ|Χ|ΩΡΙΟΠΛ|ΑΖ|ΑΛΛΟΣΟΥΣ|ΑΣΟΥΣ)$/.test(o[1])&&(s+="ΟΥΜ")),null!=(o=/^(.+?)(ΜΑΤΟΙ|ΜΑΤΟΥΣ|ΜΑΤΟ|ΜΑΤΑ|ΜΑΤΩΣ|ΜΑΤΩΝ|ΜΑΤΟΣ|ΜΑΤΕΣ|ΜΑΤΗ|ΜΑΤΗΣ|ΜΑΤΟΥ)$/.exec(s))&&(s=o[1]+"Μ",/^(ΓΡΑΜ)$/.test(o[1])?s+="Α":/^(ΓΕ|ΣΤΑ)$/.test(o[1])&&(s+="ΑΤ")),null!==(o=/^(.+?)(ΟΥΑ)$/.exec(s))&&(s=o[1]+"ΟΥ"),n.length===s.length&&null!==(o=/^(.+?)(Α|ΑΓΑΤΕ|ΑΓΑΝ|ΑΕΙ|ΑΜΑΙ|ΑΝ|ΑΣ|ΑΣΑΙ|ΑΤΑΙ|ΑΩ|Ε|ΕΙ|ΕΙΣ|ΕΙΤΕ|ΕΣΑΙ|ΕΣ|ΕΤΑΙ|Ι|ΙΕΜΑΙ|ΙΕΜΑΣΤΕ|ΙΕΤΑΙ|ΙΕΣΑΙ|ΙΕΣΑΣΤΕ|ΙΟΜΑΣΤΑΝ|ΙΟΜΟΥΝ|ΙΟΜΟΥΝΑ|ΙΟΝΤΑΝ|ΙΟΝΤΟΥΣΑΝ|ΙΟΣΑΣΤΑΝ|ΙΟΣΑΣΤΕ|ΙΟΣΟΥΝ|ΙΟΣΟΥΝΑ|ΙΟΤΑΝ|ΙΟΥΜΑ|ΙΟΥΜΑΣΤΕ|ΙΟΥΝΤΑΙ|ΙΟΥΝΤΑΝ|Η|ΗΔΕΣ|ΗΔΩΝ|ΗΘΕΙ|ΗΘΕΙΣ|ΗΘΕΙΤΕ|ΗΘΗΚΑΤΕ|ΗΘΗΚΑΝ|ΗΘΟΥΝ|ΗΘΩ|ΗΚΑΤΕ|ΗΚΑΝ|ΗΣ|ΗΣΑΝ|ΗΣΑΤΕ|ΗΣΕΙ|ΗΣΕΣ|ΗΣΟΥΝ|ΗΣΩ|Ο|ΟΙ|ΟΜΑΙ|ΟΜΑΣΤΑΝ|ΟΜΟΥΝ|ΟΜΟΥΝΑ|ΟΝΤΑΙ|ΟΝΤΑΝ|ΟΝΤΟΥΣΑΝ|ΟΣ|ΟΣΑΣΤΑΝ|ΟΣΑΣΤΕ|ΟΣΟΥΝ|ΟΣΟΥΝΑ|ΟΤΑΝ|ΟΥ|ΟΥΜΑΙ|ΟΥΜΑΣΤΕ|ΟΥΝ|ΟΥΝΤΑΙ|ΟΥΝΤΑΝ|ΟΥΣ|ΟΥΣΑΝ|ΟΥΣΑΤΕ|Υ||ΥΑ|ΥΣ|Ω|ΩΝ|ΟΙΣ)$/.exec(s))&&(s=o[1]),null!=(o=/^(.+?)(ΕΣΤΕΡ|ΕΣΤΑΤ|ΟΤΕΡ|ΟΤΑΤ|ΥΤΕΡ|ΥΤΑΤ|ΩΤΕΡ|ΩΤΑΤ)$/.exec(s))&&(/^(ΕΞ|ΕΣ|ΑΝ|ΚΑΤ|Κ|ΠΡ)$/.test(o[1])||(s=o[1]),/^(ΚΑ|Μ|ΕΛΕ|ΛΕ|ΔΕ)$/.test(o[1])&&(s+="ΥΤ")),s}var l={"ΦΑΓΙΑ":"ΦΑ","ΦΑΓΙΟΥ":"ΦΑ","ΦΑΓΙΩΝ":"ΦΑ","ΣΚΑΓΙΑ":"ΣΚΑ","ΣΚΑΓΙΟΥ":"ΣΚΑ","ΣΚΑΓΙΩΝ":"ΣΚΑ","ΣΟΓΙΟΥ":"ΣΟ","ΣΟΓΙΑ":"ΣΟ","ΣΟΓΙΩΝ":"ΣΟ","ΤΑΤΟΓΙΑ":"ΤΑΤΟ","ΤΑΤΟΓΙΟΥ":"ΤΑΤΟ","ΤΑΤΟΓΙΩΝ":"ΤΑΤΟ","ΚΡΕΑΣ":"ΚΡΕ","ΚΡΕΑΤΟΣ":"ΚΡΕ","ΚΡΕΑΤΑ":"ΚΡΕ","ΚΡΕΑΤΩΝ":"ΚΡΕ","ΠΕΡΑΣ":"ΠΕΡ","ΠΕΡΑΤΟΣ":"ΠΕΡ","ΠΕΡΑΤΑ":"ΠΕΡ","ΠΕΡΑΤΩΝ":"ΠΕΡ","ΤΕΡΑΣ":"ΤΕΡ","ΤΕΡΑΤΟΣ":"ΤΕΡ","ΤΕΡΑΤΑ":"ΤΕΡ","ΤΕΡΑΤΩΝ":"ΤΕΡ","ΦΩΣ":"ΦΩ","ΦΩΤΟΣ":"ΦΩ","ΦΩΤΑ":"ΦΩ","ΦΩΤΩΝ":"ΦΩ","ΚΑΘΕΣΤΩΣ":"ΚΑΘΕΣΤ","ΚΑΘΕΣΤΩΤΟΣ":"ΚΑΘΕΣΤ","ΚΑΘΕΣΤΩΤΑ":"ΚΑΘΕΣΤ","ΚΑΘΕΣΤΩΤΩΝ":"ΚΑΘΕΣΤ","ΓΕΓΟΝΟΣ":"ΓΕΓΟΝ","ΓΕΓΟΝΟΤΟΣ":"ΓΕΓΟΝ","ΓΕΓΟΝΟΤΑ":"ΓΕΓΟΝ","ΓΕΓΟΝΟΤΩΝ":"ΓΕΓΟΝ","ΕΥΑ":"ΕΥ"},i=["ΑΚΡΙΒΩΣ","ΑΛΑ","ΑΛΛΑ","ΑΛΛΙΩΣ","ΑΛΛΟΤΕ","ΑΜΑ","ΑΝΩ","ΑΝΑ","ΑΝΑΜΕΣΑ","ΑΝΑΜΕΤΑΞΥ","ΑΝΕΥ","ΑΝΤΙ","ΑΝΤΙΠΕΡΑ","ΑΝΤΙΟ","ΑΞΑΦΝΑ","ΑΠΟ","ΑΠΟΨΕ","ΑΡΑ","ΑΡΑΓΕ","ΑΥΡΙΟ","ΑΦΟΙ","ΑΦΟΥ","ΑΦΟΤΟΥ","ΒΡΕ","ΓΕΙΑ","ΓΙΑ","ΓΙΑΤΙ","ΓΡΑΜΜΑ","ΔΕΗ","ΔΕΝ","ΔΗΛΑΔΗ","ΔΙΧΩΣ","ΔΥΟ","ΕΑΝ","ΕΓΩ","ΕΔΩ","ΕΔΑ","ΕΙΘΕ","ΕΙΜΑΙ","ΕΙΜΑΣΤΕ","ΕΙΣΑΙ","ΕΙΣΑΣΤΕ","ΕΙΝΑΙ","ΕΙΣΤΕ","ΕΙΤΕ","ΕΚΕΙ","ΕΚΟ","ΕΛΑ","ΕΜΑΣ","ΕΜΕΙΣ","ΕΝΤΕΛΩΣ","ΕΝΤΟΣ","ΕΝΤΩΜΕΤΑΞΥ","ΕΝΩ","ΕΞΙ","ΕΞΙΣΟΥ","ΕΞΗΣ","ΕΞΩ","ΕΟΚ","ΕΠΑΝΩ","ΕΠΕΙΔΗ","ΕΠΕΙΤΑ","ΕΠΙ","ΕΠΙΣΗΣ","ΕΠΟΜΕΝΩΣ","ΕΠΤΑ","ΕΣΑΣ","ΕΣΕΙΣ","ΕΣΤΩ","ΕΣΥ","ΕΣΩ","ΕΤΣΙ","ΕΥΓΕ","ΕΦΕ","ΕΦΕΞΗΣ","ΕΧΤΕΣ","ΕΩΣ","ΗΔΗ","ΗΜΙ","ΗΠΑ","ΗΤΟΙ","ΘΕΣ","ΙΔΙΩΣ","ΙΔΗ","ΙΚΑ","ΙΣΩΣ","ΚΑΘΕ","ΚΑΘΕΤΙ","ΚΑΘΟΛΟΥ","ΚΑΘΩΣ","ΚΑΙ","ΚΑΝ","ΚΑΠΟΤΕ","ΚΑΠΟΥ","ΚΑΤΑ","ΚΑΤΙ","ΚΑΤΟΠΙΝ","ΚΑΤΩ","ΚΕΙ","ΚΙΧ","ΚΚΕ","ΚΟΛΑΝ","ΚΥΡΙΩΣ","ΚΩΣ","ΜΑΚΑΡΙ","ΜΑΛΙΣΤΑ","ΜΑΛΛΟΝ","ΜΑΙ","ΜΑΟ","ΜΑΟΥΣ","ΜΑΣ","ΜΕΘΑΥΡΙΟ","ΜΕΣ","ΜΕΣΑ","ΜΕΤΑ","ΜΕΤΑΞΥ","ΜΕΧΡΙ","ΜΗΔΕ","ΜΗΝ","ΜΗΠΩΣ","ΜΗΤΕ","ΜΙΑ","ΜΙΑΣ","ΜΙΣ","ΜΜΕ","ΜΟΛΟΝΟΤΙ","ΜΟΥ","ΜΠΑ","ΜΠΑΣ","ΜΠΟΥΦΑΝ","ΜΠΡΟΣ","ΝΑΙ","ΝΕΣ","ΝΤΑ","ΝΤΕ","ΞΑΝΑ","ΟΗΕ","ΟΚΤΩ","ΟΜΩΣ","ΟΝΕ","ΟΠΑ","ΟΠΟΥ","ΟΠΩΣ","ΟΣΟ","ΟΤΑΝ","ΟΤΕ","ΟΤΙ","ΟΥΤΕ","ΟΧΙ","ΠΑΛΙ","ΠΑΝ","ΠΑΝΟ","ΠΑΝΤΟΤΕ","ΠΑΝΤΟΥ","ΠΑΝΤΩΣ","ΠΑΝΩ","ΠΑΡΑ","ΠΕΡΑ","ΠΕΡΙ","ΠΕΡΙΠΟΥ","ΠΙΑ","ΠΙΟ","ΠΙΣΩ","ΠΛΑΙ","ΠΛΕΟΝ","ΠΛΗΝ","ΠΟΤΕ","ΠΟΥ","ΠΡΟ","ΠΡΟΣ","ΠΡΟΧΤΕΣ","ΠΡΟΧΘΕΣ","ΡΟΔΙ","ΠΩΣ","ΣΑΙ","ΣΑΣ","ΣΑΝ","ΣΕΙΣ","ΣΙΑ","ΣΚΙ","ΣΟΙ","ΣΟΥ","ΣΡΙ","ΣΥΝ","ΣΥΝΑΜΑ","ΣΧΕΔΟΝ","ΤΑΔΕ","ΤΑΞΙ","ΤΑΧΑ","ΤΕΙ","ΤΗΝ","ΤΗΣ","ΤΙΠΟΤΑ","ΤΙΠΟΤΕ","ΤΙΣ","ΤΟΝ","ΤΟΤΕ","ΤΟΥ","ΤΟΥΣ","ΤΣΑ","ΤΣΕ","ΤΣΙ","ΤΣΟΥ","ΤΩΝ","ΥΠΟ","ΥΠΟΨΗ","ΥΠΟΨΙΝ","ΥΣΤΕΡΑ","ΦΕΤΟΣ","ΦΙΣ","ΦΠΑ","ΧΑΦ","ΧΘΕΣ","ΧΤΕΣ","ΧΩΡΙΣ","ΩΣ","ΩΣΑΝ","ΩΣΟΤΟΥ","ΩΣΠΟΥ","ΩΣΤΕ","ΩΣΤΟΣΟ"],s=new RegExp("^[ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ]+$");return function(e){return"function"==typeof e.update?e.update(function(e){return n(e.toUpperCase()).toLowerCase()}):n(e.toUpperCase()).toLowerCase()}}(),e.Pipeline.registerFunction(e.el.stemmer,"stemmer-el"),e.el.stopWordFilter=e.generateStopWordFilter("αλλα αν αντι απο αυτα αυτεσ αυτη αυτο αυτοι αυτοσ αυτουσ αυτων για δε δεν εαν ειμαι ειμαστε ειναι εισαι ειστε εκεινα εκεινεσ εκεινη εκεινο εκεινοι εκεινοσ εκεινουσ εκεινων ενω επι η θα ισωσ κ και κατα κι μα με μετα μη μην να ο οι ομωσ οπωσ οσο οτι παρα ποια ποιεσ ποιο ποιοι ποιοσ ποιουσ ποιων που προσ πωσ σε στη στην στο στον τα την τησ το τον τοτε του των ωσ".split(" ")),e.Pipeline.registerFunction(e.el.stopWordFilter,"stopWordFilter-el"),e.el.normilizer=function(){var e={"Ά":"Α","ά":"α","Έ":"Ε","έ":"ε","Ή":"Η","ή":"η","Ί":"Ι","ί":"ι","Ό":"Ο","ο":"ο","Ύ":"Υ","ύ":"υ","Ώ":"Ω","ώ":"ω","Ϊ":"Ι","ϊ":"ι","Ϋ":"Υ","ϋ":"υ","ΐ":"ι","ΰ":"υ"};return function(t){if("function"==typeof t.update)return t.update(function(t){for(var r="",n=0;n=A.limit)return!0;A.cursor++}return!1}return!0}function n(){if(A.in_grouping(x,97,252)){var s=A.cursor;if(e()){if(A.cursor=s,!A.in_grouping(x,97,252))return!0;for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!0;A.cursor++}}return!1}return!0}function i(){var s,r=A.cursor;if(n()){if(A.cursor=r,!A.out_grouping(x,97,252))return;if(s=A.cursor,e()){if(A.cursor=s,!A.in_grouping(x,97,252)||A.cursor>=A.limit)return;A.cursor++}}g=A.cursor}function a(){for(;!A.in_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}return!0}function t(){var e=A.cursor;g=A.limit,p=g,v=g,i(),A.cursor=e,a()&&(p=A.cursor,a()&&(v=A.cursor))}function o(){for(var e;;){if(A.bra=A.cursor,e=A.find_among(k,6))switch(A.ket=A.cursor,e){case 1:A.slice_from("a");continue;case 2:A.slice_from("e");continue;case 3:A.slice_from("i");continue;case 4:A.slice_from("o");continue;case 5:A.slice_from("u");continue;case 6:if(A.cursor>=A.limit)break;A.cursor++;continue}break}}function u(){return g<=A.cursor}function w(){return p<=A.cursor}function c(){return v<=A.cursor}function m(){var e;if(A.ket=A.cursor,A.find_among_b(y,13)&&(A.bra=A.cursor,(e=A.find_among_b(q,11))&&u()))switch(e){case 1:A.bra=A.cursor,A.slice_from("iendo");break;case 2:A.bra=A.cursor,A.slice_from("ando");break;case 3:A.bra=A.cursor,A.slice_from("ar");break;case 4:A.bra=A.cursor,A.slice_from("er");break;case 5:A.bra=A.cursor,A.slice_from("ir");break;case 6:A.slice_del();break;case 7:A.eq_s_b(1,"u")&&A.slice_del()}}function l(e,s){if(!c())return!0;A.slice_del(),A.ket=A.cursor;var r=A.find_among_b(e,s);return r&&(A.bra=A.cursor,1==r&&c()&&A.slice_del()),!1}function d(e){return!c()||(A.slice_del(),A.ket=A.cursor,A.eq_s_b(2,e)&&(A.bra=A.cursor,c()&&A.slice_del()),!1)}function b(){var e;if(A.ket=A.cursor,e=A.find_among_b(S,46)){switch(A.bra=A.cursor,e){case 1:if(!c())return!1;A.slice_del();break;case 2:if(d("ic"))return!1;break;case 3:if(!c())return!1;A.slice_from("log");break;case 4:if(!c())return!1;A.slice_from("u");break;case 5:if(!c())return!1;A.slice_from("ente");break;case 6:if(!w())return!1;A.slice_del(),A.ket=A.cursor,e=A.find_among_b(C,4),e&&(A.bra=A.cursor,c()&&(A.slice_del(),1==e&&(A.ket=A.cursor,A.eq_s_b(2,"at")&&(A.bra=A.cursor,c()&&A.slice_del()))));break;case 7:if(l(P,3))return!1;break;case 8:if(l(F,3))return!1;break;case 9:if(d("at"))return!1}return!0}return!1}function f(){var e,s;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(W,12),A.limit_backward=s,e)){if(A.bra=A.cursor,1==e){if(!A.eq_s_b(1,"u"))return!1;A.slice_del()}return!0}return!1}function _(){var e,s,r,n;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(L,96),A.limit_backward=s,e))switch(A.bra=A.cursor,e){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"u")?(n=A.limit-A.cursor,A.eq_s_b(1,"g")?A.cursor=A.limit-n:A.cursor=A.limit-r):A.cursor=A.limit-r,A.bra=A.cursor;case 2:A.slice_del()}}function h(){var e,s;if(A.ket=A.cursor,e=A.find_among_b(z,8))switch(A.bra=A.cursor,e){case 1:u()&&A.slice_del();break;case 2:u()&&(A.slice_del(),A.ket=A.cursor,A.eq_s_b(1,"u")&&(A.bra=A.cursor,s=A.limit-A.cursor,A.eq_s_b(1,"g")&&(A.cursor=A.limit-s,u()&&A.slice_del())))}}var v,p,g,k=[new s("",-1,6),new s("á",0,1),new s("é",0,2),new s("í",0,3),new s("ó",0,4),new s("ú",0,5)],y=[new s("la",-1,-1),new s("sela",0,-1),new s("le",-1,-1),new s("me",-1,-1),new s("se",-1,-1),new s("lo",-1,-1),new s("selo",5,-1),new s("las",-1,-1),new s("selas",7,-1),new s("les",-1,-1),new s("los",-1,-1),new s("selos",10,-1),new s("nos",-1,-1)],q=[new s("ando",-1,6),new s("iendo",-1,6),new s("yendo",-1,7),new s("ándo",-1,2),new s("iéndo",-1,1),new s("ar",-1,6),new s("er",-1,6),new s("ir",-1,6),new s("ár",-1,3),new s("ér",-1,4),new s("ír",-1,5)],C=[new s("ic",-1,-1),new s("ad",-1,-1),new s("os",-1,-1),new s("iv",-1,1)],P=[new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,1)],F=[new s("ic",-1,1),new s("abil",-1,1),new s("iv",-1,1)],S=[new s("ica",-1,1),new s("ancia",-1,2),new s("encia",-1,5),new s("adora",-1,2),new s("osa",-1,1),new s("ista",-1,1),new s("iva",-1,9),new s("anza",-1,1),new s("logía",-1,3),new s("idad",-1,8),new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,2),new s("mente",-1,7),new s("amente",13,6),new s("ación",-1,2),new s("ución",-1,4),new s("ico",-1,1),new s("ismo",-1,1),new s("oso",-1,1),new s("amiento",-1,1),new s("imiento",-1,1),new s("ivo",-1,9),new s("ador",-1,2),new s("icas",-1,1),new s("ancias",-1,2),new s("encias",-1,5),new s("adoras",-1,2),new s("osas",-1,1),new s("istas",-1,1),new s("ivas",-1,9),new s("anzas",-1,1),new s("logías",-1,3),new s("idades",-1,8),new s("ables",-1,1),new s("ibles",-1,1),new s("aciones",-1,2),new s("uciones",-1,4),new s("adores",-1,2),new s("antes",-1,2),new s("icos",-1,1),new s("ismos",-1,1),new s("osos",-1,1),new s("amientos",-1,1),new s("imientos",-1,1),new s("ivos",-1,9)],W=[new s("ya",-1,1),new s("ye",-1,1),new s("yan",-1,1),new s("yen",-1,1),new s("yeron",-1,1),new s("yendo",-1,1),new s("yo",-1,1),new s("yas",-1,1),new s("yes",-1,1),new s("yais",-1,1),new s("yamos",-1,1),new s("yó",-1,1)],L=[new s("aba",-1,2),new s("ada",-1,2),new s("ida",-1,2),new s("ara",-1,2),new s("iera",-1,2),new s("ía",-1,2),new s("aría",5,2),new s("ería",5,2),new s("iría",5,2),new s("ad",-1,2),new s("ed",-1,2),new s("id",-1,2),new s("ase",-1,2),new s("iese",-1,2),new s("aste",-1,2),new s("iste",-1,2),new s("an",-1,2),new s("aban",16,2),new s("aran",16,2),new s("ieran",16,2),new s("ían",16,2),new s("arían",20,2),new s("erían",20,2),new s("irían",20,2),new s("en",-1,1),new s("asen",24,2),new s("iesen",24,2),new s("aron",-1,2),new s("ieron",-1,2),new s("arán",-1,2),new s("erán",-1,2),new s("irán",-1,2),new s("ado",-1,2),new s("ido",-1,2),new s("ando",-1,2),new s("iendo",-1,2),new s("ar",-1,2),new s("er",-1,2),new s("ir",-1,2),new s("as",-1,2),new s("abas",39,2),new s("adas",39,2),new s("idas",39,2),new s("aras",39,2),new s("ieras",39,2),new s("ías",39,2),new s("arías",45,2),new s("erías",45,2),new s("irías",45,2),new s("es",-1,1),new s("ases",49,2),new s("ieses",49,2),new s("abais",-1,2),new s("arais",-1,2),new s("ierais",-1,2),new s("íais",-1,2),new s("aríais",55,2),new s("eríais",55,2),new s("iríais",55,2),new s("aseis",-1,2),new s("ieseis",-1,2),new s("asteis",-1,2),new s("isteis",-1,2),new s("áis",-1,2),new s("éis",-1,1),new s("aréis",64,2),new s("eréis",64,2),new s("iréis",64,2),new s("ados",-1,2),new s("idos",-1,2),new s("amos",-1,2),new s("ábamos",70,2),new s("áramos",70,2),new s("iéramos",70,2),new s("íamos",70,2),new s("aríamos",74,2),new s("eríamos",74,2),new s("iríamos",74,2),new s("emos",-1,1),new s("aremos",78,2),new s("eremos",78,2),new s("iremos",78,2),new s("ásemos",78,2),new s("iésemos",78,2),new s("imos",-1,2),new s("arás",-1,2),new s("erás",-1,2),new s("irás",-1,2),new s("ís",-1,2),new s("ará",-1,2),new s("erá",-1,2),new s("irá",-1,2),new s("aré",-1,2),new s("eré",-1,2),new s("iré",-1,2),new s("ió",-1,2)],z=[new s("a",-1,1),new s("e",-1,2),new s("o",-1,1),new s("os",-1,1),new s("á",-1,1),new s("é",-1,2),new s("í",-1,1),new s("ó",-1,1)],x=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,4,10],A=new r;this.setCurrent=function(e){A.setCurrent(e)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return t(),A.limit_backward=e,A.cursor=A.limit,m(),A.cursor=A.limit,b()||(A.cursor=A.limit,f()||(A.cursor=A.limit,_())),A.cursor=A.limit,h(),A.cursor=A.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.es.stemmer,"stemmer-es"),e.es.stopWordFilter=e.generateStopWordFilter("a al algo algunas algunos ante antes como con contra cual cuando de del desde donde durante e el ella ellas ellos en entre era erais eran eras eres es esa esas ese eso esos esta estaba estabais estaban estabas estad estada estadas estado estados estamos estando estar estaremos estará estarán estarás estaré estaréis estaría estaríais estaríamos estarían estarías estas este estemos esto estos estoy estuve estuviera estuvierais estuvieran estuvieras estuvieron estuviese estuvieseis estuviesen estuvieses estuvimos estuviste estuvisteis estuviéramos estuviésemos estuvo está estábamos estáis están estás esté estéis estén estés fue fuera fuerais fueran fueras fueron fuese fueseis fuesen fueses fui fuimos fuiste fuisteis fuéramos fuésemos ha habida habidas habido habidos habiendo habremos habrá habrán habrás habré habréis habría habríais habríamos habrían habrías habéis había habíais habíamos habían habías han has hasta hay haya hayamos hayan hayas hayáis he hemos hube hubiera hubierais hubieran hubieras hubieron hubiese hubieseis hubiesen hubieses hubimos hubiste hubisteis hubiéramos hubiésemos hubo la las le les lo los me mi mis mucho muchos muy más mí mía mías mío míos nada ni no nos nosotras nosotros nuestra nuestras nuestro nuestros o os otra otras otro otros para pero poco por porque que quien quienes qué se sea seamos sean seas seremos será serán serás seré seréis sería seríais seríamos serían serías seáis sido siendo sin sobre sois somos son soy su sus suya suyas suyo suyos sí también tanto te tendremos tendrá tendrán tendrás tendré tendréis tendría tendríais tendríamos tendrían tendrías tened tenemos tenga tengamos tengan tengas tengo tengáis tenida tenidas tenido tenidos teniendo tenéis tenía teníais teníamos tenían tenías ti tiene tienen tienes todo todos tu tus tuve tuviera tuvierais tuvieran tuvieras tuvieron tuviese tuvieseis tuviesen tuvieses tuvimos tuviste tuvisteis tuviéramos tuviésemos tuvo tuya tuyas tuyo tuyos tú un una uno unos vosotras vosotros vuestra vuestras vuestro vuestros y ya yo él éramos".split(" ")),e.Pipeline.registerFunction(e.es.stopWordFilter,"stopWordFilter-es")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.fi.min.js b/assets/javascripts/lunr/min/lunr.fi.min.js new file mode 100644 index 0000000..29f5dfc --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.fi.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Finnish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(i,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e():e()(i.lunr)}(this,function(){return function(i){if(void 0===i)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===i.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");i.fi=function(){this.pipeline.reset(),this.pipeline.add(i.fi.trimmer,i.fi.stopWordFilter,i.fi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(i.fi.stemmer))},i.fi.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",i.fi.trimmer=i.trimmerSupport.generateTrimmer(i.fi.wordCharacters),i.Pipeline.registerFunction(i.fi.trimmer,"trimmer-fi"),i.fi.stemmer=function(){var e=i.stemmerSupport.Among,r=i.stemmerSupport.SnowballProgram,n=new function(){function i(){f=A.limit,d=f,n()||(f=A.cursor,n()||(d=A.cursor))}function n(){for(var i;;){if(i=A.cursor,A.in_grouping(W,97,246))break;if(A.cursor=i,i>=A.limit)return!0;A.cursor++}for(A.cursor=i;!A.out_grouping(W,97,246);){if(A.cursor>=A.limit)return!0;A.cursor++}return!1}function t(){return d<=A.cursor}function s(){var i,e;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(h,10)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.in_grouping_b(x,97,246))return;break;case 2:if(!t())return}A.slice_del()}else A.limit_backward=e}function o(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(v,9))switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"k")||(A.cursor=A.limit-r,A.slice_del());break;case 2:A.slice_del(),A.ket=A.cursor,A.eq_s_b(3,"kse")&&(A.bra=A.cursor,A.slice_from("ksi"));break;case 3:A.slice_del();break;case 4:A.find_among_b(p,6)&&A.slice_del();break;case 5:A.find_among_b(g,6)&&A.slice_del();break;case 6:A.find_among_b(j,2)&&A.slice_del()}else A.limit_backward=e}function l(){return A.find_among_b(q,7)}function a(){return A.eq_s_b(1,"i")&&A.in_grouping_b(L,97,246)}function u(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(C,30)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.eq_s_b(1,"a"))return;break;case 2:case 9:if(!A.eq_s_b(1,"e"))return;break;case 3:if(!A.eq_s_b(1,"i"))return;break;case 4:if(!A.eq_s_b(1,"o"))return;break;case 5:if(!A.eq_s_b(1,"ä"))return;break;case 6:if(!A.eq_s_b(1,"ö"))return;break;case 7:if(r=A.limit-A.cursor,!l()&&(A.cursor=A.limit-r,!A.eq_s_b(2,"ie"))){A.cursor=A.limit-r;break}if(A.cursor=A.limit-r,A.cursor<=A.limit_backward){A.cursor=A.limit-r;break}A.cursor--,A.bra=A.cursor;break;case 8:if(!A.in_grouping_b(W,97,246)||!A.out_grouping_b(W,97,246))return}A.slice_del(),k=!0}else A.limit_backward=e}function c(){var i,e,r;if(A.cursor>=d)if(e=A.limit_backward,A.limit_backward=d,A.ket=A.cursor,i=A.find_among_b(P,14)){if(A.bra=A.cursor,A.limit_backward=e,1==i){if(r=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-r}A.slice_del()}else A.limit_backward=e}function m(){var i;A.cursor>=f&&(i=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.find_among_b(F,2)?(A.bra=A.cursor,A.limit_backward=i,A.slice_del()):A.limit_backward=i)}function w(){var i,e,r,n,t,s;if(A.cursor>=f){if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.eq_s_b(1,"t")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.in_grouping_b(W,97,246)&&(A.cursor=A.limit-r,A.slice_del(),A.limit_backward=e,n=A.limit-A.cursor,A.cursor>=d&&(A.cursor=d,t=A.limit_backward,A.limit_backward=A.cursor,A.cursor=A.limit-n,A.ket=A.cursor,i=A.find_among_b(S,2))))){if(A.bra=A.cursor,A.limit_backward=t,1==i){if(s=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-s}return void A.slice_del()}A.limit_backward=e}}function _(){var i,e,r,n;if(A.cursor>=f){for(i=A.limit_backward,A.limit_backward=f,e=A.limit-A.cursor,l()&&(A.cursor=A.limit-e,A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.in_grouping_b(y,97,228)&&(A.bra=A.cursor,A.out_grouping_b(W,97,246)&&A.slice_del()),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"j")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.eq_s_b(1,"o")?A.slice_del():(A.cursor=A.limit-r,A.eq_s_b(1,"u")&&A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"o")&&(A.bra=A.cursor,A.eq_s_b(1,"j")&&A.slice_del()),A.cursor=A.limit-e,A.limit_backward=i;;){if(n=A.limit-A.cursor,A.out_grouping_b(W,97,246)){A.cursor=A.limit-n;break}if(A.cursor=A.limit-n,A.cursor<=A.limit_backward)return;A.cursor--}A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,b=A.slice_to(),A.eq_v_b(b)&&A.slice_del())}}var k,b,d,f,h=[new e("pa",-1,1),new e("sti",-1,2),new e("kaan",-1,1),new e("han",-1,1),new e("kin",-1,1),new e("hän",-1,1),new e("kään",-1,1),new e("ko",-1,1),new e("pä",-1,1),new e("kö",-1,1)],p=[new e("lla",-1,-1),new e("na",-1,-1),new e("ssa",-1,-1),new e("ta",-1,-1),new e("lta",3,-1),new e("sta",3,-1)],g=[new e("llä",-1,-1),new e("nä",-1,-1),new e("ssä",-1,-1),new e("tä",-1,-1),new e("ltä",3,-1),new e("stä",3,-1)],j=[new e("lle",-1,-1),new e("ine",-1,-1)],v=[new e("nsa",-1,3),new e("mme",-1,3),new e("nne",-1,3),new e("ni",-1,2),new e("si",-1,1),new e("an",-1,4),new e("en",-1,6),new e("än",-1,5),new e("nsä",-1,3)],q=[new e("aa",-1,-1),new e("ee",-1,-1),new e("ii",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1),new e("ää",-1,-1),new e("öö",-1,-1)],C=[new e("a",-1,8),new e("lla",0,-1),new e("na",0,-1),new e("ssa",0,-1),new e("ta",0,-1),new e("lta",4,-1),new e("sta",4,-1),new e("tta",4,9),new e("lle",-1,-1),new e("ine",-1,-1),new e("ksi",-1,-1),new e("n",-1,7),new e("han",11,1),new e("den",11,-1,a),new e("seen",11,-1,l),new e("hen",11,2),new e("tten",11,-1,a),new e("hin",11,3),new e("siin",11,-1,a),new e("hon",11,4),new e("hän",11,5),new e("hön",11,6),new e("ä",-1,8),new e("llä",22,-1),new e("nä",22,-1),new e("ssä",22,-1),new e("tä",22,-1),new e("ltä",26,-1),new e("stä",26,-1),new e("ttä",26,9)],P=[new e("eja",-1,-1),new e("mma",-1,1),new e("imma",1,-1),new e("mpa",-1,1),new e("impa",3,-1),new e("mmi",-1,1),new e("immi",5,-1),new e("mpi",-1,1),new e("impi",7,-1),new e("ejä",-1,-1),new e("mmä",-1,1),new e("immä",10,-1),new e("mpä",-1,1),new e("impä",12,-1)],F=[new e("i",-1,-1),new e("j",-1,-1)],S=[new e("mma",-1,1),new e("imma",0,-1)],y=[17,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8],W=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],L=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],x=[17,97,24,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],A=new r;this.setCurrent=function(i){A.setCurrent(i)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return i(),k=!1,A.limit_backward=e,A.cursor=A.limit,s(),A.cursor=A.limit,o(),A.cursor=A.limit,u(),A.cursor=A.limit,c(),A.cursor=A.limit,k?(m(),A.cursor=A.limit):(A.cursor=A.limit,w(),A.cursor=A.limit),_(),!0}};return function(i){return"function"==typeof i.update?i.update(function(i){return n.setCurrent(i),n.stem(),n.getCurrent()}):(n.setCurrent(i),n.stem(),n.getCurrent())}}(),i.Pipeline.registerFunction(i.fi.stemmer,"stemmer-fi"),i.fi.stopWordFilter=i.generateStopWordFilter("ei eivät emme en et ette että he heidän heidät heihin heille heillä heiltä heissä heistä heitä hän häneen hänelle hänellä häneltä hänen hänessä hänestä hänet häntä itse ja johon joiden joihin joiksi joilla joille joilta joina joissa joista joita joka joksi jolla jolle jolta jona jonka jos jossa josta jota jotka kanssa keiden keihin keiksi keille keillä keiltä keinä keissä keistä keitä keneen keneksi kenelle kenellä keneltä kenen kenenä kenessä kenestä kenet ketkä ketkä ketä koska kuin kuka kun me meidän meidät meihin meille meillä meiltä meissä meistä meitä mihin miksi mikä mille millä miltä minkä minkä minua minulla minulle minulta minun minussa minusta minut minuun minä minä missä mistä mitkä mitä mukaan mutta ne niiden niihin niiksi niille niillä niiltä niin niin niinä niissä niistä niitä noiden noihin noiksi noilla noille noilta noin noina noissa noista noita nuo nyt näiden näihin näiksi näille näillä näiltä näinä näissä näistä näitä nämä ole olemme olen olet olette oli olimme olin olisi olisimme olisin olisit olisitte olisivat olit olitte olivat olla olleet ollut on ovat poikki se sekä sen siihen siinä siitä siksi sille sillä sillä siltä sinua sinulla sinulle sinulta sinun sinussa sinusta sinut sinuun sinä sinä sitä tai te teidän teidät teihin teille teillä teiltä teissä teistä teitä tuo tuohon tuoksi tuolla tuolle tuolta tuon tuona tuossa tuosta tuota tähän täksi tälle tällä tältä tämä tämän tänä tässä tästä tätä vaan vai vaikka yli".split(" ")),i.Pipeline.registerFunction(i.fi.stopWordFilter,"stopWordFilter-fi")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.fr.min.js b/assets/javascripts/lunr/min/lunr.fr.min.js new file mode 100644 index 0000000..68cd009 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.fr.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `French` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.fr=function(){this.pipeline.reset(),this.pipeline.add(e.fr.trimmer,e.fr.stopWordFilter,e.fr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.fr.stemmer))},e.fr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.fr.trimmer=e.trimmerSupport.generateTrimmer(e.fr.wordCharacters),e.Pipeline.registerFunction(e.fr.trimmer,"trimmer-fr"),e.fr.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,s){return!(!W.eq_s(1,e)||(W.ket=W.cursor,!W.in_grouping(F,97,251)))&&(W.slice_from(r),W.cursor=s,!0)}function i(e,r,s){return!!W.eq_s(1,e)&&(W.ket=W.cursor,W.slice_from(r),W.cursor=s,!0)}function n(){for(var r,s;;){if(r=W.cursor,W.in_grouping(F,97,251)){if(W.bra=W.cursor,s=W.cursor,e("u","U",r))continue;if(W.cursor=s,e("i","I",r))continue;if(W.cursor=s,i("y","Y",r))continue}if(W.cursor=r,W.bra=r,!e("y","Y",r)){if(W.cursor=r,W.eq_s(1,"q")&&(W.bra=W.cursor,i("u","U",r)))continue;if(W.cursor=r,r>=W.limit)return;W.cursor++}}}function t(){for(;!W.in_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}for(;!W.out_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}return!1}function u(){var e=W.cursor;if(q=W.limit,g=q,p=q,W.in_grouping(F,97,251)&&W.in_grouping(F,97,251)&&W.cursor=W.limit){W.cursor=q;break}W.cursor++}while(!W.in_grouping(F,97,251))}q=W.cursor,W.cursor=e,t()||(g=W.cursor,t()||(p=W.cursor))}function o(){for(var e,r;;){if(r=W.cursor,W.bra=r,!(e=W.find_among(h,4)))break;switch(W.ket=W.cursor,e){case 1:W.slice_from("i");break;case 2:W.slice_from("u");break;case 3:W.slice_from("y");break;case 4:if(W.cursor>=W.limit)return;W.cursor++}}}function c(){return q<=W.cursor}function a(){return g<=W.cursor}function l(){return p<=W.cursor}function w(){var e,r;if(W.ket=W.cursor,e=W.find_among_b(C,43)){switch(W.bra=W.cursor,e){case 1:if(!l())return!1;W.slice_del();break;case 2:if(!l())return!1;W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")&&(W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU"));break;case 3:if(!l())return!1;W.slice_from("log");break;case 4:if(!l())return!1;W.slice_from("u");break;case 5:if(!l())return!1;W.slice_from("ent");break;case 6:if(!c())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(z,6))switch(W.bra=W.cursor,e){case 1:l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&W.slice_del()));break;case 2:l()?W.slice_del():a()&&W.slice_from("eux");break;case 3:l()&&W.slice_del();break;case 4:c()&&W.slice_from("i")}break;case 7:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(y,3))switch(W.bra=W.cursor,e){case 1:l()?W.slice_del():W.slice_from("abl");break;case 2:l()?W.slice_del():W.slice_from("iqU");break;case 3:l()&&W.slice_del()}break;case 8:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")))){W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU");break}break;case 9:W.slice_from("eau");break;case 10:if(!a())return!1;W.slice_from("al");break;case 11:if(l())W.slice_del();else{if(!a())return!1;W.slice_from("eux")}break;case 12:if(!a()||!W.out_grouping_b(F,97,251))return!1;W.slice_del();break;case 13:return c()&&W.slice_from("ant"),!1;case 14:return c()&&W.slice_from("ent"),!1;case 15:return r=W.limit-W.cursor,W.in_grouping_b(F,97,251)&&c()&&(W.cursor=W.limit-r,W.slice_del()),!1}return!0}return!1}function f(){var e,r;if(W.cursor=q){if(s=W.limit_backward,W.limit_backward=q,W.ket=W.cursor,e=W.find_among_b(P,7))switch(W.bra=W.cursor,e){case 1:if(l()){if(i=W.limit-W.cursor,!W.eq_s_b(1,"s")&&(W.cursor=W.limit-i,!W.eq_s_b(1,"t")))break;W.slice_del()}break;case 2:W.slice_from("i");break;case 3:W.slice_del();break;case 4:W.eq_s_b(2,"gu")&&W.slice_del()}W.limit_backward=s}}function b(){var e=W.limit-W.cursor;W.find_among_b(U,5)&&(W.cursor=W.limit-e,W.ket=W.cursor,W.cursor>W.limit_backward&&(W.cursor--,W.bra=W.cursor,W.slice_del()))}function d(){for(var e,r=1;W.out_grouping_b(F,97,251);)r--;if(r<=0){if(W.ket=W.cursor,e=W.limit-W.cursor,!W.eq_s_b(1,"é")&&(W.cursor=W.limit-e,!W.eq_s_b(1,"è")))return;W.bra=W.cursor,W.slice_from("e")}}function k(){if(!w()&&(W.cursor=W.limit,!f()&&(W.cursor=W.limit,!m())))return W.cursor=W.limit,void _();W.cursor=W.limit,W.ket=W.cursor,W.eq_s_b(1,"Y")?(W.bra=W.cursor,W.slice_from("i")):(W.cursor=W.limit,W.eq_s_b(1,"ç")&&(W.bra=W.cursor,W.slice_from("c")))}var p,g,q,v=[new r("col",-1,-1),new r("par",-1,-1),new r("tap",-1,-1)],h=[new r("",-1,4),new r("I",0,1),new r("U",0,2),new r("Y",0,3)],z=[new r("iqU",-1,3),new r("abl",-1,3),new r("Ièr",-1,4),new r("ièr",-1,4),new r("eus",-1,2),new r("iv",-1,1)],y=[new r("ic",-1,2),new r("abil",-1,1),new r("iv",-1,3)],C=[new r("iqUe",-1,1),new r("atrice",-1,2),new r("ance",-1,1),new r("ence",-1,5),new r("logie",-1,3),new r("able",-1,1),new r("isme",-1,1),new r("euse",-1,11),new r("iste",-1,1),new r("ive",-1,8),new r("if",-1,8),new r("usion",-1,4),new r("ation",-1,2),new r("ution",-1,4),new r("ateur",-1,2),new r("iqUes",-1,1),new r("atrices",-1,2),new r("ances",-1,1),new r("ences",-1,5),new r("logies",-1,3),new r("ables",-1,1),new r("ismes",-1,1),new r("euses",-1,11),new r("istes",-1,1),new r("ives",-1,8),new r("ifs",-1,8),new r("usions",-1,4),new r("ations",-1,2),new r("utions",-1,4),new r("ateurs",-1,2),new r("ments",-1,15),new r("ements",30,6),new r("issements",31,12),new r("ités",-1,7),new r("ment",-1,15),new r("ement",34,6),new r("issement",35,12),new r("amment",34,13),new r("emment",34,14),new r("aux",-1,10),new r("eaux",39,9),new r("eux",-1,1),new r("ité",-1,7)],x=[new r("ira",-1,1),new r("ie",-1,1),new r("isse",-1,1),new r("issante",-1,1),new r("i",-1,1),new r("irai",4,1),new r("ir",-1,1),new r("iras",-1,1),new r("ies",-1,1),new r("îmes",-1,1),new r("isses",-1,1),new r("issantes",-1,1),new r("îtes",-1,1),new r("is",-1,1),new r("irais",13,1),new r("issais",13,1),new r("irions",-1,1),new r("issions",-1,1),new r("irons",-1,1),new r("issons",-1,1),new r("issants",-1,1),new r("it",-1,1),new r("irait",21,1),new r("issait",21,1),new r("issant",-1,1),new r("iraIent",-1,1),new r("issaIent",-1,1),new r("irent",-1,1),new r("issent",-1,1),new r("iront",-1,1),new r("ît",-1,1),new r("iriez",-1,1),new r("issiez",-1,1),new r("irez",-1,1),new r("issez",-1,1)],I=[new r("a",-1,3),new r("era",0,2),new r("asse",-1,3),new r("ante",-1,3),new r("ée",-1,2),new r("ai",-1,3),new r("erai",5,2),new r("er",-1,2),new r("as",-1,3),new r("eras",8,2),new r("âmes",-1,3),new r("asses",-1,3),new r("antes",-1,3),new r("âtes",-1,3),new r("ées",-1,2),new r("ais",-1,3),new r("erais",15,2),new r("ions",-1,1),new r("erions",17,2),new r("assions",17,3),new r("erons",-1,2),new r("ants",-1,3),new r("és",-1,2),new r("ait",-1,3),new r("erait",23,2),new r("ant",-1,3),new r("aIent",-1,3),new r("eraIent",26,2),new r("èrent",-1,2),new r("assent",-1,3),new r("eront",-1,2),new r("ât",-1,3),new r("ez",-1,2),new r("iez",32,2),new r("eriez",33,2),new r("assiez",33,3),new r("erez",32,2),new r("é",-1,2)],P=[new r("e",-1,3),new r("Ière",0,2),new r("ière",0,2),new r("ion",-1,1),new r("Ier",-1,2),new r("ier",-1,2),new r("ë",-1,4)],U=[new r("ell",-1,-1),new r("eill",-1,-1),new r("enn",-1,-1),new r("onn",-1,-1),new r("ett",-1,-1)],F=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,128,130,103,8,5],S=[1,65,20,0,0,0,0,0,0,0,0,0,0,0,0,0,128],W=new s;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){var e=W.cursor;return n(),W.cursor=e,u(),W.limit_backward=e,W.cursor=W.limit,k(),W.cursor=W.limit,b(),W.cursor=W.limit,d(),W.cursor=W.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.fr.stemmer,"stemmer-fr"),e.fr.stopWordFilter=e.generateStopWordFilter("ai aie aient aies ait as au aura aurai auraient aurais aurait auras aurez auriez aurions aurons auront aux avaient avais avait avec avez aviez avions avons ayant ayez ayons c ce ceci celà ces cet cette d dans de des du elle en es est et eu eue eues eurent eus eusse eussent eusses eussiez eussions eut eux eûmes eût eûtes furent fus fusse fussent fusses fussiez fussions fut fûmes fût fûtes ici il ils j je l la le les leur leurs lui m ma mais me mes moi mon même n ne nos notre nous on ont ou par pas pour qu que quel quelle quelles quels qui s sa sans se sera serai seraient serais serait seras serez seriez serions serons seront ses soi soient sois soit sommes son sont soyez soyons suis sur t ta te tes toi ton tu un une vos votre vous y à étaient étais était étant étiez étions été étée étées étés êtes".split(" ")),e.Pipeline.registerFunction(e.fr.stopWordFilter,"stopWordFilter-fr")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.he.min.js b/assets/javascripts/lunr/min/lunr.he.min.js new file mode 100644 index 0000000..b863d3e --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.he.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.he=function(){this.pipeline.reset(),this.pipeline.add(e.he.trimmer,e.he.stopWordFilter,e.he.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.he.stemmer))},e.he.wordCharacters="֑-״א-תa-zA-Za-zA-Z0-90-9",e.he.trimmer=e.trimmerSupport.generateTrimmer(e.he.wordCharacters),e.Pipeline.registerFunction(e.he.trimmer,"trimmer-he"),e.he.stemmer=function(){var e=this;return e.result=!1,e.preRemoved=!1,e.sufRemoved=!1,e.pre={pre1:"ה ו י ת",pre2:"ב כ ל מ ש כש",pre3:"הב הכ הל המ הש בש לכ",pre4:"וב וכ ול ומ וש",pre5:"מה שה כל",pre6:"מב מכ מל ממ מש",pre7:"בה בו בי בת כה כו כי כת לה לו לי לת",pre8:"ובה ובו ובי ובת וכה וכו וכי וכת ולה ולו ולי ולת"},e.suf={suf1:"ך כ ם ן נ",suf2:"ים ות וך וכ ום ון ונ הם הן יכ יך ינ ים",suf3:"תי תך תכ תם תן תנ",suf4:"ותי ותך ותכ ותם ותן ותנ",suf5:"נו כם כן הם הן",suf6:"ונו וכם וכן והם והן",suf7:"תכם תכן תנו תהם תהן",suf8:"הוא היא הם הן אני אתה את אנו אתם אתן",suf9:"ני נו כי כו כם כן תי תך תכ תם תן",suf10:"י ך כ ם ן נ ת"},e.patterns=JSON.parse('{"hebrewPatterns": [{"pt1": [{"c": "ה", "l": 0}]}, {"pt2": [{"c": "ו", "l": 0}]}, {"pt3": [{"c": "י", "l": 0}]}, {"pt4": [{"c": "ת", "l": 0}]}, {"pt5": [{"c": "מ", "l": 0}]}, {"pt6": [{"c": "ל", "l": 0}]}, {"pt7": [{"c": "ב", "l": 0}]}, {"pt8": [{"c": "כ", "l": 0}]}, {"pt9": [{"c": "ש", "l": 0}]}, {"pt10": [{"c": "כש", "l": 0}]}, {"pt11": [{"c": "בה", "l": 0}]}, {"pt12": [{"c": "וב", "l": 0}]}, {"pt13": [{"c": "וכ", "l": 0}]}, {"pt14": [{"c": "ול", "l": 0}]}, {"pt15": [{"c": "ומ", "l": 0}]}, {"pt16": [{"c": "וש", "l": 0}]}, {"pt17": [{"c": "הב", "l": 0}]}, {"pt18": [{"c": "הכ", "l": 0}]}, {"pt19": [{"c": "הל", "l": 0}]}, {"pt20": [{"c": "המ", "l": 0}]}, {"pt21": [{"c": "הש", "l": 0}]}, {"pt22": [{"c": "מה", "l": 0}]}, {"pt23": [{"c": "שה", "l": 0}]}, {"pt24": [{"c": "כל", "l": 0}]}]}'),e.execArray=["cleanWord","removeDiacritics","removeStopWords","normalizeHebrewCharacters"],e.stem=function(){var r=0;for(e.result=!1,e.preRemoved=!1,e.sufRemoved=!1;r=0)return!0},e.normalizeHebrewCharacters=function(){return e.word=e.word.replace("ך","כ"),e.word=e.word.replace("ם","מ"),e.word=e.word.replace("ן","נ"),e.word=e.word.replace("ף","פ"),e.word=e.word.replace("ץ","צ"),!1},function(r){return"function"==typeof r.update?r.update(function(r){return e.setCurrent(r),e.stem(),e.getCurrent()}):(e.setCurrent(r),e.stem(),e.getCurrent())}}(),e.Pipeline.registerFunction(e.he.stemmer,"stemmer-he"),e.he.stopWordFilter=e.generateStopWordFilter("אבל או אולי אותו אותי אותך אותם אותן אותנו אז אחר אחרות אחרי אחריכן אחרים אחרת אי איזה איך אין איפה אל אלה אלו אם אנחנו אני אף אפשר את אתה אתכם אתכן אתם אתן באיזה באיזו בגלל בין בלבד בעבור בעזרת בכל בכן בלי במידה במקום שבו ברוב בשביל בשעה ש בתוך גם דרך הוא היא היה היי היכן היתה היתי הם הן הנה הסיבה שבגללה הרי ואילו ואת זאת זה זות יהיה יוכל יוכלו יותר מדי יכול יכולה יכולות יכולים יכל יכלה יכלו יש כאן כאשר כולם כולן כזה כי כיצד כך כל כלל כמו כן כפי כש לא לאו לאיזותך לאן לבין לה להיות להם להן לו לזה לזות לי לך לכם לכן למה למעלה למעלה מ למטה למטה מ למעט למקום שבו למרות לנו לעבר לעיכן לפיכך לפני מאד מאחורי מאיזו סיבה מאין מאיפה מבלי מבעד מדוע מה מהיכן מול מחוץ מי מידע מכאן מכל מכן מלבד מן מנין מסוגל מעט מעטים מעל מצד מקום בו מתחת מתי נגד נגר נו עד עז על עלי עליו עליה עליהם עליך עלינו עם עצמה עצמהם עצמהן עצמו עצמי עצמם עצמן עצמנו פה רק שוב של שלה שלהם שלהן שלו שלי שלך שלכה שלכם שלכן שלנו שם תהיה תחת".split(" ")),e.Pipeline.registerFunction(e.he.stopWordFilter,"stopWordFilter-he")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.hi.min.js b/assets/javascripts/lunr/min/lunr.hi.min.js new file mode 100644 index 0000000..7dbc414 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.hi.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hi=function(){this.pipeline.reset(),this.pipeline.add(e.hi.trimmer,e.hi.stopWordFilter,e.hi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hi.stemmer))},e.hi.wordCharacters="ऀ-ःऄ-एऐ-टठ-यर-िी-ॏॐ-य़ॠ-९॰-ॿa-zA-Za-zA-Z0-90-9",e.hi.trimmer=e.trimmerSupport.generateTrimmer(e.hi.wordCharacters),e.Pipeline.registerFunction(e.hi.trimmer,"trimmer-hi"),e.hi.stopWordFilter=e.generateStopWordFilter("अत अपना अपनी अपने अभी अंदर आदि आप इत्यादि इन इनका इन्हीं इन्हें इन्हों इस इसका इसकी इसके इसमें इसी इसे उन उनका उनकी उनके उनको उन्हीं उन्हें उन्हों उस उसके उसी उसे एक एवं एस ऐसे और कई कर करता करते करना करने करें कहते कहा का काफ़ी कि कितना किन्हें किन्हों किया किर किस किसी किसे की कुछ कुल के को कोई कौन कौनसा गया घर जब जहाँ जा जितना जिन जिन्हें जिन्हों जिस जिसे जीधर जैसा जैसे जो तक तब तरह तिन तिन्हें तिन्हों तिस तिसे तो था थी थे दबारा दिया दुसरा दूसरे दो द्वारा न नके नहीं ना निहायत नीचे ने पर पहले पूरा पे फिर बनी बही बहुत बाद बाला बिलकुल भी भीतर मगर मानो मे में यदि यह यहाँ यही या यिह ये रखें रहा रहे ऱ्वासा लिए लिये लेकिन व वग़ैरह वर्ग वह वहाँ वहीं वाले वुह वे वो सकता सकते सबसे सभी साथ साबुत साभ सारा से सो संग ही हुआ हुई हुए है हैं हो होता होती होते होना होने".split(" ")),e.hi.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.hi.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var t=i.toString().toLowerCase().replace(/^\s+/,"");return r.cut(t).split("|")},e.Pipeline.registerFunction(e.hi.stemmer,"stemmer-hi"),e.Pipeline.registerFunction(e.hi.stopWordFilter,"stopWordFilter-hi")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.hu.min.js b/assets/javascripts/lunr/min/lunr.hu.min.js new file mode 100644 index 0000000..ed9d909 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.hu.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Hungarian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hu=function(){this.pipeline.reset(),this.pipeline.add(e.hu.trimmer,e.hu.stopWordFilter,e.hu.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hu.stemmer))},e.hu.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.hu.trimmer=e.trimmerSupport.generateTrimmer(e.hu.wordCharacters),e.Pipeline.registerFunction(e.hu.trimmer,"trimmer-hu"),e.hu.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,n=L.cursor;if(d=L.limit,L.in_grouping(W,97,252))for(;;){if(e=L.cursor,L.out_grouping(W,97,252))return L.cursor=e,L.find_among(g,8)||(L.cursor=e,e=L.limit)return void(d=e);L.cursor++}if(L.cursor=n,L.out_grouping(W,97,252)){for(;!L.in_grouping(W,97,252);){if(L.cursor>=L.limit)return;L.cursor++}d=L.cursor}}function i(){return d<=L.cursor}function a(){var e;if(L.ket=L.cursor,(e=L.find_among_b(h,2))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e")}}function t(){var e=L.limit-L.cursor;return!!L.find_among_b(p,23)&&(L.cursor=L.limit-e,!0)}function s(){if(L.cursor>L.limit_backward){L.cursor--,L.ket=L.cursor;var e=L.cursor-1;L.limit_backward<=e&&e<=L.limit&&(L.cursor=e,L.bra=e,L.slice_del())}}function c(){var e;if(L.ket=L.cursor,(e=L.find_among_b(_,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function o(){L.ket=L.cursor,L.find_among_b(v,44)&&(L.bra=L.cursor,i()&&(L.slice_del(),a()))}function w(){var e;if(L.ket=L.cursor,(e=L.find_among_b(z,3))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("e");break;case 2:case 3:L.slice_from("a")}}function l(){var e;if(L.ket=L.cursor,(e=L.find_among_b(y,6))&&(L.bra=L.cursor,i()))switch(e){case 1:case 2:L.slice_del();break;case 3:L.slice_from("a");break;case 4:L.slice_from("e")}}function u(){var e;if(L.ket=L.cursor,(e=L.find_among_b(j,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function m(){var e;if(L.ket=L.cursor,(e=L.find_among_b(C,7))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e");break;case 3:case 4:case 5:case 6:case 7:L.slice_del()}}function k(){var e;if(L.ket=L.cursor,(e=L.find_among_b(P,12))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 9:L.slice_del();break;case 2:case 5:case 8:L.slice_from("e");break;case 3:case 6:L.slice_from("a")}}function f(){var e;if(L.ket=L.cursor,(e=L.find_among_b(F,31))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 8:case 9:case 12:case 13:case 16:case 17:case 18:L.slice_del();break;case 2:case 5:case 10:case 14:case 19:L.slice_from("a");break;case 3:case 6:case 11:case 15:case 20:L.slice_from("e")}}function b(){var e;if(L.ket=L.cursor,(e=L.find_among_b(S,42))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 5:case 6:case 9:case 10:case 11:case 14:case 15:case 16:case 17:case 20:case 21:case 24:case 25:case 26:case 29:L.slice_del();break;case 2:case 7:case 12:case 18:case 22:case 27:L.slice_from("a");break;case 3:case 8:case 13:case 19:case 23:case 28:L.slice_from("e")}}var d,g=[new n("cs",-1,-1),new n("dzs",-1,-1),new n("gy",-1,-1),new n("ly",-1,-1),new n("ny",-1,-1),new n("sz",-1,-1),new n("ty",-1,-1),new n("zs",-1,-1)],h=[new n("á",-1,1),new n("é",-1,2)],p=[new n("bb",-1,-1),new n("cc",-1,-1),new n("dd",-1,-1),new n("ff",-1,-1),new n("gg",-1,-1),new n("jj",-1,-1),new n("kk",-1,-1),new n("ll",-1,-1),new n("mm",-1,-1),new n("nn",-1,-1),new n("pp",-1,-1),new n("rr",-1,-1),new n("ccs",-1,-1),new n("ss",-1,-1),new n("zzs",-1,-1),new n("tt",-1,-1),new n("vv",-1,-1),new n("ggy",-1,-1),new n("lly",-1,-1),new n("nny",-1,-1),new n("tty",-1,-1),new n("ssz",-1,-1),new n("zz",-1,-1)],_=[new n("al",-1,1),new n("el",-1,2)],v=[new n("ba",-1,-1),new n("ra",-1,-1),new n("be",-1,-1),new n("re",-1,-1),new n("ig",-1,-1),new n("nak",-1,-1),new n("nek",-1,-1),new n("val",-1,-1),new n("vel",-1,-1),new n("ul",-1,-1),new n("nál",-1,-1),new n("nél",-1,-1),new n("ból",-1,-1),new n("ról",-1,-1),new n("tól",-1,-1),new n("bõl",-1,-1),new n("rõl",-1,-1),new n("tõl",-1,-1),new n("ül",-1,-1),new n("n",-1,-1),new n("an",19,-1),new n("ban",20,-1),new n("en",19,-1),new n("ben",22,-1),new n("képpen",22,-1),new n("on",19,-1),new n("ön",19,-1),new n("képp",-1,-1),new n("kor",-1,-1),new n("t",-1,-1),new n("at",29,-1),new n("et",29,-1),new n("ként",29,-1),new n("anként",32,-1),new n("enként",32,-1),new n("onként",32,-1),new n("ot",29,-1),new n("ért",29,-1),new n("öt",29,-1),new n("hez",-1,-1),new n("hoz",-1,-1),new n("höz",-1,-1),new n("vá",-1,-1),new n("vé",-1,-1)],z=[new n("án",-1,2),new n("én",-1,1),new n("ánként",-1,3)],y=[new n("stul",-1,2),new n("astul",0,1),new n("ástul",0,3),new n("stül",-1,2),new n("estül",3,1),new n("éstül",3,4)],j=[new n("á",-1,1),new n("é",-1,2)],C=[new n("k",-1,7),new n("ak",0,4),new n("ek",0,6),new n("ok",0,5),new n("ák",0,1),new n("ék",0,2),new n("ök",0,3)],P=[new n("éi",-1,7),new n("áéi",0,6),new n("ééi",0,5),new n("é",-1,9),new n("ké",3,4),new n("aké",4,1),new n("eké",4,1),new n("oké",4,1),new n("áké",4,3),new n("éké",4,2),new n("öké",4,1),new n("éé",3,8)],F=[new n("a",-1,18),new n("ja",0,17),new n("d",-1,16),new n("ad",2,13),new n("ed",2,13),new n("od",2,13),new n("ád",2,14),new n("éd",2,15),new n("öd",2,13),new n("e",-1,18),new n("je",9,17),new n("nk",-1,4),new n("unk",11,1),new n("ánk",11,2),new n("énk",11,3),new n("ünk",11,1),new n("uk",-1,8),new n("juk",16,7),new n("ájuk",17,5),new n("ük",-1,8),new n("jük",19,7),new n("éjük",20,6),new n("m",-1,12),new n("am",22,9),new n("em",22,9),new n("om",22,9),new n("ám",22,10),new n("ém",22,11),new n("o",-1,18),new n("á",-1,19),new n("é",-1,20)],S=[new n("id",-1,10),new n("aid",0,9),new n("jaid",1,6),new n("eid",0,9),new n("jeid",3,6),new n("áid",0,7),new n("éid",0,8),new n("i",-1,15),new n("ai",7,14),new n("jai",8,11),new n("ei",7,14),new n("jei",10,11),new n("ái",7,12),new n("éi",7,13),new n("itek",-1,24),new n("eitek",14,21),new n("jeitek",15,20),new n("éitek",14,23),new n("ik",-1,29),new n("aik",18,26),new n("jaik",19,25),new n("eik",18,26),new n("jeik",21,25),new n("áik",18,27),new n("éik",18,28),new n("ink",-1,20),new n("aink",25,17),new n("jaink",26,16),new n("eink",25,17),new n("jeink",28,16),new n("áink",25,18),new n("éink",25,19),new n("aitok",-1,21),new n("jaitok",32,20),new n("áitok",-1,22),new n("im",-1,5),new n("aim",35,4),new n("jaim",36,1),new n("eim",35,4),new n("jeim",38,1),new n("áim",35,2),new n("éim",35,3)],W=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,52,14],L=new r;this.setCurrent=function(e){L.setCurrent(e)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){var n=L.cursor;return e(),L.limit_backward=n,L.cursor=L.limit,c(),L.cursor=L.limit,o(),L.cursor=L.limit,w(),L.cursor=L.limit,l(),L.cursor=L.limit,u(),L.cursor=L.limit,k(),L.cursor=L.limit,f(),L.cursor=L.limit,b(),L.cursor=L.limit,m(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.hu.stemmer,"stemmer-hu"),e.hu.stopWordFilter=e.generateStopWordFilter("a abban ahhoz ahogy ahol aki akik akkor alatt amely amelyek amelyekben amelyeket amelyet amelynek ami amikor amit amolyan amíg annak arra arról az azok azon azonban azt aztán azután azzal azért be belül benne bár cikk cikkek cikkeket csak de e ebben eddig egy egyes egyetlen egyik egyre egyéb egész ehhez ekkor el ellen elsõ elég elõ elõször elõtt emilyen ennek erre ez ezek ezen ezt ezzel ezért fel felé hanem hiszen hogy hogyan igen ill ill. illetve ilyen ilyenkor ismét ison itt jobban jó jól kell kellett keressünk keresztül ki kívül között közül legalább legyen lehet lehetett lenne lenni lesz lett maga magát majd majd meg mellett mely melyek mert mi mikor milyen minden mindenki mindent mindig mint mintha mit mivel miért most már más másik még míg nagy nagyobb nagyon ne nekem neki nem nincs néha néhány nélkül olyan ott pedig persze rá s saját sem semmi sok sokat sokkal szemben szerint szinte számára talán tehát teljes tovább továbbá több ugyanis utolsó után utána vagy vagyis vagyok valaki valami valamint való van vannak vele vissza viszont volna volt voltak voltam voltunk által általában át én éppen és így õ õk õket össze úgy új újabb újra".split(" ")),e.Pipeline.registerFunction(e.hu.stopWordFilter,"stopWordFilter-hu")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.hy.min.js b/assets/javascripts/lunr/min/lunr.hy.min.js new file mode 100644 index 0000000..b37f792 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.hy.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hy=function(){this.pipeline.reset(),this.pipeline.add(e.hy.trimmer,e.hy.stopWordFilter)},e.hy.wordCharacters="[A-Za-z԰-֏ff-ﭏ]",e.hy.trimmer=e.trimmerSupport.generateTrimmer(e.hy.wordCharacters),e.Pipeline.registerFunction(e.hy.trimmer,"trimmer-hy"),e.hy.stopWordFilter=e.generateStopWordFilter("դու և եք էիր էիք հետո նաև նրանք որը վրա է որ պիտի են այս մեջ ն իր ու ի այդ որոնք այն կամ էր մի ես համար այլ իսկ էին ենք հետ ին թ էինք մենք նրա նա դուք եմ էի ըստ որպես ում".split(" ")),e.Pipeline.registerFunction(e.hy.stopWordFilter,"stopWordFilter-hy"),e.hy.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}(),e.Pipeline.registerFunction(e.hy.stemmer,"stemmer-hy")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.it.min.js b/assets/javascripts/lunr/min/lunr.it.min.js new file mode 100644 index 0000000..344b6a3 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.it.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Italian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.it=function(){this.pipeline.reset(),this.pipeline.add(e.it.trimmer,e.it.stopWordFilter,e.it.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.it.stemmer))},e.it.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.it.trimmer=e.trimmerSupport.generateTrimmer(e.it.wordCharacters),e.Pipeline.registerFunction(e.it.trimmer,"trimmer-it"),e.it.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!x.eq_s(1,e)||(x.ket=x.cursor,!x.in_grouping(L,97,249)))&&(x.slice_from(r),x.cursor=n,!0)}function i(){for(var r,n,i,o,t=x.cursor;;){if(x.bra=x.cursor,r=x.find_among(h,7))switch(x.ket=x.cursor,r){case 1:x.slice_from("à");continue;case 2:x.slice_from("è");continue;case 3:x.slice_from("ì");continue;case 4:x.slice_from("ò");continue;case 5:x.slice_from("ù");continue;case 6:x.slice_from("qU");continue;case 7:if(x.cursor>=x.limit)break;x.cursor++;continue}break}for(x.cursor=t;;)for(n=x.cursor;;){if(i=x.cursor,x.in_grouping(L,97,249)){if(x.bra=x.cursor,o=x.cursor,e("u","U",i))break;if(x.cursor=o,e("i","I",i))break}if(x.cursor=i,x.cursor>=x.limit)return void(x.cursor=n);x.cursor++}}function o(e){if(x.cursor=e,!x.in_grouping(L,97,249))return!1;for(;!x.out_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}return!0}function t(){if(x.in_grouping(L,97,249)){var e=x.cursor;if(x.out_grouping(L,97,249)){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return o(e);x.cursor++}return!0}return o(e)}return!1}function s(){var e,r=x.cursor;if(!t()){if(x.cursor=r,!x.out_grouping(L,97,249))return;if(e=x.cursor,x.out_grouping(L,97,249)){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return x.cursor=e,void(x.in_grouping(L,97,249)&&x.cursor=x.limit)return;x.cursor++}k=x.cursor}function a(){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}for(;!x.out_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}return!0}function u(){var e=x.cursor;k=x.limit,p=k,g=k,s(),x.cursor=e,a()&&(p=x.cursor,a()&&(g=x.cursor))}function c(){for(var e;;){if(x.bra=x.cursor,!(e=x.find_among(q,3)))break;switch(x.ket=x.cursor,e){case 1:x.slice_from("i");break;case 2:x.slice_from("u");break;case 3:if(x.cursor>=x.limit)return;x.cursor++}}}function w(){return k<=x.cursor}function l(){return p<=x.cursor}function m(){return g<=x.cursor}function f(){var e;if(x.ket=x.cursor,x.find_among_b(C,37)&&(x.bra=x.cursor,(e=x.find_among_b(z,5))&&w()))switch(e){case 1:x.slice_del();break;case 2:x.slice_from("e")}}function v(){var e;if(x.ket=x.cursor,!(e=x.find_among_b(S,51)))return!1;switch(x.bra=x.cursor,e){case 1:if(!m())return!1;x.slice_del();break;case 2:if(!m())return!1;x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"ic")&&(x.bra=x.cursor,m()&&x.slice_del());break;case 3:if(!m())return!1;x.slice_from("log");break;case 4:if(!m())return!1;x.slice_from("u");break;case 5:if(!m())return!1;x.slice_from("ente");break;case 6:if(!w())return!1;x.slice_del();break;case 7:if(!l())return!1;x.slice_del(),x.ket=x.cursor,e=x.find_among_b(P,4),e&&(x.bra=x.cursor,m()&&(x.slice_del(),1==e&&(x.ket=x.cursor,x.eq_s_b(2,"at")&&(x.bra=x.cursor,m()&&x.slice_del()))));break;case 8:if(!m())return!1;x.slice_del(),x.ket=x.cursor,e=x.find_among_b(F,3),e&&(x.bra=x.cursor,1==e&&m()&&x.slice_del());break;case 9:if(!m())return!1;x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"at")&&(x.bra=x.cursor,m()&&(x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"ic")&&(x.bra=x.cursor,m()&&x.slice_del())))}return!0}function b(){var e,r;x.cursor>=k&&(r=x.limit_backward,x.limit_backward=k,x.ket=x.cursor,e=x.find_among_b(W,87),e&&(x.bra=x.cursor,1==e&&x.slice_del()),x.limit_backward=r)}function d(){var e=x.limit-x.cursor;if(x.ket=x.cursor,x.in_grouping_b(y,97,242)&&(x.bra=x.cursor,w()&&(x.slice_del(),x.ket=x.cursor,x.eq_s_b(1,"i")&&(x.bra=x.cursor,w()))))return void x.slice_del();x.cursor=x.limit-e}function _(){d(),x.ket=x.cursor,x.eq_s_b(1,"h")&&(x.bra=x.cursor,x.in_grouping_b(U,99,103)&&w()&&x.slice_del())}var g,p,k,h=[new r("",-1,7),new r("qu",0,6),new r("á",0,1),new r("é",0,2),new r("í",0,3),new r("ó",0,4),new r("ú",0,5)],q=[new r("",-1,3),new r("I",0,1),new r("U",0,2)],C=[new r("la",-1,-1),new r("cela",0,-1),new r("gliela",0,-1),new r("mela",0,-1),new r("tela",0,-1),new r("vela",0,-1),new r("le",-1,-1),new r("cele",6,-1),new r("gliele",6,-1),new r("mele",6,-1),new r("tele",6,-1),new r("vele",6,-1),new r("ne",-1,-1),new r("cene",12,-1),new r("gliene",12,-1),new r("mene",12,-1),new r("sene",12,-1),new r("tene",12,-1),new r("vene",12,-1),new r("ci",-1,-1),new r("li",-1,-1),new r("celi",20,-1),new r("glieli",20,-1),new r("meli",20,-1),new r("teli",20,-1),new r("veli",20,-1),new r("gli",20,-1),new r("mi",-1,-1),new r("si",-1,-1),new r("ti",-1,-1),new r("vi",-1,-1),new r("lo",-1,-1),new r("celo",31,-1),new r("glielo",31,-1),new r("melo",31,-1),new r("telo",31,-1),new r("velo",31,-1)],z=[new r("ando",-1,1),new r("endo",-1,1),new r("ar",-1,2),new r("er",-1,2),new r("ir",-1,2)],P=[new r("ic",-1,-1),new r("abil",-1,-1),new r("os",-1,-1),new r("iv",-1,1)],F=[new r("ic",-1,1),new r("abil",-1,1),new r("iv",-1,1)],S=[new r("ica",-1,1),new r("logia",-1,3),new r("osa",-1,1),new r("ista",-1,1),new r("iva",-1,9),new r("anza",-1,1),new r("enza",-1,5),new r("ice",-1,1),new r("atrice",7,1),new r("iche",-1,1),new r("logie",-1,3),new r("abile",-1,1),new r("ibile",-1,1),new r("usione",-1,4),new r("azione",-1,2),new r("uzione",-1,4),new r("atore",-1,2),new r("ose",-1,1),new r("ante",-1,1),new r("mente",-1,1),new r("amente",19,7),new r("iste",-1,1),new r("ive",-1,9),new r("anze",-1,1),new r("enze",-1,5),new r("ici",-1,1),new r("atrici",25,1),new r("ichi",-1,1),new r("abili",-1,1),new r("ibili",-1,1),new r("ismi",-1,1),new r("usioni",-1,4),new r("azioni",-1,2),new r("uzioni",-1,4),new r("atori",-1,2),new r("osi",-1,1),new r("anti",-1,1),new r("amenti",-1,6),new r("imenti",-1,6),new r("isti",-1,1),new r("ivi",-1,9),new r("ico",-1,1),new r("ismo",-1,1),new r("oso",-1,1),new r("amento",-1,6),new r("imento",-1,6),new r("ivo",-1,9),new r("ità",-1,8),new r("istà",-1,1),new r("istè",-1,1),new r("istì",-1,1)],W=[new r("isca",-1,1),new r("enda",-1,1),new r("ata",-1,1),new r("ita",-1,1),new r("uta",-1,1),new r("ava",-1,1),new r("eva",-1,1),new r("iva",-1,1),new r("erebbe",-1,1),new r("irebbe",-1,1),new r("isce",-1,1),new r("ende",-1,1),new r("are",-1,1),new r("ere",-1,1),new r("ire",-1,1),new r("asse",-1,1),new r("ate",-1,1),new r("avate",16,1),new r("evate",16,1),new r("ivate",16,1),new r("ete",-1,1),new r("erete",20,1),new r("irete",20,1),new r("ite",-1,1),new r("ereste",-1,1),new r("ireste",-1,1),new r("ute",-1,1),new r("erai",-1,1),new r("irai",-1,1),new r("isci",-1,1),new r("endi",-1,1),new r("erei",-1,1),new r("irei",-1,1),new r("assi",-1,1),new r("ati",-1,1),new r("iti",-1,1),new r("eresti",-1,1),new r("iresti",-1,1),new r("uti",-1,1),new r("avi",-1,1),new r("evi",-1,1),new r("ivi",-1,1),new r("isco",-1,1),new r("ando",-1,1),new r("endo",-1,1),new r("Yamo",-1,1),new r("iamo",-1,1),new r("avamo",-1,1),new r("evamo",-1,1),new r("ivamo",-1,1),new r("eremo",-1,1),new r("iremo",-1,1),new r("assimo",-1,1),new r("ammo",-1,1),new r("emmo",-1,1),new r("eremmo",54,1),new r("iremmo",54,1),new r("immo",-1,1),new r("ano",-1,1),new r("iscano",58,1),new r("avano",58,1),new r("evano",58,1),new r("ivano",58,1),new r("eranno",-1,1),new r("iranno",-1,1),new r("ono",-1,1),new r("iscono",65,1),new r("arono",65,1),new r("erono",65,1),new r("irono",65,1),new r("erebbero",-1,1),new r("irebbero",-1,1),new r("assero",-1,1),new r("essero",-1,1),new r("issero",-1,1),new r("ato",-1,1),new r("ito",-1,1),new r("uto",-1,1),new r("avo",-1,1),new r("evo",-1,1),new r("ivo",-1,1),new r("ar",-1,1),new r("ir",-1,1),new r("erà",-1,1),new r("irà",-1,1),new r("erò",-1,1),new r("irò",-1,1)],L=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2,1],y=[17,65,0,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2],U=[17],x=new n;this.setCurrent=function(e){x.setCurrent(e)},this.getCurrent=function(){return x.getCurrent()},this.stem=function(){var e=x.cursor;return i(),x.cursor=e,u(),x.limit_backward=e,x.cursor=x.limit,f(),x.cursor=x.limit,v()||(x.cursor=x.limit,b()),x.cursor=x.limit,_(),x.cursor=x.limit_backward,c(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.it.stemmer,"stemmer-it"),e.it.stopWordFilter=e.generateStopWordFilter("a abbia abbiamo abbiano abbiate ad agl agli ai al all alla alle allo anche avemmo avendo avesse avessero avessi avessimo aveste avesti avete aveva avevamo avevano avevate avevi avevo avrai avranno avrebbe avrebbero avrei avremmo avremo avreste avresti avrete avrà avrò avuta avute avuti avuto c che chi ci coi col come con contro cui da dagl dagli dai dal dall dalla dalle dallo degl degli dei del dell della delle dello di dov dove e ebbe ebbero ebbi ed era erano eravamo eravate eri ero essendo faccia facciamo facciano facciate faccio facemmo facendo facesse facessero facessi facessimo faceste facesti faceva facevamo facevano facevate facevi facevo fai fanno farai faranno farebbe farebbero farei faremmo faremo fareste faresti farete farà farò fece fecero feci fosse fossero fossi fossimo foste fosti fu fui fummo furono gli ha hai hanno ho i il in io l la le lei li lo loro lui ma mi mia mie miei mio ne negl negli nei nel nell nella nelle nello noi non nostra nostre nostri nostro o per perché più quale quanta quante quanti quanto quella quelle quelli quello questa queste questi questo sarai saranno sarebbe sarebbero sarei saremmo saremo sareste saresti sarete sarà sarò se sei si sia siamo siano siate siete sono sta stai stando stanno starai staranno starebbe starebbero starei staremmo staremo stareste staresti starete starà starò stava stavamo stavano stavate stavi stavo stemmo stesse stessero stessi stessimo steste stesti stette stettero stetti stia stiamo stiano stiate sto su sua sue sugl sugli sui sul sull sulla sulle sullo suo suoi ti tra tu tua tue tuo tuoi tutti tutto un una uno vi voi vostra vostre vostri vostro è".split(" ")),e.Pipeline.registerFunction(e.it.stopWordFilter,"stopWordFilter-it")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.ja.min.js b/assets/javascripts/lunr/min/lunr.ja.min.js new file mode 100644 index 0000000..5f254eb --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.ja.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(e=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=e);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=e;else if(n(e))break}else if(n(e))break}function n(r){return C.cursor=r,r>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,d=_,t()||(_=C.cursor,_<3&&(_=3),t()||(d=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var r;;)if(C.bra=C.cursor,r=C.find_among(p,3))switch(C.ket=C.cursor,r){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return d<=C.cursor}function a(){var r=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-r,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var r;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.slice_del(),w=!0,a())))}function m(){var r;u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.eq_s_b(3,"gem")||(C.cursor=C.limit-r,C.slice_del(),a())))}function f(){var r,e,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,r=C.find_among_b(h,5))switch(C.bra=C.cursor,r){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(j,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(e=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-e,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,r=C.find_among_b(k,6))switch(C.bra=C.cursor,r){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(z,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var d,_,w,b=[new e("",-1,6),new e("á",0,1),new e("ä",0,1),new e("é",0,2),new e("ë",0,2),new e("í",0,3),new e("ï",0,3),new e("ó",0,4),new e("ö",0,4),new e("ú",0,5),new e("ü",0,5)],p=[new e("",-1,3),new e("I",0,2),new e("Y",0,1)],g=[new e("dd",-1,-1),new e("kk",-1,-1),new e("tt",-1,-1)],h=[new e("ene",-1,2),new e("se",-1,3),new e("en",-1,2),new e("heden",2,1),new e("s",-1,3)],k=[new e("end",-1,1),new e("ig",-1,2),new e("ing",-1,1),new e("lijk",-1,3),new e("baar",-1,4),new e("bar",-1,5)],v=[new e("aa",-1,-1),new e("ee",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(r){C.setCurrent(r)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var e=C.cursor;return r(),C.cursor=e,o(),C.limit_backward=e,C.cursor=C.limit,f(),C.cursor=C.limit_backward,s(),!0}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.nl.stemmer,"stemmer-nl"),r.nl.stopWordFilter=r.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),r.Pipeline.registerFunction(r.nl.stopWordFilter,"stopWordFilter-nl")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.no.min.js b/assets/javascripts/lunr/min/lunr.no.min.js new file mode 100644 index 0000000..92bc7e4 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.no.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Norwegian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.pt.min.js b/assets/javascripts/lunr/min/lunr.pt.min.js new file mode 100644 index 0000000..6c16996 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.pt.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Portuguese` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.pt=function(){this.pipeline.reset(),this.pipeline.add(e.pt.trimmer,e.pt.stopWordFilter,e.pt.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.pt.stemmer))},e.pt.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.pt.trimmer=e.trimmerSupport.generateTrimmer(e.pt.wordCharacters),e.Pipeline.registerFunction(e.pt.trimmer,"trimmer-pt"),e.pt.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(k,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("a~");continue;case 2:z.slice_from("o~");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function n(){if(z.out_grouping(y,97,250)){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!0;z.cursor++}return!1}return!0}function i(){if(z.in_grouping(y,97,250))for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return g=z.cursor,!0}function o(){var e,r,s=z.cursor;if(z.in_grouping(y,97,250))if(e=z.cursor,n()){if(z.cursor=e,i())return}else g=z.cursor;if(z.cursor=s,z.out_grouping(y,97,250)){if(r=z.cursor,n()){if(z.cursor=r,!z.in_grouping(y,97,250)||z.cursor>=z.limit)return;z.cursor++}g=z.cursor}}function t(){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return!0}function a(){var e=z.cursor;g=z.limit,b=g,h=g,o(),z.cursor=e,t()&&(b=z.cursor,t()&&(h=z.cursor))}function u(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(q,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("ã");continue;case 2:z.slice_from("õ");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function w(){return g<=z.cursor}function m(){return b<=z.cursor}function c(){return h<=z.cursor}function l(){var e;if(z.ket=z.cursor,!(e=z.find_among_b(F,45)))return!1;switch(z.bra=z.cursor,e){case 1:if(!c())return!1;z.slice_del();break;case 2:if(!c())return!1;z.slice_from("log");break;case 3:if(!c())return!1;z.slice_from("u");break;case 4:if(!c())return!1;z.slice_from("ente");break;case 5:if(!m())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(j,4),e&&(z.bra=z.cursor,c()&&(z.slice_del(),1==e&&(z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del()))));break;case 6:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(C,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 7:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(P,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 8:if(!c())return!1;z.slice_del(),z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del());break;case 9:if(!w()||!z.eq_s_b(1,"e"))return!1;z.slice_from("ir")}return!0}function f(){var e,r;if(z.cursor>=g){if(r=z.limit_backward,z.limit_backward=g,z.ket=z.cursor,e=z.find_among_b(S,120))return z.bra=z.cursor,1==e&&z.slice_del(),z.limit_backward=r,!0;z.limit_backward=r}return!1}function d(){var e;z.ket=z.cursor,(e=z.find_among_b(W,7))&&(z.bra=z.cursor,1==e&&w()&&z.slice_del())}function v(e,r){if(z.eq_s_b(1,e)){z.bra=z.cursor;var s=z.limit-z.cursor;if(z.eq_s_b(1,r))return z.cursor=z.limit-s,w()&&z.slice_del(),!1}return!0}function p(){var e;if(z.ket=z.cursor,e=z.find_among_b(L,4))switch(z.bra=z.cursor,e){case 1:w()&&(z.slice_del(),z.ket=z.cursor,z.limit-z.cursor,v("u","g")&&v("i","c"));break;case 2:z.slice_from("c")}}function _(){if(!l()&&(z.cursor=z.limit,!f()))return z.cursor=z.limit,void d();z.cursor=z.limit,z.ket=z.cursor,z.eq_s_b(1,"i")&&(z.bra=z.cursor,z.eq_s_b(1,"c")&&(z.cursor=z.limit,w()&&z.slice_del()))}var h,b,g,k=[new r("",-1,3),new r("ã",0,1),new r("õ",0,2)],q=[new r("",-1,3),new r("a~",0,1),new r("o~",0,2)],j=[new r("ic",-1,-1),new r("ad",-1,-1),new r("os",-1,-1),new r("iv",-1,1)],C=[new r("ante",-1,1),new r("avel",-1,1),new r("ível",-1,1)],P=[new r("ic",-1,1),new r("abil",-1,1),new r("iv",-1,1)],F=[new r("ica",-1,1),new r("ância",-1,1),new r("ência",-1,4),new r("ira",-1,9),new r("adora",-1,1),new r("osa",-1,1),new r("ista",-1,1),new r("iva",-1,8),new r("eza",-1,1),new r("logía",-1,2),new r("idade",-1,7),new r("ante",-1,1),new r("mente",-1,6),new r("amente",12,5),new r("ável",-1,1),new r("ível",-1,1),new r("ución",-1,3),new r("ico",-1,1),new r("ismo",-1,1),new r("oso",-1,1),new r("amento",-1,1),new r("imento",-1,1),new r("ivo",-1,8),new r("aça~o",-1,1),new r("ador",-1,1),new r("icas",-1,1),new r("ências",-1,4),new r("iras",-1,9),new r("adoras",-1,1),new r("osas",-1,1),new r("istas",-1,1),new r("ivas",-1,8),new r("ezas",-1,1),new r("logías",-1,2),new r("idades",-1,7),new r("uciones",-1,3),new r("adores",-1,1),new r("antes",-1,1),new r("aço~es",-1,1),new r("icos",-1,1),new r("ismos",-1,1),new r("osos",-1,1),new r("amentos",-1,1),new r("imentos",-1,1),new r("ivos",-1,8)],S=[new r("ada",-1,1),new r("ida",-1,1),new r("ia",-1,1),new r("aria",2,1),new r("eria",2,1),new r("iria",2,1),new r("ara",-1,1),new r("era",-1,1),new r("ira",-1,1),new r("ava",-1,1),new r("asse",-1,1),new r("esse",-1,1),new r("isse",-1,1),new r("aste",-1,1),new r("este",-1,1),new r("iste",-1,1),new r("ei",-1,1),new r("arei",16,1),new r("erei",16,1),new r("irei",16,1),new r("am",-1,1),new r("iam",20,1),new r("ariam",21,1),new r("eriam",21,1),new r("iriam",21,1),new r("aram",20,1),new r("eram",20,1),new r("iram",20,1),new r("avam",20,1),new r("em",-1,1),new r("arem",29,1),new r("erem",29,1),new r("irem",29,1),new r("assem",29,1),new r("essem",29,1),new r("issem",29,1),new r("ado",-1,1),new r("ido",-1,1),new r("ando",-1,1),new r("endo",-1,1),new r("indo",-1,1),new r("ara~o",-1,1),new r("era~o",-1,1),new r("ira~o",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("ir",-1,1),new r("as",-1,1),new r("adas",47,1),new r("idas",47,1),new r("ias",47,1),new r("arias",50,1),new r("erias",50,1),new r("irias",50,1),new r("aras",47,1),new r("eras",47,1),new r("iras",47,1),new r("avas",47,1),new r("es",-1,1),new r("ardes",58,1),new r("erdes",58,1),new r("irdes",58,1),new r("ares",58,1),new r("eres",58,1),new r("ires",58,1),new r("asses",58,1),new r("esses",58,1),new r("isses",58,1),new r("astes",58,1),new r("estes",58,1),new r("istes",58,1),new r("is",-1,1),new r("ais",71,1),new r("eis",71,1),new r("areis",73,1),new r("ereis",73,1),new r("ireis",73,1),new r("áreis",73,1),new r("éreis",73,1),new r("íreis",73,1),new r("ásseis",73,1),new r("ésseis",73,1),new r("ísseis",73,1),new r("áveis",73,1),new r("íeis",73,1),new r("aríeis",84,1),new r("eríeis",84,1),new r("iríeis",84,1),new r("ados",-1,1),new r("idos",-1,1),new r("amos",-1,1),new r("áramos",90,1),new r("éramos",90,1),new r("íramos",90,1),new r("ávamos",90,1),new r("íamos",90,1),new r("aríamos",95,1),new r("eríamos",95,1),new r("iríamos",95,1),new r("emos",-1,1),new r("aremos",99,1),new r("eremos",99,1),new r("iremos",99,1),new r("ássemos",99,1),new r("êssemos",99,1),new r("íssemos",99,1),new r("imos",-1,1),new r("armos",-1,1),new r("ermos",-1,1),new r("irmos",-1,1),new r("ámos",-1,1),new r("arás",-1,1),new r("erás",-1,1),new r("irás",-1,1),new r("eu",-1,1),new r("iu",-1,1),new r("ou",-1,1),new r("ará",-1,1),new r("erá",-1,1),new r("irá",-1,1)],W=[new r("a",-1,1),new r("i",-1,1),new r("o",-1,1),new r("os",-1,1),new r("á",-1,1),new r("í",-1,1),new r("ó",-1,1)],L=[new r("e",-1,1),new r("ç",-1,2),new r("é",-1,1),new r("ê",-1,1)],y=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,3,19,12,2],z=new s;this.setCurrent=function(e){z.setCurrent(e)},this.getCurrent=function(){return z.getCurrent()},this.stem=function(){var r=z.cursor;return e(),z.cursor=r,a(),z.limit_backward=r,z.cursor=z.limit,_(),z.cursor=z.limit,p(),z.cursor=z.limit_backward,u(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.pt.stemmer,"stemmer-pt"),e.pt.stopWordFilter=e.generateStopWordFilter("a ao aos aquela aquelas aquele aqueles aquilo as até com como da das de dela delas dele deles depois do dos e ela elas ele eles em entre era eram essa essas esse esses esta estamos estas estava estavam este esteja estejam estejamos estes esteve estive estivemos estiver estivera estiveram estiverem estivermos estivesse estivessem estivéramos estivéssemos estou está estávamos estão eu foi fomos for fora foram forem formos fosse fossem fui fôramos fôssemos haja hajam hajamos havemos hei houve houvemos houver houvera houveram houverei houverem houveremos houveria houveriam houvermos houverá houverão houveríamos houvesse houvessem houvéramos houvéssemos há hão isso isto já lhe lhes mais mas me mesmo meu meus minha minhas muito na nas nem no nos nossa nossas nosso nossos num numa não nós o os ou para pela pelas pelo pelos por qual quando que quem se seja sejam sejamos sem serei seremos seria seriam será serão seríamos seu seus somos sou sua suas são só também te tem temos tenha tenham tenhamos tenho terei teremos teria teriam terá terão teríamos teu teus teve tinha tinham tive tivemos tiver tivera tiveram tiverem tivermos tivesse tivessem tivéramos tivéssemos tu tua tuas tém tínhamos um uma você vocês vos à às éramos".split(" ")),e.Pipeline.registerFunction(e.pt.stopWordFilter,"stopWordFilter-pt")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.ro.min.js b/assets/javascripts/lunr/min/lunr.ro.min.js new file mode 100644 index 0000000..7277140 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.ro.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Romanian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ro=function(){this.pipeline.reset(),this.pipeline.add(e.ro.trimmer,e.ro.stopWordFilter,e.ro.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ro.stemmer))},e.ro.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.ro.trimmer=e.trimmerSupport.generateTrimmer(e.ro.wordCharacters),e.Pipeline.registerFunction(e.ro.trimmer,"trimmer-ro"),e.ro.stemmer=function(){var i=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,n=new function(){function e(e,i){L.eq_s(1,e)&&(L.ket=L.cursor,L.in_grouping(W,97,259)&&L.slice_from(i))}function n(){for(var i,r;;){if(i=L.cursor,L.in_grouping(W,97,259)&&(r=L.cursor,L.bra=r,e("u","U"),L.cursor=r,e("i","I")),L.cursor=i,L.cursor>=L.limit)break;L.cursor++}}function t(){if(L.out_grouping(W,97,259)){for(;!L.in_grouping(W,97,259);){if(L.cursor>=L.limit)return!0;L.cursor++}return!1}return!0}function a(){if(L.in_grouping(W,97,259))for(;!L.out_grouping(W,97,259);){if(L.cursor>=L.limit)return!0;L.cursor++}return!1}function o(){var e,i,r=L.cursor;if(L.in_grouping(W,97,259)){if(e=L.cursor,!t())return void(h=L.cursor);if(L.cursor=e,!a())return void(h=L.cursor)}L.cursor=r,L.out_grouping(W,97,259)&&(i=L.cursor,t()&&(L.cursor=i,L.in_grouping(W,97,259)&&L.cursor=L.limit)return!1;L.cursor++}for(;!L.out_grouping(W,97,259);){if(L.cursor>=L.limit)return!1;L.cursor++}return!0}function c(){var e=L.cursor;h=L.limit,k=h,g=h,o(),L.cursor=e,u()&&(k=L.cursor,u()&&(g=L.cursor))}function s(){for(var e;;){if(L.bra=L.cursor,e=L.find_among(z,3))switch(L.ket=L.cursor,e){case 1:L.slice_from("i");continue;case 2:L.slice_from("u");continue;case 3:if(L.cursor>=L.limit)break;L.cursor++;continue}break}}function w(){return h<=L.cursor}function m(){return k<=L.cursor}function l(){return g<=L.cursor}function f(){var e,i;if(L.ket=L.cursor,(e=L.find_among_b(C,16))&&(L.bra=L.cursor,m()))switch(e){case 1:L.slice_del();break;case 2:L.slice_from("a");break;case 3:L.slice_from("e");break;case 4:L.slice_from("i");break;case 5:i=L.limit-L.cursor,L.eq_s_b(2,"ab")||(L.cursor=L.limit-i,L.slice_from("i"));break;case 6:L.slice_from("at");break;case 7:L.slice_from("aţi")}}function p(){var e,i=L.limit-L.cursor;if(L.ket=L.cursor,(e=L.find_among_b(P,46))&&(L.bra=L.cursor,m())){switch(e){case 1:L.slice_from("abil");break;case 2:L.slice_from("ibil");break;case 3:L.slice_from("iv");break;case 4:L.slice_from("ic");break;case 5:L.slice_from("at");break;case 6:L.slice_from("it")}return _=!0,L.cursor=L.limit-i,!0}return!1}function d(){var e,i;for(_=!1;;)if(i=L.limit-L.cursor,!p()){L.cursor=L.limit-i;break}if(L.ket=L.cursor,(e=L.find_among_b(F,62))&&(L.bra=L.cursor,l())){switch(e){case 1:L.slice_del();break;case 2:L.eq_s_b(1,"ţ")&&(L.bra=L.cursor,L.slice_from("t"));break;case 3:L.slice_from("ist")}_=!0}}function b(){var e,i,r;if(L.cursor>=h){if(i=L.limit_backward,L.limit_backward=h,L.ket=L.cursor,e=L.find_among_b(q,94))switch(L.bra=L.cursor,e){case 1:if(r=L.limit-L.cursor,!L.out_grouping_b(W,97,259)&&(L.cursor=L.limit-r,!L.eq_s_b(1,"u")))break;case 2:L.slice_del()}L.limit_backward=i}}function v(){var e;L.ket=L.cursor,(e=L.find_among_b(S,5))&&(L.bra=L.cursor,w()&&1==e&&L.slice_del())}var _,g,k,h,z=[new i("",-1,3),new i("I",0,1),new i("U",0,2)],C=[new i("ea",-1,3),new i("aţia",-1,7),new i("aua",-1,2),new i("iua",-1,4),new i("aţie",-1,7),new i("ele",-1,3),new i("ile",-1,5),new i("iile",6,4),new i("iei",-1,4),new i("atei",-1,6),new i("ii",-1,4),new i("ului",-1,1),new i("ul",-1,1),new i("elor",-1,3),new i("ilor",-1,4),new i("iilor",14,4)],P=[new i("icala",-1,4),new i("iciva",-1,4),new i("ativa",-1,5),new i("itiva",-1,6),new i("icale",-1,4),new i("aţiune",-1,5),new i("iţiune",-1,6),new i("atoare",-1,5),new i("itoare",-1,6),new i("ătoare",-1,5),new i("icitate",-1,4),new i("abilitate",-1,1),new i("ibilitate",-1,2),new i("ivitate",-1,3),new i("icive",-1,4),new i("ative",-1,5),new i("itive",-1,6),new i("icali",-1,4),new i("atori",-1,5),new i("icatori",18,4),new i("itori",-1,6),new i("ători",-1,5),new i("icitati",-1,4),new i("abilitati",-1,1),new i("ivitati",-1,3),new i("icivi",-1,4),new i("ativi",-1,5),new i("itivi",-1,6),new i("icităi",-1,4),new i("abilităi",-1,1),new i("ivităi",-1,3),new i("icităţi",-1,4),new i("abilităţi",-1,1),new i("ivităţi",-1,3),new i("ical",-1,4),new i("ator",-1,5),new i("icator",35,4),new i("itor",-1,6),new i("ător",-1,5),new i("iciv",-1,4),new i("ativ",-1,5),new i("itiv",-1,6),new i("icală",-1,4),new i("icivă",-1,4),new i("ativă",-1,5),new i("itivă",-1,6)],F=[new i("ica",-1,1),new i("abila",-1,1),new i("ibila",-1,1),new i("oasa",-1,1),new i("ata",-1,1),new i("ita",-1,1),new i("anta",-1,1),new i("ista",-1,3),new i("uta",-1,1),new i("iva",-1,1),new i("ic",-1,1),new i("ice",-1,1),new i("abile",-1,1),new i("ibile",-1,1),new i("isme",-1,3),new i("iune",-1,2),new i("oase",-1,1),new i("ate",-1,1),new i("itate",17,1),new i("ite",-1,1),new i("ante",-1,1),new i("iste",-1,3),new i("ute",-1,1),new i("ive",-1,1),new i("ici",-1,1),new i("abili",-1,1),new i("ibili",-1,1),new i("iuni",-1,2),new i("atori",-1,1),new i("osi",-1,1),new i("ati",-1,1),new i("itati",30,1),new i("iti",-1,1),new i("anti",-1,1),new i("isti",-1,3),new i("uti",-1,1),new i("işti",-1,3),new i("ivi",-1,1),new i("ităi",-1,1),new i("oşi",-1,1),new i("ităţi",-1,1),new i("abil",-1,1),new i("ibil",-1,1),new i("ism",-1,3),new i("ator",-1,1),new i("os",-1,1),new i("at",-1,1),new i("it",-1,1),new i("ant",-1,1),new i("ist",-1,3),new i("ut",-1,1),new i("iv",-1,1),new i("ică",-1,1),new i("abilă",-1,1),new i("ibilă",-1,1),new i("oasă",-1,1),new i("ată",-1,1),new i("ită",-1,1),new i("antă",-1,1),new i("istă",-1,3),new i("ută",-1,1),new i("ivă",-1,1)],q=[new i("ea",-1,1),new i("ia",-1,1),new i("esc",-1,1),new i("ăsc",-1,1),new i("ind",-1,1),new i("ând",-1,1),new i("are",-1,1),new i("ere",-1,1),new i("ire",-1,1),new i("âre",-1,1),new i("se",-1,2),new i("ase",10,1),new i("sese",10,2),new i("ise",10,1),new i("use",10,1),new i("âse",10,1),new i("eşte",-1,1),new i("ăşte",-1,1),new i("eze",-1,1),new i("ai",-1,1),new i("eai",19,1),new i("iai",19,1),new i("sei",-1,2),new i("eşti",-1,1),new i("ăşti",-1,1),new i("ui",-1,1),new i("ezi",-1,1),new i("âi",-1,1),new i("aşi",-1,1),new i("seşi",-1,2),new i("aseşi",29,1),new i("seseşi",29,2),new i("iseşi",29,1),new i("useşi",29,1),new i("âseşi",29,1),new i("işi",-1,1),new i("uşi",-1,1),new i("âşi",-1,1),new i("aţi",-1,2),new i("eaţi",38,1),new i("iaţi",38,1),new i("eţi",-1,2),new i("iţi",-1,2),new i("âţi",-1,2),new i("arăţi",-1,1),new i("serăţi",-1,2),new i("aserăţi",45,1),new i("seserăţi",45,2),new i("iserăţi",45,1),new i("userăţi",45,1),new i("âserăţi",45,1),new i("irăţi",-1,1),new i("urăţi",-1,1),new i("ârăţi",-1,1),new i("am",-1,1),new i("eam",54,1),new i("iam",54,1),new i("em",-1,2),new i("asem",57,1),new i("sesem",57,2),new i("isem",57,1),new i("usem",57,1),new i("âsem",57,1),new i("im",-1,2),new i("âm",-1,2),new i("ăm",-1,2),new i("arăm",65,1),new i("serăm",65,2),new i("aserăm",67,1),new i("seserăm",67,2),new i("iserăm",67,1),new i("userăm",67,1),new i("âserăm",67,1),new i("irăm",65,1),new i("urăm",65,1),new i("ârăm",65,1),new i("au",-1,1),new i("eau",76,1),new i("iau",76,1),new i("indu",-1,1),new i("ându",-1,1),new i("ez",-1,1),new i("ească",-1,1),new i("ară",-1,1),new i("seră",-1,2),new i("aseră",84,1),new i("seseră",84,2),new i("iseră",84,1),new i("useră",84,1),new i("âseră",84,1),new i("iră",-1,1),new i("ură",-1,1),new i("âră",-1,1),new i("ează",-1,1)],S=[new i("a",-1,1),new i("e",-1,1),new i("ie",1,1),new i("i",-1,1),new i("ă",-1,1)],W=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,2,32,0,0,4],L=new r;this.setCurrent=function(e){L.setCurrent(e)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){var e=L.cursor;return n(),L.cursor=e,c(),L.limit_backward=e,L.cursor=L.limit,f(),L.cursor=L.limit,d(),L.cursor=L.limit,_||(L.cursor=L.limit,b(),L.cursor=L.limit),v(),L.cursor=L.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.ro.stemmer,"stemmer-ro"),e.ro.stopWordFilter=e.generateStopWordFilter("acea aceasta această aceea acei aceia acel acela acele acelea acest acesta aceste acestea aceşti aceştia acolo acord acum ai aia aibă aici al ale alea altceva altcineva am ar are asemenea asta astea astăzi asupra au avea avem aveţi azi aş aşadar aţi bine bucur bună ca care caut ce cel ceva chiar cinci cine cineva contra cu cum cumva curând curînd când cât câte câtva câţi cînd cît cîte cîtva cîţi că căci cărei căror cărui către da dacă dar datorită dată dau de deci deja deoarece departe deşi din dinaintea dintr- dintre doi doilea două drept după dă ea ei el ele eram este eu eşti face fata fi fie fiecare fii fim fiu fiţi frumos fără graţie halbă iar ieri la le li lor lui lângă lîngă mai mea mei mele mereu meu mi mie mine mult multă mulţi mulţumesc mâine mîine mă ne nevoie nici nicăieri nimeni nimeri nimic nişte noastre noastră noi noroc nostru nouă noştri nu opt ori oricare orice oricine oricum oricând oricât oricînd oricît oriunde patra patru patrulea pe pentru peste pic poate pot prea prima primul prin puţin puţina puţină până pînă rog sa sale sau se spate spre sub sunt suntem sunteţi sută sînt sîntem sînteţi să săi său ta tale te timp tine toate toată tot totuşi toţi trei treia treilea tu tăi tău un una unde undeva unei uneia unele uneori unii unor unora unu unui unuia unul vi voastre voastră voi vostru vouă voştri vreme vreo vreun vă zece zero zi zice îi îl îmi împotriva în înainte înaintea încotro încât încît între întrucât întrucît îţi ăla ălea ăsta ăstea ăştia şapte şase şi ştiu ţi ţie".split(" ")),e.Pipeline.registerFunction(e.ro.stopWordFilter,"stopWordFilter-ro")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.ru.min.js b/assets/javascripts/lunr/min/lunr.ru.min.js new file mode 100644 index 0000000..186cc48 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.ru.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Russian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ru=function(){this.pipeline.reset(),this.pipeline.add(e.ru.trimmer,e.ru.stopWordFilter,e.ru.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ru.stemmer))},e.ru.wordCharacters="Ѐ-҄҇-ԯᴫᵸⷠ-ⷿꙀ-ꚟ︮︯",e.ru.trimmer=e.trimmerSupport.generateTrimmer(e.ru.wordCharacters),e.Pipeline.registerFunction(e.ru.trimmer,"trimmer-ru"),e.ru.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,t=new function(){function e(){for(;!W.in_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function t(){for(;!W.out_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function w(){b=W.limit,_=b,e()&&(b=W.cursor,t()&&e()&&t()&&(_=W.cursor))}function i(){return _<=W.cursor}function u(e,n){var r,t;if(W.ket=W.cursor,r=W.find_among_b(e,n)){switch(W.bra=W.cursor,r){case 1:if(t=W.limit-W.cursor,!W.eq_s_b(1,"а")&&(W.cursor=W.limit-t,!W.eq_s_b(1,"я")))return!1;case 2:W.slice_del()}return!0}return!1}function o(){return u(h,9)}function s(e,n){var r;return W.ket=W.cursor,!!(r=W.find_among_b(e,n))&&(W.bra=W.cursor,1==r&&W.slice_del(),!0)}function c(){return s(g,26)}function m(){return!!c()&&(u(C,8),!0)}function f(){return s(k,2)}function l(){return u(P,46)}function a(){s(v,36)}function p(){var e;W.ket=W.cursor,(e=W.find_among_b(F,2))&&(W.bra=W.cursor,i()&&1==e&&W.slice_del())}function d(){var e;if(W.ket=W.cursor,e=W.find_among_b(q,4))switch(W.bra=W.cursor,e){case 1:if(W.slice_del(),W.ket=W.cursor,!W.eq_s_b(1,"н"))break;W.bra=W.cursor;case 2:if(!W.eq_s_b(1,"н"))break;case 3:W.slice_del()}}var _,b,h=[new n("в",-1,1),new n("ив",0,2),new n("ыв",0,2),new n("вши",-1,1),new n("ивши",3,2),new n("ывши",3,2),new n("вшись",-1,1),new n("ившись",6,2),new n("ывшись",6,2)],g=[new n("ее",-1,1),new n("ие",-1,1),new n("ое",-1,1),new n("ые",-1,1),new n("ими",-1,1),new n("ыми",-1,1),new n("ей",-1,1),new n("ий",-1,1),new n("ой",-1,1),new n("ый",-1,1),new n("ем",-1,1),new n("им",-1,1),new n("ом",-1,1),new n("ым",-1,1),new n("его",-1,1),new n("ого",-1,1),new n("ему",-1,1),new n("ому",-1,1),new n("их",-1,1),new n("ых",-1,1),new n("ею",-1,1),new n("ою",-1,1),new n("ую",-1,1),new n("юю",-1,1),new n("ая",-1,1),new n("яя",-1,1)],C=[new n("ем",-1,1),new n("нн",-1,1),new n("вш",-1,1),new n("ивш",2,2),new n("ывш",2,2),new n("щ",-1,1),new n("ющ",5,1),new n("ующ",6,2)],k=[new n("сь",-1,1),new n("ся",-1,1)],P=[new n("ла",-1,1),new n("ила",0,2),new n("ыла",0,2),new n("на",-1,1),new n("ена",3,2),new n("ете",-1,1),new n("ите",-1,2),new n("йте",-1,1),new n("ейте",7,2),new n("уйте",7,2),new n("ли",-1,1),new n("или",10,2),new n("ыли",10,2),new n("й",-1,1),new n("ей",13,2),new n("уй",13,2),new n("л",-1,1),new n("ил",16,2),new n("ыл",16,2),new n("ем",-1,1),new n("им",-1,2),new n("ым",-1,2),new n("н",-1,1),new n("ен",22,2),new n("ло",-1,1),new n("ило",24,2),new n("ыло",24,2),new n("но",-1,1),new n("ено",27,2),new n("нно",27,1),new n("ет",-1,1),new n("ует",30,2),new n("ит",-1,2),new n("ыт",-1,2),new n("ют",-1,1),new n("уют",34,2),new n("ят",-1,2),new n("ны",-1,1),new n("ены",37,2),new n("ть",-1,1),new n("ить",39,2),new n("ыть",39,2),new n("ешь",-1,1),new n("ишь",-1,2),new n("ю",-1,2),new n("ую",44,2)],v=[new n("а",-1,1),new n("ев",-1,1),new n("ов",-1,1),new n("е",-1,1),new n("ие",3,1),new n("ье",3,1),new n("и",-1,1),new n("еи",6,1),new n("ии",6,1),new n("ами",6,1),new n("ями",6,1),new n("иями",10,1),new n("й",-1,1),new n("ей",12,1),new n("ией",13,1),new n("ий",12,1),new n("ой",12,1),new n("ам",-1,1),new n("ем",-1,1),new n("ием",18,1),new n("ом",-1,1),new n("ям",-1,1),new n("иям",21,1),new n("о",-1,1),new n("у",-1,1),new n("ах",-1,1),new n("ях",-1,1),new n("иях",26,1),new n("ы",-1,1),new n("ь",-1,1),new n("ю",-1,1),new n("ию",30,1),new n("ью",30,1),new n("я",-1,1),new n("ия",33,1),new n("ья",33,1)],F=[new n("ост",-1,1),new n("ость",-1,1)],q=[new n("ейше",-1,1),new n("н",-1,2),new n("ейш",-1,1),new n("ь",-1,3)],S=[33,65,8,232],W=new r;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){return w(),W.cursor=W.limit,!(W.cursor=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursors||e>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor>1),f=0,l=o0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.sv.min.js b/assets/javascripts/lunr/min/lunr.sv.min.js new file mode 100644 index 0000000..3e5eb64 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.sv.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Swedish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.ta.min.js b/assets/javascripts/lunr/min/lunr.ta.min.js new file mode 100644 index 0000000..a644bed --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.ta.min.js @@ -0,0 +1 @@ +!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ta=function(){this.pipeline.reset(),this.pipeline.add(e.ta.trimmer,e.ta.stopWordFilter,e.ta.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ta.stemmer))},e.ta.wordCharacters="஀-உஊ-ஏஐ-ஙச-ட஠-னப-யர-ஹ஺-ிீ-௉ொ-௏ௐ-௙௚-௟௠-௩௪-௯௰-௹௺-௿a-zA-Za-zA-Z0-90-9",e.ta.trimmer=e.trimmerSupport.generateTrimmer(e.ta.wordCharacters),e.Pipeline.registerFunction(e.ta.trimmer,"trimmer-ta"),e.ta.stopWordFilter=e.generateStopWordFilter("அங்கு அங்கே அது அதை அந்த அவர் அவர்கள் அவள் அவன் அவை ஆக ஆகவே ஆகையால் ஆதலால் ஆதலினால் ஆனாலும் ஆனால் இங்கு இங்கே இது இதை இந்த இப்படி இவர் இவர்கள் இவள் இவன் இவை இவ்வளவு உனக்கு உனது உன் உன்னால் எங்கு எங்கே எது எதை எந்த எப்படி எவர் எவர்கள் எவள் எவன் எவை எவ்வளவு எனக்கு எனது எனவே என் என்ன என்னால் ஏது ஏன் தனது தன்னால் தானே தான் நாங்கள் நாம் நான் நீ நீங்கள்".split(" ")),e.ta.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var t=e.wordcut;t.init(),e.ta.tokenizer=function(r){if(!arguments.length||null==r||void 0==r)return[];if(Array.isArray(r))return r.map(function(t){return isLunr2?new e.Token(t.toLowerCase()):t.toLowerCase()});var i=r.toString().toLowerCase().replace(/^\s+/,"");return t.cut(i).split("|")},e.Pipeline.registerFunction(e.ta.stemmer,"stemmer-ta"),e.Pipeline.registerFunction(e.ta.stopWordFilter,"stopWordFilter-ta")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.te.min.js b/assets/javascripts/lunr/min/lunr.te.min.js new file mode 100644 index 0000000..9fa7a93 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.te.min.js @@ -0,0 +1 @@ +!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.te=function(){this.pipeline.reset(),this.pipeline.add(e.te.trimmer,e.te.stopWordFilter,e.te.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.te.stemmer))},e.te.wordCharacters="ఀ-ఄఅ-ఔక-హా-ౌౕ-ౖౘ-ౚౠ-ౡౢ-ౣ౦-౯౸-౿఼ఽ్ౝ౷౤౥",e.te.trimmer=e.trimmerSupport.generateTrimmer(e.te.wordCharacters),e.Pipeline.registerFunction(e.te.trimmer,"trimmer-te"),e.te.stopWordFilter=e.generateStopWordFilter("అందరూ అందుబాటులో అడగండి అడగడం అడ్డంగా అనుగుణంగా అనుమతించు అనుమతిస్తుంది అయితే ఇప్పటికే ఉన్నారు ఎక్కడైనా ఎప్పుడు ఎవరైనా ఎవరో ఏ ఏదైనా ఏమైనప్పటికి ఒక ఒకరు కనిపిస్తాయి కాదు కూడా గా గురించి చుట్టూ చేయగలిగింది తగిన తర్వాత దాదాపు దూరంగా నిజంగా పై ప్రకారం ప్రక్కన మధ్య మరియు మరొక మళ్ళీ మాత్రమే మెచ్చుకో వద్ద వెంట వేరుగా వ్యతిరేకంగా సంబంధం".split(" ")),e.te.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var t=e.wordcut;t.init(),e.te.tokenizer=function(r){if(!arguments.length||null==r||void 0==r)return[];if(Array.isArray(r))return r.map(function(t){return isLunr2?new e.Token(t.toLowerCase()):t.toLowerCase()});var i=r.toString().toLowerCase().replace(/^\s+/,"");return t.cut(i).split("|")},e.Pipeline.registerFunction(e.te.stemmer,"stemmer-te"),e.Pipeline.registerFunction(e.te.stopWordFilter,"stopWordFilter-te")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.th.min.js b/assets/javascripts/lunr/min/lunr.th.min.js new file mode 100644 index 0000000..dee3aac --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.th.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.th=function(){this.pipeline.reset(),this.pipeline.add(e.th.trimmer),r?this.tokenizer=e.th.tokenizer:(e.tokenizer&&(e.tokenizer=e.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.th.tokenizer))},e.th.wordCharacters="[฀-๿]",e.th.trimmer=e.trimmerSupport.generateTrimmer(e.th.wordCharacters),e.Pipeline.registerFunction(e.th.trimmer,"trimmer-th");var t=e.wordcut;t.init(),e.th.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t):t});var n=i.toString().replace(/^\s+/,"");return t.cut(n).split("|")}}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.tr.min.js b/assets/javascripts/lunr/min/lunr.tr.min.js new file mode 100644 index 0000000..563f6ec --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.tr.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Turkish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(r,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(r.lunr)}(this,function(){return function(r){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");r.tr=function(){this.pipeline.reset(),this.pipeline.add(r.tr.trimmer,r.tr.stopWordFilter,r.tr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(r.tr.stemmer))},r.tr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",r.tr.trimmer=r.trimmerSupport.generateTrimmer(r.tr.wordCharacters),r.Pipeline.registerFunction(r.tr.trimmer,"trimmer-tr"),r.tr.stemmer=function(){var i=r.stemmerSupport.Among,e=r.stemmerSupport.SnowballProgram,n=new function(){function r(r,i,e){for(;;){var n=Dr.limit-Dr.cursor;if(Dr.in_grouping_b(r,i,e)){Dr.cursor=Dr.limit-n;break}if(Dr.cursor=Dr.limit-n,Dr.cursor<=Dr.limit_backward)return!1;Dr.cursor--}return!0}function n(){var i,e;i=Dr.limit-Dr.cursor,r(Wr,97,305);for(var n=0;nDr.limit_backward&&(Dr.cursor--,e=Dr.limit-Dr.cursor,i()))?(Dr.cursor=Dr.limit-e,!0):(Dr.cursor=Dr.limit-n,r()?(Dr.cursor=Dr.limit-n,!1):(Dr.cursor=Dr.limit-n,!(Dr.cursor<=Dr.limit_backward)&&(Dr.cursor--,!!i()&&(Dr.cursor=Dr.limit-n,!0))))}function u(r){return t(r,function(){return Dr.in_grouping_b(Wr,97,305)})}function o(){return u(function(){return Dr.eq_s_b(1,"n")})}function s(){return u(function(){return Dr.eq_s_b(1,"s")})}function c(){return u(function(){return Dr.eq_s_b(1,"y")})}function l(){return t(function(){return Dr.in_grouping_b(Lr,105,305)},function(){return Dr.out_grouping_b(Wr,97,305)})}function a(){return Dr.find_among_b(ur,10)&&l()}function m(){return n()&&Dr.in_grouping_b(Lr,105,305)&&s()}function d(){return Dr.find_among_b(or,2)}function f(){return n()&&Dr.in_grouping_b(Lr,105,305)&&c()}function b(){return n()&&Dr.find_among_b(sr,4)}function w(){return n()&&Dr.find_among_b(cr,4)&&o()}function _(){return n()&&Dr.find_among_b(lr,2)&&c()}function k(){return n()&&Dr.find_among_b(ar,2)}function p(){return n()&&Dr.find_among_b(mr,4)}function g(){return n()&&Dr.find_among_b(dr,2)}function y(){return n()&&Dr.find_among_b(fr,4)}function z(){return n()&&Dr.find_among_b(br,2)}function v(){return n()&&Dr.find_among_b(wr,2)&&c()}function h(){return Dr.eq_s_b(2,"ki")}function q(){return n()&&Dr.find_among_b(_r,2)&&o()}function C(){return n()&&Dr.find_among_b(kr,4)&&c()}function P(){return n()&&Dr.find_among_b(pr,4)}function F(){return n()&&Dr.find_among_b(gr,4)&&c()}function S(){return Dr.find_among_b(yr,4)}function W(){return n()&&Dr.find_among_b(zr,2)}function L(){return n()&&Dr.find_among_b(vr,4)}function x(){return n()&&Dr.find_among_b(hr,8)}function A(){return Dr.find_among_b(qr,2)}function E(){return n()&&Dr.find_among_b(Cr,32)&&c()}function j(){return Dr.find_among_b(Pr,8)&&c()}function T(){return n()&&Dr.find_among_b(Fr,4)&&c()}function Z(){return Dr.eq_s_b(3,"ken")&&c()}function B(){var r=Dr.limit-Dr.cursor;return!(T()||(Dr.cursor=Dr.limit-r,E()||(Dr.cursor=Dr.limit-r,j()||(Dr.cursor=Dr.limit-r,Z()))))}function D(){if(A()){var r=Dr.limit-Dr.cursor;if(S()||(Dr.cursor=Dr.limit-r,W()||(Dr.cursor=Dr.limit-r,C()||(Dr.cursor=Dr.limit-r,P()||(Dr.cursor=Dr.limit-r,F()||(Dr.cursor=Dr.limit-r))))),T())return!1}return!0}function G(){if(W()){Dr.bra=Dr.cursor,Dr.slice_del();var r=Dr.limit-Dr.cursor;return Dr.ket=Dr.cursor,x()||(Dr.cursor=Dr.limit-r,E()||(Dr.cursor=Dr.limit-r,j()||(Dr.cursor=Dr.limit-r,T()||(Dr.cursor=Dr.limit-r)))),nr=!1,!1}return!0}function H(){if(!L())return!0;var r=Dr.limit-Dr.cursor;return!E()&&(Dr.cursor=Dr.limit-r,!j())}function I(){var r,i=Dr.limit-Dr.cursor;return!(S()||(Dr.cursor=Dr.limit-i,F()||(Dr.cursor=Dr.limit-i,P()||(Dr.cursor=Dr.limit-i,C()))))||(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,T()||(Dr.cursor=Dr.limit-r),!1)}function J(){var r,i=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,nr=!0,B()&&(Dr.cursor=Dr.limit-i,D()&&(Dr.cursor=Dr.limit-i,G()&&(Dr.cursor=Dr.limit-i,H()&&(Dr.cursor=Dr.limit-i,I()))))){if(Dr.cursor=Dr.limit-i,!x())return;Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,r=Dr.limit-Dr.cursor,S()||(Dr.cursor=Dr.limit-r,W()||(Dr.cursor=Dr.limit-r,C()||(Dr.cursor=Dr.limit-r,P()||(Dr.cursor=Dr.limit-r,F()||(Dr.cursor=Dr.limit-r))))),T()||(Dr.cursor=Dr.limit-r)}Dr.bra=Dr.cursor,Dr.slice_del()}function K(){var r,i,e,n;if(Dr.ket=Dr.cursor,h()){if(r=Dr.limit-Dr.cursor,p())return Dr.bra=Dr.cursor,Dr.slice_del(),i=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,W()?(Dr.bra=Dr.cursor,Dr.slice_del(),K()):(Dr.cursor=Dr.limit-i,a()&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()))),!0;if(Dr.cursor=Dr.limit-r,w()){if(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,e=Dr.limit-Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else{if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,!a()&&(Dr.cursor=Dr.limit-e,!m()&&(Dr.cursor=Dr.limit-e,!K())))return!0;Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())}return!0}if(Dr.cursor=Dr.limit-r,g()){if(n=Dr.limit-Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else if(Dr.cursor=Dr.limit-n,m())Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K());else if(Dr.cursor=Dr.limit-n,!K())return!1;return!0}}return!1}function M(r){if(Dr.ket=Dr.cursor,!g()&&(Dr.cursor=Dr.limit-r,!k()))return!1;var i=Dr.limit-Dr.cursor;if(d())Dr.bra=Dr.cursor,Dr.slice_del();else if(Dr.cursor=Dr.limit-i,m())Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K());else if(Dr.cursor=Dr.limit-i,!K())return!1;return!0}function N(r){if(Dr.ket=Dr.cursor,!z()&&(Dr.cursor=Dr.limit-r,!b()))return!1;var i=Dr.limit-Dr.cursor;return!(!m()&&(Dr.cursor=Dr.limit-i,!d()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()),!0)}function O(){var r,i=Dr.limit-Dr.cursor;return Dr.ket=Dr.cursor,!(!w()&&(Dr.cursor=Dr.limit-i,!v()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,!(!W()||(Dr.bra=Dr.cursor,Dr.slice_del(),!K()))||(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!(a()||(Dr.cursor=Dr.limit-r,m()||(Dr.cursor=Dr.limit-r,K())))||(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()),!0)))}function Q(){var r,i,e=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,!p()&&(Dr.cursor=Dr.limit-e,!f()&&(Dr.cursor=Dr.limit-e,!_())))return!1;if(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,r=Dr.limit-Dr.cursor,a())Dr.bra=Dr.cursor,Dr.slice_del(),i=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,W()||(Dr.cursor=Dr.limit-i);else if(Dr.cursor=Dr.limit-r,!W())return!0;return Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,K(),!0}function R(){var r,i,e=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,W())return Dr.bra=Dr.cursor,Dr.slice_del(),void K();if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,q())if(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else{if(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!a()&&(Dr.cursor=Dr.limit-r,!m())){if(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!W())return;if(Dr.bra=Dr.cursor,Dr.slice_del(),!K())return}Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())}else if(Dr.cursor=Dr.limit-e,!M(e)&&(Dr.cursor=Dr.limit-e,!N(e))){if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,y())return Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,i=Dr.limit-Dr.cursor,void(a()?(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())):(Dr.cursor=Dr.limit-i,W()?(Dr.bra=Dr.cursor,Dr.slice_del(),K()):(Dr.cursor=Dr.limit-i,K())));if(Dr.cursor=Dr.limit-e,!O()){if(Dr.cursor=Dr.limit-e,d())return Dr.bra=Dr.cursor,void Dr.slice_del();Dr.cursor=Dr.limit-e,K()||(Dr.cursor=Dr.limit-e,Q()||(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,(a()||(Dr.cursor=Dr.limit-e,m()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()))))}}}function U(){var r;if(Dr.ket=Dr.cursor,r=Dr.find_among_b(Sr,4))switch(Dr.bra=Dr.cursor,r){case 1:Dr.slice_from("p");break;case 2:Dr.slice_from("ç");break;case 3:Dr.slice_from("t");break;case 4:Dr.slice_from("k")}}function V(){for(;;){var r=Dr.limit-Dr.cursor;if(Dr.in_grouping_b(Wr,97,305)){Dr.cursor=Dr.limit-r;break}if(Dr.cursor=Dr.limit-r,Dr.cursor<=Dr.limit_backward)return!1;Dr.cursor--}return!0}function X(r,i,e){if(Dr.cursor=Dr.limit-r,V()){var n=Dr.limit-Dr.cursor;if(!Dr.eq_s_b(1,i)&&(Dr.cursor=Dr.limit-n,!Dr.eq_s_b(1,e)))return!0;Dr.cursor=Dr.limit-r;var t=Dr.cursor;return Dr.insert(Dr.cursor,Dr.cursor,e),Dr.cursor=t,!1}return!0}function Y(){var r=Dr.limit-Dr.cursor;(Dr.eq_s_b(1,"d")||(Dr.cursor=Dr.limit-r,Dr.eq_s_b(1,"g")))&&X(r,"a","ı")&&X(r,"e","i")&&X(r,"o","u")&&X(r,"ö","ü")}function $(){for(var r,i=Dr.cursor,e=2;;){for(r=Dr.cursor;!Dr.in_grouping(Wr,97,305);){if(Dr.cursor>=Dr.limit)return Dr.cursor=r,!(e>0)&&(Dr.cursor=i,!0);Dr.cursor++}e--}}function rr(r,i,e){for(;!Dr.eq_s(i,e);){if(Dr.cursor>=Dr.limit)return!0;Dr.cursor++}return(tr=i)!=Dr.limit||(Dr.cursor=r,!1)}function ir(){var r=Dr.cursor;return!rr(r,2,"ad")||(Dr.cursor=r,!rr(r,5,"soyad"))}function er(){var r=Dr.cursor;return!ir()&&(Dr.limit_backward=r,Dr.cursor=Dr.limit,Y(),Dr.cursor=Dr.limit,U(),!0)}var nr,tr,ur=[new i("m",-1,-1),new i("n",-1,-1),new i("miz",-1,-1),new i("niz",-1,-1),new i("muz",-1,-1),new i("nuz",-1,-1),new i("müz",-1,-1),new i("nüz",-1,-1),new i("mız",-1,-1),new i("nız",-1,-1)],or=[new i("leri",-1,-1),new i("ları",-1,-1)],sr=[new i("ni",-1,-1),new i("nu",-1,-1),new i("nü",-1,-1),new i("nı",-1,-1)],cr=[new i("in",-1,-1),new i("un",-1,-1),new i("ün",-1,-1),new i("ın",-1,-1)],lr=[new i("a",-1,-1),new i("e",-1,-1)],ar=[new i("na",-1,-1),new i("ne",-1,-1)],mr=[new i("da",-1,-1),new i("ta",-1,-1),new i("de",-1,-1),new i("te",-1,-1)],dr=[new i("nda",-1,-1),new i("nde",-1,-1)],fr=[new i("dan",-1,-1),new i("tan",-1,-1),new i("den",-1,-1),new i("ten",-1,-1)],br=[new i("ndan",-1,-1),new i("nden",-1,-1)],wr=[new i("la",-1,-1),new i("le",-1,-1)],_r=[new i("ca",-1,-1),new i("ce",-1,-1)],kr=[new i("im",-1,-1),new i("um",-1,-1),new i("üm",-1,-1),new i("ım",-1,-1)],pr=[new i("sin",-1,-1),new i("sun",-1,-1),new i("sün",-1,-1),new i("sın",-1,-1)],gr=[new i("iz",-1,-1),new i("uz",-1,-1),new i("üz",-1,-1),new i("ız",-1,-1)],yr=[new i("siniz",-1,-1),new i("sunuz",-1,-1),new i("sünüz",-1,-1),new i("sınız",-1,-1)],zr=[new i("lar",-1,-1),new i("ler",-1,-1)],vr=[new i("niz",-1,-1),new i("nuz",-1,-1),new i("nüz",-1,-1),new i("nız",-1,-1)],hr=[new i("dir",-1,-1),new i("tir",-1,-1),new i("dur",-1,-1),new i("tur",-1,-1),new i("dür",-1,-1),new i("tür",-1,-1),new i("dır",-1,-1),new i("tır",-1,-1)],qr=[new i("casına",-1,-1),new i("cesine",-1,-1)],Cr=[new i("di",-1,-1),new i("ti",-1,-1),new i("dik",-1,-1),new i("tik",-1,-1),new i("duk",-1,-1),new i("tuk",-1,-1),new i("dük",-1,-1),new i("tük",-1,-1),new i("dık",-1,-1),new i("tık",-1,-1),new i("dim",-1,-1),new i("tim",-1,-1),new i("dum",-1,-1),new i("tum",-1,-1),new i("düm",-1,-1),new i("tüm",-1,-1),new i("dım",-1,-1),new i("tım",-1,-1),new i("din",-1,-1),new i("tin",-1,-1),new i("dun",-1,-1),new i("tun",-1,-1),new i("dün",-1,-1),new i("tün",-1,-1),new i("dın",-1,-1),new i("tın",-1,-1),new i("du",-1,-1),new i("tu",-1,-1),new i("dü",-1,-1),new i("tü",-1,-1),new i("dı",-1,-1),new i("tı",-1,-1)],Pr=[new i("sa",-1,-1),new i("se",-1,-1),new i("sak",-1,-1),new i("sek",-1,-1),new i("sam",-1,-1),new i("sem",-1,-1),new i("san",-1,-1),new i("sen",-1,-1)],Fr=[new i("miş",-1,-1),new i("muş",-1,-1),new i("müş",-1,-1),new i("mış",-1,-1)],Sr=[new i("b",-1,1),new i("c",-1,2),new i("d",-1,3),new i("ğ",-1,4)],Wr=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,8,0,0,0,0,0,0,1],Lr=[1,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,1],xr=[1,64,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],Ar=[17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130],Er=[1,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],jr=[17],Tr=[65],Zr=[65],Br=[["a",xr,97,305],["e",Ar,101,252],["ı",Er,97,305],["i",jr,101,105],["o",Tr,111,117],["ö",Zr,246,252],["u",Tr,111,117]],Dr=new e;this.setCurrent=function(r){Dr.setCurrent(r)},this.getCurrent=function(){return Dr.getCurrent()},this.stem=function(){return!!($()&&(Dr.limit_backward=Dr.cursor,Dr.cursor=Dr.limit,J(),Dr.cursor=Dr.limit,nr&&(R(),Dr.cursor=Dr.limit_backward,er())))}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.tr.stemmer,"stemmer-tr"),r.tr.stopWordFilter=r.generateStopWordFilter("acaba altmış altı ama ancak arada aslında ayrıca bana bazı belki ben benden beni benim beri beş bile bin bir biri birkaç birkez birçok birşey birşeyi biz bizden bize bizi bizim bu buna bunda bundan bunlar bunları bunların bunu bunun burada böyle böylece da daha dahi de defa değil diye diğer doksan dokuz dolayı dolayısıyla dört edecek eden ederek edilecek ediliyor edilmesi ediyor elli en etmesi etti ettiği ettiğini eğer gibi göre halen hangi hatta hem henüz hep hepsi her herhangi herkesin hiç hiçbir iki ile ilgili ise itibaren itibariyle için işte kadar karşın katrilyon kendi kendilerine kendini kendisi kendisine kendisini kez ki kim kimden kime kimi kimse kırk milyar milyon mu mü mı nasıl ne neden nedenle nerde nerede nereye niye niçin o olan olarak oldu olduklarını olduğu olduğunu olmadı olmadığı olmak olması olmayan olmaz olsa olsun olup olur olursa oluyor on ona ondan onlar onlardan onları onların onu onun otuz oysa pek rağmen sadece sanki sekiz seksen sen senden seni senin siz sizden sizi sizin tarafından trilyon tüm var vardı ve veya ya yani yapacak yapmak yaptı yaptıkları yaptığı yaptığını yapılan yapılması yapıyor yedi yerine yetmiş yine yirmi yoksa yüz zaten çok çünkü öyle üzere üç şey şeyden şeyi şeyler şu şuna şunda şundan şunları şunu şöyle".split(" ")),r.Pipeline.registerFunction(r.tr.stopWordFilter,"stopWordFilter-tr")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.vi.min.js b/assets/javascripts/lunr/min/lunr.vi.min.js new file mode 100644 index 0000000..22aed28 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.vi.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.zh.min.js b/assets/javascripts/lunr/min/lunr.zh.min.js new file mode 100644 index 0000000..fda66e9 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.zh.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r(require("@node-rs/jieba")):r()(e.lunr)}(this,function(e){return function(r,t){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==r.version[0];r.zh=function(){this.pipeline.reset(),this.pipeline.add(r.zh.trimmer,r.zh.stopWordFilter,r.zh.stemmer),i?this.tokenizer=r.zh.tokenizer:(r.tokenizer&&(r.tokenizer=r.zh.tokenizer),this.tokenizerFn&&(this.tokenizerFn=r.zh.tokenizer))},r.zh.tokenizer=function(n){if(!arguments.length||null==n||void 0==n)return[];if(Array.isArray(n))return n.map(function(e){return i?new r.Token(e.toLowerCase()):e.toLowerCase()});t&&e.load(t);var o=n.toString().trim().toLowerCase(),s=[];e.cut(o,!0).forEach(function(e){s=s.concat(e.split(" "))}),s=s.filter(function(e){return!!e});var u=0;return s.map(function(e,t){if(i){var n=o.indexOf(e,u),s={};return s.position=[n,e.length],s.index=t,u=n,new r.Token(e,s)}return e})},r.zh.wordCharacters="\\w一-龥",r.zh.trimmer=r.trimmerSupport.generateTrimmer(r.zh.wordCharacters),r.Pipeline.registerFunction(r.zh.trimmer,"trimmer-zh"),r.zh.stemmer=function(){return function(e){return e}}(),r.Pipeline.registerFunction(r.zh.stemmer,"stemmer-zh"),r.zh.stopWordFilter=r.generateStopWordFilter("的 一 不 在 人 有 是 为 為 以 于 於 上 他 而 后 後 之 来 來 及 了 因 下 可 到 由 这 這 与 與 也 此 但 并 並 个 個 其 已 无 無 小 我 们 們 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 當 从 從 得 打 凡 儿 兒 尔 爾 该 該 各 给 給 跟 和 何 还 還 即 几 幾 既 看 据 據 距 靠 啦 另 么 麽 每 嘛 拿 哪 您 凭 憑 且 却 卻 让 讓 仍 啥 如 若 使 谁 誰 虽 雖 随 隨 同 所 她 哇 嗡 往 些 向 沿 哟 喲 用 咱 则 則 怎 曾 至 致 着 著 诸 諸 自".split(" ")),r.Pipeline.registerFunction(r.zh.stopWordFilter,"stopWordFilter-zh")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/tinyseg.js b/assets/javascripts/lunr/tinyseg.js new file mode 100644 index 0000000..167fa6d --- /dev/null +++ b/assets/javascripts/lunr/tinyseg.js @@ -0,0 +1,206 @@ +/** + * export the module via AMD, CommonJS or as a browser global + * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js + */ +;(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(factory) + } else if (typeof exports === 'object') { + /** + * Node. Does not work with strict CommonJS, but + * only CommonJS-like environments that support module.exports, + * like Node. + */ + module.exports = factory() + } else { + // Browser globals (root is window) + factory()(root.lunr); + } +}(this, function () { + /** + * Just return a value to define the module export. + * This example returns an object, but the module + * can return a function as the exported value. + */ + + return function(lunr) { + // TinySegmenter 0.1 -- Super compact Japanese tokenizer in Javascript + // (c) 2008 Taku Kudo + // TinySegmenter is freely distributable under the terms of a new BSD licence. + // For details, see http://chasen.org/~taku/software/TinySegmenter/LICENCE.txt + + function TinySegmenter() { + var patterns = { + "[一二三四五六七八九十百千万億兆]":"M", + "[一-龠々〆ヵヶ]":"H", + "[ぁ-ん]":"I", + "[ァ-ヴーア-ン゙ー]":"K", + "[a-zA-Za-zA-Z]":"A", + "[0-90-9]":"N" + } + this.chartype_ = []; + for (var i in patterns) { + var regexp = new RegExp(i); + this.chartype_.push([regexp, patterns[i]]); + } + + this.BIAS__ = -332 + this.BC1__ = {"HH":6,"II":2461,"KH":406,"OH":-1378}; + this.BC2__ = {"AA":-3267,"AI":2744,"AN":-878,"HH":-4070,"HM":-1711,"HN":4012,"HO":3761,"IA":1327,"IH":-1184,"II":-1332,"IK":1721,"IO":5492,"KI":3831,"KK":-8741,"MH":-3132,"MK":3334,"OO":-2920}; + this.BC3__ = {"HH":996,"HI":626,"HK":-721,"HN":-1307,"HO":-836,"IH":-301,"KK":2762,"MK":1079,"MM":4034,"OA":-1652,"OH":266}; + this.BP1__ = {"BB":295,"OB":304,"OO":-125,"UB":352}; + this.BP2__ = {"BO":60,"OO":-1762}; + this.BQ1__ = {"BHH":1150,"BHM":1521,"BII":-1158,"BIM":886,"BMH":1208,"BNH":449,"BOH":-91,"BOO":-2597,"OHI":451,"OIH":-296,"OKA":1851,"OKH":-1020,"OKK":904,"OOO":2965}; + this.BQ2__ = {"BHH":118,"BHI":-1159,"BHM":466,"BIH":-919,"BKK":-1720,"BKO":864,"OHH":-1139,"OHM":-181,"OIH":153,"UHI":-1146}; + this.BQ3__ = {"BHH":-792,"BHI":2664,"BII":-299,"BKI":419,"BMH":937,"BMM":8335,"BNN":998,"BOH":775,"OHH":2174,"OHM":439,"OII":280,"OKH":1798,"OKI":-793,"OKO":-2242,"OMH":-2402,"OOO":11699}; + this.BQ4__ = {"BHH":-3895,"BIH":3761,"BII":-4654,"BIK":1348,"BKK":-1806,"BMI":-3385,"BOO":-12396,"OAH":926,"OHH":266,"OHK":-2036,"ONN":-973}; + this.BW1__ = {",と":660,",同":727,"B1あ":1404,"B1同":542,"、と":660,"、同":727,"」と":1682,"あっ":1505,"いう":1743,"いっ":-2055,"いる":672,"うし":-4817,"うん":665,"から":3472,"がら":600,"こう":-790,"こと":2083,"こん":-1262,"さら":-4143,"さん":4573,"した":2641,"して":1104,"すで":-3399,"そこ":1977,"それ":-871,"たち":1122,"ため":601,"った":3463,"つい":-802,"てい":805,"てき":1249,"でき":1127,"です":3445,"では":844,"とい":-4915,"とみ":1922,"どこ":3887,"ない":5713,"なっ":3015,"など":7379,"なん":-1113,"にし":2468,"には":1498,"にも":1671,"に対":-912,"の一":-501,"の中":741,"ませ":2448,"まで":1711,"まま":2600,"まる":-2155,"やむ":-1947,"よっ":-2565,"れた":2369,"れで":-913,"をし":1860,"を見":731,"亡く":-1886,"京都":2558,"取り":-2784,"大き":-2604,"大阪":1497,"平方":-2314,"引き":-1336,"日本":-195,"本当":-2423,"毎日":-2113,"目指":-724,"B1あ":1404,"B1同":542,"」と":1682}; + this.BW2__ = {"..":-11822,"11":-669,"――":-5730,"−−":-13175,"いう":-1609,"うか":2490,"かし":-1350,"かも":-602,"から":-7194,"かれ":4612,"がい":853,"がら":-3198,"きた":1941,"くな":-1597,"こと":-8392,"この":-4193,"させ":4533,"され":13168,"さん":-3977,"しい":-1819,"しか":-545,"した":5078,"して":972,"しな":939,"その":-3744,"たい":-1253,"たた":-662,"ただ":-3857,"たち":-786,"たと":1224,"たは":-939,"った":4589,"って":1647,"っと":-2094,"てい":6144,"てき":3640,"てく":2551,"ては":-3110,"ても":-3065,"でい":2666,"でき":-1528,"でし":-3828,"です":-4761,"でも":-4203,"とい":1890,"とこ":-1746,"とと":-2279,"との":720,"とみ":5168,"とも":-3941,"ない":-2488,"なが":-1313,"など":-6509,"なの":2614,"なん":3099,"にお":-1615,"にし":2748,"にな":2454,"によ":-7236,"に対":-14943,"に従":-4688,"に関":-11388,"のか":2093,"ので":-7059,"のに":-6041,"のの":-6125,"はい":1073,"はが":-1033,"はず":-2532,"ばれ":1813,"まし":-1316,"まで":-6621,"まれ":5409,"めて":-3153,"もい":2230,"もの":-10713,"らか":-944,"らし":-1611,"らに":-1897,"りし":651,"りま":1620,"れた":4270,"れて":849,"れば":4114,"ろう":6067,"われ":7901,"を通":-11877,"んだ":728,"んな":-4115,"一人":602,"一方":-1375,"一日":970,"一部":-1051,"上が":-4479,"会社":-1116,"出て":2163,"分の":-7758,"同党":970,"同日":-913,"大阪":-2471,"委員":-1250,"少な":-1050,"年度":-8669,"年間":-1626,"府県":-2363,"手権":-1982,"新聞":-4066,"日新":-722,"日本":-7068,"日米":3372,"曜日":-601,"朝鮮":-2355,"本人":-2697,"東京":-1543,"然と":-1384,"社会":-1276,"立て":-990,"第に":-1612,"米国":-4268,"11":-669}; + this.BW3__ = {"あた":-2194,"あり":719,"ある":3846,"い.":-1185,"い。":-1185,"いい":5308,"いえ":2079,"いく":3029,"いた":2056,"いっ":1883,"いる":5600,"いわ":1527,"うち":1117,"うと":4798,"えと":1454,"か.":2857,"か。":2857,"かけ":-743,"かっ":-4098,"かに":-669,"から":6520,"かり":-2670,"が,":1816,"が、":1816,"がき":-4855,"がけ":-1127,"がっ":-913,"がら":-4977,"がり":-2064,"きた":1645,"けど":1374,"こと":7397,"この":1542,"ころ":-2757,"さい":-714,"さを":976,"し,":1557,"し、":1557,"しい":-3714,"した":3562,"して":1449,"しな":2608,"しま":1200,"す.":-1310,"す。":-1310,"する":6521,"ず,":3426,"ず、":3426,"ずに":841,"そう":428,"た.":8875,"た。":8875,"たい":-594,"たの":812,"たり":-1183,"たる":-853,"だ.":4098,"だ。":4098,"だっ":1004,"った":-4748,"って":300,"てい":6240,"てお":855,"ても":302,"です":1437,"でに":-1482,"では":2295,"とう":-1387,"とし":2266,"との":541,"とも":-3543,"どう":4664,"ない":1796,"なく":-903,"など":2135,"に,":-1021,"に、":-1021,"にし":1771,"にな":1906,"には":2644,"の,":-724,"の、":-724,"の子":-1000,"は,":1337,"は、":1337,"べき":2181,"まし":1113,"ます":6943,"まっ":-1549,"まで":6154,"まれ":-793,"らし":1479,"られ":6820,"るる":3818,"れ,":854,"れ、":854,"れた":1850,"れて":1375,"れば":-3246,"れる":1091,"われ":-605,"んだ":606,"んで":798,"カ月":990,"会議":860,"入り":1232,"大会":2217,"始め":1681,"市":965,"新聞":-5055,"日,":974,"日、":974,"社会":2024,"カ月":990}; + this.TC1__ = {"AAA":1093,"HHH":1029,"HHM":580,"HII":998,"HOH":-390,"HOM":-331,"IHI":1169,"IOH":-142,"IOI":-1015,"IOM":467,"MMH":187,"OOI":-1832}; + this.TC2__ = {"HHO":2088,"HII":-1023,"HMM":-1154,"IHI":-1965,"KKH":703,"OII":-2649}; + this.TC3__ = {"AAA":-294,"HHH":346,"HHI":-341,"HII":-1088,"HIK":731,"HOH":-1486,"IHH":128,"IHI":-3041,"IHO":-1935,"IIH":-825,"IIM":-1035,"IOI":-542,"KHH":-1216,"KKA":491,"KKH":-1217,"KOK":-1009,"MHH":-2694,"MHM":-457,"MHO":123,"MMH":-471,"NNH":-1689,"NNO":662,"OHO":-3393}; + this.TC4__ = {"HHH":-203,"HHI":1344,"HHK":365,"HHM":-122,"HHN":182,"HHO":669,"HIH":804,"HII":679,"HOH":446,"IHH":695,"IHO":-2324,"IIH":321,"III":1497,"IIO":656,"IOO":54,"KAK":4845,"KKA":3386,"KKK":3065,"MHH":-405,"MHI":201,"MMH":-241,"MMM":661,"MOM":841}; + this.TQ1__ = {"BHHH":-227,"BHHI":316,"BHIH":-132,"BIHH":60,"BIII":1595,"BNHH":-744,"BOHH":225,"BOOO":-908,"OAKK":482,"OHHH":281,"OHIH":249,"OIHI":200,"OIIH":-68}; + this.TQ2__ = {"BIHH":-1401,"BIII":-1033,"BKAK":-543,"BOOO":-5591}; + this.TQ3__ = {"BHHH":478,"BHHM":-1073,"BHIH":222,"BHII":-504,"BIIH":-116,"BIII":-105,"BMHI":-863,"BMHM":-464,"BOMH":620,"OHHH":346,"OHHI":1729,"OHII":997,"OHMH":481,"OIHH":623,"OIIH":1344,"OKAK":2792,"OKHH":587,"OKKA":679,"OOHH":110,"OOII":-685}; + this.TQ4__ = {"BHHH":-721,"BHHM":-3604,"BHII":-966,"BIIH":-607,"BIII":-2181,"OAAA":-2763,"OAKK":180,"OHHH":-294,"OHHI":2446,"OHHO":480,"OHIH":-1573,"OIHH":1935,"OIHI":-493,"OIIH":626,"OIII":-4007,"OKAK":-8156}; + this.TW1__ = {"につい":-4681,"東京都":2026}; + this.TW2__ = {"ある程":-2049,"いった":-1256,"ころが":-2434,"しょう":3873,"その後":-4430,"だって":-1049,"ていた":1833,"として":-4657,"ともに":-4517,"もので":1882,"一気に":-792,"初めて":-1512,"同時に":-8097,"大きな":-1255,"対して":-2721,"社会党":-3216}; + this.TW3__ = {"いただ":-1734,"してい":1314,"として":-4314,"につい":-5483,"にとっ":-5989,"に当た":-6247,"ので,":-727,"ので、":-727,"のもの":-600,"れから":-3752,"十二月":-2287}; + this.TW4__ = {"いう.":8576,"いう。":8576,"からな":-2348,"してい":2958,"たが,":1516,"たが、":1516,"ている":1538,"という":1349,"ました":5543,"ません":1097,"ようと":-4258,"よると":5865}; + this.UC1__ = {"A":484,"K":93,"M":645,"O":-505}; + this.UC2__ = {"A":819,"H":1059,"I":409,"M":3987,"N":5775,"O":646}; + this.UC3__ = {"A":-1370,"I":2311}; + this.UC4__ = {"A":-2643,"H":1809,"I":-1032,"K":-3450,"M":3565,"N":3876,"O":6646}; + this.UC5__ = {"H":313,"I":-1238,"K":-799,"M":539,"O":-831}; + this.UC6__ = {"H":-506,"I":-253,"K":87,"M":247,"O":-387}; + this.UP1__ = {"O":-214}; + this.UP2__ = {"B":69,"O":935}; + this.UP3__ = {"B":189}; + this.UQ1__ = {"BH":21,"BI":-12,"BK":-99,"BN":142,"BO":-56,"OH":-95,"OI":477,"OK":410,"OO":-2422}; + this.UQ2__ = {"BH":216,"BI":113,"OK":1759}; + this.UQ3__ = {"BA":-479,"BH":42,"BI":1913,"BK":-7198,"BM":3160,"BN":6427,"BO":14761,"OI":-827,"ON":-3212}; + this.UW1__ = {",":156,"、":156,"「":-463,"あ":-941,"う":-127,"が":-553,"き":121,"こ":505,"で":-201,"と":-547,"ど":-123,"に":-789,"の":-185,"は":-847,"も":-466,"や":-470,"よ":182,"ら":-292,"り":208,"れ":169,"を":-446,"ん":-137,"・":-135,"主":-402,"京":-268,"区":-912,"午":871,"国":-460,"大":561,"委":729,"市":-411,"日":-141,"理":361,"生":-408,"県":-386,"都":-718,"「":-463,"・":-135}; + this.UW2__ = {",":-829,"、":-829,"〇":892,"「":-645,"」":3145,"あ":-538,"い":505,"う":134,"お":-502,"か":1454,"が":-856,"く":-412,"こ":1141,"さ":878,"ざ":540,"し":1529,"す":-675,"せ":300,"そ":-1011,"た":188,"だ":1837,"つ":-949,"て":-291,"で":-268,"と":-981,"ど":1273,"な":1063,"に":-1764,"の":130,"は":-409,"ひ":-1273,"べ":1261,"ま":600,"も":-1263,"や":-402,"よ":1639,"り":-579,"る":-694,"れ":571,"を":-2516,"ん":2095,"ア":-587,"カ":306,"キ":568,"ッ":831,"三":-758,"不":-2150,"世":-302,"中":-968,"主":-861,"事":492,"人":-123,"会":978,"保":362,"入":548,"初":-3025,"副":-1566,"北":-3414,"区":-422,"大":-1769,"天":-865,"太":-483,"子":-1519,"学":760,"実":1023,"小":-2009,"市":-813,"年":-1060,"強":1067,"手":-1519,"揺":-1033,"政":1522,"文":-1355,"新":-1682,"日":-1815,"明":-1462,"最":-630,"朝":-1843,"本":-1650,"東":-931,"果":-665,"次":-2378,"民":-180,"気":-1740,"理":752,"発":529,"目":-1584,"相":-242,"県":-1165,"立":-763,"第":810,"米":509,"自":-1353,"行":838,"西":-744,"見":-3874,"調":1010,"議":1198,"込":3041,"開":1758,"間":-1257,"「":-645,"」":3145,"ッ":831,"ア":-587,"カ":306,"キ":568}; + this.UW3__ = {",":4889,"1":-800,"−":-1723,"、":4889,"々":-2311,"〇":5827,"」":2670,"〓":-3573,"あ":-2696,"い":1006,"う":2342,"え":1983,"お":-4864,"か":-1163,"が":3271,"く":1004,"け":388,"げ":401,"こ":-3552,"ご":-3116,"さ":-1058,"し":-395,"す":584,"せ":3685,"そ":-5228,"た":842,"ち":-521,"っ":-1444,"つ":-1081,"て":6167,"で":2318,"と":1691,"ど":-899,"な":-2788,"に":2745,"の":4056,"は":4555,"ひ":-2171,"ふ":-1798,"へ":1199,"ほ":-5516,"ま":-4384,"み":-120,"め":1205,"も":2323,"や":-788,"よ":-202,"ら":727,"り":649,"る":5905,"れ":2773,"わ":-1207,"を":6620,"ん":-518,"ア":551,"グ":1319,"ス":874,"ッ":-1350,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278,"・":-3794,"一":-1619,"下":-1759,"世":-2087,"両":3815,"中":653,"主":-758,"予":-1193,"二":974,"人":2742,"今":792,"他":1889,"以":-1368,"低":811,"何":4265,"作":-361,"保":-2439,"元":4858,"党":3593,"全":1574,"公":-3030,"六":755,"共":-1880,"円":5807,"再":3095,"分":457,"初":2475,"別":1129,"前":2286,"副":4437,"力":365,"動":-949,"務":-1872,"化":1327,"北":-1038,"区":4646,"千":-2309,"午":-783,"協":-1006,"口":483,"右":1233,"各":3588,"合":-241,"同":3906,"和":-837,"員":4513,"国":642,"型":1389,"場":1219,"外":-241,"妻":2016,"学":-1356,"安":-423,"実":-1008,"家":1078,"小":-513,"少":-3102,"州":1155,"市":3197,"平":-1804,"年":2416,"広":-1030,"府":1605,"度":1452,"建":-2352,"当":-3885,"得":1905,"思":-1291,"性":1822,"戸":-488,"指":-3973,"政":-2013,"教":-1479,"数":3222,"文":-1489,"新":1764,"日":2099,"旧":5792,"昨":-661,"時":-1248,"曜":-951,"最":-937,"月":4125,"期":360,"李":3094,"村":364,"東":-805,"核":5156,"森":2438,"業":484,"氏":2613,"民":-1694,"決":-1073,"法":1868,"海":-495,"無":979,"物":461,"特":-3850,"生":-273,"用":914,"町":1215,"的":7313,"直":-1835,"省":792,"県":6293,"知":-1528,"私":4231,"税":401,"立":-960,"第":1201,"米":7767,"系":3066,"約":3663,"級":1384,"統":-4229,"総":1163,"線":1255,"者":6457,"能":725,"自":-2869,"英":785,"見":1044,"調":-562,"財":-733,"費":1777,"車":1835,"軍":1375,"込":-1504,"通":-1136,"選":-681,"郎":1026,"郡":4404,"部":1200,"金":2163,"長":421,"開":-1432,"間":1302,"関":-1282,"雨":2009,"電":-1045,"非":2066,"駅":1620,"1":-800,"」":2670,"・":-3794,"ッ":-1350,"ア":551,"グ":1319,"ス":874,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278}; + this.UW4__ = {",":3930,".":3508,"―":-4841,"、":3930,"。":3508,"〇":4999,"「":1895,"」":3798,"〓":-5156,"あ":4752,"い":-3435,"う":-640,"え":-2514,"お":2405,"か":530,"が":6006,"き":-4482,"ぎ":-3821,"く":-3788,"け":-4376,"げ":-4734,"こ":2255,"ご":1979,"さ":2864,"し":-843,"じ":-2506,"す":-731,"ず":1251,"せ":181,"そ":4091,"た":5034,"だ":5408,"ち":-3654,"っ":-5882,"つ":-1659,"て":3994,"で":7410,"と":4547,"な":5433,"に":6499,"ぬ":1853,"ね":1413,"の":7396,"は":8578,"ば":1940,"ひ":4249,"び":-4134,"ふ":1345,"へ":6665,"べ":-744,"ほ":1464,"ま":1051,"み":-2082,"む":-882,"め":-5046,"も":4169,"ゃ":-2666,"や":2795,"ょ":-1544,"よ":3351,"ら":-2922,"り":-9726,"る":-14896,"れ":-2613,"ろ":-4570,"わ":-1783,"を":13150,"ん":-2352,"カ":2145,"コ":1789,"セ":1287,"ッ":-724,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637,"・":-4371,"ー":-11870,"一":-2069,"中":2210,"予":782,"事":-190,"井":-1768,"人":1036,"以":544,"会":950,"体":-1286,"作":530,"側":4292,"先":601,"党":-2006,"共":-1212,"内":584,"円":788,"初":1347,"前":1623,"副":3879,"力":-302,"動":-740,"務":-2715,"化":776,"区":4517,"協":1013,"参":1555,"合":-1834,"和":-681,"員":-910,"器":-851,"回":1500,"国":-619,"園":-1200,"地":866,"場":-1410,"塁":-2094,"士":-1413,"多":1067,"大":571,"子":-4802,"学":-1397,"定":-1057,"寺":-809,"小":1910,"屋":-1328,"山":-1500,"島":-2056,"川":-2667,"市":2771,"年":374,"庁":-4556,"後":456,"性":553,"感":916,"所":-1566,"支":856,"改":787,"政":2182,"教":704,"文":522,"方":-856,"日":1798,"時":1829,"最":845,"月":-9066,"木":-485,"来":-442,"校":-360,"業":-1043,"氏":5388,"民":-2716,"気":-910,"沢":-939,"済":-543,"物":-735,"率":672,"球":-1267,"生":-1286,"産":-1101,"田":-2900,"町":1826,"的":2586,"目":922,"省":-3485,"県":2997,"空":-867,"立":-2112,"第":788,"米":2937,"系":786,"約":2171,"経":1146,"統":-1169,"総":940,"線":-994,"署":749,"者":2145,"能":-730,"般":-852,"行":-792,"規":792,"警":-1184,"議":-244,"谷":-1000,"賞":730,"車":-1481,"軍":1158,"輪":-1433,"込":-3370,"近":929,"道":-1291,"選":2596,"郎":-4866,"都":1192,"野":-1100,"銀":-2213,"長":357,"間":-2344,"院":-2297,"際":-2604,"電":-878,"領":-1659,"題":-792,"館":-1984,"首":1749,"高":2120,"「":1895,"」":3798,"・":-4371,"ッ":-724,"ー":-11870,"カ":2145,"コ":1789,"セ":1287,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637}; + this.UW5__ = {",":465,".":-299,"1":-514,"E2":-32768,"]":-2762,"、":465,"。":-299,"「":363,"あ":1655,"い":331,"う":-503,"え":1199,"お":527,"か":647,"が":-421,"き":1624,"ぎ":1971,"く":312,"げ":-983,"さ":-1537,"し":-1371,"す":-852,"だ":-1186,"ち":1093,"っ":52,"つ":921,"て":-18,"で":-850,"と":-127,"ど":1682,"な":-787,"に":-1224,"の":-635,"は":-578,"べ":1001,"み":502,"め":865,"ゃ":3350,"ょ":854,"り":-208,"る":429,"れ":504,"わ":419,"を":-1264,"ん":327,"イ":241,"ル":451,"ン":-343,"中":-871,"京":722,"会":-1153,"党":-654,"務":3519,"区":-901,"告":848,"員":2104,"大":-1296,"学":-548,"定":1785,"嵐":-1304,"市":-2991,"席":921,"年":1763,"思":872,"所":-814,"挙":1618,"新":-1682,"日":218,"月":-4353,"査":932,"格":1356,"機":-1508,"氏":-1347,"田":240,"町":-3912,"的":-3149,"相":1319,"省":-1052,"県":-4003,"研":-997,"社":-278,"空":-813,"統":1955,"者":-2233,"表":663,"語":-1073,"議":1219,"選":-1018,"郎":-368,"長":786,"間":1191,"題":2368,"館":-689,"1":-514,"E2":-32768,"「":363,"イ":241,"ル":451,"ン":-343}; + this.UW6__ = {",":227,".":808,"1":-270,"E1":306,"、":227,"。":808,"あ":-307,"う":189,"か":241,"が":-73,"く":-121,"こ":-200,"じ":1782,"す":383,"た":-428,"っ":573,"て":-1014,"で":101,"と":-105,"な":-253,"に":-149,"の":-417,"は":-236,"も":-206,"り":187,"る":-135,"を":195,"ル":-673,"ン":-496,"一":-277,"中":201,"件":-800,"会":624,"前":302,"区":1792,"員":-1212,"委":798,"学":-960,"市":887,"広":-695,"後":535,"業":-697,"相":753,"社":-507,"福":974,"空":-822,"者":1811,"連":463,"郎":1082,"1":-270,"E1":306,"ル":-673,"ン":-496}; + + return this; + } + TinySegmenter.prototype.ctype_ = function(str) { + for (var i in this.chartype_) { + if (str.match(this.chartype_[i][0])) { + return this.chartype_[i][1]; + } + } + return "O"; + } + + TinySegmenter.prototype.ts_ = function(v) { + if (v) { return v; } + return 0; + } + + TinySegmenter.prototype.segment = function(input) { + if (input == null || input == undefined || input == "") { + return []; + } + var result = []; + var seg = ["B3","B2","B1"]; + var ctype = ["O","O","O"]; + var o = input.split(""); + for (i = 0; i < o.length; ++i) { + seg.push(o[i]); + ctype.push(this.ctype_(o[i])) + } + seg.push("E1"); + seg.push("E2"); + seg.push("E3"); + ctype.push("O"); + ctype.push("O"); + ctype.push("O"); + var word = seg[3]; + var p1 = "U"; + var p2 = "U"; + var p3 = "U"; + for (var i = 4; i < seg.length - 3; ++i) { + var score = this.BIAS__; + var w1 = seg[i-3]; + var w2 = seg[i-2]; + var w3 = seg[i-1]; + var w4 = seg[i]; + var w5 = seg[i+1]; + var w6 = seg[i+2]; + var c1 = ctype[i-3]; + var c2 = ctype[i-2]; + var c3 = ctype[i-1]; + var c4 = ctype[i]; + var c5 = ctype[i+1]; + var c6 = ctype[i+2]; + score += this.ts_(this.UP1__[p1]); + score += this.ts_(this.UP2__[p2]); + score += this.ts_(this.UP3__[p3]); + score += this.ts_(this.BP1__[p1 + p2]); + score += this.ts_(this.BP2__[p2 + p3]); + score += this.ts_(this.UW1__[w1]); + score += this.ts_(this.UW2__[w2]); + score += this.ts_(this.UW3__[w3]); + score += this.ts_(this.UW4__[w4]); + score += this.ts_(this.UW5__[w5]); + score += this.ts_(this.UW6__[w6]); + score += this.ts_(this.BW1__[w2 + w3]); + score += this.ts_(this.BW2__[w3 + w4]); + score += this.ts_(this.BW3__[w4 + w5]); + score += this.ts_(this.TW1__[w1 + w2 + w3]); + score += this.ts_(this.TW2__[w2 + w3 + w4]); + score += this.ts_(this.TW3__[w3 + w4 + w5]); + score += this.ts_(this.TW4__[w4 + w5 + w6]); + score += this.ts_(this.UC1__[c1]); + score += this.ts_(this.UC2__[c2]); + score += this.ts_(this.UC3__[c3]); + score += this.ts_(this.UC4__[c4]); + score += this.ts_(this.UC5__[c5]); + score += this.ts_(this.UC6__[c6]); + score += this.ts_(this.BC1__[c2 + c3]); + score += this.ts_(this.BC2__[c3 + c4]); + score += this.ts_(this.BC3__[c4 + c5]); + score += this.ts_(this.TC1__[c1 + c2 + c3]); + score += this.ts_(this.TC2__[c2 + c3 + c4]); + score += this.ts_(this.TC3__[c3 + c4 + c5]); + score += this.ts_(this.TC4__[c4 + c5 + c6]); + // score += this.ts_(this.TC5__[c4 + c5 + c6]); + score += this.ts_(this.UQ1__[p1 + c1]); + score += this.ts_(this.UQ2__[p2 + c2]); + score += this.ts_(this.UQ3__[p3 + c3]); + score += this.ts_(this.BQ1__[p2 + c2 + c3]); + score += this.ts_(this.BQ2__[p2 + c3 + c4]); + score += this.ts_(this.BQ3__[p3 + c2 + c3]); + score += this.ts_(this.BQ4__[p3 + c3 + c4]); + score += this.ts_(this.TQ1__[p2 + c1 + c2 + c3]); + score += this.ts_(this.TQ2__[p2 + c2 + c3 + c4]); + score += this.ts_(this.TQ3__[p3 + c1 + c2 + c3]); + score += this.ts_(this.TQ4__[p3 + c2 + c3 + c4]); + var p = "O"; + if (score > 0) { + result.push(word); + word = ""; + p = "B"; + } + p1 = p2; + p2 = p3; + p3 = p; + word += seg[i]; + } + result.push(word); + + return result; + } + + lunr.TinySegmenter = TinySegmenter; + }; + +})); \ No newline at end of file diff --git a/assets/javascripts/lunr/wordcut.js b/assets/javascripts/lunr/wordcut.js new file mode 100644 index 0000000..0d898c9 --- /dev/null +++ b/assets/javascripts/lunr/wordcut.js @@ -0,0 +1,6708 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.lunr || (g.lunr = {})).wordcut = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1; + }) + this.addWords(words, false) + } + if(finalize){ + this.finalizeDict(); + } + }, + + dictSeek: function (l, r, ch, strOffset, pos) { + var ans = null; + while (l <= r) { + var m = Math.floor((l + r) / 2), + dict_item = this.dict[m], + len = dict_item.length; + if (len <= strOffset) { + l = m + 1; + } else { + var ch_ = dict_item[strOffset]; + if (ch_ < ch) { + l = m + 1; + } else if (ch_ > ch) { + r = m - 1; + } else { + ans = m; + if (pos == LEFT) { + r = m - 1; + } else { + l = m + 1; + } + } + } + } + return ans; + }, + + isFinal: function (acceptor) { + return this.dict[acceptor.l].length == acceptor.strOffset; + }, + + createAcceptor: function () { + return { + l: 0, + r: this.dict.length - 1, + strOffset: 0, + isFinal: false, + dict: this, + transit: function (ch) { + return this.dict.transit(this, ch); + }, + isError: false, + tag: "DICT", + w: 1, + type: "DICT" + }; + }, + + transit: function (acceptor, ch) { + var l = this.dictSeek(acceptor.l, + acceptor.r, + ch, + acceptor.strOffset, + LEFT); + if (l !== null) { + var r = this.dictSeek(l, + acceptor.r, + ch, + acceptor.strOffset, + RIGHT); + acceptor.l = l; + acceptor.r = r; + acceptor.strOffset++; + acceptor.isFinal = this.isFinal(acceptor); + } else { + acceptor.isError = true; + } + return acceptor; + }, + + sortuniq: function(a){ + return a.sort().filter(function(item, pos, arr){ + return !pos || item != arr[pos - 1]; + }) + }, + + flatten: function(a){ + //[[1,2],[3]] -> [1,2,3] + return [].concat.apply([], a); + } +}; +module.exports = WordcutDict; + +}).call(this,"/dist/tmp") +},{"glob":16,"path":22}],3:[function(require,module,exports){ +var WordRule = { + createAcceptor: function(tag) { + if (tag["WORD_RULE"]) + return null; + + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + var lch = ch.toLowerCase(); + if (lch >= "a" && lch <= "z") { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "WORD_RULE", + type: "WORD_RULE", + w: 1}; + } +}; + +var NumberRule = { + createAcceptor: function(tag) { + if (tag["NUMBER_RULE"]) + return null; + + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (ch >= "0" && ch <= "9") { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "NUMBER_RULE", + type: "NUMBER_RULE", + w: 1}; + } +}; + +var SpaceRule = { + tag: "SPACE_RULE", + createAcceptor: function(tag) { + + if (tag["SPACE_RULE"]) + return null; + + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (ch == " " || ch == "\t" || ch == "\r" || ch == "\n" || + ch == "\u00A0" || ch=="\u2003"//nbsp and emsp + ) { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: SpaceRule.tag, + w: 1, + type: "SPACE_RULE"}; + } +} + +var SingleSymbolRule = { + tag: "SINSYM", + createAcceptor: function(tag) { + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (this.strOffset == 0 && ch.match(/^[\@\(\)\/\,\-\."`]$/)) { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "SINSYM", + w: 1, + type: "SINSYM"}; + } +} + + +var LatinRules = [WordRule, SpaceRule, SingleSymbolRule, NumberRule]; + +module.exports = LatinRules; + +},{}],4:[function(require,module,exports){ +var _ = require("underscore") + , WordcutCore = require("./wordcut_core"); +var PathInfoBuilder = { + + /* + buildByPartAcceptors: function(path, acceptors, i) { + var + var genInfos = partAcceptors.reduce(function(genInfos, acceptor) { + + }, []); + + return genInfos; + } + */ + + buildByAcceptors: function(path, finalAcceptors, i) { + var self = this; + var infos = finalAcceptors.map(function(acceptor) { + var p = i - acceptor.strOffset + 1 + , _info = path[p]; + + var info = {p: p, + mw: _info.mw + (acceptor.mw === undefined ? 0 : acceptor.mw), + w: acceptor.w + _info.w, + unk: (acceptor.unk ? acceptor.unk : 0) + _info.unk, + type: acceptor.type}; + + if (acceptor.type == "PART") { + for(var j = p + 1; j <= i; j++) { + path[j].merge = p; + } + info.merge = p; + } + + return info; + }); + return infos.filter(function(info) { return info; }); + }, + + fallback: function(path, leftBoundary, text, i) { + var _info = path[leftBoundary]; + if (text[i].match(/[\u0E48-\u0E4E]/)) { + if (leftBoundary != 0) + leftBoundary = path[leftBoundary].p; + return {p: leftBoundary, + mw: 0, + w: 1 + _info.w, + unk: 1 + _info.unk, + type: "UNK"}; +/* } else if(leftBoundary > 0 && path[leftBoundary].type !== "UNK") { + leftBoundary = path[leftBoundary].p; + return {p: leftBoundary, + w: 1 + _info.w, + unk: 1 + _info.unk, + type: "UNK"}; */ + } else { + return {p: leftBoundary, + mw: _info.mw, + w: 1 + _info.w, + unk: 1 + _info.unk, + type: "UNK"}; + } + }, + + build: function(path, finalAcceptors, i, leftBoundary, text) { + var basicPathInfos = this.buildByAcceptors(path, finalAcceptors, i); + if (basicPathInfos.length > 0) { + return basicPathInfos; + } else { + return [this.fallback(path, leftBoundary, text, i)]; + } + } +}; + +module.exports = function() { + return _.clone(PathInfoBuilder); +} + +},{"./wordcut_core":8,"underscore":25}],5:[function(require,module,exports){ +var _ = require("underscore"); + + +var PathSelector = { + selectPath: function(paths) { + var path = paths.reduce(function(selectedPath, path) { + if (selectedPath == null) { + return path; + } else { + if (path.unk < selectedPath.unk) + return path; + if (path.unk == selectedPath.unk) { + if (path.mw < selectedPath.mw) + return path + if (path.mw == selectedPath.mw) { + if (path.w < selectedPath.w) + return path; + } + } + return selectedPath; + } + }, null); + return path; + }, + + createPath: function() { + return [{p:null, w:0, unk:0, type: "INIT", mw:0}]; + } +}; + +module.exports = function() { + return _.clone(PathSelector); +}; + +},{"underscore":25}],6:[function(require,module,exports){ +function isMatch(pat, offset, ch) { + if (pat.length <= offset) + return false; + var _ch = pat[offset]; + return _ch == ch || + (_ch.match(/[กข]/) && ch.match(/[ก-ฮ]/)) || + (_ch.match(/[มบ]/) && ch.match(/[ก-ฮ]/)) || + (_ch.match(/\u0E49/) && ch.match(/[\u0E48-\u0E4B]/)); +} + +var Rule0 = { + pat: "เหก็ม", + createAcceptor: function(tag) { + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (isMatch(Rule0.pat, this.strOffset,ch)) { + this.isFinal = (this.strOffset + 1 == Rule0.pat.length); + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "THAI_RULE", + type: "THAI_RULE", + w: 1}; + } +}; + +var PartRule = { + createAcceptor: function(tag) { + return {strOffset: 0, + patterns: [ + "แก", "เก", "ก้", "กก์", "กา", "กี", "กิ", "กืก" + ], + isFinal: false, + transit: function(ch) { + var offset = this.strOffset; + this.patterns = this.patterns.filter(function(pat) { + return isMatch(pat, offset, ch); + }); + + if (this.patterns.length > 0) { + var len = 1 + offset; + this.isFinal = this.patterns.some(function(pat) { + return pat.length == len; + }); + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "PART", + type: "PART", + unk: 1, + w: 1}; + } +}; + +var ThaiRules = [Rule0, PartRule]; + +module.exports = ThaiRules; + +},{}],7:[function(require,module,exports){ +var sys = require("sys") + , WordcutDict = require("./dict") + , WordcutCore = require("./wordcut_core") + , PathInfoBuilder = require("./path_info_builder") + , PathSelector = require("./path_selector") + , Acceptors = require("./acceptors") + , latinRules = require("./latin_rules") + , thaiRules = require("./thai_rules") + , _ = require("underscore"); + + +var Wordcut = Object.create(WordcutCore); +Wordcut.defaultPathInfoBuilder = PathInfoBuilder; +Wordcut.defaultPathSelector = PathSelector; +Wordcut.defaultAcceptors = Acceptors; +Wordcut.defaultLatinRules = latinRules; +Wordcut.defaultThaiRules = thaiRules; +Wordcut.defaultDict = WordcutDict; + + +Wordcut.initNoDict = function(dict_path) { + var self = this; + self.pathInfoBuilder = new self.defaultPathInfoBuilder; + self.pathSelector = new self.defaultPathSelector; + self.acceptors = new self.defaultAcceptors; + self.defaultLatinRules.forEach(function(rule) { + self.acceptors.creators.push(rule); + }); + self.defaultThaiRules.forEach(function(rule) { + self.acceptors.creators.push(rule); + }); +}; + +Wordcut.init = function(dict_path, withDefault, additionalWords) { + withDefault = withDefault || false; + this.initNoDict(); + var dict = _.clone(this.defaultDict); + dict.init(dict_path, withDefault, additionalWords); + this.acceptors.creators.push(dict); +}; + +module.exports = Wordcut; + +},{"./acceptors":1,"./dict":2,"./latin_rules":3,"./path_info_builder":4,"./path_selector":5,"./thai_rules":6,"./wordcut_core":8,"sys":28,"underscore":25}],8:[function(require,module,exports){ +var WordcutCore = { + + buildPath: function(text) { + var self = this + , path = self.pathSelector.createPath() + , leftBoundary = 0; + self.acceptors.reset(); + for (var i = 0; i < text.length; i++) { + var ch = text[i]; + self.acceptors.transit(ch); + + var possiblePathInfos = self + .pathInfoBuilder + .build(path, + self.acceptors.getFinalAcceptors(), + i, + leftBoundary, + text); + var selectedPath = self.pathSelector.selectPath(possiblePathInfos) + + path.push(selectedPath); + if (selectedPath.type !== "UNK") { + leftBoundary = i; + } + } + return path; + }, + + pathToRanges: function(path) { + var e = path.length - 1 + , ranges = []; + + while (e > 0) { + var info = path[e] + , s = info.p; + + if (info.merge !== undefined && ranges.length > 0) { + var r = ranges[ranges.length - 1]; + r.s = info.merge; + s = r.s; + } else { + ranges.push({s:s, e:e}); + } + e = s; + } + return ranges.reverse(); + }, + + rangesToText: function(text, ranges, delimiter) { + return ranges.map(function(r) { + return text.substring(r.s, r.e); + }).join(delimiter); + }, + + cut: function(text, delimiter) { + var path = this.buildPath(text) + , ranges = this.pathToRanges(path); + return this + .rangesToText(text, ranges, + (delimiter === undefined ? "|" : delimiter)); + }, + + cutIntoRanges: function(text, noText) { + var path = this.buildPath(text) + , ranges = this.pathToRanges(path); + + if (!noText) { + ranges.forEach(function(r) { + r.text = text.substring(r.s, r.e); + }); + } + return ranges; + }, + + cutIntoArray: function(text) { + var path = this.buildPath(text) + , ranges = this.pathToRanges(path); + + return ranges.map(function(r) { + return text.substring(r.s, r.e) + }); + } +}; + +module.exports = WordcutCore; + +},{}],9:[function(require,module,exports){ +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// 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 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. + +// when used in node, this will actually load the util module we depend on +// versus loading the builtin util module as happens otherwise +// this is a bug in node module loading as far as I am concerned +var util = require('util/'); + +var pSlice = Array.prototype.slice; +var hasOwn = Object.prototype.hasOwnProperty; + +// 1. The assert module provides functions that throw +// AssertionError's when particular conditions are not met. The +// assert module must conform to the following interface. + +var assert = module.exports = ok; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({ message: message, +// actual: actual, +// expected: expected }) + +assert.AssertionError = function AssertionError(options) { + this.name = 'AssertionError'; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + if (options.message) { + this.message = options.message; + this.generatedMessage = false; + } else { + this.message = getMessage(this); + this.generatedMessage = true; + } + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } + else { + // non v8 browsers so we can have a stacktrace + var err = new Error(); + if (err.stack) { + var out = err.stack; + + // try to strip useless frames + var fn_name = stackStartFunction.name; + var idx = out.indexOf('\n' + fn_name); + if (idx >= 0) { + // once we have located the function frame + // we need to strip out everything before it (and its line) + var next_line = out.indexOf('\n', idx + 1); + out = out.substring(next_line + 1); + } + + this.stack = out; + } + } +}; + +// assert.AssertionError instanceof Error +util.inherits(assert.AssertionError, Error); + +function replacer(key, value) { + if (util.isUndefined(value)) { + return '' + value; + } + if (util.isNumber(value) && !isFinite(value)) { + return value.toString(); + } + if (util.isFunction(value) || util.isRegExp(value)) { + return value.toString(); + } + return value; +} + +function truncate(s, n) { + if (util.isString(s)) { + return s.length < n ? s : s.slice(0, n); + } else { + return s; + } +} + +function getMessage(self) { + return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + + self.operator + ' ' + + truncate(JSON.stringify(self.expected, replacer), 128); +} + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. All of the following functions must throw an AssertionError +// when a corresponding condition is not met, with a message that +// may be undefined if not provided. All assertion methods provide +// both the actual and expected values to the assertion error for +// display purposes. + +function fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, !!guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +function ok(value, message) { + if (!value) fail(value, true, message, '==', assert.ok); +} +assert.ok = ok; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, '==', assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, '!=', assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected)) { + fail(actual, expected, message, 'deepEqual', assert.deepEqual); + } +}; + +function _deepEqual(actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } else if (util.isBuffer(actual) && util.isBuffer(expected)) { + if (actual.length != expected.length) return false; + + for (var i = 0; i < actual.length; i++) { + if (actual[i] !== expected[i]) return false; + } + + return true; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (util.isDate(actual) && util.isDate(expected)) { + return actual.getTime() === expected.getTime(); + + // 7.3 If the expected value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object with the same source and + // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). + } else if (util.isRegExp(actual) && util.isRegExp(expected)) { + return actual.source === expected.source && + actual.global === expected.global && + actual.multiline === expected.multiline && + actual.lastIndex === expected.lastIndex && + actual.ignoreCase === expected.ignoreCase; + + // 7.4. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if (!util.isObject(actual) && !util.isObject(expected)) { + return actual == expected; + + // 7.5 For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv(a, b) { + if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) + return false; + // an identical 'prototype' property. + if (a.prototype !== b.prototype) return false; + // if one is a primitive, the other must be same + if (util.isPrimitive(a) || util.isPrimitive(b)) { + return a === b; + } + var aIsArgs = isArguments(a), + bIsArgs = isArguments(b); + if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) + return false; + if (aIsArgs) { + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + var ka = objectKeys(a), + kb = objectKeys(b), + key, i; + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key])) return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected)) { + fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); + } +}; + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, '===', assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as +// determined by !==. assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, '!==', assert.notStrictEqual); + } +}; + +function expectedException(actual, expected) { + if (!actual || !expected) { + return false; + } + + if (Object.prototype.toString.call(expected) == '[object RegExp]') { + return expected.test(actual); + } else if (actual instanceof expected) { + return true; + } else if (expected.call({}, actual) === true) { + return true; + } + + return false; +} + +function _throws(shouldThrow, block, expected, message) { + var actual; + + if (util.isString(expected)) { + message = expected; + expected = null; + } + + try { + block(); + } catch (e) { + actual = e; + } + + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + + (message ? ' ' + message : '.'); + + if (shouldThrow && !actual) { + fail(actual, expected, 'Missing expected exception' + message); + } + + if (!shouldThrow && expectedException(actual, expected)) { + fail(actual, expected, 'Got unwanted exception' + message); + } + + if ((shouldThrow && actual && expected && + !expectedException(actual, expected)) || (!shouldThrow && actual)) { + throw actual; + } +} + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [true].concat(pSlice.call(arguments))); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function(err) { if (err) {throw err;}}; + +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + if (hasOwn.call(obj, key)) keys.push(key); + } + return keys; +}; + +},{"util/":28}],10:[function(require,module,exports){ +'use strict'; +module.exports = balanced; +function balanced(a, b, str) { + if (a instanceof RegExp) a = maybeMatch(a, str); + if (b instanceof RegExp) b = maybeMatch(b, str); + + var r = range(a, b, str); + + return r && { + start: r[0], + end: r[1], + pre: str.slice(0, r[0]), + body: str.slice(r[0] + a.length, r[1]), + post: str.slice(r[1] + b.length) + }; +} + +function maybeMatch(reg, str) { + var m = str.match(reg); + return m ? m[0] : null; +} + +balanced.range = range; +function range(a, b, str) { + var begs, beg, left, right, result; + var ai = str.indexOf(a); + var bi = str.indexOf(b, ai + 1); + var i = ai; + + if (ai >= 0 && bi > 0) { + begs = []; + left = str.length; + + while (i >= 0 && !result) { + if (i == ai) { + begs.push(i); + ai = str.indexOf(a, i + 1); + } else if (begs.length == 1) { + result = [ begs.pop(), bi ]; + } else { + beg = begs.pop(); + if (beg < left) { + left = beg; + right = bi; + } + + bi = str.indexOf(b, i + 1); + } + + i = ai < bi && ai >= 0 ? ai : bi; + } + + if (begs.length) { + result = [ left, right ]; + } + } + + return result; +} + +},{}],11:[function(require,module,exports){ +var concatMap = require('concat-map'); +var balanced = require('balanced-match'); + +module.exports = expandTop; + +var escSlash = '\0SLASH'+Math.random()+'\0'; +var escOpen = '\0OPEN'+Math.random()+'\0'; +var escClose = '\0CLOSE'+Math.random()+'\0'; +var escComma = '\0COMMA'+Math.random()+'\0'; +var escPeriod = '\0PERIOD'+Math.random()+'\0'; + +function numeric(str) { + return parseInt(str, 10) == str + ? parseInt(str, 10) + : str.charCodeAt(0); +} + +function escapeBraces(str) { + return str.split('\\\\').join(escSlash) + .split('\\{').join(escOpen) + .split('\\}').join(escClose) + .split('\\,').join(escComma) + .split('\\.').join(escPeriod); +} + +function unescapeBraces(str) { + return str.split(escSlash).join('\\') + .split(escOpen).join('{') + .split(escClose).join('}') + .split(escComma).join(',') + .split(escPeriod).join('.'); +} + + +// Basically just str.split(","), but handling cases +// where we have nested braced sections, which should be +// treated as individual members, like {a,{b,c},d} +function parseCommaParts(str) { + if (!str) + return ['']; + + var parts = []; + var m = balanced('{', '}', str); + + if (!m) + return str.split(','); + + var pre = m.pre; + var body = m.body; + var post = m.post; + var p = pre.split(','); + + p[p.length-1] += '{' + body + '}'; + var postParts = parseCommaParts(post); + if (post.length) { + p[p.length-1] += postParts.shift(); + p.push.apply(p, postParts); + } + + parts.push.apply(parts, p); + + return parts; +} + +function expandTop(str) { + if (!str) + return []; + + // I don't know why Bash 4.3 does this, but it does. + // Anything starting with {} will have the first two bytes preserved + // but *only* at the top level, so {},a}b will not expand to anything, + // but a{},b}c will be expanded to [a}c,abc]. + // One could argue that this is a bug in Bash, but since the goal of + // this module is to match Bash's rules, we escape a leading {} + if (str.substr(0, 2) === '{}') { + str = '\\{\\}' + str.substr(2); + } + + return expand(escapeBraces(str), true).map(unescapeBraces); +} + +function identity(e) { + return e; +} + +function embrace(str) { + return '{' + str + '}'; +} +function isPadded(el) { + return /^-?0\d/.test(el); +} + +function lte(i, y) { + return i <= y; +} +function gte(i, y) { + return i >= y; +} + +function expand(str, isTop) { + var expansions = []; + + var m = balanced('{', '}', str); + if (!m || /\$$/.test(m.pre)) return [str]; + + var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); + var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); + var isSequence = isNumericSequence || isAlphaSequence; + var isOptions = m.body.indexOf(',') >= 0; + if (!isSequence && !isOptions) { + // {a},b} + if (m.post.match(/,.*\}/)) { + str = m.pre + '{' + m.body + escClose + m.post; + return expand(str); + } + return [str]; + } + + var n; + if (isSequence) { + n = m.body.split(/\.\./); + } else { + n = parseCommaParts(m.body); + if (n.length === 1) { + // x{{a,b}}y ==> x{a}y x{b}y + n = expand(n[0], false).map(embrace); + if (n.length === 1) { + var post = m.post.length + ? expand(m.post, false) + : ['']; + return post.map(function(p) { + return m.pre + n[0] + p; + }); + } + } + } + + // at this point, n is the parts, and we know it's not a comma set + // with a single entry. + + // no need to expand pre, since it is guaranteed to be free of brace-sets + var pre = m.pre; + var post = m.post.length + ? expand(m.post, false) + : ['']; + + var N; + + if (isSequence) { + var x = numeric(n[0]); + var y = numeric(n[1]); + var width = Math.max(n[0].length, n[1].length) + var incr = n.length == 3 + ? Math.abs(numeric(n[2])) + : 1; + var test = lte; + var reverse = y < x; + if (reverse) { + incr *= -1; + test = gte; + } + var pad = n.some(isPadded); + + N = []; + + for (var i = x; test(i, y); i += incr) { + var c; + if (isAlphaSequence) { + c = String.fromCharCode(i); + if (c === '\\') + c = ''; + } else { + c = String(i); + if (pad) { + var need = width - c.length; + if (need > 0) { + var z = new Array(need + 1).join('0'); + if (i < 0) + c = '-' + z + c.slice(1); + else + c = z + c; + } + } + } + N.push(c); + } + } else { + N = concatMap(n, function(el) { return expand(el, false) }); + } + + for (var j = 0; j < N.length; j++) { + for (var k = 0; k < post.length; k++) { + var expansion = pre + N[j] + post[k]; + if (!isTop || isSequence || expansion) + expansions.push(expansion); + } + } + + return expansions; +} + + +},{"balanced-match":10,"concat-map":13}],12:[function(require,module,exports){ + +},{}],13:[function(require,module,exports){ +module.exports = function (xs, fn) { + var res = []; + for (var i = 0; i < xs.length; i++) { + var x = fn(xs[i], i); + if (isArray(x)) res.push.apply(res, x); + else res.push(x); + } + return res; +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +},{}],14:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } + throw TypeError('Uncaught, unspecified "error" event.'); + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],15:[function(require,module,exports){ +(function (process){ +exports.alphasort = alphasort +exports.alphasorti = alphasorti +exports.setopts = setopts +exports.ownProp = ownProp +exports.makeAbs = makeAbs +exports.finish = finish +exports.mark = mark +exports.isIgnored = isIgnored +exports.childrenIgnored = childrenIgnored + +function ownProp (obj, field) { + return Object.prototype.hasOwnProperty.call(obj, field) +} + +var path = require("path") +var minimatch = require("minimatch") +var isAbsolute = require("path-is-absolute") +var Minimatch = minimatch.Minimatch + +function alphasorti (a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()) +} + +function alphasort (a, b) { + return a.localeCompare(b) +} + +function setupIgnores (self, options) { + self.ignore = options.ignore || [] + + if (!Array.isArray(self.ignore)) + self.ignore = [self.ignore] + + if (self.ignore.length) { + self.ignore = self.ignore.map(ignoreMap) + } +} + +function ignoreMap (pattern) { + var gmatcher = null + if (pattern.slice(-3) === '/**') { + var gpattern = pattern.replace(/(\/\*\*)+$/, '') + gmatcher = new Minimatch(gpattern) + } + + return { + matcher: new Minimatch(pattern), + gmatcher: gmatcher + } +} + +function setopts (self, pattern, options) { + if (!options) + options = {} + + // base-matching: just use globstar for that. + if (options.matchBase && -1 === pattern.indexOf("/")) { + if (options.noglobstar) { + throw new Error("base matching requires globstar") + } + pattern = "**/" + pattern + } + + self.silent = !!options.silent + self.pattern = pattern + self.strict = options.strict !== false + self.realpath = !!options.realpath + self.realpathCache = options.realpathCache || Object.create(null) + self.follow = !!options.follow + self.dot = !!options.dot + self.mark = !!options.mark + self.nodir = !!options.nodir + if (self.nodir) + self.mark = true + self.sync = !!options.sync + self.nounique = !!options.nounique + self.nonull = !!options.nonull + self.nosort = !!options.nosort + self.nocase = !!options.nocase + self.stat = !!options.stat + self.noprocess = !!options.noprocess + + self.maxLength = options.maxLength || Infinity + self.cache = options.cache || Object.create(null) + self.statCache = options.statCache || Object.create(null) + self.symlinks = options.symlinks || Object.create(null) + + setupIgnores(self, options) + + self.changedCwd = false + var cwd = process.cwd() + if (!ownProp(options, "cwd")) + self.cwd = cwd + else { + self.cwd = options.cwd + self.changedCwd = path.resolve(options.cwd) !== cwd + } + + self.root = options.root || path.resolve(self.cwd, "/") + self.root = path.resolve(self.root) + if (process.platform === "win32") + self.root = self.root.replace(/\\/g, "/") + + self.nomount = !!options.nomount + + // disable comments and negation unless the user explicitly + // passes in false as the option. + options.nonegate = options.nonegate === false ? false : true + options.nocomment = options.nocomment === false ? false : true + deprecationWarning(options) + + self.minimatch = new Minimatch(pattern, options) + self.options = self.minimatch.options +} + +// TODO(isaacs): remove entirely in v6 +// exported to reset in tests +exports.deprecationWarned +function deprecationWarning(options) { + if (!options.nonegate || !options.nocomment) { + if (process.noDeprecation !== true && !exports.deprecationWarned) { + var msg = 'glob WARNING: comments and negation will be disabled in v6' + if (process.throwDeprecation) + throw new Error(msg) + else if (process.traceDeprecation) + console.trace(msg) + else + console.error(msg) + + exports.deprecationWarned = true + } + } +} + +function finish (self) { + var nou = self.nounique + var all = nou ? [] : Object.create(null) + + for (var i = 0, l = self.matches.length; i < l; i ++) { + var matches = self.matches[i] + if (!matches || Object.keys(matches).length === 0) { + if (self.nonull) { + // do like the shell, and spit out the literal glob + var literal = self.minimatch.globSet[i] + if (nou) + all.push(literal) + else + all[literal] = true + } + } else { + // had matches + var m = Object.keys(matches) + if (nou) + all.push.apply(all, m) + else + m.forEach(function (m) { + all[m] = true + }) + } + } + + if (!nou) + all = Object.keys(all) + + if (!self.nosort) + all = all.sort(self.nocase ? alphasorti : alphasort) + + // at *some* point we statted all of these + if (self.mark) { + for (var i = 0; i < all.length; i++) { + all[i] = self._mark(all[i]) + } + if (self.nodir) { + all = all.filter(function (e) { + return !(/\/$/.test(e)) + }) + } + } + + if (self.ignore.length) + all = all.filter(function(m) { + return !isIgnored(self, m) + }) + + self.found = all +} + +function mark (self, p) { + var abs = makeAbs(self, p) + var c = self.cache[abs] + var m = p + if (c) { + var isDir = c === 'DIR' || Array.isArray(c) + var slash = p.slice(-1) === '/' + + if (isDir && !slash) + m += '/' + else if (!isDir && slash) + m = m.slice(0, -1) + + if (m !== p) { + var mabs = makeAbs(self, m) + self.statCache[mabs] = self.statCache[abs] + self.cache[mabs] = self.cache[abs] + } + } + + return m +} + +// lotta situps... +function makeAbs (self, f) { + var abs = f + if (f.charAt(0) === '/') { + abs = path.join(self.root, f) + } else if (isAbsolute(f) || f === '') { + abs = f + } else if (self.changedCwd) { + abs = path.resolve(self.cwd, f) + } else { + abs = path.resolve(f) + } + return abs +} + + +// Return true, if pattern ends with globstar '**', for the accompanying parent directory. +// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents +function isIgnored (self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function(item) { + return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) + }) +} + +function childrenIgnored (self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function(item) { + return !!(item.gmatcher && item.gmatcher.match(path)) + }) +} + +}).call(this,require('_process')) +},{"_process":24,"minimatch":20,"path":22,"path-is-absolute":23}],16:[function(require,module,exports){ +(function (process){ +// Approach: +// +// 1. Get the minimatch set +// 2. For each pattern in the set, PROCESS(pattern, false) +// 3. Store matches per-set, then uniq them +// +// PROCESS(pattern, inGlobStar) +// Get the first [n] items from pattern that are all strings +// Join these together. This is PREFIX. +// If there is no more remaining, then stat(PREFIX) and +// add to matches if it succeeds. END. +// +// If inGlobStar and PREFIX is symlink and points to dir +// set ENTRIES = [] +// else readdir(PREFIX) as ENTRIES +// If fail, END +// +// with ENTRIES +// If pattern[n] is GLOBSTAR +// // handle the case where the globstar match is empty +// // by pruning it out, and testing the resulting pattern +// PROCESS(pattern[0..n] + pattern[n+1 .. $], false) +// // handle other cases. +// for ENTRY in ENTRIES (not dotfiles) +// // attach globstar + tail onto the entry +// // Mark that this entry is a globstar match +// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true) +// +// else // not globstar +// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) +// Test ENTRY against pattern[n] +// If fails, continue +// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) +// +// Caveat: +// Cache all stats and readdirs results to minimize syscall. Since all +// we ever care about is existence and directory-ness, we can just keep +// `true` for files, and [children,...] for directories, or `false` for +// things that don't exist. + +module.exports = glob + +var fs = require('fs') +var minimatch = require('minimatch') +var Minimatch = minimatch.Minimatch +var inherits = require('inherits') +var EE = require('events').EventEmitter +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path-is-absolute') +var globSync = require('./sync.js') +var common = require('./common.js') +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var inflight = require('inflight') +var util = require('util') +var childrenIgnored = common.childrenIgnored +var isIgnored = common.isIgnored + +var once = require('once') + +function glob (pattern, options, cb) { + if (typeof options === 'function') cb = options, options = {} + if (!options) options = {} + + if (options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return globSync(pattern, options) + } + + return new Glob(pattern, options, cb) +} + +glob.sync = globSync +var GlobSync = glob.GlobSync = globSync.GlobSync + +// old api surface +glob.glob = glob + +glob.hasMagic = function (pattern, options_) { + var options = util._extend({}, options_) + options.noprocess = true + + var g = new Glob(pattern, options) + var set = g.minimatch.set + if (set.length > 1) + return true + + for (var j = 0; j < set[0].length; j++) { + if (typeof set[0][j] !== 'string') + return true + } + + return false +} + +glob.Glob = Glob +inherits(Glob, EE) +function Glob (pattern, options, cb) { + if (typeof options === 'function') { + cb = options + options = null + } + + if (options && options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return new GlobSync(pattern, options) + } + + if (!(this instanceof Glob)) + return new Glob(pattern, options, cb) + + setopts(this, pattern, options) + this._didRealPath = false + + // process each pattern in the minimatch set + var n = this.minimatch.set.length + + // The matches are stored as {: true,...} so that + // duplicates are automagically pruned. + // Later, we do an Object.keys() on these. + // Keep them as a list so we can fill in when nonull is set. + this.matches = new Array(n) + + if (typeof cb === 'function') { + cb = once(cb) + this.on('error', cb) + this.on('end', function (matches) { + cb(null, matches) + }) + } + + var self = this + var n = this.minimatch.set.length + this._processing = 0 + this.matches = new Array(n) + + this._emitQueue = [] + this._processQueue = [] + this.paused = false + + if (this.noprocess) + return this + + if (n === 0) + return done() + + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false, done) + } + + function done () { + --self._processing + if (self._processing <= 0) + self._finish() + } +} + +Glob.prototype._finish = function () { + assert(this instanceof Glob) + if (this.aborted) + return + + if (this.realpath && !this._didRealpath) + return this._realpath() + + common.finish(this) + this.emit('end', this.found) +} + +Glob.prototype._realpath = function () { + if (this._didRealpath) + return + + this._didRealpath = true + + var n = this.matches.length + if (n === 0) + return this._finish() + + var self = this + for (var i = 0; i < this.matches.length; i++) + this._realpathSet(i, next) + + function next () { + if (--n === 0) + self._finish() + } +} + +Glob.prototype._realpathSet = function (index, cb) { + var matchset = this.matches[index] + if (!matchset) + return cb() + + var found = Object.keys(matchset) + var self = this + var n = found.length + + if (n === 0) + return cb() + + var set = this.matches[index] = Object.create(null) + found.forEach(function (p, i) { + // If there's a problem with the stat, then it means that + // one or more of the links in the realpath couldn't be + // resolved. just return the abs value in that case. + p = self._makeAbs(p) + fs.realpath(p, self.realpathCache, function (er, real) { + if (!er) + set[real] = true + else if (er.syscall === 'stat') + set[p] = true + else + self.emit('error', er) // srsly wtf right here + + if (--n === 0) { + self.matches[index] = set + cb() + } + }) + }) +} + +Glob.prototype._mark = function (p) { + return common.mark(this, p) +} + +Glob.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} + +Glob.prototype.abort = function () { + this.aborted = true + this.emit('abort') +} + +Glob.prototype.pause = function () { + if (!this.paused) { + this.paused = true + this.emit('pause') + } +} + +Glob.prototype.resume = function () { + if (this.paused) { + this.emit('resume') + this.paused = false + if (this._emitQueue.length) { + var eq = this._emitQueue.slice(0) + this._emitQueue.length = 0 + for (var i = 0; i < eq.length; i ++) { + var e = eq[i] + this._emitMatch(e[0], e[1]) + } + } + if (this._processQueue.length) { + var pq = this._processQueue.slice(0) + this._processQueue.length = 0 + for (var i = 0; i < pq.length; i ++) { + var p = pq[i] + this._processing-- + this._process(p[0], p[1], p[2], p[3]) + } + } + } +} + +Glob.prototype._process = function (pattern, index, inGlobStar, cb) { + assert(this instanceof Glob) + assert(typeof cb === 'function') + + if (this.aborted) + return + + this._processing++ + if (this.paused) { + this._processQueue.push([pattern, index, inGlobStar, cb]) + return + } + + //console.error('PROCESS %d', this._processing, pattern) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // see if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index, cb) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip _processing + if (childrenIgnored(this, read)) + return cb() + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb) +} + +Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + +Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return cb() + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries) + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return cb() + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this._emitMatch(index, e) + } + // This was the last one, and no stats were needed + return cb() + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + this._process([e].concat(remain), index, inGlobStar, cb) + } + cb() +} + +Glob.prototype._emitMatch = function (index, e) { + if (this.aborted) + return + + if (this.matches[index][e]) + return + + if (isIgnored(this, e)) + return + + if (this.paused) { + this._emitQueue.push([index, e]) + return + } + + var abs = this._makeAbs(e) + + if (this.nodir) { + var c = this.cache[abs] + if (c === 'DIR' || Array.isArray(c)) + return + } + + if (this.mark) + e = this._mark(e) + + this.matches[index][e] = true + + var st = this.statCache[abs] + if (st) + this.emit('stat', e, st) + + this.emit('match', e) +} + +Glob.prototype._readdirInGlobStar = function (abs, cb) { + if (this.aborted) + return + + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false, cb) + + var lstatkey = 'lstat\0' + abs + var self = this + var lstatcb = inflight(lstatkey, lstatcb_) + + if (lstatcb) + fs.lstat(abs, lstatcb) + + function lstatcb_ (er, lstat) { + if (er) + return cb() + + var isSym = lstat.isSymbolicLink() + self.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && !lstat.isDirectory()) { + self.cache[abs] = 'FILE' + cb() + } else + self._readdir(abs, false, cb) + } +} + +Glob.prototype._readdir = function (abs, inGlobStar, cb) { + if (this.aborted) + return + + cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb) + if (!cb) + return + + //console.error('RD %j %j', +inGlobStar, abs) + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs, cb) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return cb() + + if (Array.isArray(c)) + return cb(null, c) + } + + var self = this + fs.readdir(abs, readdirCb(this, abs, cb)) +} + +function readdirCb (self, abs, cb) { + return function (er, entries) { + if (er) + self._readdirError(abs, er, cb) + else + self._readdirEntries(abs, entries, cb) + } +} + +Glob.prototype._readdirEntries = function (abs, entries, cb) { + if (this.aborted) + return + + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + return cb(null, entries) +} + +Glob.prototype._readdirError = function (f, er, cb) { + if (this.aborted) + return + + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + this.cache[this._makeAbs(f)] = 'FILE' + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) { + this.emit('error', er) + // If the error is handled, then we abort + // if not, we threw out of here + this.abort() + } + if (!this.silent) + console.error('glob error', er) + break + } + + return cb() +} + +Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + + +Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + //console.error('pgs2', prefix, remain[0], entries) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return cb() + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false, cb) + + var isSym = this.symlinks[abs] + var len = entries.length + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return cb() + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true, cb) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true, cb) + } + + cb() +} + +Glob.prototype._processSimple = function (prefix, index, cb) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var self = this + this._stat(prefix, function (er, exists) { + self._processSimple2(prefix, index, er, exists, cb) + }) +} +Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) { + + //console.error('ps2', prefix, exists) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return cb() + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this._emitMatch(index, prefix) + cb() +} + +// Returns either 'DIR', 'FILE', or false +Glob.prototype._stat = function (f, cb) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return cb() + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return cb(null, c) + + if (needDir && c === 'FILE') + return cb() + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (stat !== undefined) { + if (stat === false) + return cb(null, stat) + else { + var type = stat.isDirectory() ? 'DIR' : 'FILE' + if (needDir && type === 'FILE') + return cb() + else + return cb(null, type, stat) + } + } + + var self = this + var statcb = inflight('stat\0' + abs, lstatcb_) + if (statcb) + fs.lstat(abs, statcb) + + function lstatcb_ (er, lstat) { + if (lstat && lstat.isSymbolicLink()) { + // If it's a symlink, then treat it as the target, unless + // the target does not exist, then treat it as a file. + return fs.stat(abs, function (er, stat) { + if (er) + self._stat2(f, abs, null, lstat, cb) + else + self._stat2(f, abs, er, stat, cb) + }) + } else { + self._stat2(f, abs, er, lstat, cb) + } + } +} + +Glob.prototype._stat2 = function (f, abs, er, stat, cb) { + if (er) { + this.statCache[abs] = false + return cb() + } + + var needDir = f.slice(-1) === '/' + this.statCache[abs] = stat + + if (abs.slice(-1) === '/' && !stat.isDirectory()) + return cb(null, false, stat) + + var c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + + if (needDir && c !== 'DIR') + return cb() + + return cb(null, c, stat) +} + +}).call(this,require('_process')) +},{"./common.js":15,"./sync.js":17,"_process":24,"assert":9,"events":14,"fs":12,"inflight":18,"inherits":19,"minimatch":20,"once":21,"path":22,"path-is-absolute":23,"util":28}],17:[function(require,module,exports){ +(function (process){ +module.exports = globSync +globSync.GlobSync = GlobSync + +var fs = require('fs') +var minimatch = require('minimatch') +var Minimatch = minimatch.Minimatch +var Glob = require('./glob.js').Glob +var util = require('util') +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path-is-absolute') +var common = require('./common.js') +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var childrenIgnored = common.childrenIgnored + +function globSync (pattern, options) { + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') + + return new GlobSync(pattern, options).found +} + +function GlobSync (pattern, options) { + if (!pattern) + throw new Error('must provide pattern') + + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') + + if (!(this instanceof GlobSync)) + return new GlobSync(pattern, options) + + setopts(this, pattern, options) + + if (this.noprocess) + return this + + var n = this.minimatch.set.length + this.matches = new Array(n) + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false) + } + this._finish() +} + +GlobSync.prototype._finish = function () { + assert(this instanceof GlobSync) + if (this.realpath) { + var self = this + this.matches.forEach(function (matchset, index) { + var set = self.matches[index] = Object.create(null) + for (var p in matchset) { + try { + p = self._makeAbs(p) + var real = fs.realpathSync(p, self.realpathCache) + set[real] = true + } catch (er) { + if (er.syscall === 'stat') + set[self._makeAbs(p)] = true + else + throw er + } + } + }) + } + common.finish(this) +} + + +GlobSync.prototype._process = function (pattern, index, inGlobStar) { + assert(this instanceof GlobSync) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // See if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip processing + if (childrenIgnored(this, read)) + return + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar) +} + + +GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) { + var entries = this._readdir(abs, inGlobStar) + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix.slice(-1) !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this.matches[index][e] = true + } + // This was the last one, and no stats were needed + return + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) + newPattern = [prefix, e] + else + newPattern = [e] + this._process(newPattern.concat(remain), index, inGlobStar) + } +} + + +GlobSync.prototype._emitMatch = function (index, e) { + var abs = this._makeAbs(e) + if (this.mark) + e = this._mark(e) + + if (this.matches[index][e]) + return + + if (this.nodir) { + var c = this.cache[this._makeAbs(e)] + if (c === 'DIR' || Array.isArray(c)) + return + } + + this.matches[index][e] = true + if (this.stat) + this._stat(e) +} + + +GlobSync.prototype._readdirInGlobStar = function (abs) { + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false) + + var entries + var lstat + var stat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + // lstat failed, doesn't exist + return null + } + + var isSym = lstat.isSymbolicLink() + this.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && !lstat.isDirectory()) + this.cache[abs] = 'FILE' + else + entries = this._readdir(abs, false) + + return entries +} + +GlobSync.prototype._readdir = function (abs, inGlobStar) { + var entries + + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return null + + if (Array.isArray(c)) + return c + } + + try { + return this._readdirEntries(abs, fs.readdirSync(abs)) + } catch (er) { + this._readdirError(abs, er) + return null + } +} + +GlobSync.prototype._readdirEntries = function (abs, entries) { + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + + // mark and cache dir-ness + return entries +} + +GlobSync.prototype._readdirError = function (f, er) { + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + this.cache[this._makeAbs(f)] = 'FILE' + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) + throw er + if (!this.silent) + console.error('glob error', er) + break + } +} + +GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) { + + var entries = this._readdir(abs, inGlobStar) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false) + + var len = entries.length + var isSym = this.symlinks[abs] + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true) + } +} + +GlobSync.prototype._processSimple = function (prefix, index) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var exists = this._stat(prefix) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this.matches[index][prefix] = true +} + +// Returns either 'DIR', 'FILE', or false +GlobSync.prototype._stat = function (f) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return false + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return c + + if (needDir && c === 'FILE') + return false + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (!stat) { + var lstat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + return false + } + + if (lstat.isSymbolicLink()) { + try { + stat = fs.statSync(abs) + } catch (er) { + stat = lstat + } + } else { + stat = lstat + } + } + + this.statCache[abs] = stat + + var c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + + if (needDir && c !== 'DIR') + return false + + return c +} + +GlobSync.prototype._mark = function (p) { + return common.mark(this, p) +} + +GlobSync.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} + +}).call(this,require('_process')) +},{"./common.js":15,"./glob.js":16,"_process":24,"assert":9,"fs":12,"minimatch":20,"path":22,"path-is-absolute":23,"util":28}],18:[function(require,module,exports){ +(function (process){ +var wrappy = require('wrappy') +var reqs = Object.create(null) +var once = require('once') + +module.exports = wrappy(inflight) + +function inflight (key, cb) { + if (reqs[key]) { + reqs[key].push(cb) + return null + } else { + reqs[key] = [cb] + return makeres(key) + } +} + +function makeres (key) { + return once(function RES () { + var cbs = reqs[key] + var len = cbs.length + var args = slice(arguments) + + // XXX It's somewhat ambiguous whether a new callback added in this + // pass should be queued for later execution if something in the + // list of callbacks throws, or if it should just be discarded. + // However, it's such an edge case that it hardly matters, and either + // choice is likely as surprising as the other. + // As it happens, we do go ahead and schedule it for later execution. + try { + for (var i = 0; i < len; i++) { + cbs[i].apply(null, args) + } + } finally { + if (cbs.length > len) { + // added more in the interim. + // de-zalgo, just in case, but don't call again. + cbs.splice(0, len) + process.nextTick(function () { + RES.apply(null, args) + }) + } else { + delete reqs[key] + } + } + }) +} + +function slice (args) { + var length = args.length + var array = [] + + for (var i = 0; i < length; i++) array[i] = args[i] + return array +} + +}).call(this,require('_process')) +},{"_process":24,"once":21,"wrappy":29}],19:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],20:[function(require,module,exports){ +module.exports = minimatch +minimatch.Minimatch = Minimatch + +var path = { sep: '/' } +try { + path = require('path') +} catch (er) {} + +var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} +var expand = require('brace-expansion') + +var plTypes = { + '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, + '?': { open: '(?:', close: ')?' }, + '+': { open: '(?:', close: ')+' }, + '*': { open: '(?:', close: ')*' }, + '@': { open: '(?:', close: ')' } +} + +// any single thing other than / +// don't need to escape / when using new RegExp() +var qmark = '[^/]' + +// * => any number of characters +var star = qmark + '*?' + +// ** when dots are allowed. Anything goes, except .. and . +// not (^ or / followed by one or two dots followed by $ or /), +// followed by anything, any number of times. +var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?' + +// not a ^ or / followed by a dot, +// followed by anything, any number of times. +var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?' + +// characters that need to be escaped in RegExp. +var reSpecials = charSet('().*{}+?[]^$\\!') + +// "abc" -> { a:true, b:true, c:true } +function charSet (s) { + return s.split('').reduce(function (set, c) { + set[c] = true + return set + }, {}) +} + +// normalizes slashes. +var slashSplit = /\/+/ + +minimatch.filter = filter +function filter (pattern, options) { + options = options || {} + return function (p, i, list) { + return minimatch(p, pattern, options) + } +} + +function ext (a, b) { + a = a || {} + b = b || {} + var t = {} + Object.keys(b).forEach(function (k) { + t[k] = b[k] + }) + Object.keys(a).forEach(function (k) { + t[k] = a[k] + }) + return t +} + +minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return minimatch + + var orig = minimatch + + var m = function minimatch (p, pattern, options) { + return orig.minimatch(p, pattern, ext(def, options)) + } + + m.Minimatch = function Minimatch (pattern, options) { + return new orig.Minimatch(pattern, ext(def, options)) + } + + return m +} + +Minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return Minimatch + return minimatch.defaults(def).Minimatch +} + +function minimatch (p, pattern, options) { + if (typeof pattern !== 'string') { + throw new TypeError('glob pattern string required') + } + + if (!options) options = {} + + // shortcut: comments match nothing. + if (!options.nocomment && pattern.charAt(0) === '#') { + return false + } + + // "" only matches "" + if (pattern.trim() === '') return p === '' + + return new Minimatch(pattern, options).match(p) +} + +function Minimatch (pattern, options) { + if (!(this instanceof Minimatch)) { + return new Minimatch(pattern, options) + } + + if (typeof pattern !== 'string') { + throw new TypeError('glob pattern string required') + } + + if (!options) options = {} + pattern = pattern.trim() + + // windows support: need to use /, not \ + if (path.sep !== '/') { + pattern = pattern.split(path.sep).join('/') + } + + this.options = options + this.set = [] + this.pattern = pattern + this.regexp = null + this.negate = false + this.comment = false + this.empty = false + + // make the set of regexps etc. + this.make() +} + +Minimatch.prototype.debug = function () {} + +Minimatch.prototype.make = make +function make () { + // don't do it more than once. + if (this._made) return + + var pattern = this.pattern + var options = this.options + + // empty patterns and comments match nothing. + if (!options.nocomment && pattern.charAt(0) === '#') { + this.comment = true + return + } + if (!pattern) { + this.empty = true + return + } + + // step 1: figure out negation, etc. + this.parseNegate() + + // step 2: expand braces + var set = this.globSet = this.braceExpand() + + if (options.debug) this.debug = console.error + + this.debug(this.pattern, set) + + // step 3: now we have a set, so turn each one into a series of path-portion + // matching patterns. + // These will be regexps, except in the case of "**", which is + // set to the GLOBSTAR object for globstar behavior, + // and will not contain any / characters + set = this.globParts = set.map(function (s) { + return s.split(slashSplit) + }) + + this.debug(this.pattern, set) + + // glob --> regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) + + this.debug(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return s.indexOf(false) === -1 + }) + + this.debug(this.pattern, set) + + this.set = set +} + +Minimatch.prototype.parseNegate = parseNegate +function parseNegate () { + var pattern = this.pattern + var negate = false + var options = this.options + var negateOffset = 0 + + if (options.nonegate) return + + for (var i = 0, l = pattern.length + ; i < l && pattern.charAt(i) === '!' + ; i++) { + negate = !negate + negateOffset++ + } + + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate +} + +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = function (pattern, options) { + return braceExpand(pattern, options) +} + +Minimatch.prototype.braceExpand = braceExpand + +function braceExpand (pattern, options) { + if (!options) { + if (this instanceof Minimatch) { + options = this.options + } else { + options = {} + } + } + + pattern = typeof pattern === 'undefined' + ? this.pattern : pattern + + if (typeof pattern === 'undefined') { + throw new TypeError('undefined pattern') + } + + if (options.nobrace || + !pattern.match(/\{.*\}/)) { + // shortcut. no need to expand. + return [pattern] + } + + return expand(pattern) +} + +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +Minimatch.prototype.parse = parse +var SUBPARSE = {} +function parse (pattern, isSub) { + if (pattern.length > 1024 * 64) { + throw new TypeError('pattern is too long') + } + + var options = this.options + + // shortcuts + if (!options.noglobstar && pattern === '**') return GLOBSTAR + if (pattern === '') return '' + + var re = '' + var hasMagic = !!options.nocase + var escaping = false + // ? => one single character + var patternListStack = [] + var negativeLists = [] + var stateChar + var inClass = false + var reClassStart = -1 + var classStart = -1 + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + var patternStart = pattern.charAt(0) === '.' ? '' // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))' + : '(?!\\.)' + var self = this + + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case '*': + re += star + hasMagic = true + break + case '?': + re += qmark + hasMagic = true + break + default: + re += '\\' + stateChar + break + } + self.debug('clearStateChar %j %j', stateChar, re) + stateChar = false + } + } + + for (var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i++) { + this.debug('%s\t%s %s %j', pattern, i, re, c) + + // skip over any that are escaped. + if (escaping && reSpecials[c]) { + re += '\\' + c + escaping = false + continue + } + + switch (c) { + case '/': + // completely not allowed, even escaped. + // Should already be path-split by now. + return false + + case '\\': + clearStateChar() + escaping = true + continue + + // the various stateChar values + // for the "extglob" stuff. + case '?': + case '*': + case '+': + case '@': + case '!': + this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c) + + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + this.debug(' in class') + if (c === '!' && i === classStart + 1) c = '^' + re += c + continue + } + + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + self.debug('call clearStateChar %j', stateChar) + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue + + case '(': + if (inClass) { + re += '(' + continue + } + + if (!stateChar) { + re += '\\(' + continue + } + + patternListStack.push({ + type: stateChar, + start: i - 1, + reStart: re.length, + open: plTypes[stateChar].open, + close: plTypes[stateChar].close + }) + // negation is (?:(?!js)[^/]*) + re += stateChar === '!' ? '(?:(?!(?:' : '(?:' + this.debug('plType %j %j', stateChar, re) + stateChar = false + continue + + case ')': + if (inClass || !patternListStack.length) { + re += '\\)' + continue + } + + clearStateChar() + hasMagic = true + var pl = patternListStack.pop() + // negation is (?:(?!js)[^/]*) + // The others are (?:) + re += pl.close + if (pl.type === '!') { + negativeLists.push(pl) + } + pl.reEnd = re.length + continue + + case '|': + if (inClass || !patternListStack.length || escaping) { + re += '\\|' + escaping = false + continue + } + + clearStateChar() + re += '|' + continue + + // these are mostly the same in regexp and glob + case '[': + // swallow any state-tracking char before the [ + clearStateChar() + + if (inClass) { + re += '\\' + c + continue + } + + inClass = true + classStart = i + reClassStart = re.length + re += c + continue + + case ']': + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += '\\' + c + escaping = false + continue + } + + // handle the case where we left a class open. + // "[z-a]" is valid, equivalent to "\[z-a\]" + if (inClass) { + // split where the last [ was, make sure we don't have + // an invalid re. if so, re-walk the contents of the + // would-be class to re-translate any characters that + // were passed through as-is + // TODO: It would probably be faster to determine this + // without a try/catch and a new RegExp, but it's tricky + // to do safely. For now, this is safe and works. + var cs = pattern.substring(classStart + 1, i) + try { + RegExp('[' + cs + ']') + } catch (er) { + // not a valid class! + var sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]' + hasMagic = hasMagic || sp[1] + inClass = false + continue + } + } + + // finish up the class. + hasMagic = true + inClass = false + re += c + continue + + default: + // swallow any state char that wasn't consumed + clearStateChar() + + if (escaping) { + // no need + escaping = false + } else if (reSpecials[c] + && !(c === '^' && inClass)) { + re += '\\' + } + + re += c + + } // switch + } // for + + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + cs = pattern.substr(classStart + 1) + sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + hasMagic = hasMagic || sp[1] + } + + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + pl.open.length) + this.debug('setting tail', re, pl) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) { + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = '\\' + } + + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + '|' + }) + + this.debug('tail=%j\n %s', tail, tail, pl, re) + var t = pl.type === '*' ? star + : pl.type === '?' ? qmark + : '\\' + pl.type + + hasMagic = true + re = re.slice(0, pl.reStart) + t + '\\(' + tail + } + + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += '\\\\' + } + + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + var addPatternStart = false + switch (re.charAt(0)) { + case '.': + case '[': + case '(': addPatternStart = true + } + + // Hack to work around lack of negative lookbehind in JS + // A pattern like: *.!(x).!(y|z) needs to ensure that a name + // like 'a.xyz.yz' doesn't match. So, the first negative + // lookahead, has to look ALL the way ahead, to the end of + // the pattern. + for (var n = negativeLists.length - 1; n > -1; n--) { + var nl = negativeLists[n] + + var nlBefore = re.slice(0, nl.reStart) + var nlFirst = re.slice(nl.reStart, nl.reEnd - 8) + var nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + var nlAfter = re.slice(nl.reEnd) + + nlLast += nlAfter + + // Handle nested stuff like *(*.js|!(*.json)), where open parens + // mean that we should *not* include the ) in the bit that is considered + // "after" the negated section. + var openParensBefore = nlBefore.split('(').length - 1 + var cleanAfter = nlAfter + for (i = 0; i < openParensBefore; i++) { + cleanAfter = cleanAfter.replace(/\)[+*?]?/, '') + } + nlAfter = cleanAfter + + var dollar = '' + if (nlAfter === '' && isSub !== SUBPARSE) { + dollar = '$' + } + var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast + re = newRe + } + + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== '' && hasMagic) { + re = '(?=.)' + re + } + + if (addPatternStart) { + re = patternStart + re + } + + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [re, hasMagic] + } + + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } + + var flags = options.nocase ? 'i' : '' + try { + var regExp = new RegExp('^' + re + '$', flags) + } catch (er) { + // If it was an invalid regular expression, then it can't match + // anything. This trick looks for a character after the end of + // the string, which is of course impossible, except in multi-line + // mode, but it's not a /m regex. + return new RegExp('$.') + } + + regExp._glob = pattern + regExp._src = re + + return regExp +} + +minimatch.makeRe = function (pattern, options) { + return new Minimatch(pattern, options || {}).makeRe() +} + +Minimatch.prototype.makeRe = makeRe +function makeRe () { + if (this.regexp || this.regexp === false) return this.regexp + + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + var set = this.set + + if (!set.length) { + this.regexp = false + return this.regexp + } + var options = this.options + + var twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + var flags = options.nocase ? 'i' : '' + + var re = set.map(function (pattern) { + return pattern.map(function (p) { + return (p === GLOBSTAR) ? twoStar + : (typeof p === 'string') ? regExpEscape(p) + : p._src + }).join('\\\/') + }).join('|') + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = '^(?:' + re + ')$' + + // can match anything, as long as it's not this. + if (this.negate) re = '^(?!' + re + ').*$' + + try { + this.regexp = new RegExp(re, flags) + } catch (ex) { + this.regexp = false + } + return this.regexp +} + +minimatch.match = function (list, pattern, options) { + options = options || {} + var mm = new Minimatch(pattern, options) + list = list.filter(function (f) { + return mm.match(f) + }) + if (mm.options.nonull && !list.length) { + list.push(pattern) + } + return list +} + +Minimatch.prototype.match = match +function match (f, partial) { + this.debug('match', f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === '' + + if (f === '/' && partial) return true + + var options = this.options + + // windows: need to use /, not \ + if (path.sep !== '/') { + f = f.split(path.sep).join('/') + } + + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + this.debug(this.pattern, 'split', f) + + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. + + var set = this.set + this.debug(this.pattern, 'set', set) + + // Find the basename of the path by looking for the last non-empty segment + var filename + var i + for (i = f.length - 1; i >= 0; i--) { + filename = f[i] + if (filename) break + } + + for (i = 0; i < set.length; i++) { + var pattern = set[i] + var file = f + if (options.matchBase && pattern.length === 1) { + file = [filename] + } + var hit = this.matchOne(file, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate + } + } + + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate +} + +// set partial to true to test if, for example, +// "/a/b" matches the start of "/*/b/*/d" +// Partial means, if you run out of file before you run +// out of pattern, then that's fine, as long as all +// the parts match. +Minimatch.prototype.matchOne = function (file, pattern, partial) { + var options = this.options + + this.debug('matchOne', + { 'this': this, file: file, pattern: pattern }) + + this.debug('matchOne', file.length, pattern.length) + + for (var fi = 0, + pi = 0, + fl = file.length, + pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi++, pi++) { + this.debug('matchOne loop') + var p = pattern[pi] + var f = file[fi] + + this.debug(pattern, p, f) + + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false + + if (p === GLOBSTAR) { + this.debug('GLOBSTAR', [pattern, p, f]) + + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + var pr = pi + 1 + if (pr === pl) { + this.debug('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for (; fi < fl; fi++) { + if (file[fi] === '.' || file[fi] === '..' || + (!options.dot && file[fi].charAt(0) === '.')) return false + } + return true + } + + // ok, let's see if we can swallow whatever we can. + while (fr < fl) { + var swallowee = file[fr] + + this.debug('\nglobstar while', file, fr, pattern, pr, swallowee) + + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + this.debug('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === '.' || swallowee === '..' || + (!options.dot && swallowee.charAt(0) === '.')) { + this.debug('dot detected!', file, fr, pattern, pr) + break + } + + // ** swallows a segment, and continue. + this.debug('globstar swallow a segment, and continue') + fr++ + } + } + + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + if (partial) { + // ran out of file + this.debug('\n>>> no match, partial?', file, fr, pattern, pr) + if (fr === fl) return true + } + return false + } + + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === 'string') { + if (options.nocase) { + hit = f.toLowerCase() === p.toLowerCase() + } else { + hit = f === p + } + this.debug('string match', p, f, hit) + } else { + hit = f.match(p) + this.debug('pattern match', p, f, hit) + } + + if (!hit) return false + } + + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* + + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + var emptyFileEnd = (fi === fl - 1) && (file[fi] === '') + return emptyFileEnd + } + + // should be unreachable. + throw new Error('wtf?') +} + +// replace stuff like \* with * +function globUnescape (s) { + return s.replace(/\\(.)/g, '$1') +} + +function regExpEscape (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') +} + +},{"brace-expansion":11,"path":22}],21:[function(require,module,exports){ +var wrappy = require('wrappy') +module.exports = wrappy(once) +module.exports.strict = wrappy(onceStrict) + +once.proto = once(function () { + Object.defineProperty(Function.prototype, 'once', { + value: function () { + return once(this) + }, + configurable: true + }) + + Object.defineProperty(Function.prototype, 'onceStrict', { + value: function () { + return onceStrict(this) + }, + configurable: true + }) +}) + +function once (fn) { + var f = function () { + if (f.called) return f.value + f.called = true + return f.value = fn.apply(this, arguments) + } + f.called = false + return f +} + +function onceStrict (fn) { + var f = function () { + if (f.called) + throw new Error(f.onceError) + f.called = true + return f.value = fn.apply(this, arguments) + } + var name = fn.name || 'Function wrapped with `once`' + f.onceError = name + " shouldn't be called more than once" + f.called = false + return f +} + +},{"wrappy":29}],22:[function(require,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; + +}).call(this,require('_process')) +},{"_process":24}],23:[function(require,module,exports){ +(function (process){ +'use strict'; + +function posix(path) { + return path.charAt(0) === '/'; +} + +function win32(path) { + // https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56 + var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; + var result = splitDeviceRe.exec(path); + var device = result[1] || ''; + var isUnc = Boolean(device && device.charAt(1) !== ':'); + + // UNC paths are always absolute + return Boolean(result[2] || isUnc); +} + +module.exports = process.platform === 'win32' ? win32 : posix; +module.exports.posix = posix; +module.exports.win32 = win32; + +}).call(this,require('_process')) +},{"_process":24}],24:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],25:[function(require,module,exports){ +// Underscore.js 1.8.3 +// http://underscorejs.org +// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `exports` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var + push = ArrayProto.push, + slice = ArrayProto.slice, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind, + nativeCreate = Object.create; + + // Naked function reference for surrogate-prototype-swapping. + var Ctor = function(){}; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.8.3'; + + // Internal function that returns an efficient (for current engines) version + // of the passed-in callback, to be repeatedly applied in other Underscore + // functions. + var optimizeCb = function(func, context, argCount) { + if (context === void 0) return func; + switch (argCount == null ? 3 : argCount) { + case 1: return function(value) { + return func.call(context, value); + }; + case 2: return function(value, other) { + return func.call(context, value, other); + }; + case 3: return function(value, index, collection) { + return func.call(context, value, index, collection); + }; + case 4: return function(accumulator, value, index, collection) { + return func.call(context, accumulator, value, index, collection); + }; + } + return function() { + return func.apply(context, arguments); + }; + }; + + // A mostly-internal function to generate callbacks that can be applied + // to each element in a collection, returning the desired result — either + // identity, an arbitrary callback, a property matcher, or a property accessor. + var cb = function(value, context, argCount) { + if (value == null) return _.identity; + if (_.isFunction(value)) return optimizeCb(value, context, argCount); + if (_.isObject(value)) return _.matcher(value); + return _.property(value); + }; + _.iteratee = function(value, context) { + return cb(value, context, Infinity); + }; + + // An internal function for creating assigner functions. + var createAssigner = function(keysFunc, undefinedOnly) { + return function(obj) { + var length = arguments.length; + if (length < 2 || obj == null) return obj; + for (var index = 1; index < length; index++) { + var source = arguments[index], + keys = keysFunc(source), + l = keys.length; + for (var i = 0; i < l; i++) { + var key = keys[i]; + if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; + } + } + return obj; + }; + }; + + // An internal function for creating a new object that inherits from another. + var baseCreate = function(prototype) { + if (!_.isObject(prototype)) return {}; + if (nativeCreate) return nativeCreate(prototype); + Ctor.prototype = prototype; + var result = new Ctor; + Ctor.prototype = null; + return result; + }; + + var property = function(key) { + return function(obj) { + return obj == null ? void 0 : obj[key]; + }; + }; + + // Helper for collection methods to determine whether a collection + // should be iterated as an array or as an object + // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength + // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 + var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; + var getLength = property('length'); + var isArrayLike = function(collection) { + var length = getLength(collection); + return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; + }; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles raw objects in addition to array-likes. Treats all + // sparse array-likes as if they were dense. + _.each = _.forEach = function(obj, iteratee, context) { + iteratee = optimizeCb(iteratee, context); + var i, length; + if (isArrayLike(obj)) { + for (i = 0, length = obj.length; i < length; i++) { + iteratee(obj[i], i, obj); + } + } else { + var keys = _.keys(obj); + for (i = 0, length = keys.length; i < length; i++) { + iteratee(obj[keys[i]], keys[i], obj); + } + } + return obj; + }; + + // Return the results of applying the iteratee to each element. + _.map = _.collect = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + results = Array(length); + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + results[index] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + + // Create a reducing function iterating left or right. + function createReduce(dir) { + // Optimized iterator function as using arguments.length + // in the main function will deoptimize the, see #1991. + function iterator(obj, iteratee, memo, keys, index, length) { + for (; index >= 0 && index < length; index += dir) { + var currentKey = keys ? keys[index] : index; + memo = iteratee(memo, obj[currentKey], currentKey, obj); + } + return memo; + } + + return function(obj, iteratee, memo, context) { + iteratee = optimizeCb(iteratee, context, 4); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + index = dir > 0 ? 0 : length - 1; + // Determine the initial value if none is provided. + if (arguments.length < 3) { + memo = obj[keys ? keys[index] : index]; + index += dir; + } + return iterator(obj, iteratee, memo, keys, index, length); + }; + } + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. + _.reduce = _.foldl = _.inject = createReduce(1); + + // The right-associative version of reduce, also known as `foldr`. + _.reduceRight = _.foldr = createReduce(-1); + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, predicate, context) { + var key; + if (isArrayLike(obj)) { + key = _.findIndex(obj, predicate, context); + } else { + key = _.findKey(obj, predicate, context); + } + if (key !== void 0 && key !== -1) return obj[key]; + }; + + // Return all the elements that pass a truth test. + // Aliased as `select`. + _.filter = _.select = function(obj, predicate, context) { + var results = []; + predicate = cb(predicate, context); + _.each(obj, function(value, index, list) { + if (predicate(value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, predicate, context) { + return _.filter(obj, _.negate(cb(predicate)), context); + }; + + // Determine whether all of the elements match a truth test. + // Aliased as `all`. + _.every = _.all = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (!predicate(obj[currentKey], currentKey, obj)) return false; + } + return true; + }; + + // Determine if at least one element in the object matches a truth test. + // Aliased as `any`. + _.some = _.any = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (predicate(obj[currentKey], currentKey, obj)) return true; + } + return false; + }; + + // Determine if the array or object contains a given item (using `===`). + // Aliased as `includes` and `include`. + _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + if (typeof fromIndex != 'number' || guard) fromIndex = 0; + return _.indexOf(obj, item, fromIndex) >= 0; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + var func = isFunc ? method : value[method]; + return func == null ? func : func.apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, _.property(key)); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs) { + return _.filter(obj, _.matcher(attrs)); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.find(obj, _.matcher(attrs)); + }; + + // Return the maximum element (or element-based computation). + _.max = function(obj, iteratee, context) { + var result = -Infinity, lastComputed = -Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value > result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function(value, index, list) { + computed = iteratee(value, index, list); + if (computed > lastComputed || computed === -Infinity && result === -Infinity) { + result = value; + lastComputed = computed; + } + }); + } + return result; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iteratee, context) { + var result = Infinity, lastComputed = Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value < result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function(value, index, list) { + computed = iteratee(value, index, list); + if (computed < lastComputed || computed === Infinity && result === Infinity) { + result = value; + lastComputed = computed; + } + }); + } + return result; + }; + + // Shuffle a collection, using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). + _.shuffle = function(obj) { + var set = isArrayLike(obj) ? obj : _.values(obj); + var length = set.length; + var shuffled = Array(length); + for (var index = 0, rand; index < length; index++) { + rand = _.random(0, index); + if (rand !== index) shuffled[index] = shuffled[rand]; + shuffled[rand] = set[index]; + } + return shuffled; + }; + + // Sample **n** random values from a collection. + // If **n** is not specified, returns a single random element. + // The internal `guard` argument allows it to work with `map`. + _.sample = function(obj, n, guard) { + if (n == null || guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; + + // Sort the object's values by a criterion produced by an iteratee. + _.sortBy = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value: value, + index: index, + criteria: iteratee(value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(behavior) { + return function(obj, iteratee, context) { + var result = {}; + iteratee = cb(iteratee, context); + _.each(obj, function(value, index) { + var key = iteratee(value, index, obj); + behavior(result, value, key); + }); + return result; + }; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function(result, value, key) { + if (_.has(result, key)) result[key].push(value); else result[key] = [value]; + }); + + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function(result, value, key) { + result[key] = value; + }); + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function(result, value, key) { + if (_.has(result, key)) result[key]++; else result[key] = 1; + }); + + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (isArrayLike(obj)) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return isArrayLike(obj) ? obj.length : _.keys(obj).length; + }; + + // Split a collection into two arrays: one whose elements all satisfy the given + // predicate, and one whose elements all do not satisfy the predicate. + _.partition = function(obj, predicate, context) { + predicate = cb(predicate, context); + var pass = [], fail = []; + _.each(obj, function(value, key, obj) { + (predicate(value, key, obj) ? pass : fail).push(value); + }); + return [pass, fail]; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[0]; + return _.initial(array, array.length - n); + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. + _.initial = function(array, n, guard) { + return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[array.length - 1]; + return _.rest(array, Math.max(0, array.length - n)); + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, n == null || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, strict, startIndex) { + var output = [], idx = 0; + for (var i = startIndex || 0, length = getLength(input); i < length; i++) { + var value = input[i]; + if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { + //flatten current level of array or arguments object + if (!shallow) value = flatten(value, shallow, strict); + var j = 0, len = value.length; + output.length += len; + while (j < len) { + output[idx++] = value[j++]; + } + } else if (!strict) { + output[idx++] = value; + } + } + return output; + }; + + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function(array, shallow) { + return flatten(array, shallow, false); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iteratee, context) { + if (!_.isBoolean(isSorted)) { + context = iteratee; + iteratee = isSorted; + isSorted = false; + } + if (iteratee != null) iteratee = cb(iteratee, context); + var result = []; + var seen = []; + for (var i = 0, length = getLength(array); i < length; i++) { + var value = array[i], + computed = iteratee ? iteratee(value, i, array) : value; + if (isSorted) { + if (!i || seen !== computed) result.push(value); + seen = computed; + } else if (iteratee) { + if (!_.contains(seen, computed)) { + seen.push(computed); + result.push(value); + } + } else if (!_.contains(result, value)) { + result.push(value); + } + } + return result; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(flatten(arguments, true, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var result = []; + var argsLength = arguments.length; + for (var i = 0, length = getLength(array); i < length; i++) { + var item = array[i]; + if (_.contains(result, item)) continue; + for (var j = 1; j < argsLength; j++) { + if (!_.contains(arguments[j], item)) break; + } + if (j === argsLength) result.push(item); + } + return result; + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = flatten(arguments, true, true, 1); + return _.filter(array, function(value){ + return !_.contains(rest, value); + }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + return _.unzip(arguments); + }; + + // Complement of _.zip. Unzip accepts an array of arrays and groups + // each array's elements on shared indices + _.unzip = function(array) { + var length = array && _.max(array, getLength).length || 0; + var result = Array(length); + + for (var index = 0; index < length; index++) { + result[index] = _.pluck(array, index); + } + return result; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + var result = {}; + for (var i = 0, length = getLength(list); i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // Generator function to create the findIndex and findLastIndex functions + function createPredicateIndexFinder(dir) { + return function(array, predicate, context) { + predicate = cb(predicate, context); + var length = getLength(array); + var index = dir > 0 ? 0 : length - 1; + for (; index >= 0 && index < length; index += dir) { + if (predicate(array[index], index, array)) return index; + } + return -1; + }; + } + + // Returns the first index on an array-like that passes a predicate test + _.findIndex = createPredicateIndexFinder(1); + _.findLastIndex = createPredicateIndexFinder(-1); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iteratee, context) { + iteratee = cb(iteratee, context, 1); + var value = iteratee(obj); + var low = 0, high = getLength(array); + while (low < high) { + var mid = Math.floor((low + high) / 2); + if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; + } + return low; + }; + + // Generator function to create the indexOf and lastIndexOf functions + function createIndexFinder(dir, predicateFind, sortedIndex) { + return function(array, item, idx) { + var i = 0, length = getLength(array); + if (typeof idx == 'number') { + if (dir > 0) { + i = idx >= 0 ? idx : Math.max(idx + length, i); + } else { + length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; + } + } else if (sortedIndex && idx && length) { + idx = sortedIndex(array, item); + return array[idx] === item ? idx : -1; + } + if (item !== item) { + idx = predicateFind(slice.call(array, i, length), _.isNaN); + return idx >= 0 ? idx + i : -1; + } + for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { + if (array[idx] === item) return idx; + } + return -1; + }; + } + + // Return the position of the first occurrence of an item in an array, + // or -1 if the item is not included in the array. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); + _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (stop == null) { + stop = start || 0; + start = 0; + } + step = step || 1; + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var range = Array(length); + + for (var idx = 0; idx < length; idx++, start += step) { + range[idx] = start; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Determines whether to execute a function as a constructor + // or a normal function with the provided arguments + var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { + if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); + var self = baseCreate(sourceFunc.prototype); + var result = sourceFunc.apply(self, args); + if (_.isObject(result)) return result; + return self; + }; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); + var args = slice.call(arguments, 2); + var bound = function() { + return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); + }; + return bound; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. _ acts + // as a placeholder, allowing any combination of arguments to be pre-filled. + _.partial = function(func) { + var boundArgs = slice.call(arguments, 1); + var bound = function() { + var position = 0, length = boundArgs.length; + var args = Array(length); + for (var i = 0; i < length; i++) { + args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; + } + while (position < arguments.length) args.push(arguments[position++]); + return executeBound(func, bound, this, this, args); + }; + return bound; + }; + + // Bind a number of an object's methods to that object. Remaining arguments + // are the method names to be bound. Useful for ensuring that all callbacks + // defined on an object belong to it. + _.bindAll = function(obj) { + var i, length = arguments.length, key; + if (length <= 1) throw new Error('bindAll must be passed function names'); + for (i = 1; i < length; i++) { + key = arguments[i]; + obj[key] = _.bind(obj[key], obj); + } + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memoize = function(key) { + var cache = memoize.cache; + var address = '' + (hasher ? hasher.apply(this, arguments) : key); + if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); + return cache[address]; + }; + memoize.cache = {}; + return memoize; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ + return func.apply(null, args); + }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = _.partial(_.delay, _, 1); + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + if (!options) options = {}; + var later = function() { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + if (!timeout) context = args = null; + }; + return function() { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0 || remaining > wait) { + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + previous = now; + result = func.apply(context, args); + if (!timeout) context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; + + var later = function() { + var last = _.now() - timestamp; + + if (last < wait && last >= 0) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + if (!timeout) context = args = null; + } + } + }; + + return function() { + context = this; + args = arguments; + timestamp = _.now(); + var callNow = immediate && !timeout; + if (!timeout) timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + context = args = null; + } + + return result; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return _.partial(wrapper, func); + }; + + // Returns a negated version of the passed-in predicate. + _.negate = function(predicate) { + return function() { + return !predicate.apply(this, arguments); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var args = arguments; + var start = args.length - 1; + return function() { + var i = start; + var result = args[start].apply(this, arguments); + while (i--) result = args[i].call(this, result); + return result; + }; + }; + + // Returns a function that will only be executed on and after the Nth call. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Returns a function that will only be executed up to (but not including) the Nth call. + _.before = function(times, func) { + var memo; + return function() { + if (--times > 0) { + memo = func.apply(this, arguments); + } + if (times <= 1) func = null; + return memo; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = _.partial(_.before, 2); + + // Object Functions + // ---------------- + + // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. + var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); + var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', + 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; + + function collectNonEnumProps(obj, keys) { + var nonEnumIdx = nonEnumerableProps.length; + var constructor = obj.constructor; + var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto; + + // Constructor is a special case. + var prop = 'constructor'; + if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); + + while (nonEnumIdx--) { + prop = nonEnumerableProps[nonEnumIdx]; + if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { + keys.push(prop); + } + } + } + + // Retrieve the names of an object's own properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = function(obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve all the property names of an object. + _.allKeys = function(obj) { + if (!_.isObject(obj)) return []; + var keys = []; + for (var key in obj) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + + // Returns the results of applying the iteratee to each element of the object + // In contrast to _.map it returns an object + _.mapObject = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = _.keys(obj), + length = keys.length, + results = {}, + currentKey; + for (var index = 0; index < length; index++) { + currentKey = keys[index]; + results[currentKey] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = createAssigner(_.allKeys); + + // Assigns a given object with all the own properties in the passed-in object(s) + // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) + _.extendOwn = _.assign = createAssigner(_.keys); + + // Returns the first key on an object that passes a predicate test + _.findKey = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = _.keys(obj), key; + for (var i = 0, length = keys.length; i < length; i++) { + key = keys[i]; + if (predicate(obj[key], key, obj)) return key; + } + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(object, oiteratee, context) { + var result = {}, obj = object, iteratee, keys; + if (obj == null) return result; + if (_.isFunction(oiteratee)) { + keys = _.allKeys(obj); + iteratee = optimizeCb(oiteratee, context); + } else { + keys = flatten(arguments, false, false, 1); + iteratee = function(value, key, obj) { return key in obj; }; + obj = Object(obj); + } + for (var i = 0, length = keys.length; i < length; i++) { + var key = keys[i]; + var value = obj[key]; + if (iteratee(value, key, obj)) result[key] = value; + } + return result; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj, iteratee, context) { + if (_.isFunction(iteratee)) { + iteratee = _.negate(iteratee); + } else { + var keys = _.map(flatten(arguments, false, false, 1), String); + iteratee = function(value, key) { + return !_.contains(keys, key); + }; + } + return _.pick(obj, iteratee, context); + }; + + // Fill in a given object with default properties. + _.defaults = createAssigner(_.allKeys, true); + + // Creates an object that inherits from the given prototype object. + // If additional properties are provided then they will be added to the + // created object. + _.create = function(prototype, props) { + var result = baseCreate(prototype); + if (props) _.extendOwn(result, props); + return result; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Returns whether an object has a given set of `key:value` pairs. + _.isMatch = function(object, attrs) { + var keys = _.keys(attrs), length = keys.length; + if (object == null) return !length; + var obj = Object(object); + for (var i = 0; i < length; i++) { + var key = keys[i]; + if (attrs[key] !== obj[key] || !(key in obj)) return false; + } + return true; + }; + + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a === 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className !== toString.call(b)) return false; + switch (className) { + // Strings, numbers, regular expressions, dates, and booleans are compared by value. + case '[object RegExp]': + // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return '' + a === '' + b; + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. + // Object(NaN) is equivalent to NaN + if (+a !== +a) return +b !== +b; + // An `egal` comparison is performed for other numeric values. + return +a === 0 ? 1 / +a === 1 / b : +a === +b; + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a === +b; + } + + var areArrays = className === '[object Array]'; + if (!areArrays) { + if (typeof a != 'object' || typeof b != 'object') return false; + + // Objects with different constructors are not equivalent, but `Object`s or `Array`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && + _.isFunction(bCtor) && bCtor instanceof bCtor) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + } + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + + // Initializing stack of traversed objects. + // It's done here since we only need them for objects and arrays comparison. + aStack = aStack || []; + bStack = bStack || []; + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] === a) return bStack[length] === b; + } + + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + + // Recursively compare objects and arrays. + if (areArrays) { + // Compare array lengths to determine if a deep comparison is necessary. + length = a.length; + if (length !== b.length) return false; + // Deep compare the contents, ignoring non-numeric properties. + while (length--) { + if (!eq(a[length], b[length], aStack, bStack)) return false; + } + } else { + // Deep compare objects. + var keys = _.keys(a), key; + length = keys.length; + // Ensure that both objects contain the same number of properties before comparing deep equality. + if (_.keys(b).length !== length) return false; + while (length--) { + // Deep compare each member + key = keys[length]; + if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return true; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; + return _.keys(obj).length === 0; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) === '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + var type = typeof obj; + return type === 'function' || type === 'object' && !!obj; + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. + _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) === '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE < 9), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return _.has(obj, 'callee'); + }; + } + + // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, + // IE 11 (#1621), and in Safari 8 (#1929). + if (typeof /./ != 'function' && typeof Int8Array != 'object') { + _.isFunction = function(obj) { + return typeof obj == 'function' || false; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj !== +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return obj != null && hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iteratees. + _.identity = function(value) { + return value; + }; + + // Predicate-generating functions. Often useful outside of Underscore. + _.constant = function(value) { + return function() { + return value; + }; + }; + + _.noop = function(){}; + + _.property = property; + + // Generates a function for a given object that returns a given property. + _.propertyOf = function(obj) { + return obj == null ? function(){} : function(key) { + return obj[key]; + }; + }; + + // Returns a predicate for checking whether an object has a given set of + // `key:value` pairs. + _.matcher = _.matches = function(attrs) { + attrs = _.extendOwn({}, attrs); + return function(obj) { + return _.isMatch(obj, attrs); + }; + }; + + // Run a function **n** times. + _.times = function(n, iteratee, context) { + var accum = Array(Math.max(0, n)); + iteratee = optimizeCb(iteratee, context, 1); + for (var i = 0; i < n; i++) accum[i] = iteratee(i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // A (possibly faster) way to get the current timestamp as an integer. + _.now = Date.now || function() { + return new Date().getTime(); + }; + + // List of HTML entities for escaping. + var escapeMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' + }; + var unescapeMap = _.invert(escapeMap); + + // Functions for escaping and unescaping strings to/from HTML interpolation. + var createEscaper = function(map) { + var escaper = function(match) { + return map[match]; + }; + // Regexes for identifying a key that needs to be escaped + var source = '(?:' + _.keys(map).join('|') + ')'; + var testRegexp = RegExp(source); + var replaceRegexp = RegExp(source, 'g'); + return function(string) { + string = string == null ? '' : '' + string; + return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; + }; + }; + _.escape = createEscaper(escapeMap); + _.unescape = createEscaper(unescapeMap); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function(object, property, fallback) { + var value = object == null ? void 0 : object[property]; + if (value === void 0) { + value = fallback; + } + return _.isFunction(value) ? value.call(object) : value; + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\u2028|\u2029/g; + + var escapeChar = function(match) { + return '\\' + escapes[match]; + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + // NB: `oldSettings` only exists for backwards compatibility. + _.template = function(text, settings, oldSettings) { + if (!settings && oldSettings) settings = oldSettings; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset).replace(escaper, escapeChar); + index = offset + match.length; + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } else if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } else if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + + // Adobe VMs need the match returned to produce the correct offest. + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + 'return __p;\n'; + + try { + var render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled source as a convenience for precompilation. + var argument = settings.variable || 'obj'; + template.source = 'function(' + argument + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function. Start chaining a wrapped Underscore object. + _.chain = function(obj) { + var instance = _(obj); + instance._chain = true; + return instance; + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(instance, obj) { + return instance._chain ? _(obj).chain() : obj; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + _.each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result(this, func.apply(_, args)); + }; + }); + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; + return result(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + _.each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result(this, method.apply(this._wrapped, arguments)); + }; + }); + + // Extracts the result from a wrapped and chained object. + _.prototype.value = function() { + return this._wrapped; + }; + + // Provide unwrapping proxy for some methods used in engine operations + // such as arithmetic and JSON stringification. + _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; + + _.prototype.toString = function() { + return '' + this._wrapped; + }; + + // AMD registration happens at the end for compatibility with AMD loaders + // that may not enforce next-turn semantics on modules. Even though general + // practice for AMD registration is to be anonymous, underscore registers + // as a named module because, like jQuery, it is a base library that is + // popular enough to be bundled in a third party lib, but not be part of + // an AMD load request. Those cases could generate an error when an + // anonymous define() is called outside of a loader request. + if (typeof define === 'function' && define.amd) { + define('underscore', [], function() { + return _; + }); + } +}.call(this)); + +},{}],26:[function(require,module,exports){ +arguments[4][19][0].apply(exports,arguments) +},{"dup":19}],27:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],28:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = require('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":27,"_process":24,"inherits":26}],29:[function(require,module,exports){ +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy (fn, cb) { + if (fn && cb) return wrappy(fn)(cb) + + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') + + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] + }) + + return wrapper + + function wrapper() { + var args = new Array(arguments.length) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + var ret = fn.apply(this, args) + var cb = args[args.length-1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) + } + return ret + } +} + +},{}]},{},[7])(7) +}); \ No newline at end of file diff --git a/assets/javascripts/workers/search.c7c1ca2c.min.js b/assets/javascripts/workers/search.c7c1ca2c.min.js new file mode 100644 index 0000000..2d6f767 --- /dev/null +++ b/assets/javascripts/workers/search.c7c1ca2c.min.js @@ -0,0 +1,2 @@ +"use strict";(()=>{var xe=Object.create;var G=Object.defineProperty,ve=Object.defineProperties,Se=Object.getOwnPropertyDescriptor,Te=Object.getOwnPropertyDescriptors,Qe=Object.getOwnPropertyNames,J=Object.getOwnPropertySymbols,Ee=Object.getPrototypeOf,Z=Object.prototype.hasOwnProperty,be=Object.prototype.propertyIsEnumerable;var K=Math.pow,X=(t,e,r)=>e in t?G(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,_=(t,e)=>{for(var r in e||(e={}))Z.call(e,r)&&X(t,r,e[r]);if(J)for(var r of J(e))be.call(e,r)&&X(t,r,e[r]);return t},B=(t,e)=>ve(t,Te(e));var Le=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var we=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Qe(e))!Z.call(t,i)&&i!==r&&G(t,i,{get:()=>e[i],enumerable:!(n=Se(e,i))||n.enumerable});return t};var Pe=(t,e,r)=>(r=t!=null?xe(Ee(t)):{},we(e||!t||!t.__esModule?G(r,"default",{value:t,enumerable:!0}):r,t));var W=(t,e,r)=>new Promise((n,i)=>{var s=u=>{try{a(r.next(u))}catch(c){i(c)}},o=u=>{try{a(r.throw(u))}catch(c){i(c)}},a=u=>u.done?n(u.value):Promise.resolve(u.value).then(s,o);a((r=r.apply(t,e)).next())});var re=Le((ee,te)=>{(function(){var t=function(e){var r=new t.Builder;return r.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),r.searchPipeline.add(t.stemmer),e.call(r,r),r.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(r){e.console&&console.warn&&console.warn(r)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var r=Object.create(null),n=Object.keys(e),i=0;i0){var f=t.utils.clone(r)||{};f.position=[a,c],f.index=s.length,s.push(new t.Token(n.slice(a,o),f))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,r){r in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+r),e.label=r,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var r=e.label&&e.label in this.registeredFunctions;r||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. +`,e)},t.Pipeline.load=function(e){var r=new t.Pipeline;return e.forEach(function(n){var i=t.Pipeline.registeredFunctions[n];if(i)r.add(i);else throw new Error("Cannot load unregistered function: "+n)}),r},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(r){t.Pipeline.warnIfFunctionNotRegistered(r),this._stack.push(r)},this)},t.Pipeline.prototype.after=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");n=n+1,this._stack.splice(n,0,r)},t.Pipeline.prototype.before=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");this._stack.splice(n,0,r)},t.Pipeline.prototype.remove=function(e){var r=this._stack.indexOf(e);r!=-1&&this._stack.splice(r,1)},t.Pipeline.prototype.run=function(e){for(var r=this._stack.length,n=0;n1&&(oe&&(n=s),o!=e);)i=n-r,s=r+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ou?f+=2:a==u&&(r+=n[c+1]*i[f+1],c+=2,f+=2);return r},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),r=1,n=0;r0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}if(s.str.length==0&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var c=s.node.edges["*"];else{var c=new t.TokenSet;s.node.edges["*"]=c}s.str.length==1&&(c.final=!0),i.push({node:c,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var f=s.str.charAt(0),g=s.str.charAt(1),l;g in s.node.edges?l=s.node.edges[g]:(l=new t.TokenSet,s.node.edges[g]=l),s.str.length==1&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:f+s.str.slice(2)})}}}return n},t.TokenSet.fromString=function(e){for(var r=new t.TokenSet,n=r,i=0,s=e.length;i=e;r--){var n=this.uncheckedNodes[r],i=n.child.toString();i in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[i]:(n.child._str=i,this.minimizedNodes[i]=n.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(r){var n=new t.QueryParser(e,r);n.parse()})},t.Index.prototype.query=function(e){for(var r=new t.Query(this.fields),n=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,r){var n=e[this._ref],i=Object.keys(this._fields);this._documents[n]=r||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,r;do e=this.next(),r=e.charCodeAt(0);while(r>47&&r<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var r=e.next();if(r==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(r.charCodeAt(0)==92){e.escapeCharacter();continue}if(r==":")return t.QueryLexer.lexField;if(r=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(r=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(r=="+"&&e.width()===1||r=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(r.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,r){this.lexer=new t.QueryLexer(e),this.query=r,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var r=e.peekLexeme();if(r!=null)switch(r.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(n+=" with value '"+r.str+"'"),new t.QueryParseError(n,r.start,r.end)}},t.QueryParser.parsePresence=function(e){var r=e.consumeLexeme();if(r!=null){switch(r.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+r.str+"'";throw new t.QueryParseError(n,r.start,r.end)}var i=e.peekLexeme();if(i==null){var n="expecting term or field, found nothing";throw new t.QueryParseError(n,r.start,r.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(n,i.start,i.end)}}},t.QueryParser.parseField=function(e){var r=e.consumeLexeme();if(r!=null){if(e.query.allFields.indexOf(r.str)==-1){var n=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+r.str+"', possible fields: "+n;throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.fields=[r.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,r.start,r.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var r=e.consumeLexeme();if(r!=null){e.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(n==null){e.nextClause();return}switch(n.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+n.type+"'";throw new t.QueryParseError(i,n.start,n.end)}}},t.QueryParser.parseEditDistance=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="edit distance must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.editDistance=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="boost must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.boost=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,r){typeof define=="function"&&define.amd?define(r):typeof ee=="object"?te.exports=r():e.lunr=r()}(this,function(){return t})})()});var Y=Pe(re());function ne(t,e=document){let r=ke(t,e);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${t}" to be present`);return r}function ke(t,e=document){return e.querySelector(t)||void 0}Object.entries||(Object.entries=function(t){let e=[];for(let r of Object.keys(t))e.push([r,t[r]]);return e});Object.values||(Object.values=function(t){let e=[];for(let r of Object.keys(t))e.push(t[r]);return e});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(t,e){typeof t=="object"?(this.scrollLeft=t.left,this.scrollTop=t.top):(this.scrollLeft=t,this.scrollTop=e)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...t){let e=this.parentNode;if(e){t.length===0&&e.removeChild(this);for(let r=t.length-1;r>=0;r--){let n=t[r];typeof n=="string"?n=document.createTextNode(n):n.parentNode&&n.parentNode.removeChild(n),r?e.insertBefore(this.previousSibling,n):e.replaceChild(n,this)}}}));function ie(t){let e=new Map;for(let r of t){let[n]=r.location.split("#"),i=e.get(n);typeof i=="undefined"?e.set(n,r):(e.set(r.location,r),r.parent=i)}return e}function H(t,e,r){var s;e=new RegExp(e,"g");let n,i=0;do{n=e.exec(t);let o=(s=n==null?void 0:n.index)!=null?s:t.length;if(in?e(r,1,n,n=i):t.charAt(i)===">"&&(t.charAt(n+1)==="/"?--s===0&&e(r++,2,n,i+1):t.charAt(i-1)!=="/"&&s++===0&&e(r,0,n,i+1),n=i+1);i>n&&e(r,1,n,i)}function oe(t,e,r,n=!1){return q([t],e,r,n).pop()}function q(t,e,r,n=!1){let i=[0];for(let s=1;s>>2&1023,c=a[0]>>>12;i.push(+(u>c)+i[i.length-1])}return t.map((s,o)=>{let a=0,u=new Map;for(let f of r.sort((g,l)=>g-l)){let g=f&1048575,l=f>>>20;if(i[l]!==o)continue;let m=u.get(l);typeof m=="undefined"&&u.set(l,m=[]),m.push(g)}if(u.size===0)return s;let c=[];for(let[f,g]of u){let l=e[f],m=l[0]>>>12,x=l[l.length-1]>>>12,v=l[l.length-1]>>>2&1023;n&&m>a&&c.push(s.slice(a,m));let d=s.slice(m,x+v);for(let y of g.sort((b,E)=>E-b)){let b=(l[y]>>>12)-m,E=(l[y]>>>2&1023)+b;d=[d.slice(0,b),"",d.slice(b,E),"",d.slice(E)].join("")}if(a=x+v,c.push(d)===2)break}return n&&a{var f;switch(i[f=o+=s]||(i[f]=[]),a){case 0:case 2:i[o].push(u<<12|c-u<<2|a);break;case 1:let g=r[n].slice(u,c);H(g,lunr.tokenizer.separator,(l,m)=>{if(typeof lunr.segmenter!="undefined"){let x=g.slice(l,m);if(/^[MHIK]$/.test(lunr.segmenter.ctype_(x))){let v=lunr.segmenter.segment(x);for(let d=0,y=0;dr){return t.trim().split(/"([^"]+)"/g).map((r,n)=>n&1?r.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g," +"):r).join("").replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g,"").split(/\s+/g).reduce((r,n)=>{let i=e(n);return[...r,...Array.isArray(i)?i:[i]]},[]).map(r=>/([~^]$)/.test(r)?`${r}1`:r).map(r=>/(^[+-]|[~^]\d+$)/.test(r)?r:`${r}*`).join(" ")}function ce(t){return ue(t,e=>{let r=[],n=new lunr.QueryLexer(e);n.run();for(let{type:i,str:s,start:o,end:a}of n.lexemes)switch(i){case"FIELD":["title","text","tags"].includes(s)||(e=[e.slice(0,a)," ",e.slice(a+1)].join(""));break;case"TERM":H(s,lunr.tokenizer.separator,(...u)=>{r.push([e.slice(0,o),s.slice(...u),e.slice(a)].join(""))})}return r})}function le(t){let e=new lunr.Query(["title","text","tags"]);new lunr.QueryParser(t,e).parse();for(let n of e.clauses)n.usePipeline=!0,n.term.startsWith("*")&&(n.wildcard=lunr.Query.wildcard.LEADING,n.term=n.term.slice(1)),n.term.endsWith("*")&&(n.wildcard=lunr.Query.wildcard.TRAILING,n.term=n.term.slice(0,-1));return e.clauses}function he(t,e){var i;let r=new Set(t),n={};for(let s=0;s0;){let o=i[--s];for(let u=1;un[o]-u&&(r.add(t.slice(o,o+u)),i[s++]=o+u);let a=o+n[o];n[a]&&ar=>{if(typeof r[e]=="undefined")return;let n=[r.location,e].join(":");return t.set(n,lunr.tokenizer.table=[]),r[e]}}function Re(t,e){let[r,n]=[new Set(t),new Set(e)];return[...new Set([...r].filter(i=>!n.has(i)))]}var U=class{constructor({config:e,docs:r,options:n}){let i=Oe(this.table=new Map);this.map=ie(r),this.options=n,this.index=lunr(function(){this.metadataWhitelist=["position"],this.b(0),e.lang.length===1&&e.lang[0]!=="en"?this.use(lunr[e.lang[0]]):e.lang.length>1&&this.use(lunr.multiLanguage(...e.lang)),this.tokenizer=ae,lunr.tokenizer.separator=new RegExp(e.separator),lunr.segmenter="TinySegmenter"in lunr?new lunr.TinySegmenter:void 0;let s=Re(["trimmer","stopWordFilter","stemmer"],e.pipeline);for(let o of e.lang.map(a=>a==="en"?lunr:lunr[a]))for(let a of s)this.pipeline.remove(o[a]),this.searchPipeline.remove(o[a]);this.ref("location");for(let[o,a]of Object.entries(e.fields))this.field(o,B(_({},a),{extractor:i(o)}));for(let o of r)this.add(o,{boost:o.boost})})}search(e){if(e=e.replace(new RegExp("\\p{sc=Han}+","gu"),s=>[...fe(s,this.index.invertedIndex)].join("* ")),e=ce(e),!e)return{items:[]};let r=le(e).filter(s=>s.presence!==lunr.Query.presence.PROHIBITED),n=this.index.search(e).reduce((s,{ref:o,score:a,matchData:u})=>{let c=this.map.get(o);if(typeof c!="undefined"){c=_({},c),c.tags&&(c.tags=[...c.tags]);let f=he(r,Object.keys(u.metadata));for(let l of this.index.fields){if(typeof c[l]=="undefined")continue;let m=[];for(let d of Object.values(u.metadata))typeof d[l]!="undefined"&&m.push(...d[l].position);if(!m.length)continue;let x=this.table.get([c.location,l].join(":")),v=Array.isArray(c[l])?q:oe;c[l]=v(c[l],x,m,l!=="text")}let g=+!c.parent+Object.values(f).filter(l=>l).length/Object.keys(f).length;s.push(B(_({},c),{score:a*(1+K(g,2)),terms:f}))}return s},[]).sort((s,o)=>o.score-s.score).reduce((s,o)=>{let a=this.map.get(o.location);if(typeof a!="undefined"){let u=a.parent?a.parent.location:a.location;s.set(u,[...s.get(u)||[],o])}return s},new Map);for(let[s,o]of n)if(!o.find(a=>a.location===s)){let a=this.map.get(s);o.push(B(_({},a),{score:0,terms:{}}))}let i;if(this.options.suggest){let s=this.index.query(o=>{for(let a of r)o.term(a.term,{fields:["title"],presence:lunr.Query.presence.REQUIRED,wildcard:lunr.Query.wildcard.TRAILING})});i=s.length?Object.keys(s[0].matchData.metadata):[]}return _({items:[...n.values()]},typeof i!="undefined"&&{suggest:i})}};var de;function Ie(t){return W(this,null,function*(){let e="../lunr";if(typeof parent!="undefined"&&"IFrameWorker"in parent){let n=ne("script[src]"),[i]=n.src.split("/worker");e=e.replace("..",i)}let r=[];for(let n of t.lang){switch(n){case"ja":r.push(`${e}/tinyseg.js`);break;case"hi":case"th":r.push(`${e}/wordcut.js`);break}n!=="en"&&r.push(`${e}/min/lunr.${n}.min.js`)}t.lang.length>1&&r.push(`${e}/min/lunr.multi.min.js`),r.length&&(yield importScripts(`${e}/min/lunr.stemmer.support.min.js`,...r))})}function Fe(t){return W(this,null,function*(){switch(t.type){case 0:return yield Ie(t.data.config),de=new U(t.data),{type:1};case 2:let e=t.data;try{return{type:3,data:de.search(e)}}catch(r){return console.warn(`Invalid query: ${e} \u2013 see https://bit.ly/2s3ChXG`),console.warn(r),{type:3,data:{items:[]}}}default:throw new TypeError("Invalid message type")}})}self.lunr=Y.default;Y.default.utils.warn=console.warn;addEventListener("message",t=>W(void 0,null,function*(){postMessage(yield Fe(t.data))}));})(); diff --git a/docs/assets/sfe_favicon.png b/assets/sfe_favicon.png similarity index 100% rename from docs/assets/sfe_favicon.png rename to assets/sfe_favicon.png diff --git a/assets/stylesheets/main.f15084e1.min.css b/assets/stylesheets/main.f15084e1.min.css new file mode 100644 index 0000000..c16bde4 --- /dev/null +++ b/assets/stylesheets/main.f15084e1.min.css @@ -0,0 +1 @@ +@charset "UTF-8";html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;box-sizing:border-box}*,:after,:before{box-sizing:inherit}@media (prefers-reduced-motion){*,:after,:before{transition:none!important}}body{margin:0}a,button,input,label{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}hr{border:0;box-sizing:initial;display:block;height:.05rem;overflow:visible;padding:0}small{font-size:80%}sub,sup{line-height:1em}img{border-style:none}table{border-collapse:initial;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{background:#0000;border:0;font-family:inherit;font-size:inherit;margin:0;padding:0}input{border:0;outline:none}:root{--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:#526cfe1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-scheme=default]{color-scheme:light}[data-md-color-scheme=default] img[src$="#gh-dark-mode-only"],[data-md-color-scheme=default] img[src$="#only-dark"]{display:none}:root,[data-md-color-scheme=default]{--md-hue:225deg;--md-default-fg-color:#000000de;--md-default-fg-color--light:#0000008a;--md-default-fg-color--lighter:#00000052;--md-default-fg-color--lightest:#00000012;--md-default-bg-color:#fff;--md-default-bg-color--light:#ffffffb3;--md-default-bg-color--lighter:#ffffff4d;--md-default-bg-color--lightest:#ffffff1f;--md-code-fg-color:#36464e;--md-code-bg-color:#f5f5f5;--md-code-bg-color--light:#f5f5f5b3;--md-code-bg-color--lighter:#f5f5f54d;--md-code-hl-color:#4287ff;--md-code-hl-color--light:#4287ff1a;--md-code-hl-number-color:#d52a2a;--md-code-hl-special-color:#db1457;--md-code-hl-function-color:#a846b9;--md-code-hl-constant-color:#6e59d9;--md-code-hl-keyword-color:#3f6ec6;--md-code-hl-string-color:#1c7d4d;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-del-color:#f5503d26;--md-typeset-ins-color:#0bd57026;--md-typeset-kbd-color:#fafafa;--md-typeset-kbd-accent-color:#fff;--md-typeset-kbd-border-color:#b8b8b8;--md-typeset-mark-color:#ffff0080;--md-typeset-table-color:#0000001f;--md-typeset-table-color--light:rgba(0,0,0,.035);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-warning-fg-color:#000000de;--md-warning-bg-color:#ff9;--md-footer-fg-color:#fff;--md-footer-fg-color--light:#ffffffb3;--md-footer-fg-color--lighter:#ffffff73;--md-footer-bg-color:#000000de;--md-footer-bg-color--dark:#00000052;--md-shadow-z1:0 0.2rem 0.5rem #0000000d,0 0 0.05rem #0000001a;--md-shadow-z2:0 0.2rem 0.5rem #0000001a,0 0 0.05rem #00000040;--md-shadow-z3:0 0.2rem 0.5rem #0003,0 0 0.05rem #00000059}.md-icon svg{fill:currentcolor;display:block;height:1.2rem;width:1.2rem}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;--md-text-font-family:var(--md-text-font,_),-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;--md-code-font-family:var(--md-code-font,_),SFMono-Regular,Consolas,Menlo,monospace}aside,body,input{font-feature-settings:"kern","liga";color:var(--md-typeset-color);font-family:var(--md-text-font-family)}code,kbd,pre{font-feature-settings:"kern";font-family:var(--md-code-font-family)}:root{--md-typeset-table-sort-icon:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--asc:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--desc:url('data:image/svg+xml;charset=utf-8,')}.md-typeset{-webkit-print-color-adjust:exact;color-adjust:exact;font-size:.8rem;line-height:1.6;overflow-wrap:break-word}@media print{.md-typeset{font-size:.68rem}}.md-typeset blockquote,.md-typeset dl,.md-typeset figure,.md-typeset ol,.md-typeset pre,.md-typeset ul{margin-bottom:1em;margin-top:1em}.md-typeset h1{color:var(--md-default-fg-color--light);font-size:2em;line-height:1.3;margin:0 0 1.25em}.md-typeset h1,.md-typeset h2{font-weight:300;letter-spacing:-.01em}.md-typeset h2{font-size:1.5625em;line-height:1.4;margin:1.6em 0 .64em}.md-typeset h3{font-size:1.25em;font-weight:400;letter-spacing:-.01em;line-height:1.5;margin:1.6em 0 .8em}.md-typeset h2+h3{margin-top:.8em}.md-typeset h4{font-weight:700;letter-spacing:-.01em;margin:1em 0}.md-typeset h5,.md-typeset h6{color:var(--md-default-fg-color--light);font-size:.8em;font-weight:700;letter-spacing:-.01em;margin:1.25em 0}.md-typeset h5{text-transform:uppercase}.md-typeset h5 code{text-transform:none}.md-typeset hr{border-bottom:.05rem solid var(--md-default-fg-color--lightest);display:flow-root;margin:1.5em 0}.md-typeset a{color:var(--md-typeset-a-color);word-break:break-word}.md-typeset a,.md-typeset a:before{transition:color 125ms}.md-typeset a:focus,.md-typeset a:hover{color:var(--md-accent-fg-color)}.md-typeset a:focus code,.md-typeset a:hover code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-typeset a code{color:var(--md-typeset-a-color)}.md-typeset a.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset code,.md-typeset kbd,.md-typeset pre{color:var(--md-code-fg-color);direction:ltr;font-variant-ligatures:none;transition:background-color 125ms}@media print{.md-typeset code,.md-typeset kbd,.md-typeset pre{white-space:pre-wrap}}.md-typeset code{background-color:var(--md-code-bg-color);border-radius:.1rem;-webkit-box-decoration-break:clone;box-decoration-break:clone;font-size:.85em;padding:0 .2941176471em;transition:color 125ms,background-color 125ms;word-break:break-word}.md-typeset code:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-typeset pre{display:flow-root;line-height:1.4;position:relative}.md-typeset pre>code{-webkit-box-decoration-break:slice;box-decoration-break:slice;box-shadow:none;display:block;margin:0;outline-color:var(--md-accent-fg-color);overflow:auto;padding:.7720588235em 1.1764705882em;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin;touch-action:auto;word-break:normal}.md-typeset pre>code:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-typeset pre>code::-webkit-scrollbar{height:.2rem;width:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}.md-typeset kbd{background-color:var(--md-typeset-kbd-color);border-radius:.1rem;box-shadow:0 .1rem 0 .05rem var(--md-typeset-kbd-border-color),0 .1rem 0 var(--md-typeset-kbd-border-color),0 -.1rem .2rem var(--md-typeset-kbd-accent-color) inset;color:var(--md-default-fg-color);display:inline-block;font-size:.75em;padding:0 .6666666667em;vertical-align:text-top;word-break:break-word}.md-typeset mark{background-color:var(--md-typeset-mark-color);-webkit-box-decoration-break:clone;box-decoration-break:clone;color:inherit;word-break:break-word}.md-typeset abbr{cursor:help;text-decoration:none}.md-typeset [data-preview],.md-typeset abbr{border-bottom:.05rem dotted var(--md-default-fg-color--light)}.md-typeset small{opacity:.75}[dir=ltr] .md-typeset sub,[dir=ltr] .md-typeset sup{margin-left:.078125em}[dir=rtl] .md-typeset sub,[dir=rtl] .md-typeset sup{margin-right:.078125em}[dir=ltr] .md-typeset blockquote{padding-left:.6rem}[dir=rtl] .md-typeset blockquote{padding-right:.6rem}[dir=ltr] .md-typeset blockquote{border-left:.2rem solid var(--md-default-fg-color--lighter)}[dir=rtl] .md-typeset blockquote{border-right:.2rem solid var(--md-default-fg-color--lighter)}.md-typeset blockquote{color:var(--md-default-fg-color--light);margin-left:0;margin-right:0}.md-typeset ul{list-style-type:disc}.md-typeset ul[type]{list-style-type:revert-layer}[dir=ltr] .md-typeset ol,[dir=ltr] .md-typeset ul{margin-left:.625em}[dir=rtl] .md-typeset ol,[dir=rtl] .md-typeset ul{margin-right:.625em}.md-typeset ol,.md-typeset ul{padding:0}.md-typeset ol:not([hidden]),.md-typeset ul:not([hidden]){display:flow-root}.md-typeset ol ol,.md-typeset ul ol{list-style-type:lower-alpha}.md-typeset ol ol ol,.md-typeset ul ol ol{list-style-type:lower-roman}.md-typeset ol ol ol ol,.md-typeset ul ol ol ol{list-style-type:upper-alpha}.md-typeset ol ol ol ol ol,.md-typeset ul ol ol ol ol{list-style-type:upper-roman}.md-typeset ol[type],.md-typeset ul[type]{list-style-type:revert-layer}[dir=ltr] .md-typeset ol li,[dir=ltr] .md-typeset ul li{margin-left:1.25em}[dir=rtl] .md-typeset ol li,[dir=rtl] .md-typeset ul li{margin-right:1.25em}.md-typeset ol li,.md-typeset ul li{margin-bottom:.5em}.md-typeset ol li blockquote,.md-typeset ol li p,.md-typeset ul li blockquote,.md-typeset ul li p{margin:.5em 0}.md-typeset ol li:last-child,.md-typeset ul li:last-child{margin-bottom:0}[dir=ltr] .md-typeset ol li ol,[dir=ltr] .md-typeset ol li ul,[dir=ltr] .md-typeset ul li ol,[dir=ltr] .md-typeset ul li ul{margin-left:.625em}[dir=rtl] .md-typeset ol li ol,[dir=rtl] .md-typeset ol li ul,[dir=rtl] .md-typeset ul li ol,[dir=rtl] .md-typeset ul li ul{margin-right:.625em}.md-typeset ol li ol,.md-typeset ol li ul,.md-typeset ul li ol,.md-typeset ul li ul{margin-bottom:.5em;margin-top:.5em}[dir=ltr] .md-typeset dd{margin-left:1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em}.md-typeset dd{margin-bottom:1.5em;margin-top:1em}.md-typeset img,.md-typeset svg,.md-typeset video{height:auto;max-width:100%}.md-typeset img[align=left]{margin:1em 1em 1em 0}.md-typeset img[align=right]{margin:1em 0 1em 1em}.md-typeset img[align]:only-child{margin-top:0}.md-typeset figure{display:flow-root;margin:1em auto;max-width:100%;text-align:center;width:-moz-fit-content;width:fit-content}.md-typeset figure img{display:block;margin:0 auto}.md-typeset figcaption{font-style:italic;margin:1em auto;max-width:24rem}.md-typeset iframe{max-width:100%}.md-typeset table:not([class]){background-color:var(--md-default-bg-color);border:.05rem solid var(--md-typeset-table-color);border-radius:.1rem;display:inline-block;font-size:.64rem;max-width:100%;overflow:auto;touch-action:auto}@media print{.md-typeset table:not([class]){display:table}}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) td>:first-child,.md-typeset table:not([class]) th>:first-child{margin-top:0}.md-typeset table:not([class]) td>:last-child,.md-typeset table:not([class]) th>:last-child{margin-bottom:0}.md-typeset table:not([class]) td:not([align]),.md-typeset table:not([class]) th:not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) td:not([align]),[dir=rtl] .md-typeset table:not([class]) th:not([align]){text-align:right}.md-typeset table:not([class]) th{font-weight:700;min-width:5rem;padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) td{border-top:.05rem solid var(--md-typeset-table-color);padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) tbody tr{transition:background-color 125ms}.md-typeset table:not([class]) tbody tr:hover{background-color:var(--md-typeset-table-color--light);box-shadow:0 .05rem 0 var(--md-default-bg-color) inset}.md-typeset table:not([class]) a{word-break:normal}.md-typeset table th[role=columnheader]{cursor:pointer}[dir=ltr] .md-typeset table th[role=columnheader]:after{margin-left:.5em}[dir=rtl] .md-typeset table th[role=columnheader]:after{margin-right:.5em}.md-typeset table th[role=columnheader]:after{content:"";display:inline-block;height:1.2em;-webkit-mask-image:var(--md-typeset-table-sort-icon);mask-image:var(--md-typeset-table-sort-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset table th[role=columnheader]:hover:after{background-color:var(--md-default-fg-color--lighter)}.md-typeset table th[role=columnheader][aria-sort=ascending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--asc);mask-image:var(--md-typeset-table-sort-icon--asc)}.md-typeset table th[role=columnheader][aria-sort=descending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--desc);mask-image:var(--md-typeset-table-sort-icon--desc)}.md-typeset__scrollwrap{margin:1em -.8rem;overflow-x:auto;touch-action:auto}.md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}@media print{.md-typeset__table{display:block}}html .md-typeset__table table{display:table;margin:0;overflow:hidden;width:100%}@media screen and (max-width:44.984375em){.md-content__inner>pre{margin:1em -.8rem}.md-content__inner>pre code{border-radius:0}}.md-typeset .md-author{border-radius:100%;display:block;flex-shrink:0;height:1.6rem;overflow:hidden;position:relative;transition:color 125ms,transform 125ms;width:1.6rem}.md-typeset .md-author img{display:block}.md-typeset .md-author--more{background:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--lighter);font-size:.6rem;font-weight:700;line-height:1.6rem;text-align:center}.md-typeset .md-author--long{height:2.4rem;width:2.4rem}.md-typeset a.md-author{transform:scale(1)}.md-typeset a.md-author img{border-radius:100%;filter:grayscale(100%) opacity(75%);transition:filter 125ms}.md-typeset a.md-author:focus,.md-typeset a.md-author:hover{transform:scale(1.1);z-index:1}.md-typeset a.md-author:focus img,.md-typeset a.md-author:hover img{filter:grayscale(0)}.md-banner{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color);overflow:auto}@media print{.md-banner{display:none}}.md-banner--warning{background-color:var(--md-warning-bg-color);color:var(--md-warning-fg-color)}.md-banner__inner{font-size:.7rem;margin:.6rem auto;padding:0 .8rem}[dir=ltr] .md-banner__button{float:right}[dir=rtl] .md-banner__button{float:left}.md-banner__button{color:inherit;cursor:pointer;transition:opacity .25s}.no-js .md-banner__button{display:none}.md-banner__button:hover{opacity:.7}html{font-size:125%;height:100%;overflow-x:hidden}@media screen and (min-width:100em){html{font-size:137.5%}}@media screen and (min-width:125em){html{font-size:150%}}body{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;font-size:.5rem;min-height:100%;position:relative;width:100%}@media print{body{display:block}}@media screen and (max-width:59.984375em){body[data-md-scrolllock]{position:fixed}}.md-grid{margin-left:auto;margin-right:auto;max-width:61rem}.md-container{display:flex;flex-direction:column;flex-grow:1}@media print{.md-container{display:block}}.md-main{flex-grow:1}.md-main__inner{display:flex;height:100%;margin-top:1.5rem}.md-ellipsis{overflow:hidden;text-overflow:ellipsis}.md-toggle{display:none}.md-option{height:0;opacity:0;position:absolute;width:0}.md-option:checked+label:not([hidden]){display:block}.md-option.focus-visible+label{outline-color:var(--md-accent-fg-color);outline-style:auto}.md-skip{background-color:var(--md-default-fg-color);border-radius:.1rem;color:var(--md-default-bg-color);font-size:.64rem;margin:.5rem;opacity:0;outline-color:var(--md-accent-fg-color);padding:.3rem .5rem;position:fixed;transform:translateY(.4rem);z-index:-1}.md-skip:focus{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 175ms 75ms;z-index:10}@page{margin:25mm}:root{--md-clipboard-icon:url('data:image/svg+xml;charset=utf-8,')}.md-clipboard{border-radius:.1rem;color:var(--md-default-fg-color--lightest);cursor:pointer;height:1.5em;outline-color:var(--md-accent-fg-color);outline-offset:.1rem;transition:color .25s;width:1.5em;z-index:1}@media print{.md-clipboard{display:none}}.md-clipboard:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}:hover>.md-clipboard{color:var(--md-default-fg-color--light)}.md-clipboard:focus,.md-clipboard:hover{color:var(--md-accent-fg-color)}.md-clipboard:after{background-color:currentcolor;content:"";display:block;height:1.125em;margin:0 auto;-webkit-mask-image:var(--md-clipboard-icon);mask-image:var(--md-clipboard-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:1.125em}.md-clipboard--inline{cursor:pointer}.md-clipboard--inline code{transition:color .25s,background-color .25s}.md-clipboard--inline:focus code,.md-clipboard--inline:hover code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}:root{--md-code-select-icon:url('data:image/svg+xml;charset=utf-8,');--md-code-copy-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .md-code__content{display:grid}.md-code__nav{background-color:var(--md-code-bg-color--lighter);border-radius:.1rem;display:flex;gap:.2rem;padding:.2rem;position:absolute;right:.25em;top:.25em;transition:background-color .25s;z-index:1}:hover>.md-code__nav{background-color:var(--md-code-bg-color--light)}.md-code__button{color:var(--md-default-fg-color--lightest);cursor:pointer;display:block;height:1.5em;outline-color:var(--md-accent-fg-color);outline-offset:.1rem;transition:color .25s;width:1.5em}:hover>*>.md-code__button{color:var(--md-default-fg-color--light)}.md-code__button.focus-visible,.md-code__button:hover{color:var(--md-accent-fg-color)}.md-code__button--active{color:var(--md-default-fg-color)!important}.md-code__button:after{background-color:currentcolor;content:"";display:block;height:1.125em;margin:0 auto;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:1.125em}.md-code__button[data-md-type=select]:after{-webkit-mask-image:var(--md-code-select-icon);mask-image:var(--md-code-select-icon)}.md-code__button[data-md-type=copy]:after{-webkit-mask-image:var(--md-code-copy-icon);mask-image:var(--md-code-copy-icon)}@keyframes consent{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes overlay{0%{opacity:0}to{opacity:1}}.md-consent__overlay{animation:overlay .25s both;-webkit-backdrop-filter:blur(.1rem);backdrop-filter:blur(.1rem);background-color:#0000008a;height:100%;opacity:1;position:fixed;top:0;width:100%;z-index:5}.md-consent__inner{animation:consent .5s cubic-bezier(.1,.7,.1,1) both;background-color:var(--md-default-bg-color);border:0;border-radius:.1rem;bottom:0;box-shadow:0 0 .2rem #0000001a,0 .2rem .4rem #0003;max-height:100%;overflow:auto;padding:0;position:fixed;width:100%;z-index:5}.md-consent__form{padding:.8rem}.md-consent__settings{display:none;margin:1em 0}input:checked+.md-consent__settings{display:block}.md-consent__controls{margin-bottom:.8rem}.md-typeset .md-consent__controls .md-button{display:inline}@media screen and (max-width:44.984375em){.md-typeset .md-consent__controls .md-button{display:block;margin-top:.4rem;text-align:center;width:100%}}.md-consent label{cursor:pointer}.md-content{flex-grow:1;min-width:0}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}@media screen and (min-width:76.25em){[dir=ltr] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}[dir=ltr] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner,[dir=rtl] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem}[dir=rtl] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}}.md-content__inner:before{content:"";display:block;height:.4rem}.md-content__inner>:last-child{margin-bottom:0}[dir=ltr] .md-content__button{float:right}[dir=rtl] .md-content__button{float:left}[dir=ltr] .md-content__button{margin-left:.4rem}[dir=rtl] .md-content__button{margin-right:.4rem}.md-content__button{margin:.4rem 0;padding:0}@media print{.md-content__button{display:none}}.md-typeset .md-content__button{color:var(--md-default-fg-color--lighter)}.md-content__button svg{display:inline;vertical-align:top}[dir=rtl] .md-content__button svg{transform:scaleX(-1)}[dir=ltr] .md-dialog{right:.8rem}[dir=rtl] .md-dialog{left:.8rem}.md-dialog{background-color:var(--md-default-fg-color);border-radius:.1rem;bottom:.8rem;box-shadow:var(--md-shadow-z3);min-width:11.1rem;opacity:0;padding:.4rem .6rem;pointer-events:none;position:fixed;transform:translateY(100%);transition:transform 0ms .4s,opacity .4s;z-index:4}@media print{.md-dialog{display:none}}.md-dialog--active{opacity:1;pointer-events:auto;transform:translateY(0);transition:transform .4s cubic-bezier(.075,.85,.175,1),opacity .4s}.md-dialog__inner{color:var(--md-default-bg-color);font-size:.7rem}.md-feedback{margin:2em 0 1em;text-align:center}.md-feedback fieldset{border:none;margin:0;padding:0}.md-feedback__title{font-weight:700;margin:1em auto}.md-feedback__inner{position:relative}.md-feedback__list{display:flex;flex-wrap:wrap;place-content:baseline center;position:relative}.md-feedback__list:hover .md-icon:not(:disabled){color:var(--md-default-fg-color--lighter)}:disabled .md-feedback__list{min-height:1.8rem}.md-feedback__icon{color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;margin:0 .1rem;transition:color 125ms}.md-feedback__icon:not(:disabled).md-icon:hover{color:var(--md-accent-fg-color)}.md-feedback__icon:disabled{color:var(--md-default-fg-color--lightest);pointer-events:none}.md-feedback__note{opacity:0;position:relative;transform:translateY(.4rem);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-feedback__note>*{margin:0 auto;max-width:16rem}:disabled .md-feedback__note{opacity:1;transform:translateY(0)}@media print{.md-feedback{display:none}}.md-footer{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color)}@media print{.md-footer{display:none}}.md-footer__inner{justify-content:space-between;overflow:auto;padding:.2rem}.md-footer__inner:not([hidden]){display:flex}.md-footer__link{align-items:end;display:flex;flex-grow:0.01;margin-bottom:.4rem;margin-top:1rem;max-width:100%;outline-color:var(--md-accent-fg-color);overflow:hidden;transition:opacity .25s}.md-footer__link:focus,.md-footer__link:hover{opacity:.7}[dir=rtl] .md-footer__link svg{transform:scaleX(-1)}@media screen and (max-width:44.984375em){.md-footer__link--prev{flex-shrink:0}.md-footer__link--prev .md-footer__title{display:none}}[dir=ltr] .md-footer__link--next{margin-left:auto}[dir=rtl] .md-footer__link--next{margin-right:auto}.md-footer__link--next{text-align:right}[dir=rtl] .md-footer__link--next{text-align:left}.md-footer__title{flex-grow:1;font-size:.9rem;margin-bottom:.7rem;max-width:calc(100% - 2.4rem);padding:0 1rem;white-space:nowrap}.md-footer__button{margin:.2rem;padding:.4rem}.md-footer__direction{font-size:.64rem;opacity:.7}.md-footer-meta{background-color:var(--md-footer-bg-color--dark)}.md-footer-meta__inner{display:flex;flex-wrap:wrap;justify-content:space-between;padding:.2rem}html .md-footer-meta.md-typeset a{color:var(--md-footer-fg-color--light)}html .md-footer-meta.md-typeset a:focus,html .md-footer-meta.md-typeset a:hover{color:var(--md-footer-fg-color)}.md-copyright{color:var(--md-footer-fg-color--lighter);font-size:.64rem;margin:auto .6rem;padding:.4rem 0;width:100%}@media screen and (min-width:45em){.md-copyright{width:auto}}.md-copyright__highlight{color:var(--md-footer-fg-color--light)}.md-social{display:inline-flex;gap:.2rem;margin:0 .4rem;padding:.2rem 0 .6rem}@media screen and (min-width:45em){.md-social{padding:.6rem 0}}.md-social__link{display:inline-block;height:1.6rem;text-align:center;width:1.6rem}.md-social__link:before{line-height:1.9}.md-social__link svg{fill:currentcolor;max-height:.8rem;vertical-align:-25%}.md-typeset .md-button{border:.1rem solid;border-radius:.1rem;color:var(--md-primary-fg-color);cursor:pointer;display:inline-block;font-weight:700;padding:.625em 2em;transition:color 125ms,background-color 125ms,border-color 125ms}.md-typeset .md-button--primary{background-color:var(--md-primary-fg-color);border-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color)}.md-typeset .md-button:focus,.md-typeset .md-button:hover{background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[dir=ltr] .md-typeset .md-input{border-top-left-radius:.1rem}[dir=ltr] .md-typeset .md-input,[dir=rtl] .md-typeset .md-input{border-top-right-radius:.1rem}[dir=rtl] .md-typeset .md-input{border-top-left-radius:.1rem}.md-typeset .md-input{border-bottom:.1rem solid var(--md-default-fg-color--lighter);box-shadow:var(--md-shadow-z1);font-size:.8rem;height:1.8rem;padding:0 .6rem;transition:border .25s,box-shadow .25s}.md-typeset .md-input:focus,.md-typeset .md-input:hover{border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input--stretch{width:100%}.md-header{background-color:var(--md-primary-fg-color);box-shadow:0 0 .2rem #0000,0 .2rem .4rem #0000;color:var(--md-primary-bg-color);display:block;left:0;position:sticky;right:0;top:0;z-index:4}@media print{.md-header{display:none}}.md-header[hidden]{transform:translateY(-100%);transition:transform .25s cubic-bezier(.8,0,.6,1),box-shadow .25s}.md-header--shadow{box-shadow:0 0 .2rem #0000001a,0 .2rem .4rem #0003;transition:transform .25s cubic-bezier(.1,.7,.1,1),box-shadow .25s}.md-header__inner{align-items:center;display:flex;padding:0 .2rem}.md-header__button{color:currentcolor;cursor:pointer;margin:.2rem;outline-color:var(--md-accent-fg-color);padding:.4rem;position:relative;transition:opacity .25s;vertical-align:middle;z-index:1}.md-header__button:hover{opacity:.7}.md-header__button:not([hidden]){display:inline-block}.md-header__button:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-header__button.md-logo{margin:.2rem;padding:.4rem}@media screen and (max-width:76.234375em){.md-header__button.md-logo{display:none}}.md-header__button.md-logo img,.md-header__button.md-logo svg{fill:currentcolor;display:block;height:1.2rem;width:auto}@media screen and (min-width:60em){.md-header__button[for=__search]{display:none}}.no-js .md-header__button[for=__search]{display:none}[dir=rtl] .md-header__button[for=__search] svg{transform:scaleX(-1)}@media screen and (min-width:76.25em){.md-header__button[for=__drawer]{display:none}}.md-header__topic{display:flex;max-width:100%;position:absolute;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;white-space:nowrap}.md-header__topic+.md-header__topic{opacity:0;pointer-events:none;transform:translateX(1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__topic+.md-header__topic{transform:translateX(-1.25rem)}.md-header__topic:first-child{font-weight:700}[dir=ltr] .md-header__title{margin-left:1rem;margin-right:.4rem}[dir=rtl] .md-header__title{margin-left:.4rem;margin-right:1rem}.md-header__title{flex-grow:1;font-size:.9rem;height:2.4rem;line-height:2.4rem}.md-header__title--active .md-header__topic{opacity:0;pointer-events:none;transform:translateX(-1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__title--active .md-header__topic{transform:translateX(1.25rem)}.md-header__title--active .md-header__topic+.md-header__topic{opacity:1;pointer-events:auto;transform:translateX(0);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;z-index:0}.md-header__title>.md-header__ellipsis{height:100%;position:relative;width:100%}.md-header__option{display:flex;flex-shrink:0;max-width:100%;transition:max-width 0ms .25s,opacity .25s .25s;white-space:nowrap}[data-md-toggle=search]:checked~.md-header .md-header__option{max-width:0;opacity:0;transition:max-width 0ms,opacity 0ms}.md-header__option>input{bottom:0}.md-header__source{display:none}@media screen and (min-width:60em){[dir=ltr] .md-header__source{margin-left:1rem}[dir=rtl] .md-header__source{margin-right:1rem}.md-header__source{display:block;max-width:11.7rem;width:11.7rem}}@media screen and (min-width:76.25em){[dir=ltr] .md-header__source{margin-left:1.4rem}[dir=rtl] .md-header__source{margin-right:1.4rem}}.md-meta{color:var(--md-default-fg-color--light);font-size:.7rem;line-height:1.3}.md-meta__list{display:inline-flex;flex-wrap:wrap;list-style:none;margin:0;padding:0}.md-meta__item:not(:last-child):after{content:"·";margin-left:.2rem;margin-right:.2rem}.md-meta__link{color:var(--md-typeset-a-color)}.md-meta__link:focus,.md-meta__link:hover{color:var(--md-accent-fg-color)}.md-draft{background-color:#ff1744;border-radius:.125em;color:#fff;display:inline-block;font-weight:700;padding-left:.5714285714em;padding-right:.5714285714em}:root{--md-nav-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-nav-icon--next:url('data:image/svg+xml;charset=utf-8,');--md-toc-icon:url('data:image/svg+xml;charset=utf-8,')}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{color:var(--md-default-fg-color--light);display:block;font-weight:700;overflow:hidden;padding:0 .6rem;text-overflow:ellipsis}.md-nav__title .md-nav__button{display:none}.md-nav__title .md-nav__button img{height:100%;width:auto}.md-nav__title .md-nav__button.md-logo img,.md-nav__title .md-nav__button.md-logo svg{fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__list{list-style:none;margin:0;padding:0}.md-nav__link{align-items:flex-start;display:flex;gap:.4rem;margin-top:.625em;scroll-snap-align:start;transition:color 125ms}.md-nav__link--passed,.md-nav__link--passed code{color:var(--md-default-fg-color--light)}.md-nav__item .md-nav__link--active,.md-nav__item .md-nav__link--active code{color:var(--md-typeset-a-color)}.md-nav__link .md-ellipsis{position:relative}.md-nav__link .md-ellipsis code{word-break:normal}[dir=ltr] .md-nav__link .md-icon:last-child{margin-left:auto}[dir=rtl] .md-nav__link .md-icon:last-child{margin-right:auto}.md-nav__link .md-typeset{font-size:.7rem;line-height:1.3}.md-nav__link svg{fill:currentcolor;flex-shrink:0;height:1.3em;position:relative}.md-nav__link[for]:focus,.md-nav__link[for]:hover,.md-nav__link[href]:focus,.md-nav__link[href]:hover{color:var(--md-accent-fg-color);cursor:pointer}.md-nav__link[for]:focus code,.md-nav__link[for]:hover code,.md-nav__link[href]:focus code,.md-nav__link[href]:hover code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-nav__link.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-nav--primary .md-nav__link[for=__toc]{display:none}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{background-color:currentcolor;display:block;height:100%;-webkit-mask-image:var(--md-toc-icon);mask-image:var(--md-toc-icon);width:100%}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__container>.md-nav__link{margin-top:0}.md-nav__container>.md-nav__link:first-child{flex-grow:1;min-width:0}.md-nav__icon{flex-shrink:0}.md-nav__source{display:none}@media screen and (max-width:76.234375em){.md-nav--primary,.md-nav--primary .md-nav{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;height:100%;left:0;position:absolute;right:0;top:0;z-index:1}.md-nav--primary .md-nav__item,.md-nav--primary .md-nav__title{font-size:.8rem;line-height:1.5}.md-nav--primary .md-nav__title{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);cursor:pointer;height:5.6rem;line-height:2.4rem;padding:3rem .8rem .2rem;position:relative;white-space:nowrap}[dir=ltr] .md-nav--primary .md-nav__title .md-nav__icon{left:.4rem}[dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon{right:.4rem}.md-nav--primary .md-nav__title .md-nav__icon{display:block;height:1.2rem;margin:.2rem;position:absolute;top:.4rem;width:1.2rem}.md-nav--primary .md-nav__title .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--prev);mask-image:var(--md-nav-icon--prev);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}.md-nav--primary .md-nav__title~.md-nav__list{background-color:var(--md-default-bg-color);box-shadow:0 .05rem 0 var(--md-default-fg-color--lightest) inset;overflow-y:auto;scroll-snap-type:y mandatory;touch-action:pan-y}.md-nav--primary .md-nav__title~.md-nav__list>:first-child{border-top:0}.md-nav--primary .md-nav__title[for=__drawer]{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);font-weight:700}.md-nav--primary .md-nav__title .md-logo{display:block;left:.2rem;margin:.2rem;padding:.4rem;position:absolute;right:.2rem;top:.2rem}.md-nav--primary .md-nav__list{flex:1}.md-nav--primary .md-nav__item{border-top:.05rem solid var(--md-default-fg-color--lightest)}.md-nav--primary .md-nav__item--active>.md-nav__link{color:var(--md-typeset-a-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:focus,.md-nav--primary .md-nav__item--active>.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link{margin-top:0;padding:.6rem .8rem}.md-nav--primary .md-nav__link svg{margin-top:.1em}.md-nav--primary .md-nav__link>.md-nav__link{padding:0}[dir=ltr] .md-nav--primary .md-nav__link .md-nav__icon{margin-right:-.2rem}[dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon{margin-left:-.2rem}.md-nav--primary .md-nav__link .md-nav__icon{font-size:1.2rem;height:1.2rem;width:1.2rem}.md-nav--primary .md-nav__link .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-nav--primary .md-nav__icon:after{transform:scale(-1)}.md-nav--primary .md-nav--secondary .md-nav{background-color:initial;position:static}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem}.md-nav--secondary{background-color:initial}.md-nav__toggle~.md-nav{display:flex;opacity:0;transform:translateX(100%);transition:transform .25s cubic-bezier(.8,0,.6,1),opacity 125ms 50ms}[dir=rtl] .md-nav__toggle~.md-nav{transform:translateX(-100%)}.md-nav__toggle:checked~.md-nav{opacity:1;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 125ms 125ms}.md-nav__toggle:checked~.md-nav>.md-nav__list{-webkit-backface-visibility:hidden;backface-visibility:hidden}}@media screen and (max-width:59.984375em){.md-nav--primary .md-nav__link[for=__toc]{display:flex}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--primary .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:flex}.md-nav__source{background-color:var(--md-primary-fg-color--dark);color:var(--md-primary-bg-color);display:block;padding:0 .2rem}}@media screen and (min-width:60em) and (max-width:76.234375em){.md-nav--integrated .md-nav__link[for=__toc]{display:flex}.md-nav--integrated .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--integrated .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:flex}}@media screen and (min-width:60em){.md-nav{margin-bottom:-.4rem}.md-nav--secondary .md-nav__title{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);position:sticky;top:0;z-index:1}.md-nav--secondary .md-nav__title[for=__toc]{scroll-snap-align:start}.md-nav--secondary .md-nav__title .md-nav__icon{display:none}[dir=ltr] .md-nav--secondary .md-nav__list{padding-left:.6rem}[dir=rtl] .md-nav--secondary .md-nav__list{padding-right:.6rem}.md-nav--secondary .md-nav__list{padding-bottom:.4rem}[dir=ltr] .md-nav--secondary .md-nav__item>.md-nav__link{margin-right:.4rem}[dir=rtl] .md-nav--secondary .md-nav__item>.md-nav__link{margin-left:.4rem}}@media screen and (min-width:76.25em){.md-nav{margin-bottom:-.4rem;transition:max-height .25s cubic-bezier(.86,0,.07,1)}.md-nav--primary .md-nav__title{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);position:sticky;top:0;z-index:1}.md-nav--primary .md-nav__title[for=__drawer]{scroll-snap-align:start}.md-nav--primary .md-nav__title .md-nav__icon{display:none}[dir=ltr] .md-nav--primary .md-nav__list{padding-left:.6rem}[dir=rtl] .md-nav--primary .md-nav__list{padding-right:.6rem}.md-nav--primary .md-nav__list{padding-bottom:.4rem}[dir=ltr] .md-nav--primary .md-nav__item>.md-nav__link{margin-right:.4rem}[dir=rtl] .md-nav--primary .md-nav__item>.md-nav__link{margin-left:.4rem}.md-nav__toggle~.md-nav{display:grid;grid-template-rows:minmax(.4rem,0fr);opacity:0;transition:grid-template-rows .25s cubic-bezier(.86,0,.07,1),opacity .25s,visibility 0ms .25s;visibility:collapse}.md-nav__toggle~.md-nav>.md-nav__list{overflow:hidden}.md-nav__toggle.md-toggle--indeterminate~.md-nav,.md-nav__toggle:checked~.md-nav{grid-template-rows:minmax(.4rem,1fr);opacity:1;transition:grid-template-rows .25s cubic-bezier(.86,0,.07,1),opacity .15s .1s,visibility 0ms;visibility:visible}.md-nav__toggle.md-toggle--indeterminate~.md-nav{transition:none}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--section{display:block;margin:1.25em 0}.md-nav__item--section:last-child{margin-bottom:0}.md-nav__item--section>.md-nav__link{font-weight:700}.md-nav__item--section>.md-nav__link[for]{color:var(--md-default-fg-color--light)}.md-nav__item--section>.md-nav__link:not(.md-nav__container){pointer-events:none}.md-nav__item--section>.md-nav__link .md-icon,.md-nav__item--section>.md-nav__link>[for]{display:none}[dir=ltr] .md-nav__item--section>.md-nav{margin-left:-.6rem}[dir=rtl] .md-nav__item--section>.md-nav{margin-right:-.6rem}.md-nav__item--section>.md-nav{display:block;opacity:1;visibility:visible}.md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item{padding:0}.md-nav__icon{border-radius:100%;height:.9rem;transition:background-color .25s;width:.9rem}.md-nav__icon:hover{background-color:var(--md-accent-fg-color--transparent)}.md-nav__icon:after{background-color:currentcolor;border-radius:100%;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:transform .25s;vertical-align:-.1rem;width:100%}[dir=rtl] .md-nav__icon:after{transform:rotate(180deg)}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link .md-nav__icon:after,.md-nav__item--nested .md-toggle--indeterminate~.md-nav__link .md-nav__icon:after{transform:rotate(90deg)}.md-nav--lifted>.md-nav__list>.md-nav__item,.md-nav--lifted>.md-nav__title{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active{display:block}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);margin-top:0;position:sticky;top:0;z-index:1}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link:not(.md-nav__container){pointer-events:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active.md-nav__item--section{margin:0}[dir=ltr] .md-nav--lifted>.md-nav__list>.md-nav__item>.md-nav:not(.md-nav--secondary){margin-left:-.6rem}[dir=rtl] .md-nav--lifted>.md-nav__list>.md-nav__item>.md-nav:not(.md-nav--secondary){margin-right:-.6rem}.md-nav--lifted>.md-nav__list>.md-nav__item>[for]{color:var(--md-default-fg-color--light)}.md-nav--lifted .md-nav[data-md-level="1"]{grid-template-rows:minmax(.4rem,1fr);opacity:1;visibility:visible}[dir=ltr] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-left:.05rem solid var(--md-primary-fg-color)}[dir=rtl] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-right:.05rem solid var(--md-primary-fg-color)}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{display:block;margin-bottom:1.25em;opacity:1;visibility:visible}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary>.md-nav__list{overflow:visible;padding-bottom:0}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary>.md-nav__title{display:none}}.md-pagination{font-size:.8rem;font-weight:700;gap:.4rem}.md-pagination,.md-pagination>*{align-items:center;display:flex;justify-content:center}.md-pagination>*{border-radius:.2rem;height:1.8rem;min-width:1.8rem;text-align:center}.md-pagination__current{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light)}.md-pagination__link{transition:color 125ms,background-color 125ms}.md-pagination__link:focus,.md-pagination__link:hover{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-pagination__link:focus svg,.md-pagination__link:hover svg{color:var(--md-accent-fg-color)}.md-pagination__link.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-pagination__link svg{fill:currentcolor;color:var(--md-default-fg-color--lighter);display:block;max-height:100%;width:1.2rem}:root{--md-path-icon:url('data:image/svg+xml;charset=utf-8,')}.md-path{font-size:.7rem;margin:0 .8rem;overflow:auto;padding-top:1.2rem}.md-path:not([hidden]){display:block}@media screen and (min-width:76.25em){.md-path{margin:0 1.2rem}}.md-path__list{align-items:center;display:flex;gap:.2rem;list-style:none;margin:0;padding:0}.md-path__item:not(:first-child){display:inline-flex;gap:.2rem;white-space:nowrap}.md-path__item:not(:first-child):before{background-color:var(--md-default-fg-color--lighter);content:"";display:inline;height:.8rem;-webkit-mask-image:var(--md-path-icon);mask-image:var(--md-path-icon);width:.8rem}.md-path__link{align-items:center;color:var(--md-default-fg-color--light);display:flex}.md-path__link:focus,.md-path__link:hover{color:var(--md-accent-fg-color)}:root{--md-post-pin-icon:url('data:image/svg+xml;charset=utf-8,')}.md-post__back{border-bottom:.05rem solid var(--md-default-fg-color--lightest);margin-bottom:1.2rem;padding-bottom:1.2rem}@media screen and (max-width:76.234375em){.md-post__back{display:none}}[dir=rtl] .md-post__back svg{transform:scaleX(-1)}.md-post__authors{display:flex;flex-direction:column;gap:.6rem;margin:0 .6rem 1.2rem}.md-post .md-post__meta a{transition:color 125ms}.md-post .md-post__meta a:focus,.md-post .md-post__meta a:hover{color:var(--md-accent-fg-color)}.md-post__title{color:var(--md-default-fg-color--light);font-weight:700}.md-post--excerpt{margin-bottom:3.2rem}.md-post--excerpt .md-post__header{align-items:center;display:flex;gap:.6rem;min-height:1.6rem}.md-post--excerpt .md-post__authors{align-items:center;display:inline-flex;flex-direction:row;gap:.2rem;margin:0;min-height:2.4rem}[dir=ltr] .md-post--excerpt .md-post__meta .md-meta__list{margin-right:.4rem}[dir=rtl] .md-post--excerpt .md-post__meta .md-meta__list{margin-left:.4rem}.md-post--excerpt .md-post__content>:first-child{--md-scroll-margin:6rem;margin-top:0}.md-post>.md-nav--secondary{margin:1em 0}.md-pin{background:var(--md-default-fg-color--lightest);border-radius:1rem;margin-top:-.05rem;padding:.2rem}.md-pin:after{background-color:currentcolor;content:"";display:block;height:.6rem;margin:0 auto;-webkit-mask-image:var(--md-post-pin-icon);mask-image:var(--md-post-pin-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.6rem}.md-profile{align-items:center;display:flex;font-size:.7rem;gap:.6rem;line-height:1.4;width:100%}.md-profile__description{flex-grow:1}.md-content--post{display:flex}@media screen and (max-width:76.234375em){.md-content--post{flex-flow:column-reverse}}.md-content--post>.md-content__inner{flex-grow:1;min-width:0}@media screen and (min-width:76.25em){[dir=ltr] .md-content--post>.md-content__inner{margin-left:1.2rem}[dir=rtl] .md-content--post>.md-content__inner{margin-right:1.2rem}}@media screen and (max-width:76.234375em){.md-sidebar.md-sidebar--post{padding:0;position:static;width:100%}.md-sidebar.md-sidebar--post .md-sidebar__scrollwrap{overflow:visible}.md-sidebar.md-sidebar--post .md-sidebar__inner{padding:0}.md-sidebar.md-sidebar--post .md-post__meta{margin-left:.6rem;margin-right:.6rem}.md-sidebar.md-sidebar--post .md-nav__item{border:none;display:inline}.md-sidebar.md-sidebar--post .md-nav__list{display:inline-flex;flex-wrap:wrap;gap:.6rem;padding-bottom:.6rem;padding-top:.6rem}.md-sidebar.md-sidebar--post .md-nav__link{padding:0}.md-sidebar.md-sidebar--post .md-nav{height:auto;margin-bottom:0;position:static}}:root{--md-progress-value:0;--md-progress-delay:400ms}.md-progress{background:var(--md-primary-bg-color);height:.075rem;opacity:min(clamp(0,var(--md-progress-value),1),clamp(0,100 - var(--md-progress-value),1));position:fixed;top:0;transform:scaleX(calc(var(--md-progress-value)*1%));transform-origin:left;transition:transform .5s cubic-bezier(.19,1,.22,1),opacity .25s var(--md-progress-delay);width:100%;z-index:4}:root{--md-search-result-icon:url('data:image/svg+xml;charset=utf-8,')}.md-search{position:relative}@media screen and (min-width:60em){.md-search{padding:.2rem 0}}.no-js .md-search{display:none}.md-search__overlay{opacity:0;z-index:1}@media screen and (max-width:59.984375em){[dir=ltr] .md-search__overlay{left:-2.2rem}[dir=rtl] .md-search__overlay{right:-2.2rem}.md-search__overlay{background-color:var(--md-default-bg-color);border-radius:1rem;height:2rem;overflow:hidden;pointer-events:none;position:absolute;top:-1rem;transform-origin:center;transition:transform .3s .1s,opacity .2s .2s;width:2rem}[data-md-toggle=search]:checked~.md-header .md-search__overlay{opacity:1;transition:transform .4s,opacity .1s}}@media screen and (min-width:60em){[dir=ltr] .md-search__overlay{left:0}[dir=rtl] .md-search__overlay{right:0}.md-search__overlay{background-color:#0000008a;cursor:pointer;height:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0}[data-md-toggle=search]:checked~.md-header .md-search__overlay{height:200vh;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@media screen and (max-width:29.984375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(45)}}@media screen and (min-width:30em) and (max-width:44.984375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(60)}}@media screen and (min-width:45em) and (max-width:59.984375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(75)}}.md-search__inner{-webkit-backface-visibility:hidden;backface-visibility:hidden}@media screen and (max-width:59.984375em){[dir=ltr] .md-search__inner{left:0}[dir=rtl] .md-search__inner{right:0}.md-search__inner{height:0;opacity:0;overflow:hidden;position:fixed;top:0;transform:translateX(5%);transition:width 0ms .3s,height 0ms .3s,transform .15s cubic-bezier(.4,0,.2,1) .15s,opacity .15s .15s;width:0;z-index:2}[dir=rtl] .md-search__inner{transform:translateX(-5%)}[data-md-toggle=search]:checked~.md-header .md-search__inner{height:100%;opacity:1;transform:translateX(0);transition:width 0ms 0ms,height 0ms 0ms,transform .15s cubic-bezier(.1,.7,.1,1) .15s,opacity .15s .15s;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__inner{float:right}[dir=rtl] .md-search__inner{float:left}.md-search__inner{padding:.1rem 0;position:relative;transition:width .25s cubic-bezier(.1,.7,.1,1);width:11.7rem}}@media screen and (min-width:60em) and (max-width:76.234375em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}}@media screen and (min-width:76.25em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}}.md-search__form{background-color:var(--md-default-bg-color);box-shadow:0 0 .6rem #0000;height:2.4rem;position:relative;transition:color .25s,background-color .25s;z-index:2}@media screen and (min-width:60em){.md-search__form{background-color:#00000042;border-radius:.1rem;height:1.8rem}.md-search__form:hover{background-color:#ffffff1f}}[data-md-toggle=search]:checked~.md-header .md-search__form{background-color:var(--md-default-bg-color);border-radius:.1rem .1rem 0 0;box-shadow:0 0 .6rem #00000012;color:var(--md-default-fg-color)}[dir=ltr] .md-search__input{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__input{padding-left:2.2rem;padding-right:3.6rem}.md-search__input{background:#0000;font-size:.9rem;height:100%;position:relative;text-overflow:ellipsis;width:100%;z-index:2}.md-search__input::placeholder{transition:color .25s}.md-search__input::placeholder,.md-search__input~.md-search__icon{color:var(--md-default-fg-color--light)}.md-search__input::-ms-clear{display:none}@media screen and (max-width:59.984375em){.md-search__input{font-size:.9rem;height:2.4rem;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__input{padding-left:2.2rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input{color:inherit;font-size:.8rem}.md-search__input::placeholder{color:var(--md-primary-bg-color--light)}.md-search__input+.md-search__icon{color:var(--md-primary-bg-color)}[data-md-toggle=search]:checked~.md-header .md-search__input{text-overflow:clip}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:#0000}}.md-search__icon{cursor:pointer;display:inline-block;height:1.2rem;transition:color .25s,opacity .25s;width:1.2rem}.md-search__icon:hover{opacity:.7}[dir=ltr] .md-search__icon[for=__search]{left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem}.md-search__icon[for=__search]{position:absolute;top:.3rem;z-index:2}[dir=rtl] .md-search__icon[for=__search] svg{transform:scaleX(-1)}@media screen and (max-width:59.984375em){[dir=ltr] .md-search__icon[for=__search]{left:.8rem}[dir=rtl] .md-search__icon[for=__search]{right:.8rem}.md-search__icon[for=__search]{top:.6rem}.md-search__icon[for=__search] svg:first-child{display:none}}@media screen and (min-width:60em){.md-search__icon[for=__search]{pointer-events:none}.md-search__icon[for=__search] svg:last-child{display:none}}[dir=ltr] .md-search__options{right:.5rem}[dir=rtl] .md-search__options{left:.5rem}.md-search__options{pointer-events:none;position:absolute;top:.3rem;z-index:2}@media screen and (max-width:59.984375em){[dir=ltr] .md-search__options{right:.8rem}[dir=rtl] .md-search__options{left:.8rem}.md-search__options{top:.6rem}}[dir=ltr] .md-search__options>.md-icon{margin-left:.2rem}[dir=rtl] .md-search__options>.md-icon{margin-right:.2rem}.md-search__options>.md-icon{color:var(--md-default-fg-color--light);opacity:0;transform:scale(.75);transition:transform .15s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-search__options>.md-icon:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>.md-icon{opacity:1;pointer-events:auto;transform:scale(1)}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>.md-icon:hover{opacity:.7}[dir=ltr] .md-search__suggest{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__suggest{padding-left:2.2rem;padding-right:3.6rem}.md-search__suggest{align-items:center;color:var(--md-default-fg-color--lighter);display:flex;font-size:.9rem;height:100%;opacity:0;position:absolute;top:0;transition:opacity 50ms;white-space:nowrap;width:100%}@media screen and (min-width:60em){[dir=ltr] .md-search__suggest{padding-left:2.2rem}[dir=rtl] .md-search__suggest{padding-right:2.2rem}.md-search__suggest{font-size:.8rem}}[data-md-toggle=search]:checked~.md-header .md-search__suggest{opacity:1;transition:opacity .3s .1s}[dir=ltr] .md-search__output{border-bottom-left-radius:.1rem}[dir=ltr] .md-search__output,[dir=rtl] .md-search__output{border-bottom-right-radius:.1rem}[dir=rtl] .md-search__output{border-bottom-left-radius:.1rem}.md-search__output{overflow:hidden;position:absolute;width:100%;z-index:1}@media screen and (max-width:59.984375em){.md-search__output{bottom:0;top:2.4rem}}@media screen and (min-width:60em){.md-search__output{opacity:0;top:1.9rem;transition:opacity .4s}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:var(--md-shadow-z3);opacity:1}}.md-search__scrollwrap{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);height:100%;overflow-y:auto;touch-action:pan-y}@media (-webkit-max-device-pixel-ratio:1),(max-resolution:1dppx){.md-search__scrollwrap{transform:translateZ(0)}}@media screen and (min-width:60em) and (max-width:76.234375em){.md-search__scrollwrap{width:23.4rem}}@media screen and (min-width:76.25em){.md-search__scrollwrap{width:34.4rem}}@media screen and (min-width:60em){.md-search__scrollwrap{max-height:0;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-search__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}}.md-search-result{color:var(--md-default-fg-color);word-break:break-word}.md-search-result__meta{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.8rem;padding:0 .8rem;scroll-snap-align:start}@media screen and (min-width:60em){[dir=ltr] .md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem}}.md-search-result__list{list-style:none;margin:0;padding:0;-webkit-user-select:none;user-select:none}.md-search-result__item{box-shadow:0 -.05rem var(--md-default-fg-color--lightest)}.md-search-result__item:first-child{box-shadow:none}.md-search-result__link{display:block;outline:none;scroll-snap-align:start;transition:background-color .25s}.md-search-result__link:focus,.md-search-result__link:hover{background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:last-child p:last-child{margin-bottom:.6rem}.md-search-result__more>summary{cursor:pointer;display:block;outline:none;position:sticky;scroll-snap-align:start;top:0;z-index:1}.md-search-result__more>summary::marker{display:none}.md-search-result__more>summary::-webkit-details-marker{display:none}.md-search-result__more>summary>div{color:var(--md-typeset-a-color);font-size:.64rem;padding:.75em .8rem;transition:color .25s,background-color .25s}@media screen and (min-width:60em){[dir=ltr] .md-search-result__more>summary>div{padding-left:2.2rem}[dir=rtl] .md-search-result__more>summary>div{padding-right:2.2rem}}.md-search-result__more>summary:focus>div,.md-search-result__more>summary:hover>div{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more[open]>summary{background-color:var(--md-default-bg-color)}.md-search-result__article{overflow:hidden;padding:0 .8rem;position:relative}@media screen and (min-width:60em){[dir=ltr] .md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem}}[dir=ltr] .md-search-result__icon{left:0}[dir=rtl] .md-search-result__icon{right:0}.md-search-result__icon{color:var(--md-default-fg-color--light);height:1.2rem;margin:.5rem;position:absolute;width:1.2rem}@media screen and (max-width:59.984375em){.md-search-result__icon{display:none}}.md-search-result__icon:after{background-color:currentcolor;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-search-result-icon);mask-image:var(--md-search-result-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-search-result__icon:after{transform:scaleX(-1)}.md-search-result .md-typeset{color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.6}.md-search-result .md-typeset h1{color:var(--md-default-fg-color);font-size:.8rem;font-weight:400;line-height:1.4;margin:.55rem 0}.md-search-result .md-typeset h1 mark{text-decoration:none}.md-search-result .md-typeset h2{color:var(--md-default-fg-color);font-size:.64rem;font-weight:700;line-height:1.6;margin:.5em 0}.md-search-result .md-typeset h2 mark{text-decoration:none}.md-search-result__terms{color:var(--md-default-fg-color);display:block;font-size:.64rem;font-style:italic;margin:.5em 0}.md-search-result mark{background-color:initial;color:var(--md-accent-fg-color);text-decoration:underline}.md-select{position:relative;z-index:1}.md-select__inner{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);left:50%;margin-top:.2rem;max-height:0;opacity:0;position:absolute;top:calc(100% - .2rem);transform:translate3d(-50%,.3rem,0);transition:transform .25s 375ms,opacity .25s .25s,max-height 0ms .5s}.md-select:focus-within .md-select__inner,.md-select:hover .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select__inner:after{border-bottom:.2rem solid #0000;border-bottom-color:var(--md-default-bg-color);border-left:.2rem solid #0000;border-right:.2rem solid #0000;border-top:0;content:"";height:0;left:50%;margin-left:-.2rem;margin-top:-.2rem;position:absolute;top:0;width:0}.md-select__list{border-radius:.1rem;font-size:.8rem;list-style-type:none;margin:0;max-height:inherit;overflow:auto;padding:0}.md-select__item{line-height:1.8rem}[dir=ltr] .md-select__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-select__link{padding-left:1.2rem;padding-right:.6rem}.md-select__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:background-color .25s,color .25s;width:100%}.md-select__link:focus,.md-select__link:hover{color:var(--md-accent-fg-color)}.md-select__link:focus{background-color:var(--md-default-fg-color--lightest)}.md-sidebar{align-self:flex-start;flex-shrink:0;padding:1.2rem 0;position:sticky;top:2.4rem;width:12.1rem}@media print{.md-sidebar{display:none}}@media screen and (max-width:76.234375em){[dir=ltr] .md-sidebar--primary{left:-12.1rem}[dir=rtl] .md-sidebar--primary{right:-12.1rem}.md-sidebar--primary{background-color:var(--md-default-bg-color);display:block;height:100%;position:fixed;top:0;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),box-shadow .25s;width:12.1rem;z-index:5}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:var(--md-shadow-z3);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{transform:translateX(-12.1rem)}.md-sidebar--primary .md-sidebar__scrollwrap{bottom:0;left:0;margin:0;overflow:hidden;position:absolute;right:0;scroll-snap-type:none;top:0}}@media screen and (min-width:76.25em){.md-sidebar{height:0}.no-js .md-sidebar{height:auto}.md-header--lifted~.md-container .md-sidebar{top:4.8rem}}.md-sidebar--secondary{display:none;order:2}@media screen and (min-width:60em){.md-sidebar--secondary{height:0}.no-js .md-sidebar--secondary{height:auto}.md-sidebar--secondary:not([hidden]){display:block}.md-sidebar--secondary .md-sidebar__scrollwrap{touch-action:pan-y}}.md-sidebar__scrollwrap{scrollbar-gutter:stable;-webkit-backface-visibility:hidden;backface-visibility:hidden;margin:0 .2rem;overflow-y:auto;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin}.md-sidebar__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-sidebar__scrollwrap:focus-within,.md-sidebar__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-sidebar__scrollwrap:focus-within::-webkit-scrollbar-thumb,.md-sidebar__scrollwrap:hover::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-sidebar__scrollwrap:focus-within::-webkit-scrollbar-thumb:hover,.md-sidebar__scrollwrap:hover::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@supports selector(::-webkit-scrollbar){.md-sidebar__scrollwrap{scrollbar-gutter:auto}[dir=ltr] .md-sidebar__inner{padding-right:calc(100% - 11.5rem)}[dir=rtl] .md-sidebar__inner{padding-left:calc(100% - 11.5rem)}}@media screen and (max-width:76.234375em){.md-overlay{background-color:#0000008a;height:0;opacity:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0;z-index:5}[data-md-toggle=drawer]:checked~.md-overlay{height:100%;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@keyframes facts{0%{height:0}to{height:.65rem}}@keyframes fact{0%{opacity:0;transform:translateY(100%)}50%{opacity:0}to{opacity:1;transform:translateY(0)}}:root{--md-source-forks-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-repositories-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-stars-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-source{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:block;font-size:.65rem;line-height:1.2;outline-color:var(--md-accent-fg-color);transition:opacity .25s;white-space:nowrap}.md-source:hover{opacity:.7}.md-source__icon{display:inline-block;height:2.4rem;vertical-align:middle;width:2rem}[dir=ltr] .md-source__icon svg{margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem}.md-source__icon svg{margin-top:.6rem}[dir=ltr] .md-source__icon+.md-source__repository{padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{padding-right:2rem}[dir=ltr] .md-source__icon+.md-source__repository{margin-left:-2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem}[dir=ltr] .md-source__repository{margin-left:.6rem}[dir=rtl] .md-source__repository{margin-right:.6rem}.md-source__repository{display:inline-block;max-width:calc(100% - 1.2rem);overflow:hidden;text-overflow:ellipsis;vertical-align:middle}.md-source__facts{display:flex;font-size:.55rem;gap:.4rem;list-style-type:none;margin:.1rem 0 0;opacity:.75;overflow:hidden;padding:0;width:100%}.md-source__repository--active .md-source__facts{animation:facts .25s ease-in}.md-source__fact{overflow:hidden;text-overflow:ellipsis}.md-source__repository--active .md-source__fact{animation:fact .4s ease-out}[dir=ltr] .md-source__fact:before{margin-right:.1rem}[dir=rtl] .md-source__fact:before{margin-left:.1rem}.md-source__fact:before{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:text-top;width:.6rem}.md-source__fact:nth-child(1n+2){flex-shrink:0}.md-source__fact--version:before{-webkit-mask-image:var(--md-source-version-icon);mask-image:var(--md-source-version-icon)}.md-source__fact--stars:before{-webkit-mask-image:var(--md-source-stars-icon);mask-image:var(--md-source-stars-icon)}.md-source__fact--forks:before{-webkit-mask-image:var(--md-source-forks-icon);mask-image:var(--md-source-forks-icon)}.md-source__fact--repositories:before{-webkit-mask-image:var(--md-source-repositories-icon);mask-image:var(--md-source-repositories-icon)}.md-source-file{margin:1em 0}[dir=ltr] .md-source-file__fact{margin-right:.6rem}[dir=rtl] .md-source-file__fact{margin-left:.6rem}.md-source-file__fact{align-items:center;color:var(--md-default-fg-color--light);display:inline-flex;font-size:.68rem;gap:.3rem}.md-source-file__fact .md-icon{flex-shrink:0;margin-bottom:.05rem}[dir=ltr] .md-source-file__fact .md-author{float:left}[dir=rtl] .md-source-file__fact .md-author{float:right}.md-source-file__fact .md-author{margin-right:.2rem}.md-source-file__fact svg{width:.9rem}:root{--md-status:url('data:image/svg+xml;charset=utf-8,');--md-status--new:url('data:image/svg+xml;charset=utf-8,');--md-status--deprecated:url('data:image/svg+xml;charset=utf-8,');--md-status--encrypted:url('data:image/svg+xml;charset=utf-8,')}.md-status:after{background-color:var(--md-default-fg-color--light);content:"";display:inline-block;height:1.125em;-webkit-mask-image:var(--md-status);mask-image:var(--md-status);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:text-bottom;width:1.125em}.md-status:hover:after{background-color:currentcolor}.md-status--new:after{-webkit-mask-image:var(--md-status--new);mask-image:var(--md-status--new)}.md-status--deprecated:after{-webkit-mask-image:var(--md-status--deprecated);mask-image:var(--md-status--deprecated)}.md-status--encrypted:after{-webkit-mask-image:var(--md-status--encrypted);mask-image:var(--md-status--encrypted)}.md-tabs{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);display:block;line-height:1.3;overflow:auto;width:100%;z-index:3}@media print{.md-tabs{display:none}}@media screen and (max-width:76.234375em){.md-tabs{display:none}}.md-tabs[hidden]{pointer-events:none}[dir=ltr] .md-tabs__list{margin-left:.2rem}[dir=rtl] .md-tabs__list{margin-right:.2rem}.md-tabs__list{contain:content;display:flex;list-style:none;margin:0;overflow:auto;padding:0;scrollbar-width:none;white-space:nowrap}.md-tabs__list::-webkit-scrollbar{display:none}.md-tabs__item{height:2.4rem;padding-left:.6rem;padding-right:.6rem}.md-tabs__item--active .md-tabs__link{color:inherit;opacity:1}.md-tabs__link{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:flex;font-size:.7rem;margin-top:.8rem;opacity:.7;outline-color:var(--md-accent-fg-color);outline-offset:.2rem;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .25s}.md-tabs__link:focus,.md-tabs__link:hover{color:inherit;opacity:1}[dir=ltr] .md-tabs__link svg{margin-right:.4rem}[dir=rtl] .md-tabs__link svg{margin-left:.4rem}.md-tabs__link svg{fill:currentcolor;height:1.3em}.md-tabs__item:nth-child(2) .md-tabs__link{transition-delay:20ms}.md-tabs__item:nth-child(3) .md-tabs__link{transition-delay:40ms}.md-tabs__item:nth-child(4) .md-tabs__link{transition-delay:60ms}.md-tabs__item:nth-child(5) .md-tabs__link{transition-delay:80ms}.md-tabs__item:nth-child(6) .md-tabs__link{transition-delay:.1s}.md-tabs__item:nth-child(7) .md-tabs__link{transition-delay:.12s}.md-tabs__item:nth-child(8) .md-tabs__link{transition-delay:.14s}.md-tabs__item:nth-child(9) .md-tabs__link{transition-delay:.16s}.md-tabs__item:nth-child(10) .md-tabs__link{transition-delay:.18s}.md-tabs__item:nth-child(11) .md-tabs__link{transition-delay:.2s}.md-tabs__item:nth-child(12) .md-tabs__link{transition-delay:.22s}.md-tabs__item:nth-child(13) .md-tabs__link{transition-delay:.24s}.md-tabs__item:nth-child(14) .md-tabs__link{transition-delay:.26s}.md-tabs__item:nth-child(15) .md-tabs__link{transition-delay:.28s}.md-tabs__item:nth-child(16) .md-tabs__link{transition-delay:.3s}.md-tabs[hidden] .md-tabs__link{opacity:0;transform:translateY(50%);transition:transform 0ms .1s,opacity .1s}:root{--md-tag-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .md-tags:not([hidden]){display:inline-flex;flex-wrap:wrap;gap:.5em;margin-bottom:.75em;margin-top:-.125em}.md-typeset .md-tag{align-items:center;background:var(--md-default-fg-color--lightest);border-radius:2.4rem;display:inline-flex;font-size:.64rem;font-size:min(.8em,.64rem);font-weight:700;gap:.5em;letter-spacing:normal;line-height:1.6;padding:.3125em .78125em}.md-typeset .md-tag[href]{-webkit-tap-highlight-color:transparent;color:inherit;outline:none;transition:color 125ms,background-color 125ms}.md-typeset .md-tag[href]:focus,.md-typeset .md-tag[href]:hover{background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[id]>.md-typeset .md-tag{vertical-align:text-top}.md-typeset .md-tag-shadow{opacity:.5}.md-typeset .md-tag-icon:before{background-color:var(--md-default-fg-color--lighter);content:"";display:inline-block;height:1.2em;-webkit-mask-image:var(--md-tag-icon);mask-image:var(--md-tag-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset .md-tag-icon[href]:focus:before,.md-typeset .md-tag-icon[href]:hover:before{background-color:var(--md-accent-bg-color)}@keyframes pulse{0%{transform:scale(.95)}75%{transform:scale(1)}to{transform:scale(.95)}}:root{--md-annotation-bg-icon:url('data:image/svg+xml;charset=utf-8,');--md-annotation-icon:url('data:image/svg+xml;charset=utf-8,')}.md-tooltip{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);font-family:var(--md-text-font-family);left:clamp(var(--md-tooltip-0,0rem) + .8rem,var(--md-tooltip-x),100vw + var(--md-tooltip-0,0rem) + .8rem - var(--md-tooltip-width) - 2 * .8rem);max-width:calc(100vw - 1.6rem);opacity:0;position:absolute;top:var(--md-tooltip-y);transform:translateY(-.4rem);transition:transform 0ms .25s,opacity .25s,z-index .25s;width:var(--md-tooltip-width);z-index:0}.md-tooltip--active{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,z-index 0ms;z-index:2}.md-tooltip--inline{font-weight:700;-webkit-user-select:none;user-select:none;width:auto}.md-tooltip--inline:not(.md-tooltip--active){transform:translateY(.2rem) scale(.9)}.md-tooltip--inline .md-tooltip__inner{font-size:.5rem;padding:.2rem .4rem}[hidden]+.md-tooltip--inline{display:none}.focus-visible>.md-tooltip,.md-tooltip:target{outline:var(--md-accent-fg-color) auto}.md-tooltip__inner{font-size:.64rem;padding:.8rem}.md-tooltip__inner.md-typeset>:first-child{margin-top:0}.md-tooltip__inner.md-typeset>:last-child{margin-bottom:0}.md-annotation{font-style:normal;font-weight:400;outline:none;text-align:initial;vertical-align:text-bottom;white-space:normal}[dir=rtl] .md-annotation{direction:rtl}code .md-annotation{font-family:var(--md-code-font-family);font-size:inherit}.md-annotation:not([hidden]){display:inline-block;line-height:1.25}.md-annotation__index{border-radius:.01px;cursor:pointer;display:inline-block;margin-left:.4ch;margin-right:.4ch;outline:none;overflow:hidden;position:relative;-webkit-user-select:none;user-select:none;vertical-align:text-top;z-index:0}.md-annotation .md-annotation__index{transition:z-index .25s}@media screen{.md-annotation__index{width:2.2ch}[data-md-visible]>.md-annotation__index{animation:pulse 2s infinite}.md-annotation__index:before{background:var(--md-default-bg-color);-webkit-mask-image:var(--md-annotation-bg-icon);mask-image:var(--md-annotation-bg-icon)}.md-annotation__index:after,.md-annotation__index:before{content:"";height:2.2ch;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:-.1ch;width:2.2ch;z-index:-1}.md-annotation__index:after{background-color:var(--md-default-fg-color--lighter);-webkit-mask-image:var(--md-annotation-icon);mask-image:var(--md-annotation-icon);transform:scale(1.0001);transition:background-color .25s,transform .25s}.md-tooltip--active+.md-annotation__index:after{transform:rotate(45deg)}.md-tooltip--active+.md-annotation__index:after,:hover>.md-annotation__index:after{background-color:var(--md-accent-fg-color)}}.md-tooltip--active+.md-annotation__index{animation-play-state:paused;transition-duration:0ms;z-index:2}.md-annotation__index [data-md-annotation-id]{display:inline-block}@media print{.md-annotation__index [data-md-annotation-id]{background:var(--md-default-fg-color--lighter);border-radius:2ch;color:var(--md-default-bg-color);font-weight:700;padding:0 .6ch;white-space:nowrap}.md-annotation__index [data-md-annotation-id]:after{content:attr(data-md-annotation-id)}}.md-typeset .md-annotation-list{counter-reset:xxx;list-style:none}.md-typeset .md-annotation-list li{position:relative}[dir=ltr] .md-typeset .md-annotation-list li:before{left:-2.125em}[dir=rtl] .md-typeset .md-annotation-list li:before{right:-2.125em}.md-typeset .md-annotation-list li:before{background:var(--md-default-fg-color--lighter);border-radius:2ch;color:var(--md-default-bg-color);content:counter(xxx);counter-increment:xxx;font-size:.8875em;font-weight:700;height:2ch;line-height:1.25;min-width:2ch;padding:0 .6ch;position:absolute;text-align:center;top:.25em}:root{--md-tooltip-width:20rem;--md-tooltip-tail:0.3rem}.md-tooltip2{-webkit-backface-visibility:hidden;backface-visibility:hidden;color:var(--md-default-fg-color);font-family:var(--md-text-font-family);opacity:0;pointer-events:none;position:absolute;top:calc(var(--md-tooltip-host-y) + var(--md-tooltip-y));transform:translateY(-.4rem);transform-origin:calc(var(--md-tooltip-host-x) + var(--md-tooltip-x)) 0;transition:transform 0ms .25s,opacity .25s,z-index .25s;width:100%;z-index:0}.md-tooltip2:before{border-left:var(--md-tooltip-tail) solid #0000;border-right:var(--md-tooltip-tail) solid #0000;content:"";display:block;left:clamp(1.5 * .8rem,var(--md-tooltip-host-x) + var(--md-tooltip-x) - var(--md-tooltip-tail),100vw - 2 * var(--md-tooltip-tail) - 1.5 * .8rem);position:absolute;z-index:1}.md-tooltip2--top:before{border-top:var(--md-tooltip-tail) solid var(--md-default-bg-color);bottom:calc(var(--md-tooltip-tail)*-1 + .025rem);filter:drop-shadow(0 1px 0 hsla(0,0%,0%,.05))}.md-tooltip2--bottom:before{border-bottom:var(--md-tooltip-tail) solid var(--md-default-bg-color);filter:drop-shadow(0 -1px 0 hsla(0,0%,0%,.05));top:calc(var(--md-tooltip-tail)*-1 + .025rem)}.md-tooltip2--active{opacity:1;transform:translateY(0);transition:transform .4s cubic-bezier(0,1,.5,1),opacity .25s,z-index 0ms;z-index:2}.md-tooltip2__inner{scrollbar-gutter:stable;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);left:clamp(.8rem,var(--md-tooltip-host-x) - .8rem,100vw - var(--md-tooltip-width) - .8rem);max-height:40vh;max-width:calc(100vw - 1.6rem);position:relative;scrollbar-width:thin}.md-tooltip2__inner::-webkit-scrollbar{height:.2rem;width:.2rem}.md-tooltip2__inner::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-tooltip2__inner::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}[role=dialog]>.md-tooltip2__inner{font-size:.64rem;overflow:auto;padding:0 .8rem;pointer-events:auto;width:var(--md-tooltip-width)}[role=dialog]>.md-tooltip2__inner:after,[role=dialog]>.md-tooltip2__inner:before{content:"";display:block;height:.8rem;position:sticky;width:100%;z-index:10}[role=dialog]>.md-tooltip2__inner:before{background:linear-gradient(var(--md-default-bg-color),#0000 75%);top:0}[role=dialog]>.md-tooltip2__inner:after{background:linear-gradient(#0000,var(--md-default-bg-color) 75%);bottom:0}[role=tooltip]>.md-tooltip2__inner{font-size:.5rem;font-weight:700;left:clamp(.8rem,var(--md-tooltip-host-x) + var(--md-tooltip-x) - var(--md-tooltip-width)/2,100vw - var(--md-tooltip-width) - .8rem);max-width:min(100vw - 2 * .8rem,400px);padding:.2rem .4rem;-webkit-user-select:none;user-select:none;width:-moz-fit-content;width:fit-content}.md-tooltip2__inner.md-typeset>:first-child{margin-top:0}.md-tooltip2__inner.md-typeset>:last-child{margin-bottom:0}[dir=ltr] .md-top{margin-left:50%}[dir=rtl] .md-top{margin-right:50%}.md-top{background-color:var(--md-default-bg-color);border-radius:1.6rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color--light);cursor:pointer;display:block;font-size:.7rem;outline:none;padding:.4rem .8rem;position:fixed;top:3.2rem;transform:translate(-50%);transition:color 125ms,background-color 125ms,transform 125ms cubic-bezier(.4,0,.2,1),opacity 125ms;z-index:2}@media print{.md-top{display:none}}[dir=rtl] .md-top{transform:translate(50%)}.md-top[hidden]{opacity:0;pointer-events:none;transform:translate(-50%,.2rem);transition-duration:0ms}[dir=rtl] .md-top[hidden]{transform:translate(50%,.2rem)}.md-top:focus,.md-top:hover{background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top svg{display:inline-block;vertical-align:-.5em}@keyframes hoverfix{0%{pointer-events:none}}:root{--md-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-version{flex-shrink:0;font-size:.8rem;height:2.4rem}[dir=ltr] .md-version__current{margin-left:1.4rem;margin-right:.4rem}[dir=rtl] .md-version__current{margin-left:.4rem;margin-right:1.4rem}.md-version__current{color:inherit;cursor:pointer;outline:none;position:relative;top:.05rem}[dir=ltr] .md-version__current:after{margin-left:.4rem}[dir=rtl] .md-version__current:after{margin-right:.4rem}.md-version__current:after{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-image:var(--md-version-icon);mask-image:var(--md-version-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.4rem}.md-version__alias{margin-left:.3rem;opacity:.7}.md-version__list{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);list-style-type:none;margin:.2rem .8rem;max-height:0;opacity:0;overflow:auto;padding:0;position:absolute;scroll-snap-type:y mandatory;top:.15rem;transition:max-height 0ms .5s,opacity .25s .25s;z-index:3}.md-version:focus-within .md-version__list,.md-version:hover .md-version__list{max-height:10rem;opacity:1;transition:max-height 0ms,opacity .25s}@media (hover:none),(pointer:coarse){.md-version:hover .md-version__list{animation:hoverfix .25s forwards}.md-version:focus-within .md-version__list{animation:none}}.md-version__item{line-height:1.8rem}[dir=ltr] .md-version__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-version__link{padding-left:1.2rem;padding-right:.6rem}.md-version__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:color .25s,background-color .25s;white-space:nowrap;width:100%}.md-version__link:focus,.md-version__link:hover{color:var(--md-accent-fg-color)}.md-version__link:focus{background-color:var(--md-default-fg-color--lightest)}:root{--md-admonition-icon--note:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--abstract:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--info:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--tip:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--success:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--question:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--warning:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--failure:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--danger:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--bug:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--example:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--quote:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .admonition,.md-typeset details{background-color:var(--md-admonition-bg-color);border:.075rem solid #448aff;border-radius:.2rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid;transition:box-shadow 125ms}@media print{.md-typeset .admonition,.md-typeset details{box-shadow:none}}.md-typeset .admonition:focus-within,.md-typeset details:focus-within{box-shadow:0 0 0 .2rem #448aff1a}.md-typeset .admonition>*,.md-typeset details>*{box-sizing:border-box}.md-typeset .admonition .admonition,.md-typeset .admonition details,.md-typeset details .admonition,.md-typeset details details{margin-bottom:1em;margin-top:1em}.md-typeset .admonition .md-typeset__scrollwrap,.md-typeset details .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset .admonition .md-typeset__table,.md-typeset details .md-typeset__table{padding:0 .6rem}.md-typeset .admonition>.tabbed-set:only-child,.md-typeset details>.tabbed-set:only-child{margin-top:0}html .md-typeset .admonition>:last-child,html .md-typeset details>:last-child{margin-bottom:.6rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{padding-left:2rem;padding-right:.6rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{padding-left:.6rem;padding-right:2rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{border-left-width:.2rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-right-width:.2rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{border-top-left-radius:.1rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary,[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-top-right-radius:.1rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-top-left-radius:.1rem}.md-typeset .admonition-title,.md-typeset summary{background-color:#448aff1a;border:none;font-weight:700;margin:0 -.6rem;padding-bottom:.4rem;padding-top:.4rem;position:relative}html .md-typeset .admonition-title:last-child,html .md-typeset summary:last-child{margin-bottom:0}[dir=ltr] .md-typeset .admonition-title:before,[dir=ltr] .md-typeset summary:before{left:.6rem}[dir=rtl] .md-typeset .admonition-title:before,[dir=rtl] .md-typeset summary:before{right:.6rem}.md-typeset .admonition-title:before,.md-typeset summary:before{background-color:#448aff;content:"";height:1rem;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;width:1rem}.md-typeset .admonition-title code,.md-typeset summary code{box-shadow:0 0 0 .05rem var(--md-default-fg-color--lightest)}.md-typeset .admonition.note,.md-typeset details.note{border-color:#448aff}.md-typeset .admonition.note:focus-within,.md-typeset details.note:focus-within{box-shadow:0 0 0 .2rem #448aff1a}.md-typeset .note>.admonition-title,.md-typeset .note>summary{background-color:#448aff1a}.md-typeset .note>.admonition-title:before,.md-typeset .note>summary:before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note)}.md-typeset .note>.admonition-title:after,.md-typeset .note>summary:after{color:#448aff}.md-typeset .admonition.abstract,.md-typeset details.abstract{border-color:#00b0ff}.md-typeset .admonition.abstract:focus-within,.md-typeset details.abstract:focus-within{box-shadow:0 0 0 .2rem #00b0ff1a}.md-typeset .abstract>.admonition-title,.md-typeset .abstract>summary{background-color:#00b0ff1a}.md-typeset .abstract>.admonition-title:before,.md-typeset .abstract>summary:before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract)}.md-typeset .abstract>.admonition-title:after,.md-typeset .abstract>summary:after{color:#00b0ff}.md-typeset .admonition.info,.md-typeset details.info{border-color:#00b8d4}.md-typeset .admonition.info:focus-within,.md-typeset details.info:focus-within{box-shadow:0 0 0 .2rem #00b8d41a}.md-typeset .info>.admonition-title,.md-typeset .info>summary{background-color:#00b8d41a}.md-typeset .info>.admonition-title:before,.md-typeset .info>summary:before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info)}.md-typeset .info>.admonition-title:after,.md-typeset .info>summary:after{color:#00b8d4}.md-typeset .admonition.tip,.md-typeset details.tip{border-color:#00bfa5}.md-typeset .admonition.tip:focus-within,.md-typeset details.tip:focus-within{box-shadow:0 0 0 .2rem #00bfa51a}.md-typeset .tip>.admonition-title,.md-typeset .tip>summary{background-color:#00bfa51a}.md-typeset .tip>.admonition-title:before,.md-typeset .tip>summary:before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip)}.md-typeset .tip>.admonition-title:after,.md-typeset .tip>summary:after{color:#00bfa5}.md-typeset .admonition.success,.md-typeset details.success{border-color:#00c853}.md-typeset .admonition.success:focus-within,.md-typeset details.success:focus-within{box-shadow:0 0 0 .2rem #00c8531a}.md-typeset .success>.admonition-title,.md-typeset .success>summary{background-color:#00c8531a}.md-typeset .success>.admonition-title:before,.md-typeset .success>summary:before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success)}.md-typeset .success>.admonition-title:after,.md-typeset .success>summary:after{color:#00c853}.md-typeset .admonition.question,.md-typeset details.question{border-color:#64dd17}.md-typeset .admonition.question:focus-within,.md-typeset details.question:focus-within{box-shadow:0 0 0 .2rem #64dd171a}.md-typeset .question>.admonition-title,.md-typeset .question>summary{background-color:#64dd171a}.md-typeset .question>.admonition-title:before,.md-typeset .question>summary:before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question)}.md-typeset .question>.admonition-title:after,.md-typeset .question>summary:after{color:#64dd17}.md-typeset .admonition.warning,.md-typeset details.warning{border-color:#ff9100}.md-typeset .admonition.warning:focus-within,.md-typeset details.warning:focus-within{box-shadow:0 0 0 .2rem #ff91001a}.md-typeset .warning>.admonition-title,.md-typeset .warning>summary{background-color:#ff91001a}.md-typeset .warning>.admonition-title:before,.md-typeset .warning>summary:before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning)}.md-typeset .warning>.admonition-title:after,.md-typeset .warning>summary:after{color:#ff9100}.md-typeset .admonition.failure,.md-typeset details.failure{border-color:#ff5252}.md-typeset .admonition.failure:focus-within,.md-typeset details.failure:focus-within{box-shadow:0 0 0 .2rem #ff52521a}.md-typeset .failure>.admonition-title,.md-typeset .failure>summary{background-color:#ff52521a}.md-typeset .failure>.admonition-title:before,.md-typeset .failure>summary:before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure)}.md-typeset .failure>.admonition-title:after,.md-typeset .failure>summary:after{color:#ff5252}.md-typeset .admonition.danger,.md-typeset details.danger{border-color:#ff1744}.md-typeset .admonition.danger:focus-within,.md-typeset details.danger:focus-within{box-shadow:0 0 0 .2rem #ff17441a}.md-typeset .danger>.admonition-title,.md-typeset .danger>summary{background-color:#ff17441a}.md-typeset .danger>.admonition-title:before,.md-typeset .danger>summary:before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger)}.md-typeset .danger>.admonition-title:after,.md-typeset .danger>summary:after{color:#ff1744}.md-typeset .admonition.bug,.md-typeset details.bug{border-color:#f50057}.md-typeset .admonition.bug:focus-within,.md-typeset details.bug:focus-within{box-shadow:0 0 0 .2rem #f500571a}.md-typeset .bug>.admonition-title,.md-typeset .bug>summary{background-color:#f500571a}.md-typeset .bug>.admonition-title:before,.md-typeset .bug>summary:before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug)}.md-typeset .bug>.admonition-title:after,.md-typeset .bug>summary:after{color:#f50057}.md-typeset .admonition.example,.md-typeset details.example{border-color:#7c4dff}.md-typeset .admonition.example:focus-within,.md-typeset details.example:focus-within{box-shadow:0 0 0 .2rem #7c4dff1a}.md-typeset .example>.admonition-title,.md-typeset .example>summary{background-color:#7c4dff1a}.md-typeset .example>.admonition-title:before,.md-typeset .example>summary:before{background-color:#7c4dff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example)}.md-typeset .example>.admonition-title:after,.md-typeset .example>summary:after{color:#7c4dff}.md-typeset .admonition.quote,.md-typeset details.quote{border-color:#9e9e9e}.md-typeset .admonition.quote:focus-within,.md-typeset details.quote:focus-within{box-shadow:0 0 0 .2rem #9e9e9e1a}.md-typeset .quote>.admonition-title,.md-typeset .quote>summary{background-color:#9e9e9e1a}.md-typeset .quote>.admonition-title:before,.md-typeset .quote>summary:before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote)}.md-typeset .quote>.admonition-title:after,.md-typeset .quote>summary:after{color:#9e9e9e}:root{--md-footnotes-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .footnote{color:var(--md-default-fg-color--light);font-size:.64rem}[dir=ltr] .md-typeset .footnote>ol{margin-left:0}[dir=rtl] .md-typeset .footnote>ol{margin-right:0}.md-typeset .footnote>ol>li{transition:color 125ms}.md-typeset .footnote>ol>li:target{color:var(--md-default-fg-color)}.md-typeset .footnote>ol>li:focus-within .footnote-backref{opacity:1;transform:translateX(0);transition:none}.md-typeset .footnote>ol>li:hover .footnote-backref,.md-typeset .footnote>ol>li:target .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li>:first-child{margin-top:0}.md-typeset .footnote-ref{font-size:.75em;font-weight:700}html .md-typeset .footnote-ref{outline-offset:.1rem}.md-typeset [id^="fnref:"]:target>.footnote-ref{outline:auto}.md-typeset .footnote-backref{color:var(--md-typeset-a-color);display:inline-block;font-size:0;opacity:0;transform:translateX(.25rem);transition:color .25s,transform .25s .25s,opacity 125ms .25s;vertical-align:text-bottom}@media print{.md-typeset .footnote-backref{color:var(--md-typeset-a-color);opacity:1;transform:translateX(0)}}[dir=rtl] .md-typeset .footnote-backref{transform:translateX(-.25rem)}.md-typeset .footnote-backref:hover{color:var(--md-accent-fg-color)}.md-typeset .footnote-backref:before{background-color:currentcolor;content:"";display:inline-block;height:.8rem;-webkit-mask-image:var(--md-footnotes-icon);mask-image:var(--md-footnotes-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.8rem}[dir=rtl] .md-typeset .footnote-backref:before svg{transform:scaleX(-1)}[dir=ltr] .md-typeset .headerlink{margin-left:.5rem}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem}.md-typeset .headerlink{color:var(--md-default-fg-color--lighter);display:inline-block;opacity:0;transition:color .25s,opacity 125ms}@media print{.md-typeset .headerlink{display:none}}.md-typeset .headerlink:focus,.md-typeset :hover>.headerlink,.md-typeset :target>.headerlink{opacity:1;transition:color .25s,opacity 125ms}.md-typeset .headerlink:focus,.md-typeset .headerlink:hover,.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset :target{--md-scroll-margin:3.6rem;--md-scroll-offset:0rem;scroll-margin-top:calc(var(--md-scroll-margin) - var(--md-scroll-offset))}@media screen and (min-width:76.25em){.md-header--lifted~.md-container .md-typeset :target{--md-scroll-margin:6rem}}.md-typeset h1:target,.md-typeset h2:target,.md-typeset h3:target{--md-scroll-offset:0.2rem}.md-typeset h4:target{--md-scroll-offset:0.15rem}.md-typeset div.arithmatex{overflow:auto}@media screen and (max-width:44.984375em){.md-typeset div.arithmatex{margin:0 -.8rem}.md-typeset div.arithmatex>*{width:min-content}}.md-typeset div.arithmatex>*{margin-left:auto!important;margin-right:auto!important;padding:0 .8rem;touch-action:auto}.md-typeset div.arithmatex>* mjx-container{margin:0!important}.md-typeset div.arithmatex mjx-assistive-mml{height:0}.md-typeset del.critic{background-color:var(--md-typeset-del-color)}.md-typeset del.critic,.md-typeset ins.critic{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset ins.critic{background-color:var(--md-typeset-ins-color)}.md-typeset .critic.comment{-webkit-box-decoration-break:clone;box-decoration-break:clone;color:var(--md-code-hl-comment-color)}.md-typeset .critic.comment:before{content:"/* "}.md-typeset .critic.comment:after{content:" */"}.md-typeset .critic.block{box-shadow:none;display:block;margin:1em 0;overflow:auto;padding-left:.8rem;padding-right:.8rem}.md-typeset .critic.block>:first-child{margin-top:.5em}.md-typeset .critic.block>:last-child{margin-bottom:.5em}:root{--md-details-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset details{display:flow-root;overflow:visible;padding-top:0}.md-typeset details[open]>summary:after{transform:rotate(90deg)}.md-typeset details:not([open]){box-shadow:none;padding-bottom:0}.md-typeset details:not([open])>summary{border-radius:.1rem}[dir=ltr] .md-typeset summary{padding-right:1.8rem}[dir=rtl] .md-typeset summary{padding-left:1.8rem}[dir=ltr] .md-typeset summary{border-top-left-radius:.1rem}[dir=ltr] .md-typeset summary,[dir=rtl] .md-typeset summary{border-top-right-radius:.1rem}[dir=rtl] .md-typeset summary{border-top-left-radius:.1rem}.md-typeset summary{cursor:pointer;display:block;min-height:1rem;overflow:hidden}.md-typeset summary.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset summary:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[dir=ltr] .md-typeset summary:after{right:.4rem}[dir=rtl] .md-typeset summary:after{left:.4rem}.md-typeset summary:after{background-color:currentcolor;content:"";height:1rem;-webkit-mask-image:var(--md-details-icon);mask-image:var(--md-details-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;transform:rotate(0deg);transition:transform .25s;width:1rem}[dir=rtl] .md-typeset summary:after{transform:rotate(180deg)}.md-typeset summary::marker{display:none}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset .emojione,.md-typeset .gemoji,.md-typeset .twemoji{--md-icon-size:1.125em;display:inline-flex;height:var(--md-icon-size);vertical-align:text-top}.md-typeset .emojione svg,.md-typeset .gemoji svg,.md-typeset .twemoji svg{fill:currentcolor;max-height:100%;width:var(--md-icon-size)}.md-typeset .lg,.md-typeset .xl,.md-typeset .xxl,.md-typeset .xxxl{vertical-align:text-bottom}.md-typeset .middle{vertical-align:middle}.md-typeset .lg{--md-icon-size:1.5em}.md-typeset .xl{--md-icon-size:2.25em}.md-typeset .xxl{--md-icon-size:3em}.md-typeset .xxxl{--md-icon-size:4em}.highlight .o,.highlight .ow{color:var(--md-code-hl-operator-color)}.highlight .p{color:var(--md-code-hl-punctuation-color)}.highlight .cpf,.highlight .l,.highlight .s,.highlight .s1,.highlight .s2,.highlight .sb,.highlight .sc,.highlight .si,.highlight .ss{color:var(--md-code-hl-string-color)}.highlight .cp,.highlight .se,.highlight .sh,.highlight .sr,.highlight .sx{color:var(--md-code-hl-special-color)}.highlight .il,.highlight .m,.highlight .mb,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:var(--md-code-hl-number-color)}.highlight .k,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt{color:var(--md-code-hl-keyword-color)}.highlight .kc,.highlight .n{color:var(--md-code-hl-name-color)}.highlight .bp,.highlight .nb,.highlight .no{color:var(--md-code-hl-constant-color)}.highlight .nc,.highlight .ne,.highlight .nf,.highlight .nn{color:var(--md-code-hl-function-color)}.highlight .nd,.highlight .ni,.highlight .nl,.highlight .nt{color:var(--md-code-hl-keyword-color)}.highlight .c,.highlight .c1,.highlight .ch,.highlight .cm,.highlight .cs,.highlight .sd{color:var(--md-code-hl-comment-color)}.highlight .na,.highlight .nv,.highlight .vc,.highlight .vg,.highlight .vi{color:var(--md-code-hl-variable-color)}.highlight .ge,.highlight .gh,.highlight .go,.highlight .gp,.highlight .gr,.highlight .gs,.highlight .gt,.highlight .gu{color:var(--md-code-hl-generic-color)}.highlight .gd,.highlight .gi{border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight .gd{background-color:var(--md-typeset-del-color)}.highlight .gi{background-color:var(--md-typeset-ins-color)}.highlight .hll{background-color:var(--md-code-hl-color--light);box-shadow:2px 0 0 0 var(--md-code-hl-color) inset;display:block;margin:0 -1.1764705882em;padding:0 1.1764705882em}.highlight span.filename{background-color:var(--md-code-bg-color);border-bottom:.05rem solid var(--md-default-fg-color--lightest);border-top-left-radius:.1rem;border-top-right-radius:.1rem;display:flow-root;font-size:.85em;font-weight:700;margin-top:1em;padding:.6617647059em 1.1764705882em;position:relative}.highlight span.filename+pre{margin-top:0}.highlight span.filename+pre>code{border-top-left-radius:0;border-top-right-radius:0}.highlight [data-linenos]:before{background-color:var(--md-code-bg-color);box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;color:var(--md-default-fg-color--light);content:attr(data-linenos);float:left;left:-1.1764705882em;margin-left:-1.1764705882em;margin-right:1.1764705882em;padding-left:1.1764705882em;position:sticky;-webkit-user-select:none;user-select:none;z-index:3}.highlight code a[id]{position:absolute;visibility:hidden}.highlight code[data-md-copying]{display:initial}.highlight code[data-md-copying] .hll{display:contents}.highlight code[data-md-copying] .md-annotation{display:none}.highlighttable{display:flow-root}.highlighttable tbody,.highlighttable td{display:block;padding:0}.highlighttable tr{display:flex}.highlighttable pre{margin:0}.highlighttable th.filename{flex-grow:1;padding:0;text-align:left}.highlighttable th.filename span.filename{margin-top:0}.highlighttable .linenos{background-color:var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-top-left-radius:.1rem;font-size:.85em;padding:.7720588235em 0 .7720588235em 1.1764705882em;-webkit-user-select:none;user-select:none}.highlighttable .linenodiv{box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset}.highlighttable .linenodiv pre{color:var(--md-default-fg-color--light);text-align:right}.highlighttable .linenodiv span[class]{padding-right:.5882352941em}.highlighttable .code{flex:1;min-width:0}.linenodiv a{color:inherit}.md-typeset .highlighttable{direction:ltr;margin:1em 0}.md-typeset .highlighttable>tbody>tr>.code>div>pre>code{border-bottom-left-radius:0;border-top-left-radius:0}.md-typeset .highlight+.result{border:.05rem solid var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem;border-top-width:.1rem;margin-top:-1.125em;overflow:visible;padding:0 1em}.md-typeset .highlight+.result:after{clear:both;content:"";display:block}@media screen and (max-width:44.984375em){.md-content__inner>.highlight{margin:1em -.8rem}.md-content__inner>.highlight>.filename,.md-content__inner>.highlight>.highlighttable>tbody>tr>.code>div>pre>code,.md-content__inner>.highlight>.highlighttable>tbody>tr>.filename span.filename,.md-content__inner>.highlight>.highlighttable>tbody>tr>.linenos,.md-content__inner>.highlight>pre>code{border-radius:0}.md-content__inner>.highlight+.result{border-left-width:0;border-radius:0;border-right-width:0;margin-left:-.8rem;margin-right:-.8rem}}.md-typeset .keys kbd:after,.md-typeset .keys kbd:before{-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys span{color:var(--md-default-fg-color--light);padding:0 .2em}.md-typeset .keys .key-alt:before,.md-typeset .keys .key-left-alt:before,.md-typeset .keys .key-right-alt:before{content:"⎇";padding-right:.4em}.md-typeset .keys .key-command:before,.md-typeset .keys .key-left-command:before,.md-typeset .keys .key-right-command:before{content:"⌘";padding-right:.4em}.md-typeset .keys .key-control:before,.md-typeset .keys .key-left-control:before,.md-typeset .keys .key-right-control:before{content:"⌃";padding-right:.4em}.md-typeset .keys .key-left-meta:before,.md-typeset .keys .key-meta:before,.md-typeset .keys .key-right-meta:before{content:"◆";padding-right:.4em}.md-typeset .keys .key-left-option:before,.md-typeset .keys .key-option:before,.md-typeset .keys .key-right-option:before{content:"⌥";padding-right:.4em}.md-typeset .keys .key-left-shift:before,.md-typeset .keys .key-right-shift:before,.md-typeset .keys .key-shift:before{content:"⇧";padding-right:.4em}.md-typeset .keys .key-left-super:before,.md-typeset .keys .key-right-super:before,.md-typeset .keys .key-super:before{content:"❖";padding-right:.4em}.md-typeset .keys .key-left-windows:before,.md-typeset .keys .key-right-windows:before,.md-typeset .keys .key-windows:before{content:"⊞";padding-right:.4em}.md-typeset .keys .key-arrow-down:before{content:"↓";padding-right:.4em}.md-typeset .keys .key-arrow-left:before{content:"←";padding-right:.4em}.md-typeset .keys .key-arrow-right:before{content:"→";padding-right:.4em}.md-typeset .keys .key-arrow-up:before{content:"↑";padding-right:.4em}.md-typeset .keys .key-backspace:before{content:"⌫";padding-right:.4em}.md-typeset .keys .key-backtab:before{content:"⇤";padding-right:.4em}.md-typeset .keys .key-caps-lock:before{content:"⇪";padding-right:.4em}.md-typeset .keys .key-clear:before{content:"⌧";padding-right:.4em}.md-typeset .keys .key-context-menu:before{content:"☰";padding-right:.4em}.md-typeset .keys .key-delete:before{content:"⌦";padding-right:.4em}.md-typeset .keys .key-eject:before{content:"⏏";padding-right:.4em}.md-typeset .keys .key-end:before{content:"⤓";padding-right:.4em}.md-typeset .keys .key-escape:before{content:"⎋";padding-right:.4em}.md-typeset .keys .key-home:before{content:"⤒";padding-right:.4em}.md-typeset .keys .key-insert:before{content:"⎀";padding-right:.4em}.md-typeset .keys .key-page-down:before{content:"⇟";padding-right:.4em}.md-typeset .keys .key-page-up:before{content:"⇞";padding-right:.4em}.md-typeset .keys .key-print-screen:before{content:"⎙";padding-right:.4em}.md-typeset .keys .key-tab:after{content:"⇥";padding-left:.4em}.md-typeset .keys .key-num-enter:after{content:"⌤";padding-left:.4em}.md-typeset .keys .key-enter:after{content:"⏎";padding-left:.4em}:root{--md-tabbed-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-tabbed-icon--next:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .tabbed-set{border-radius:.1rem;display:flex;flex-flow:column wrap;margin:1em 0;position:relative}.md-typeset .tabbed-set>input{height:0;opacity:0;position:absolute;width:0}.md-typeset .tabbed-set>input:target{--md-scroll-offset:0.625em}.md-typeset .tabbed-set>input.focus-visible~.tabbed-labels:before{background-color:var(--md-accent-fg-color)}.md-typeset .tabbed-labels{-ms-overflow-style:none;box-shadow:0 -.05rem var(--md-default-fg-color--lightest) inset;display:flex;max-width:100%;overflow:auto;scrollbar-width:none}@media print{.md-typeset .tabbed-labels{display:contents}}@media screen{.js .md-typeset .tabbed-labels{position:relative}.js .md-typeset .tabbed-labels:before{background:var(--md-default-fg-color);bottom:0;content:"";display:block;height:2px;left:0;position:absolute;transform:translateX(var(--md-indicator-x));transition:width 225ms,background-color .25s,transform .25s;transition-timing-function:cubic-bezier(.4,0,.2,1);width:var(--md-indicator-width)}}.md-typeset .tabbed-labels::-webkit-scrollbar{display:none}.md-typeset .tabbed-labels>label{border-bottom:.1rem solid #0000;border-radius:.1rem .1rem 0 0;color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;font-size:.64rem;font-weight:700;padding:.78125em 1.25em .625em;scroll-margin-inline-start:1rem;transition:background-color .25s,color .25s;white-space:nowrap;width:auto}@media print{.md-typeset .tabbed-labels>label:first-child{order:1}.md-typeset .tabbed-labels>label:nth-child(2){order:2}.md-typeset .tabbed-labels>label:nth-child(3){order:3}.md-typeset .tabbed-labels>label:nth-child(4){order:4}.md-typeset .tabbed-labels>label:nth-child(5){order:5}.md-typeset .tabbed-labels>label:nth-child(6){order:6}.md-typeset .tabbed-labels>label:nth-child(7){order:7}.md-typeset .tabbed-labels>label:nth-child(8){order:8}.md-typeset .tabbed-labels>label:nth-child(9){order:9}.md-typeset .tabbed-labels>label:nth-child(10){order:10}.md-typeset .tabbed-labels>label:nth-child(11){order:11}.md-typeset .tabbed-labels>label:nth-child(12){order:12}.md-typeset .tabbed-labels>label:nth-child(13){order:13}.md-typeset .tabbed-labels>label:nth-child(14){order:14}.md-typeset .tabbed-labels>label:nth-child(15){order:15}.md-typeset .tabbed-labels>label:nth-child(16){order:16}.md-typeset .tabbed-labels>label:nth-child(17){order:17}.md-typeset .tabbed-labels>label:nth-child(18){order:18}.md-typeset .tabbed-labels>label:nth-child(19){order:19}.md-typeset .tabbed-labels>label:nth-child(20){order:20}}.md-typeset .tabbed-labels>label:hover{color:var(--md-default-fg-color)}.md-typeset .tabbed-labels>label>[href]:first-child{color:inherit}.md-typeset .tabbed-labels--linked>label{padding:0}.md-typeset .tabbed-labels--linked>label>a{display:block;padding:.78125em 1.25em .625em}.md-typeset .tabbed-content{width:100%}@media print{.md-typeset .tabbed-content{display:contents}}.md-typeset .tabbed-block{display:none}@media print{.md-typeset .tabbed-block{display:block}.md-typeset .tabbed-block:first-child{order:1}.md-typeset .tabbed-block:nth-child(2){order:2}.md-typeset .tabbed-block:nth-child(3){order:3}.md-typeset .tabbed-block:nth-child(4){order:4}.md-typeset .tabbed-block:nth-child(5){order:5}.md-typeset .tabbed-block:nth-child(6){order:6}.md-typeset .tabbed-block:nth-child(7){order:7}.md-typeset .tabbed-block:nth-child(8){order:8}.md-typeset .tabbed-block:nth-child(9){order:9}.md-typeset .tabbed-block:nth-child(10){order:10}.md-typeset .tabbed-block:nth-child(11){order:11}.md-typeset .tabbed-block:nth-child(12){order:12}.md-typeset .tabbed-block:nth-child(13){order:13}.md-typeset .tabbed-block:nth-child(14){order:14}.md-typeset .tabbed-block:nth-child(15){order:15}.md-typeset .tabbed-block:nth-child(16){order:16}.md-typeset .tabbed-block:nth-child(17){order:17}.md-typeset .tabbed-block:nth-child(18){order:18}.md-typeset .tabbed-block:nth-child(19){order:19}.md-typeset .tabbed-block:nth-child(20){order:20}}.md-typeset .tabbed-block>.highlight:first-child>pre,.md-typeset .tabbed-block>pre:first-child{margin:0}.md-typeset .tabbed-block>.highlight:first-child>pre>code,.md-typeset .tabbed-block>pre:first-child>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-block>.highlight:first-child>.filename{border-top-left-radius:0;border-top-right-radius:0;margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable{margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.filename span.filename,.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.linenos{border-top-left-radius:0;border-top-right-radius:0;margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.code>div>pre>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-block>.highlight:first-child+.result{margin-top:-.125em}.md-typeset .tabbed-block>.tabbed-set{margin:0}.md-typeset .tabbed-button{align-self:center;border-radius:100%;color:var(--md-default-fg-color--light);cursor:pointer;display:block;height:.9rem;margin-top:.1rem;pointer-events:auto;transition:background-color .25s;width:.9rem}.md-typeset .tabbed-button:hover{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-typeset .tabbed-button:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-tabbed-icon--prev);mask-image:var(--md-tabbed-icon--prev);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color .25s,transform .25s;width:100%}.md-typeset .tabbed-control{background:linear-gradient(to right,var(--md-default-bg-color) 60%,#0000);display:flex;height:1.9rem;justify-content:start;pointer-events:none;position:absolute;transition:opacity 125ms;width:1.2rem}[dir=rtl] .md-typeset .tabbed-control{transform:rotate(180deg)}.md-typeset .tabbed-control[hidden]{opacity:0}.md-typeset .tabbed-control--next{background:linear-gradient(to left,var(--md-default-bg-color) 60%,#0000);justify-content:end;right:0}.md-typeset .tabbed-control--next .tabbed-button:after{-webkit-mask-image:var(--md-tabbed-icon--next);mask-image:var(--md-tabbed-icon--next)}@media screen and (max-width:44.984375em){[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels{padding-right:.8rem}.md-content__inner>.tabbed-set .tabbed-labels{margin:0 -.8rem;max-width:100vw;scroll-padding-inline-start:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-left:.8rem}.md-content__inner>.tabbed-set .tabbed-labels:after{content:""}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{padding-right:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{margin-left:-.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{margin-right:-.8rem}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{width:2rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{padding-left:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{margin-right:-.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{margin-left:-.8rem}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{width:2rem}}@media screen{.md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){color:var(--md-default-fg-color)}.md-typeset .no-js .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .no-js .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .no-js .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .no-js .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .no-js .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .no-js .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .no-js .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .no-js .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .no-js .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .no-js .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .no-js .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .no-js .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .no-js .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .no-js .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .no-js .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .no-js .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .no-js .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .no-js .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .no-js .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .no-js .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9),.md-typeset [role=dialog] .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset [role=dialog] .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset [role=dialog] .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset [role=dialog] .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset [role=dialog] .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset [role=dialog] .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset [role=dialog] .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset [role=dialog] .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset [role=dialog] .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset [role=dialog] .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset [role=dialog] .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset [role=dialog] .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset [role=dialog] .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset [role=dialog] .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset [role=dialog] .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset [role=dialog] .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset [role=dialog] .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset [role=dialog] .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset [role=dialog] .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset [role=dialog] .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9),.no-js .md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.no-js .md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.no-js .md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.no-js .md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.no-js .md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.no-js .md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.no-js .md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.no-js .md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.no-js .md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.no-js .md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.no-js .md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.no-js .md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.no-js .md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.no-js .md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.no-js .md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.no-js .md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.no-js .md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.no-js .md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.no-js .md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.no-js .md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9),[role=dialog] .md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,[role=dialog] .md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),[role=dialog] .md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),[role=dialog] .md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),[role=dialog] .md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),[role=dialog] .md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),[role=dialog] .md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),[role=dialog] .md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),[role=dialog] .md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),[role=dialog] .md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),[role=dialog] .md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),[role=dialog] .md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),[role=dialog] .md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),[role=dialog] .md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),[role=dialog] .md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),[role=dialog] .md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),[role=dialog] .md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),[role=dialog] .md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),[role=dialog] .md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),[role=dialog] .md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){border-color:var(--md-default-fg-color)}}.md-typeset .tabbed-set>input:first-child.focus-visible~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10).focus-visible~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11).focus-visible~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12).focus-visible~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13).focus-visible~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14).focus-visible~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15).focus-visible~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16).focus-visible~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17).focus-visible~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18).focus-visible~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19).focus-visible~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2).focus-visible~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20).focus-visible~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3).focus-visible~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4).focus-visible~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5).focus-visible~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6).focus-visible~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7).focus-visible~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8).focus-visible~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9).focus-visible~.tabbed-labels>:nth-child(9){color:var(--md-accent-fg-color)}.md-typeset .tabbed-set>input:first-child:checked~.tabbed-content>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-content>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-content>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-content>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-content>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-content>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-content>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-content>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-content>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-content>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-content>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-content>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-content>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-content>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-content>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-content>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-content>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-content>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-content>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-content>:nth-child(9){display:block}:root{--md-tasklist-icon:url('data:image/svg+xml;charset=utf-8,');--md-tasklist-icon--checked:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .task-list-item{list-style-type:none;position:relative}[dir=ltr] .md-typeset .task-list-item [type=checkbox]{left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em}.md-typeset .task-list-control [type=checkbox]{opacity:0;z-index:-1}[dir=ltr] .md-typeset .task-list-indicator:before{left:-1.5em}[dir=rtl] .md-typeset .task-list-indicator:before{right:-1.5em}.md-typeset .task-list-indicator:before{background-color:var(--md-default-fg-color--lightest);content:"";height:1.25em;-webkit-mask-image:var(--md-tasklist-icon);mask-image:var(--md-tasklist-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.15em;width:1.25em}.md-typeset [type=checkbox]:checked+.task-list-indicator:before{background-color:#00e676;-webkit-mask-image:var(--md-tasklist-icon--checked);mask-image:var(--md-tasklist-icon--checked)}@media print{.giscus,[id=__comments]{display:none}}:root>*{--md-mermaid-font-family:var(--md-text-font-family),sans-serif;--md-mermaid-edge-color:var(--md-code-fg-color);--md-mermaid-node-bg-color:var(--md-accent-fg-color--transparent);--md-mermaid-node-fg-color:var(--md-accent-fg-color);--md-mermaid-label-bg-color:var(--md-default-bg-color);--md-mermaid-label-fg-color:var(--md-code-fg-color);--md-mermaid-sequence-actor-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-actor-fg-color:var(--md-mermaid-label-fg-color);--md-mermaid-sequence-actor-border-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-actor-line-color:var(--md-default-fg-color--lighter);--md-mermaid-sequence-actorman-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-actorman-line-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-box-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-box-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-label-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-label-fg-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-loop-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-loop-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-loop-border-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-message-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-message-line-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-note-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-note-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-note-border-color:var(--md-mermaid-label-fg-color);--md-mermaid-sequence-number-bg-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-number-fg-color:var(--md-accent-bg-color)}.mermaid{line-height:normal;margin:1em 0}.md-typeset .grid{grid-gap:.4rem;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,16rem),1fr));margin:1em 0}.md-typeset .grid.cards>ol,.md-typeset .grid.cards>ul{display:contents}.md-typeset .grid.cards>ol>li,.md-typeset .grid.cards>ul>li,.md-typeset .grid>.card{border:.05rem solid var(--md-default-fg-color--lightest);border-radius:.1rem;display:block;margin:0;padding:.8rem;transition:border .25s,box-shadow .25s}.md-typeset .grid.cards>ol>li:focus-within,.md-typeset .grid.cards>ol>li:hover,.md-typeset .grid.cards>ul>li:focus-within,.md-typeset .grid.cards>ul>li:hover,.md-typeset .grid>.card:focus-within,.md-typeset .grid>.card:hover{border-color:#0000;box-shadow:var(--md-shadow-z2)}.md-typeset .grid.cards>ol>li>hr,.md-typeset .grid.cards>ul>li>hr,.md-typeset .grid>.card>hr{margin-bottom:1em;margin-top:1em}.md-typeset .grid.cards>ol>li>:first-child,.md-typeset .grid.cards>ul>li>:first-child,.md-typeset .grid>.card>:first-child{margin-top:0}.md-typeset .grid.cards>ol>li>:last-child,.md-typeset .grid.cards>ul>li>:last-child,.md-typeset .grid>.card>:last-child{margin-bottom:0}.md-typeset .grid>*,.md-typeset .grid>.admonition,.md-typeset .grid>.highlight>*,.md-typeset .grid>.highlighttable,.md-typeset .grid>.md-typeset details,.md-typeset .grid>details,.md-typeset .grid>pre{margin-bottom:0;margin-top:0}.md-typeset .grid>.highlight>pre:only-child,.md-typeset .grid>.highlight>pre>code,.md-typeset .grid>.highlighttable,.md-typeset .grid>.highlighttable>tbody,.md-typeset .grid>.highlighttable>tbody>tr,.md-typeset .grid>.highlighttable>tbody>tr>.code,.md-typeset .grid>.highlighttable>tbody>tr>.code>.highlight,.md-typeset .grid>.highlighttable>tbody>tr>.code>.highlight>pre,.md-typeset .grid>.highlighttable>tbody>tr>.code>.highlight>pre>code{height:100%}.md-typeset .grid>.tabbed-set{margin-bottom:0;margin-top:0}@media screen and (min-width:45em){[dir=ltr] .md-typeset .inline{float:left}[dir=rtl] .md-typeset .inline{float:right}[dir=ltr] .md-typeset .inline{margin-right:.8rem}[dir=rtl] .md-typeset .inline{margin-left:.8rem}.md-typeset .inline{margin-bottom:.8rem;margin-top:0;width:11.7rem}[dir=ltr] .md-typeset .inline.end{float:right}[dir=rtl] .md-typeset .inline.end{float:left}[dir=ltr] .md-typeset .inline.end{margin-left:.8rem;margin-right:0}[dir=rtl] .md-typeset .inline.end{margin-left:0;margin-right:.8rem}} \ No newline at end of file diff --git a/assets/stylesheets/palette.ab4e12ef.min.css b/assets/stylesheets/palette.ab4e12ef.min.css new file mode 100644 index 0000000..75aaf84 --- /dev/null +++ b/assets/stylesheets/palette.ab4e12ef.min.css @@ -0,0 +1 @@ +@media screen{[data-md-color-scheme=slate]{--md-default-fg-color:hsla(var(--md-hue),15%,90%,0.82);--md-default-fg-color--light:hsla(var(--md-hue),15%,90%,0.56);--md-default-fg-color--lighter:hsla(var(--md-hue),15%,90%,0.32);--md-default-fg-color--lightest:hsla(var(--md-hue),15%,90%,0.12);--md-default-bg-color:hsla(var(--md-hue),15%,14%,1);--md-default-bg-color--light:hsla(var(--md-hue),15%,14%,0.54);--md-default-bg-color--lighter:hsla(var(--md-hue),15%,14%,0.26);--md-default-bg-color--lightest:hsla(var(--md-hue),15%,14%,0.07);--md-code-fg-color:hsla(var(--md-hue),18%,86%,0.82);--md-code-bg-color:hsla(var(--md-hue),15%,18%,1);--md-code-bg-color--light:hsla(var(--md-hue),15%,18%,0.9);--md-code-bg-color--lighter:hsla(var(--md-hue),15%,18%,0.54);--md-code-hl-color:#2977ff;--md-code-hl-color--light:#2977ff1a;--md-code-hl-number-color:#e6695b;--md-code-hl-special-color:#f06090;--md-code-hl-function-color:#c973d9;--md-code-hl-constant-color:#9383e2;--md-code-hl-keyword-color:#6791e0;--md-code-hl-string-color:#2fb170;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-kbd-color:hsla(var(--md-hue),15%,90%,0.12);--md-typeset-kbd-accent-color:hsla(var(--md-hue),15%,90%,0.2);--md-typeset-kbd-border-color:hsla(var(--md-hue),15%,14%,1);--md-typeset-mark-color:#4287ff4d;--md-typeset-table-color:hsla(var(--md-hue),15%,95%,0.12);--md-typeset-table-color--light:hsla(var(--md-hue),15%,95%,0.035);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-footer-bg-color:hsla(var(--md-hue),15%,10%,0.87);--md-footer-bg-color--dark:hsla(var(--md-hue),15%,8%,1);--md-shadow-z1:0 0.2rem 0.5rem #0000000d,0 0 0.05rem #0000001a;--md-shadow-z2:0 0.2rem 0.5rem #00000040,0 0 0.05rem #00000040;--md-shadow-z3:0 0.2rem 0.5rem #0006,0 0 0.05rem #00000059;color-scheme:dark}[data-md-color-scheme=slate] img[src$="#gh-light-mode-only"],[data-md-color-scheme=slate] img[src$="#only-light"]{display:none}[data-md-color-scheme=slate][data-md-color-primary=pink]{--md-typeset-a-color:#ed5487}[data-md-color-scheme=slate][data-md-color-primary=purple]{--md-typeset-a-color:#c46fd3}[data-md-color-scheme=slate][data-md-color-primary=deep-purple]{--md-typeset-a-color:#a47bea}[data-md-color-scheme=slate][data-md-color-primary=indigo]{--md-typeset-a-color:#5488e8}[data-md-color-scheme=slate][data-md-color-primary=teal]{--md-typeset-a-color:#00ccb8}[data-md-color-scheme=slate][data-md-color-primary=green]{--md-typeset-a-color:#71c174}[data-md-color-scheme=slate][data-md-color-primary=deep-orange]{--md-typeset-a-color:#ff764d}[data-md-color-scheme=slate][data-md-color-primary=brown]{--md-typeset-a-color:#c1775c}[data-md-color-scheme=slate][data-md-color-primary=black],[data-md-color-scheme=slate][data-md-color-primary=blue-grey],[data-md-color-scheme=slate][data-md-color-primary=grey],[data-md-color-scheme=slate][data-md-color-primary=white]{--md-typeset-a-color:#5e8bde}[data-md-color-switching] *,[data-md-color-switching] :after,[data-md-color-switching] :before{transition-duration:0ms!important}}[data-md-color-accent=red]{--md-accent-fg-color:#ff1947;--md-accent-fg-color--transparent:#ff19471a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=pink]{--md-accent-fg-color:#f50056;--md-accent-fg-color--transparent:#f500561a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=purple]{--md-accent-fg-color:#df41fb;--md-accent-fg-color--transparent:#df41fb1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=deep-purple]{--md-accent-fg-color:#7c4dff;--md-accent-fg-color--transparent:#7c4dff1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=indigo]{--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:#526cfe1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=blue]{--md-accent-fg-color:#4287ff;--md-accent-fg-color--transparent:#4287ff1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=light-blue]{--md-accent-fg-color:#0091eb;--md-accent-fg-color--transparent:#0091eb1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=cyan]{--md-accent-fg-color:#00bad6;--md-accent-fg-color--transparent:#00bad61a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=teal]{--md-accent-fg-color:#00bda4;--md-accent-fg-color--transparent:#00bda41a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=green]{--md-accent-fg-color:#00c753;--md-accent-fg-color--transparent:#00c7531a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=light-green]{--md-accent-fg-color:#63de17;--md-accent-fg-color--transparent:#63de171a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=lime]{--md-accent-fg-color:#b0eb00;--md-accent-fg-color--transparent:#b0eb001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=yellow]{--md-accent-fg-color:#ffd500;--md-accent-fg-color--transparent:#ffd5001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=amber]{--md-accent-fg-color:#fa0;--md-accent-fg-color--transparent:#ffaa001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=orange]{--md-accent-fg-color:#ff9100;--md-accent-fg-color--transparent:#ff91001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=deep-orange]{--md-accent-fg-color:#ff6e42;--md-accent-fg-color--transparent:#ff6e421a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-primary=red]{--md-primary-fg-color:#ef5552;--md-primary-fg-color--light:#e57171;--md-primary-fg-color--dark:#e53734;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=pink]{--md-primary-fg-color:#e92063;--md-primary-fg-color--light:#ec417a;--md-primary-fg-color--dark:#c3185d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=purple]{--md-primary-fg-color:#ab47bd;--md-primary-fg-color--light:#bb69c9;--md-primary-fg-color--dark:#8c24a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=deep-purple]{--md-primary-fg-color:#7e56c2;--md-primary-fg-color--light:#9574cd;--md-primary-fg-color--dark:#673ab6;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=indigo]{--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=blue]{--md-primary-fg-color:#2094f3;--md-primary-fg-color--light:#42a5f5;--md-primary-fg-color--dark:#1975d2;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=light-blue]{--md-primary-fg-color:#02a6f2;--md-primary-fg-color--light:#28b5f6;--md-primary-fg-color--dark:#0287cf;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=cyan]{--md-primary-fg-color:#00bdd6;--md-primary-fg-color--light:#25c5da;--md-primary-fg-color--dark:#0097a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=teal]{--md-primary-fg-color:#009485;--md-primary-fg-color--light:#26a699;--md-primary-fg-color--dark:#007a6c;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=green]{--md-primary-fg-color:#4cae4f;--md-primary-fg-color--light:#68bb6c;--md-primary-fg-color--dark:#398e3d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=light-green]{--md-primary-fg-color:#8bc34b;--md-primary-fg-color--light:#9ccc66;--md-primary-fg-color--dark:#689f38;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=lime]{--md-primary-fg-color:#cbdc38;--md-primary-fg-color--light:#d3e156;--md-primary-fg-color--dark:#b0b52c;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=yellow]{--md-primary-fg-color:#ffec3d;--md-primary-fg-color--light:#ffee57;--md-primary-fg-color--dark:#fbc02d;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=amber]{--md-primary-fg-color:#ffc105;--md-primary-fg-color--light:#ffc929;--md-primary-fg-color--dark:#ffa200;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=orange]{--md-primary-fg-color:#ffa724;--md-primary-fg-color--light:#ffa724;--md-primary-fg-color--dark:#fa8900;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=deep-orange]{--md-primary-fg-color:#ff6e42;--md-primary-fg-color--light:#ff8a66;--md-primary-fg-color--dark:#f4511f;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=brown]{--md-primary-fg-color:#795649;--md-primary-fg-color--light:#8d6e62;--md-primary-fg-color--dark:#5d4037;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=grey]{--md-primary-fg-color:#757575;--md-primary-fg-color--light:#9e9e9e;--md-primary-fg-color--dark:#616161;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-typeset-a-color:#4051b5}[data-md-color-primary=blue-grey]{--md-primary-fg-color:#546d78;--md-primary-fg-color--light:#607c8a;--md-primary-fg-color--dark:#455a63;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-typeset-a-color:#4051b5}[data-md-color-primary=light-green]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#72ad2e}[data-md-color-primary=lime]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#8b990a}[data-md-color-primary=yellow]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#b8a500}[data-md-color-primary=amber]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#d19d00}[data-md-color-primary=orange]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#e68a00}[data-md-color-primary=white]{--md-primary-fg-color:hsla(var(--md-hue),0%,100%,1);--md-primary-fg-color--light:hsla(var(--md-hue),0%,100%,0.7);--md-primary-fg-color--dark:hsla(var(--md-hue),0%,0%,0.07);--md-primary-bg-color:hsla(var(--md-hue),0%,0%,0.87);--md-primary-bg-color--light:hsla(var(--md-hue),0%,0%,0.54);--md-typeset-a-color:#4051b5}[data-md-color-primary=white] .md-button{color:var(--md-typeset-a-color)}[data-md-color-primary=white] .md-button--primary{background-color:var(--md-typeset-a-color);border-color:var(--md-typeset-a-color);color:hsla(var(--md-hue),0%,100%,1)}@media screen and (min-width:60em){[data-md-color-primary=white] .md-search__form{background-color:hsla(var(--md-hue),0%,0%,.07)}[data-md-color-primary=white] .md-search__form:hover{background-color:hsla(var(--md-hue),0%,0%,.32)}[data-md-color-primary=white] .md-search__input+.md-search__icon{color:hsla(var(--md-hue),0%,0%,.87)}}@media screen and (min-width:76.25em){[data-md-color-primary=white] .md-tabs{border-bottom:.05rem solid #00000012}}[data-md-color-primary=black]{--md-primary-fg-color:hsla(var(--md-hue),15%,9%,1);--md-primary-fg-color--light:hsla(var(--md-hue),15%,9%,0.54);--md-primary-fg-color--dark:hsla(var(--md-hue),15%,9%,1);--md-primary-bg-color:hsla(var(--md-hue),15%,100%,1);--md-primary-bg-color--light:hsla(var(--md-hue),15%,100%,0.7);--md-typeset-a-color:#4051b5}[data-md-color-primary=black] .md-button{color:var(--md-typeset-a-color)}[data-md-color-primary=black] .md-button--primary{background-color:var(--md-typeset-a-color);border-color:var(--md-typeset-a-color);color:hsla(var(--md-hue),0%,100%,1)}[data-md-color-primary=black] .md-header{background-color:hsla(var(--md-hue),15%,9%,1)}@media screen and (max-width:59.984375em){[data-md-color-primary=black] .md-nav__source{background-color:hsla(var(--md-hue),15%,11%,.87)}}@media screen and (max-width:76.234375em){html [data-md-color-primary=black] .md-nav--primary .md-nav__title[for=__drawer]{background-color:hsla(var(--md-hue),15%,9%,1)}}@media screen and (min-width:76.25em){[data-md-color-primary=black] .md-tabs{background-color:hsla(var(--md-hue),15%,9%,1)}} \ No newline at end of file diff --git a/css/timeago.css b/css/timeago.css new file mode 100644 index 0000000..f7ab7d6 --- /dev/null +++ b/css/timeago.css @@ -0,0 +1,15 @@ +/* + timeago output is dynamic, which breaks when you print a page. + + This CSS is only included when type: timeago + and ensures fallback to type "iso_date" when printing. + + */ + +.git-revision-date-localized-plugin-iso_date { display: none } + +@media print { + .git-revision-date-localized-plugin-iso_date { display: inline } + .git-revision-date-localized-plugin-timeago { display: none } +} + diff --git a/docs/api_arduino.md b/docs/api_arduino.md deleted file mode 100644 index 15126c4..0000000 --- a/docs/api_arduino.md +++ /dev/null @@ -1,44 +0,0 @@ -# Arduino Print - -Methods used to support Arduino Print functionality. - -### setCursor() - -This method is called set the "cursor" position in the device. The library supports the Arduino `Print` interface, enabling the use of a `print()` and `println()` methods. The set cursor position defines where to start text output for this functionality. - -```c++ -void setCursor(uint8_t x, uint8_t y) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| x | `uint8_t` | The X coordinate of the cursor| -| y | `uint8_t` | The Y coordinate of the cursor| - -### setColor() - -This method is called to set the current color of the system. This is used by the Arduino `Print` interface functionality - - -```c++ -void setColor(uint8_t clr) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| `clr` | `uint8_t` | The color to set. 0 = black, > 0 = white| - -### getColor() - -This method is called to get the current color of the system. This is used by the Arduino `Print` interface functionality - - -```c++ -uint8_t getColor(void) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| return value| `uint8_t` | The current color| - - diff --git a/docs/api_device.md b/docs/api_device.md deleted file mode 100644 index 138794d..0000000 --- a/docs/api_device.md +++ /dev/null @@ -1,101 +0,0 @@ -# Device Operations - -Methods to setup the device, get device information and change display options. - -## Initialization - -### begin() -This method is called to initialize the OLED library and connection to the OLED device. This method must be called before calling any graphics methods. - -```c++ -bool begin(TwoWire &wirePort, uint8_t address) -``` - -| Parameter | Type | Description | -| :------------ | :---------- | :---------------------------------------------- | -| `wirePort` | `TwoWire` | **optional**. The Wire port. If not provided, the default port is used| -| `address` | `uint8_t` | **optional**. I2C Address. If not provided, the default address is used.| -| return value | `bool` | ```true``` on success, ```false``` on startup failure | - -### reset() -When called, this method reset the library state and OLED device to their intial state. Helpful to reset the OLED after waking up a system from a sleep state. - -```C++ -void reset() -``` - -| Parameter | Type | Description | -| :------------ | :---------- | :---------------------------------------------- | -| return value | `bool` | ```true``` on success, ```false``` on startup failure | - - -## Geometry - -### getWidth() -This method returns the width, in pixels, of the connected OLED device - -```c++ -uint8_t getWidth(void) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| return value | `uint8_t` | The width in pixels of the connected OLED device | - -### getHeight() -This method returns the height, in pixels, of the connected OLED device - -```c++ -uint8_t getHeight(void) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| return value | `uint8_t` | The height in pixels of the connected OLED device | - -## Display Modes - -### invert() -This method inverts the current graphics on the display. This results of this command happen immediatly. - -```c++ -void invert(bool bInvert) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| ```bInvert``` | `bool` | ```true``` - the screen is inverted. ```false``` - the screen is set to normal | - -### flipVertical() -When called, the screen contents are flipped vertically if the flip parameter is true, or restored to normal display if the flip parameter is false. - -```c++ -void flipVertical(bool bFlip) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| ```bFlip``` | `bool` | ```true``` - the screen is flipped vertically. ```false``` - the screen is set to normal | - -### flipHorizontal() -When called, the screen contents are flipped horizontally if the flip parameter is true, or restored to normal display if the flip parameter is false. - -```c++ -void flipHorizontal(bool bFlip) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| ```bFlip``` | `bool` | ```true``` - the screen is flipped horizontally. ```false``` - the screen is set to normal | - -### displayPower() -Used to turn the OLED display on or off. - -```c++ -void displayPower(bool bEnable) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| ```bEnable``` | `bool` | ```true``` - the OLED display is powered on (default). ```false``` - the OLED dsiplay is powered off. | - diff --git a/docs/api_draw.md b/docs/api_draw.md deleted file mode 100644 index 624821f..0000000 --- a/docs/api_draw.md +++ /dev/null @@ -1,131 +0,0 @@ -# Drawing Settings/State - -Methods for setting the drawing state of the library. - -### setFont() - -This method is called to set the current font in the library. The current font is used when calling the ```text()``` method on this device. - -The default font for the device is `5x7`. - -```c++ -void setFont(QwiicFont& theFont) -void setFont(const QwiicFont * theFont) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| `theFont` | `QwiicFont` | The font to set as current in the device| -| `theFont` | `QwiicFont*` | Pointer to the font to set as current in the device.| - -For the library, fonts are added to your program by including them via include files which are part of this library. - -The following fonts are included: - -| Font | Include File | Font Variable | Description| -| :--- | :--- | :--- | :--- | -| 5x7 | `` | `QW_FONT_5X7`| A full, 5 x 7 font| -| 31x48 | `` |`QW_FONT_31X48`| A full, 31 x 48 font| -| Seven Segment | `` |`QW_FONT_7SEGMENT`| Numbers only| -| 8x16 | `` | `QW_FONT_8X16`| A full, 8 x 16 font| -| Large Numbers | `` |`QW_FONT_LARGENUM`| Numbers only| - -For each font, the font variables are objects with the following attributes: - -| Attribute | Value | -| :--- | :--- | -| `width` | The font width in pixels| -| `height` | The font height in pixels| -| `start` | The font start character offset| -| `n_chars` | The number of characters| -| `map_width` | The width of the font map| - -Example use of a font object attribute: -```C++ -#include - -int myFontWidth = QW_FONT_31X48.width; -``` - -### getFont() -This method returns the current font for the device. - -```c++ -QwiicFont * getFont(void) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| return value | `QwiicFont*` | A pointer to the current font. See `setFont()` for font object details.| - -### getFontName() - -This method returns the height in pixels of a provided String based on the current device font. - -```c++ -String getFontName(void) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| return value | String | The name of the current font.| - -### getStringWidth() - -This method returns the width in pixels of a provided String based on the current device font. - -```c++ -unsigned int getStringWidth(String text) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| text | `String` | The string used to determine width | -| return value | `unsigned int` | The width of the provide string, as determined using the current font.| - -### getStringHeight() - -This method returns the height in pixels of a provided String based on the current device font. - -```c++ -unsigned int getStringHeight(String text) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| text | `String` | The string used to determine height | -| return value | `unsigned int` | The height of the provide string, as determined using the current font.| - -### setDrawMode() -This method sets the current draw mode for the library. The draw mode determines how pixels are set on the screen during drawing operations. - -```c++ -void setDrawMode(grRasterOp_t rop) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| rop | `grRasterOp_t` | The raster operation (ROP) to set the graphics system to.| - -Raster operations device how source (pixels to draw) are represented on the destination device. The available Raster Operation (ROP) codes are: - -| ROP Code | Description| -| :--- | :--- | -| grROPCopy | **default** Drawn pixel values are copied to the device screen| -| grROPNotCopy | A not operation is applied to the source value before copying to screen| -| grROPNot | A not operation is applied to the destination (screen) value | -| grROPXOR | A XOR operation is performed between the source and destination values| -| grROPBlack | A value of 0, or black is drawn to the destination | -| grROPWhite | A value of 1, or black is drawn to the destination | - - -### getDrawMode() -This method returns the current draw mode for the library. The draw mode determines how pixels are set on the screen during drawing operations. - -```c++ -grRasterOp_t getDrawMode(void) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| return value | `grRasterOp_t` | The current aster operation (ROP) of the graphics system.| diff --git a/docs/api_graphics.md b/docs/api_graphics.md deleted file mode 100644 index dab3928..0000000 --- a/docs/api_graphics.md +++ /dev/null @@ -1,190 +0,0 @@ -# Graphics Methods - -Methods used to draw and display graphics. - -### display() -When called, any pending display updates are sent to the connected OLED device. This includes drawn graphics and erase commands. - -```c++ -void display(void) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| NONE| | | - -### erase() -Erases all graphics on the device, placing the display in a blank state. The erase update isn't sent to the device until the next ```display()``` call on the device. - -```c++ -void erase(void) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| NONE| | | - -### pixel() - -Set the value of a pixel on the screen. - -```c++ -void pixel(uint8_t x, uint8_t y, uint8_t clr) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| x | `uint8_t` | The X coordinate of the pixel to set| -| y | `uint8_t` | The Y coordinate of the pixel to set| -| clr | `uint8_t` | **optional** The color value to set the pixel. This defaults to white (1).| - -### line() - -Draw a line on the screen. - -Note: If a line is horizontal (y0 = y1) or vertical (x0 = x1), optimized draw algorithms are used by the library. - -```c++ -void line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| x0 | `uint8_t` | The start X coordinate of the line| -| y0 | `uint8_t` | The start Y coordinate of the line| -| x1 | `uint8_t` | The end X coordinate of the line| -| y1 | `uint8_t` | The end Y coordinate of the line| -| clr | `uint8_t` | **optional** The color value to draw the line. This defaults to white (1).| - -### rectangle() - -Draw a rectangle on the screen. - -```c++ -void rectangle(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| x0 | `uint8_t` | The start X coordinate of the rectangle - upper left corner| -| y0 | `uint8_t` | The start Y coordinate of the rectangle - upper left corner| -| width | `uint8_t` | The width of the rectangle| -| height | `uint8_t` | The height of the rectangle| -| clr | `uint8_t` | **optional** The color value to draw the line. This defaults to white (1).| - -### rectangleFill() - -Draw a filled rectangle on the screen. - -```c++ -void rectangleFill(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| x0 | `uint8_t` | The start X coordinate of the rectangle - upper left corner| -| y0 | `uint8_t` | The start Y coordinate of the rectangle - upper left corner| -| width | `uint8_t` | The width of the rectangle| -| height | `uint8_t` | The height of the rectangle| -| clr | `uint8_t` | **optional** The color value to draw the line. This defaults to white (1).| - -### circle() - -Draw a circle on the screen. - -```c++ -void circle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| x0 | `uint8_t` | The X coordinate of the circle center| -| y0 | `uint8_t` | The Y coordinate of the circle center| -| radius | `uint8_t` | The radius of the circle| -| clr | `uint8_t` | **optional** The color value to draw the circle. This defaults to white (1).| - -### circleFill() - -Draw a filled circle on the screen. - -```c++ -void circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| x0 | `uint8_t` | The X coordinate of the circle center| -| y0 | `uint8_t` | The Y coordinate of the circle center| -| radius | `uint8_t` | The radius of the circle| -| clr | `uint8_t` | **optional** The color value to draw the circle. This defaults to white (1).| - -### bitmap() - -Draws a bitmap on the screen. - -The bitmap should be 8 bit encoded - each pixel contains 8 y values. - -```c++ -void bitmap(uint8_t x0, uint8_t y0, uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height ) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| x0 | `uint8_t` | The X coordinate to place the bitmap - upper left corner| -| y0 | `uint8_t` | The Y coordinate to place the bitmap - upper left corner| -| pBitmap | `uint8_t *` | A pointer to the bitmap array| -| bmp_width | `uint8_t` | The width of the bitmap| -| bmp_height | `uint8_t` | The height of the bitmap| - -### bitmap() - -Draws a bitmap on the screen. - -The bitmap should be 8 bit encoded - each pixel contains 8 y values. - -The coordinate [x1,y1] allows for only a portion of bitmap to be drawn. - -```c++ -void bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, - uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height ) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| x0 | `uint8_t` | The X coordinate to place the bitmap - upper left corner| -| y0 | `uint8_t` | The Y coordinate to place the bitmap - upper left corner| -| x1 | `uint8_t` | The end X coordinate of the bitmap - lower right corner| -| y1 | `uint8_t` | The end Y coordinate of the bitmap - lower right corner| -| pBitmap | `uint8_t *` | A pointer to the bitmap array| -| bmp_width | `uint8_t` | The width of the bitmap| -| bmp_height | `uint8_t` | The height of the bitmap| - -### bitmap() - -Draws a bitmap on the screen using a Bitmap object for the bitmap data. - -```c++ -void bitmap(uint8_t x0, uint8_t y0, QwiicBitmap& bitmap) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| x0 | `uint8_t` | The X coordinate to place the bitmap - upper left corner| -| y0 | `uint8_t` | The Y coordinate to place the bitmap - upper left corner| -| Bitmap | `QwiicBitmap` | A bitmap object| - -### text() - -Draws a string using the current font on the screen. - -```c++ -void text(uint8_t x0, uint8_t y0, const char * text, uint8_t clr) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| x0 | `uint8_t` | The X coordinate to start drawing the text| -| y0 | `uint8_t` | The Y coordinate to start drawing the text| -| text | `const char*` | The string to draw on the screen | -| text | `String` | The Arduino string to draw on the screen | -| clr | `uint8_t` | **optional** The color value to draw the circle. This defaults to white (1).| diff --git a/docs/api_scroll.md b/docs/api_scroll.md deleted file mode 100644 index e7f60a9..0000000 --- a/docs/api_scroll.md +++ /dev/null @@ -1,89 +0,0 @@ -# Scrolling - -Methods for device scrolling - -### scrollStop() -If the device is in a scrolling mode, calling this method stops the scroll, and restores the device to normal display operation. This action is performed immediately. - -```c++ -void scrollStop(void) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| NONE| | | - - - -### scrollRight() -This method is called to start the device scrolling the displayed graphics to the right. This action is performed immediately. - -The screen will scroll until the ```scrollStop()``` method is called. - -```c++ -void scrollRight(uint8_t start, uint8_t stop, uint8_t interval) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| `start` | `uint8_t` | The start page address of the scroll - valid values are 0 thru 7| -| `stop` | `uint8_t` | The stop/end page address of the scroll - valid values are 0 thru 7| -| `interval` | `uint8_t` | The time interval between scroll step - values listed below | - -Defined values for the `interval` parameter: - -| Defined Symbol | Time Interval Between Steps | -| :--- | :---| -|`SCROLL_INTERVAL_2_FRAMES` | 2 | -|`SCROLL_INTERVAL_3_FRAMES` | 3 | -|`SCROLL_INTERVAL_4_FRAMES` | 4 | -|`SCROLL_INTERVAL_5_FRAMES` | 5 | -|`SCROLL_INTERVAL_25_FRAMES` | 25 | -|`SCROLL_INTERVAL_64_FRAMES` | 64 | -|`SCROLL_INTERVAL_128_FRAMES` | 128 | -|`SCROLL_INTERVAL_256_FRAMES` | 256 | - -### scrollVertRight() -This method is called to start the device scrolling the displayed graphics vertically and to the right. This action is performed immediately. - -The screen will scroll until the ```scrollStop()``` method is called. - -```c++ -void scrolVertlRight(uint8_t start, uint8_t stop, uint8_t interval) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| `start` | `uint8_t` | The start page address of the scroll - valid values are 0 thru 7| -| `stop` | `uint8_t` | The stop/end page address of the scroll - valid values are 0 thru 7| -| `interval` | `uint8_t` | The time interval between scroll step - values listed in ```scrollRight``` | - -### scrollLeft() -This method is called start to the device scrolling the displayed graphics to the left. This action is performed immediately. - -The screen will scroll until the ```scrollStop()``` method is called. - -```c++ -void scrollLeft(uint8_t start, uint8_t stop, uint8_t interval) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| `start` | `uint8_t` | The start page address of the scroll - valid values are 0 thru 7| -| `stop` | `uint8_t` | The stop/end page address of the scroll - valid values are 0 thru 7| -| `interval` | `uint8_t` | The time interval between scroll step - values listed in ```scrollRight``` | - -### scrollVertLeft() -This method is called to start the device scrolling the displayed graphics vertically and to the left. This action is performed immediately. - -The screen will scroll until the ```scrollStop()``` method is called. - -```c++ -void scrolVertlLeft(uint8_t start, uint8_t stop, uint8_t interval) -``` - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| `start` | `uint8_t` | The start page address of the scroll - valid values are 0 thru 7| -| `stop` | `uint8_t` | The stop/end page address of the scroll - valid values are 0 thru 7| -| `interval` | `uint8_t` | The time interval between scroll step - values listed in ```scrollRight``` | diff --git a/docs/github/contribute.md b/docs/github/contribute.md deleted file mode 100644 index 85d9937..0000000 --- a/docs/github/contribute.md +++ /dev/null @@ -1,38 +0,0 @@ -# Contribute: Help Fix our Mistake! -Spot something wrong? Feel free to contribute our open-source design and documentation. - -## Improve our Documentation -All of this documentation can be modified by you! Please help us make it better. - -* These pages are contained in the [`docs` folder of the SparkFun Qwiic OLED Arduino Library repository](https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library/tree/main/docs). - -### Submit a Correction -1. Fork this repo -2. Add your corrections or improvements to the markdown file -3. File a pull request with your changes, and enjoy making the ~~words~~ ~~worlds~~ world a better place. - * Once received, the documentation specialist will automatically be notified. - * We will review your suggested improvements to make sure they are correct and fit within our documentation standards. - -## Improve our Hardware Design -All of our designs are open-source! Please help us make it better. - -* Our board design files are contained in the `Hardware` folder of their respective repositories: - -* [SparkFun Micro OLED Breakout (Qwiic)](https://github.com/sparkfun/Qwiic_Micro_OLED/tree/main/Hardware) -* [SparkFun Qwiic OLED Display (0.91 in, 128x32)](https://github.com/sparkfun/SparkFun_Qwiic_OLED-0.91/tree/main/Hardware) -* [SparkFun Transparent Graphical OLED Breakout (Qwiic)](https://github.com/sparkfun/Qwiic_Transparent_Graphical_OLED/tree/main/Hardware) -* [SparkFun Qwiic OLED - (1.3in., 128x64)](https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library/tree/main/Hardware) - -### Submit a Design Improvement -1. Fork this repo -2. Add your design improvements -3. File a pull request with your changes, and enjoy making the ~~words~~ ~~worlds~~ world a better place. - * Once received, the engineer in charge of the original design will automatically be notified. - * We will review your suggested improvements, if they are within our board design standards and meet our product design requirements, we will flag these changes for our next board revision. *(Please note, that even if your suggestion is accepted, these changes may not be immediate. We may have to cycle through our current product inventory first.)* - -## Contributors -Let's provided some recognition to the contributors for this project! - -![GitHub Contributors Image](https://contrib.rocks/image?repo=sparkfun/SparkFun_Qwiic_OLED_Arduino_Library/) -
- diff --git a/docs/github/file_issue.md b/docs/github/file_issue.md deleted file mode 100644 index 9407e2a..0000000 --- a/docs/github/file_issue.md +++ /dev/null @@ -1,52 +0,0 @@ -# Did we make a mistake? - -Spot something wrong? Please let us know. - -!!! attention - This is not where customers should seek assistance on a product. If you require technical assistance or have questions about a product that is not working as expected, please head over to the [SparkFun Technical Assistance](https://www.sparkfun.com/technical_assistance) page for some initial troubleshooting. -
- [SparkFun Technical Assistance Page](https://www.sparkfun.com/technical_assistance){ .md-button .md-button--primary } -
- - If you can't find what you need there, you'll need a [Forum Account](https://forum.sparkfun.com/ucp.php?mode=register) to search product forums and post questions. - -## Discrepancies in the Documentation - -All of this documentation can be modified by you! Please help us make it better. - -* The documentation files for these pages are contained in the [`docs` folder of the SparkFun Qwiic OLED Arduino Library repository](https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library/tree/main/docs). - -### Spot something wrong? -If a section of the documentation is incorrect, please [open an issue](https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library/issues) and let us know. - -### Do you have a suggested correction? -1. With a GitHub account, fork this repo -2. Add your correction(s) or improvement(s) to the markdown file(s) -3. File a pull request with your changes, and enjoy making the ~~words~~ ~~worlds~~ world a better place. - * Once received, the documentation specialist will automatically be notified. - * We will review your suggested improvement(s) to make sure they are correct and fit within our documentation standards. - -## Problems in the Hardware Design - -All of our designs are open-source! Please help us make it better. - -Our board design files are contained in the `Hardware` folder of their respective repositories: - -* [SparkFun Micro OLED Breakout (Qwiic)](https://github.com/sparkfun/Qwiic_Micro_OLED/tree/main/Hardware) -* [SparkFun Qwiic OLED Display (0.91 in, 128x32)](https://github.com/sparkfun/SparkFun_Qwiic_OLED-0.91/tree/main/Hardware) -* [SparkFun Transparent Graphical OLED Breakout (Qwiic)](https://github.com/sparkfun/Qwiic_Transparent_Graphical_OLED/tree/main/Hardware) -* [SparkFun Qwiic OLED - (1.3in., 128x64)](https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library/tree/main/Hardware) - -### Does something not make sense? -If part of the design is confusing, please [open an issue](https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library/issues) and let us know. - -### Did we forget to include an important function of the board? -* Please keep in mind that we may intentionally exclude certain functions of the board to meet our product design requirements. *(For example, our Qwiic Micro boards are intended to fit on a small board layout and only use I2C communication; therefore, we may not have the SPI and interrupt pins available for users.)* -* If part of the board's functionality is missing, please [open an issue](https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library/issues) and file a feature request. - -### Do you wish to contribute directly to improving the board design? -1. With a GitHub account, Fork this repo -2. Add your design improvement(s) -3. File a pull request with your changes, and enjoy making the ~~words~~ ~~worlds~~ world a better place. - * Once received, the engineer in charge of the original design will automatically be notified. - * We will review your suggested improvement(s), if they are within our board design standards and meet our product design requirements, we will flag these changes for our next board revision. *(Please note, that even if your suggestion is accepted, these changes may not be immediate. We may have to cycle through our current product inventory first.)* diff --git a/docs/hug_0p91.md b/docs/hug_0p91.md deleted file mode 100644 index 806739d..0000000 --- a/docs/hug_0p91.md +++ /dev/null @@ -1,505 +0,0 @@ -## Introduction - -The [SparkFun Qwiic OLED Display](https://www.sparkfun.com/products/24606) can display up to four lines of text and features 128x32 pixels in a small 0.91” (diagonal) frame. As an OLED, this display does not have a back light layer (unlike LCDs) and therefore it’s thinner, consumes less power, and has higher contrast. - -
- -
- -In this section, we'll go over the hardware and how to hookup the breakout board. - - - -### Required Materials - -To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary. - -* 1x [SparkFun RedBoard Plus [DEV-18158]](https://www.sparkfun.com/products/18158) -* 1x [Reversible USB A to C Cable - 0.8m [CAB-15425]](https://www.sparkfun.com/products/15425) -* 1x Qwiic Cable - * [Flexible Qwiic Cable - 50mm [PRT-17260]](https://www.sparkfun.com/products/17260), for short distances - * [Flexible Qwiic Cable - 500mm [PRT-17257]](https://www.sparkfun.com/products/17257), for those that need to wire the board farther away from your microcontroller -* 1x [SparkFun Qwiic OLED Display (0.91 in., 128x32) [LCD-22495]](https://www.sparkfun.com/products/22495) - - - -#### Microcontroller - -To get started, you'll need a microcontroller to, well, control everything. We used the RedBoard with the ATmega328P for the Qwiic micro OLED. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier. - - - - - -#### USB Cable - -Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller. - - - - -#### Qwiic - -If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed: - - - - - -You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs. - - - -Of course, you will also need a Qwiic Micro OLED if you have not added that to you cart already. - -
- -
- - - -## Hardware Overview - -In this section, we will highlight the hardware and pins that are broken out on the SparkFun Qwiic OLED Display (0.91 in., 128x32). - -
- - - - - - - - - -
Top ViewBottom View
Top ViewBottom View
-
- - - -### OLED Display (0.91", 128x32) - -The OLED screen has a pixel resolution of 128x32, a panel size of 30.0mm x 11.5mm x 1.2mm, and an active area of 22.384mm x 5.584mm. The driver chip is the SSD1306. For information can be found in the datasheet linked in the Resources. - -
- - - - - - - -
OLED Highlighted
OLED Highlighted
-
- -!!! note - The SparkFun Qwiic OLED Arduino Library works for multiple displays. However, there are some caveats in the size of the display with the text. While you can technically display all fonts in the narrow OLED display, some characters (numbers, letters, and/or symbols depending on the font) will be too big to fully display on the screen. For example, the fonts for the 31x48 (i.e. `&QW_FONT_31X48`) and large numbers (i.e. `&QW_FONT_LARGENUM`) are too big to fit within the display. - - Using the OLED display (0.91", 128x32) we found that we were able to fit: - - * 4x lines, 21x characters using the 5x7 (i.e. `&QW_FONT_5X7`) - * 2x lines, 14x characters using the 8x16 (i.e. `&QW_FONT_8X16`) - * 2x lines, 11x characters using the 7 segment (i.e. `&QW_FONT_7SEGMENT`) - - - -### Power - -Power is applied through the vertical Qwiic connectors on the back of the board. The recommended input voltage is **3.3V**. The logic levels for the Qwiic OLED Display (0.9", 128x32) is **3.3V**. - -
- - - - - - - -
Power
Power
-
- - - -### Qwiic and I2C - -There are two vertical Qwiic connectors populated on the back of the board. You can use either connectors to provide power and send data through I2C. The [Qwiic ecosystem](https://www.sparkfun.com/qwiic) is made for fast prototyping by removing the need for soldering. All you need to do is plug a Qwiic cable into the Qwiic connector and voila! - -* **SCL** — I2C clock -* **SDA** — I2C data -* **3.3V** — Power -* **GND** — Ground - -
- - - - - - - -
Qwiic Connectors
Vertical Qwiic Connectors
-
- -The address of the display is **0x3C**. - -!!! note - On the back of the board, the power and I2C pins are broken out to test points. These are used in our production department for quality control using custom testbeds. These could be an alternative option to connect to the pins. However, we recommend using the Qwiic connectors to easily connect to the OLED display. Note that the I2C pins are also in a different order compared to a standard I2C Qwiic connector should you decide to solder to the test points. - -
- - - - - - - -
I2C Test Points
I2C Test Points
-
- - - -### Jumpers - -!!!note - If this is your first time working with jumpers, check out the [How to Work with Jumper Pads and PCB Traces](https://learn.sparkfun.com/tutorials/how-to-work-with-jumper-pads-and-pcb-traces/all) tutorial for more information. - -The board includes a 1x3 jumper on the back of the board. - -* **I2C** — This three way jumper labeled **I2C** is connected to two 4.7kΩ pull-up resistors to the I2C data and clock lines. For users that have multiple Qwiic-enabled devices with pull-up resistors enabled, the parallel equivalent resistance will create too strong of a pull-up for the bus to operate correctly. As a general rule of thumb, [disable all but one pair of pull-up resistors](https://learn.sparkfun.com/tutorials/i2c/all#i2c-at-the-hardware-level) if multiple devices are connected to the bus. - -
- - - - - - - -
Jumpers Highlighted
Jumpers Highlighted
-
- - - -### Board Dimensions - -Version 1.1 is a bit smaller than previous versions since the board includes vertical Qwiic connectors on the back of the board. The overall board size is 1.75 in x 0.5 in. The mounting holes have also moved to toward the top of the board. - -
- - - - - - - -
Board Dimensions
Board Dimensions
-
- - - -## Hardware Hookup - -In this section, we'll go over how to connect to the display. We will go just a bit further and talk about how to mount the display. - - - -### Connecting via Qwiic Connector - -Insert a Qwiic cable between your chosen microcontroller and Qwiic OLED. Then insert a USB cable between the microcontroller and your computer's COM port. For the scope of this tutorial, the USB cable provides power and allows us to upload code to the microcontroller. Of course, you can also debug the display by opening a Serial Terminal. - -
- - - - - - - -
USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, Qwiic OLED (0.9 in., 12x32)
USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, Qwiic OLED (0.9 in., 12x32)
-
- -Once you have finished prototyping, you could continue to use the USB cable and add a 5V power supply or battery pack. - - - -### Mounting the Qwiic OLED (0.9", 128x32) - -Grab the board dimensions and cut out a rectangle in the enclosure. For users that want to mount the board so that the OLED display is flush against the enclosure, you will need to look at the dimensions based on the OLED. You will need to add a little tolerance so that the display can fit through the rectangle. For users that need to quickly mount the board, you will could also cut out rectangles based on the vertical Qwiic connector so that the wires can lead into the enclosure. Then cut out the mounting holes so that the board is right side up. In this case, we used a cardboard box as a quick example to demonstrate the Qwiic wires connecting leading into the enclosure. - -
- - - - - - - - -
5V Battery Pack, USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, and Qwiic OLED (0.9 in., 12x32), stuffed in a cardboard box.5V Battery Pack, USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, and Qwiic OLED (0.9 in., 12x32) Mounted
Qwiic OLED Display Mounted in an Enclosure
-
- -!!! note - To easily display text and graphics on the board, we recommend mounting the board right side up. There is an option in the example code to flip the text horizontally and vertically should you decide to mount the board upside down, but you would need to also determine the position of the text. - -For a more durable enclosure, you could use wood, metal, or plastic. However, you will need additional tools to cut into the material. - - - -## Software - -The Qwiic OLED (0.91", 128x32) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED Library's [Software Setup](../software/) has instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library [API Reference](../api_device/) guide. - - - - - -## Resources - -Now that you've successfully got your OLED Display (0.9", 128x36) up and running, it's time to incorporate it into your own project! For more information, check out the resources below: - -* [Schematic (PDF)](https://github.com/sparkfun/SparkFun_Qwiic_OLED-0.91/blob/main/docs/assets/board_files/SparkFun_Qwiic_OLED-0p91_Schematic_v11.pdf) -* [Eagle Files (ZIP)](https://github.com/sparkfun/SparkFun_Qwiic_OLED-0.91/blob/main/docs/assets/board_files/SparkFun_Qwiic_OLED-0p9in_v11.zip?raw=true) -* [Board Dimensions (PNG)](https://raw.githubusercontent.com/sparkfun/SparkFun_Qwiic_OLED-0.91/main/docs/assets/img/SparkFun_Qwiic_OLED-0p9in_Board_Dimensions.png) -* [Datasheet (PDF)](https://github.com/sparkfun/SparkFun_Qwiic_OLED-0.91/blob/main/docs/component_documentation/SPEC%20AMO091-12832BFG02-H14%20VER%20A.pdf._看图王.pdf) (0.91", 128x32, SSD1306) -* [ReadtheDocs: Qwiic_OLED_Display_Py](https://qwiic-oled-display-py.readthedocs.io/en/latest/) -* [Qwiic OLED Display Python Package Repo](https://github.com/sparkfun/Qwiic_OLED_Display_Py) -* [Github Hardware Repo](https://github.com/sparkfun/SparkFun_Qwiic_OLED-0.91/) diff --git a/docs/hug_1p3.md b/docs/hug_1p3.md deleted file mode 100644 index 0cc25e0..0000000 --- a/docs/hug_1p3.md +++ /dev/null @@ -1 +0,0 @@ -The Qwiic OLED 1.3in has its own [hook-up guide](https://docs.sparkfun.com/SparkFun_Qwiic_OLED_1.3in/). diff --git a/docs/hug_micro_view.md b/docs/hug_micro_view.md deleted file mode 100644 index 6fbb6e2..0000000 --- a/docs/hug_micro_view.md +++ /dev/null @@ -1,550 +0,0 @@ -## Introduction - -The [Qwiic Micro OLED](https://www.sparkfun.com/products/22495) is a Qwiic enabled version of our micro OLED display! This small monochrome, blue-on-black OLED display displays incredibly clear images. - -
- -
- -
- -
- -This hookup guide will show you how to get started drawing objects and characters on your OLED. - - - -### Required Materials - -To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary. - -* 1x [SparkFun RedBoard Plus [DEV-18158]](https://www.sparkfun.com/products/18158) -* 1x [Reversible USB A to C Cable - 0.8m [CAB-15425]](https://www.sparkfun.com/products/15425) -* 1x Qwiic Cable - * [Flexible Qwiic Cable - 50mm [PRT-17260]](https://www.sparkfun.com/products/17260), for short distances - * [Flexible Qwiic Cable - 500mm [PRT-17257]](https://www.sparkfun.com/products/17257), for those that need to wire the board farther away from your microcontroller -* 1x [SparkFun Micro OLED Breakout (Qwiic) [LCD-22495]](https://www.sparkfun.com/products/22495) - - - -#### Microcontroller - -To get started, you'll need a microcontroller to, well, control everything. We used the RedBoard with the ATmega328P for the Qwiic micro OLED. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier. - - - - - -#### USB Cable - -Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller. - - - - -#### Qwiic - -If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed: - - - - - -You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs. - - - -Of course, you will also need a Qwiic Micro OLED if you have not added that to you cart already. - -
- -
- - -### Suggested Reading - -If you aren't familiar with the Qwiic Connection System, we recommend reading [here for an overview](https://www.sparkfun.com/qwiic). - -
- - - - - - - -
-
Qwiic Connection System -
-
-
- -We would also recommend taking a look at the following tutorials if you aren't familiar with them. - - - - - -### Hardware Overview - -Listed below are some of the operating ranges and characteristics of the Qwiic Micro OLED. - -
- - - - - - - - - - - - - - - - - -
Characteristic - Range -
Voltage - 3.3V -
Temperature - -40°C to 85°C -
I2C Address - 0X3D (Default) or 0X3C (Closed Jumper) -
-
- - -###Pins - -Power and I2C pins are broken out to the 1x4 PTH pins as well as the two horizontal Qwiic connectors. - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Pin - Description - Direction -
GND - Ground - In -
3.3V - Power - In -
SDA - I2C Data - In -
SCL - I2C Clock - In -
-
- - - -### Jumpers - -There are several jumpers on board that can be changed to facilitate several different functions. The first of which is the I2C pull-up jumper to disable the 2.2kΩ pull up resistors on the I2C data and clock lines, highlighted below. If multiple boards are connected to the I2C bus, the equivalent resistance goes down, increasing your pull up strength. If multiple boards are connected on the same bus, make sure [only one board has the pull-up resistors connected](https://learn.sparkfun.com/tutorials/i2c/i2c-at-the-hardware-level). - -
- - - - - - - -
I2C Pull-Up Jumper
I2C Pull-Up Jumper
-
- - -The ADDR jumper (highlighted below) can be used to change the I2C address of the board. The default jumper is open by default, pulling the address pin high and giving us an I2C address of **0X3D**. Closing this jumper will ground the address pin, giving us an I2C address of 0X3C. - -
- - - - - - - -
Address Jumper
Address Jumper
-
- - - -### Board Dimensions - -!!! note "Revision Change" - For V11, we have optimized the two mounting hole locations to match the mounting holes located on a standard 1.0" x 1.0" Qwiic-sized board. The overall functionality of the Qwiic Micro OLED breakout board is the same as the previous version! - -The overall board size is 1.08" x 1.17". There is a v-score for users that want to remove the mounting holes. - -
- - - - - - - -
Board Dimensions
Board Dimensions
-
- - - - - -## Hardware Assembly - -If you haven't yet [assembled your Qwiic Shield](https://learn.sparkfun.com/tutorials/qwiic-shield-for-arduino--photon-hookup-guide), now would be the time to head on over to that tutorial. With the shield assembled, SparkFun's Qwiic environment means that connecting the screen could not be easier. Just plug one end of the Qwiic cable into the OLED display, the other into the Qwiic Shield and you'll be ready to start displaying images on your little display. - -
- - - - -
Qwiic Micro OLED Connected to Arduino and Qwiic Shield
-
- - -If you have a built-in Qwiic connector, you can skip the hardware assembly of the Qwiic Shield and simply insert a Qwiic cable between the two boards. Have more than one Qwiic-enabled device? You can daisy chain it to the board as well! Below is an example with the SAM-M8Q and the Qwiic Micro OLED daisy chained together to the RedBoard Qwiic. - -
- - - - -
Qwiic Micro OLED Connected to RedBoard Qwiic and Qwiic GPS(SAM-M8Q)
-
- -!!! note - The initial launch of the Qwiic micro OLED breakout board had the OLED loosely attached to the breakout board. For users that received those boards, be careful handling it! You can either use your own enclosure for the OLED display, or you can use some double sided foam tape for a less permanent solution. - -
- - - - -
Taped Screen
-
- - The current production of the boards includes the double sided foam tape. - - - -## Software - -The SparkFun Micro OLED Breakout (Qwiic) uses the SparkFun QWIIC OLED Arduino Library. The [SparkFun Qwiic OLED library Getting Started guide](software.md) has library setup instructions and usage examples. Additionally, the full library API documentation is available in the [SparkFun Qwiic OLED Library API Reference guide](api_device.md). - - - - - -## Resources - -Now that you've successfully got your OLED displaying things, it's time to incorporate it into your own project! - -For more on the Qwiic Micro OLED, check out the links below: - -* [Schematic (PDF)](https://cdn.sparkfun.com/assets/d/0/e/4/1/Qwiic_OLED_Breakout.pdf) -* [Eagle Files (ZIP)](https://cdn.sparkfun.com/assets/c/b/c/f/d/Qwiic_OLED_Breakout_1.zip) -* [Datasheet (PDF)](https://cdn.sparkfun.com/assets/learn_tutorials/3/0/8/SSD1306.pdf) -* [Bitmap Generator](http://en.radzio.dxp.pl/bitmap_converter/) -* [Qwiic System Landing Page](https://www.sparkfun.com/qwiic) -* [Qwiic Micro OLED Python Package](https://github.com/sparkfun/Qwiic_Micro_OLED_Py) -* [GitHub Hardware Repo](https://github.com/sparkfun/Qwiic_Micro_OLED) -- Board design files for the Qwiic Micro OLED. -* [Product Showcase: Qwiic Presence Sensor & OLED](https://www.youtube.com/watch?v=OBOgxnctzwI) diff --git a/docs/hug_transparent.md b/docs/hug_transparent.md deleted file mode 100644 index cb744b7..0000000 --- a/docs/hug_transparent.md +++ /dev/null @@ -1,715 +0,0 @@ -## Introduction - -The future is here! You asked and we delivered - our [Qwiic Transparent Graphical OLED Breakout](https://www.sparkfun.com/products/15173) allows you to display custom images on a transparent screen using either I2C or SPI connections. - -With Qwiic connectors it's quick (ha ha) and easy to get started with your own images. However, we still have broken out 0.1"-spaced pins in case you prefer to use a breadboard. Brilliantly lit in the dark and still visible by daylight, this OLED sports a display area of 128x64 pixels, 128x56 of which are completely transparent. Control of the OLED is based on the [HyperDisplay library](https://learn.sparkfun.com/tutorials/transparent-graphical-oled-breakout-hookup-guide#software-setup-and-programming) or SparkFun Qwiic OLED Arduino Library! For the scope of this tutorial, we will be using the SparkFun Qwiic OLED Arduino Library. - -
- -
- -
- -
- -This hookup guide will show you how to get started drawing objects and characters on your OLED. - -### Required Materials - -To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary. - -* 1x [SparkFun Thing Plus - ESP32 WROOOM (USB-C) [WRL-20168]](https://www.sparkfun.com/products/18158) -* 1x [Reversible USB A to C Cable - 0.8m [CAB-15425]](https://www.sparkfun.com/products/15425) -* 1x Qwiic Cable - * [Flexible Qwiic Cable - 50mm [PRT-17260]](https://www.sparkfun.com/products/17260), for short distances - * [Flexible Qwiic Cable - 500mm [PRT-17257]](https://www.sparkfun.com/products/17257), for those that need to wire the board farther away from your microcontroller -* 1x [SparkFun Transparent Graphical OLED Breakout (Qwiic)[LCD-15173]](https://www.sparkfun.com/products/15173) - - - -#### Microcontroller - -To get started, you'll need a microcontroller to, well, control everything. We used the SparkFun Thing Plus - ESP32 WROOOM. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier. - - - - - -#### USB Cable - -Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller. - - - - -#### Qwiic - -If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed: - - - - - -You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs. - - - -Of course, you will also need A Tranparent Graphical OLED Breakout if you have not added that to you cart already. - -
- -
- - - -###Suggested Reading - -If you aren't familiar with the Qwiic Connection System, we recommend reading [here for an overview](https://www.sparkfun.com/qwiic). - -
- - - - - - - -
-
Qwiic Connection System -
-
-
- -We would also recommend taking a look at the following tutorials if you aren't familiar with them. - - - - -## Hardware Overview - -Listed below are some of the operating ranges and characteristics of the Transparent Graphical OLED Breakout. - -
- - - - - - - - - - - - - - - - - -
Characteristic - Range -
Voltage - 1.65V-3.3V,
typically 3.3V via the Qwiic Cable -
Supply Current - 400 mA -
I2C Address - 0X3C (Default), 0X3D (Closed Jumper) -
-
- - - -###Graphical Display - -The graphical display is where all the fun stuff happens. The glass itself measures 42mm x 27.16mm, with a pixel display that is 35.5 x 18mm. It houses 128x64 pixels, 128x56 of which are transparent. - -
- - - - - - - -
Display Screen
Graphical Display
-
- - - -###Qwiic Connectors - -There are two Qwiic connectors on the board such that you can daisy-chain the boards should you choose to do so. If you're unfamiliar with our Qwiic Connect System, head on over to our [Qwiic page](https://www.sparkfun.com/qwiic) to see the advantages! - -
- - - - - - - -
Qwiic Connectors
Qwiic Connectors
-
- - - -###GPIO Pins - -When you look at the GPIO pins, you'll notice that the labels are different from one side to the other. One side is labeled for I2C, the other side is labeled for SPI. - - -
- - - - - - - - - -
I2C PinsSPI Pins
I2C LabelsSPI Labels
-
- - - -###Power LED - -This bad boy will light up when the board is powered up correctly. - -
- - - - - - - -
I2C Pins
Power LED
-
- -You can disable the power LED by cutting the LED jumpers on the back of the board. - -
- - - - - - - -
Power LED Jumpers
Power LED Jumpers
-
- - - -###JPX Jumpers - -The JPX jumpers are used to either change the I2C address or configure the board to use SPI communications. The other two jumpers allow you to disconnect the power LED and to disconnect the I2C pull-up resistors when chaining several Qwiic devices. - -
- - - - - - - - - - - - - - - - - - - - - -
Jumper - Function -
JP1 - Holds the Chip Select line low when closed. Close for I2C, open for SPI -
JP2 - Selects the address in I2C mode. Closed for 0x30 by default and open for 0x31. Open for SPI mode to release the D/C pin -
JP3 - Used to select I2C or SPI mode. Close for I2C, open for SPI -
JP4 - This jumper should be closed for I2C and open for SPI. This connection allows SDA to be bi-directional -
-
- -
- - - - - - - -
JP1-JP4
JPX Jumper
-
- - - -###I2C Pull-Up Jumper - -I2C devices contain open drains so we include resistors on our boards to allow these devices to pull pins high. This becomes a problem if you have a large number of I2C devices chained together. If you plan to daisy chain more than a few Qwiic boards together, you'll need to cut this I2C pull-up jumper. - - -
- - - - - - - -
JP1 to JP4
I2C PU Jumper
-
- - - -## Hardware Hookup - -Now that you know what's available on your breakout board we can check out the options for connecting it to the brains of your project. There are two options to use - either I2C or SPI - and they each have their own advantages and drawbacks. Read on to choose the best option for your setup. - -!!! warning - Reminder! This breakout can only handle up to 3.3V on the pins, so make sure to do some level shifting if you're using a 5V microcontroller. - - - -### I2C (Qwiic) - -The easiest way to start using the Transparent Graphical OLED is to use a [Qwiic Cable](https://www.sparkfun.com/products/15081) along with a Qwiic compatible microcontroller (such as the [ESP32 Thing Plus](https://www.sparkfun.com/products/14689)). You can also use the [Qwiic Breadboard Cable](https://www.sparkfun.com/products/14425) to attach any I2C capable microcontroller, or take the scenic route and [solder](https://learn.sparkfun.com/tutorials/how-to-solder---through-hole-soldering) in all the I2C wires to the plated-through connections on the board. - -
- - - - - - - - - -
Qwiic ConnectorI2C Pinout
Top ViewI2C Pinout/i>
-
- - -So why use I2C? It's easy to connect with the Qwiic system, and you can put up to two of the Transparent Graphical Breakouts on the same bus without using any more microcontroller pins. That simplicity comes at a cost to performance though. The maximum clock speed of the I2C bus is 400 kHz, and there is additional overhead in data transmission to indicate which bytes are data and which are commands. This means that the I2C connection is best for showing static images. - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Breakout Pin - Microcontroller Pin Requirements -
GND - Ground pin. Connect these so the two devices agree on voltages -
3V3 - 3.3V supply pin, capable of up to 400 mA output -
SDA - SDA - the bi-directional data line of your chosen I2C port -
SCL - SCL - the clock line of your chosen I2C port -
SA0 - Optional : change the I2C address of the breakout. Make sure to cut JP2 -
RST - Optional : reset the breakout to a known state by pulsing this low -
-
- - - -### SPI - -SPI solves the I2C speed problems. With SPI there is a control signal that indicates data or command and the maximum clock speed is 10 MHz -- giving SPI 50x more speed! However, it doesn't have the same conveniences of the polarized Qwiic connector and low pin usage. You'll need to [solder](https://learn.sparkfun.com/tutorials/how-to-solder---through-hole-soldering) to the pins. - -
- - - - - - - -
SPI Pinout
SPI Pinout
-
- -You can use SPI to connect as many breakouts as you want. For N displays you will need to use at least N + 3 data pins. That's because the MOSI, SCLK, and D/C pins can be shared between displays but each breakout needs its own dedicated Chip Select (CS) pin. - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Breakout Pin - Microcontroller Pin Requirements -
CS - A GPIO pin, set low when talking to the breakout -
D/C - A GPIO pin, indicates if bytes are data or commands -
SCLK - The clock output of your chosen SPI port -
MOSI - The data output of your chosen SPI port -
3V3 - 3.3V supply pin, capable of up to 400 mA output -
GND - Ground pin. Connect these so the two devices agree on voltages -
-
- -!!! warning - Make sure to cut jumpers JP1, JP2, JP3, and JP4 when using SPI mode! - -
- - - - - - - -
Cut Jumpers for SPI Mode
Cut Jumpers for SPI Mode
-
- - - -## Software - -The Transparent OLED Breakout (Qwiic) uses the SparkFun QWIIC OLED Arduino Library. The [SparkFun Qwiic OLED library Getting Started guide](software.md) has library setup instructions and usage examples. Additionally, the full library API documentation is available in the [SparkFun Qwiic OLED Library API Reference guide](api_device.md). - - - - - -## Resources - -For more information on the Transparent Graphical OLED Breakout, check out some of the links here: - -* [Schematic (PDF)](https://cdn.sparkfun.com/assets/5/e/7/b/5/SparkFun_Transparent_Graphical_OLED_Breakout.pdf) -* [Eagle Files (ZIP)](https://cdn.sparkfun.com/assets/2/0/2/c/b/TransparentGraphicalOLEDBreakout.zip) -* [GitHub Hardware Repo](https://github.com/sparkfun/Qwiic_Transparent_Graphical_OLED) -* [SFE Product Showcase](https://youtu.be/vzFuVbxBfXI) diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index f75cf33..0000000 --- a/docs/index.md +++ /dev/null @@ -1 +0,0 @@ -Placeholder file for index redirect functionality. diff --git a/docs/introduction.md b/docs/introduction.md deleted file mode 100644 index b2334df..0000000 --- a/docs/introduction.md +++ /dev/null @@ -1,242 +0,0 @@ -![SparkFun Qwiic OLED Arduino Library](img/OLEDLibBanner.png "SparkFun Qwiic OLED Arduino Library") - -The SparkFun Qwiic OLED Arduino Library is a single graphics module that supports all SparkFun OLED boards based on the SSD1306 from Solomon Systech. Prior to this library, three different libraries were used to support our four different OLED boards. - -The SparkFun Qwiic OLED Library delivers a common implementation for all our Qwiic OLED products, delivering a unified, fast, and efficient solution that implements a familiar and easy to understand user experience. - - - -### Key Features - -* Implements common graphics capabilities: pixel, line, rectangle, filled rectangle, circle, filled circle, bitmap, text and raster operators (i.e. XOR). -* Smart data transfer to the device – only sends _dirty_ regions of the graphics buffer to the OLED device, not the entire buffer. -* High performance – 2x faster than our previous OLED library, often much higher. -* Efficient memory usage. No dynamic memory utilized. Static resources are loaded once, and only on explicit declaration. -* Implements a familiar interface, making migration from older libraries straight forward - - - -### Getting Started - -The [Software Setup](software.md) outlines library installation and the general use of the Qwiic OLED library. - -Detailed examples are included as part of the library installation process and available in the Arduino IDE menu: **File** > **Examples** > **SparkFun Qwiic OLED Arduino Library**. A walk-thru of key examples is contained in the [Examples](../sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/) section of this documentation set. - -!!! note - For v1.0.5 of the SparkFun Qwiic OLED Arduino Library, we named the library as SparkFun Qwiic OLED Graphics Library. After v1.0.6, we updated the name to say SparkFun Qwiic OLED Arduino Library. You may have multiple versions in your Arduino libraries folder if you installed the library more than once. To avoid confusion, issues compiling, and to use the latest version, we recommend removing the "_SparkFun Qwiic OLED Graphics Library_" folder should you decide to use the latest and greatest version. This will probably be located under **..Documents\Arduino\libraries**, that is if you are using Windows. - -!!! note - Note that we have more than one Arduino Library for the micro OLED. If you have the older Arduino Library, make sure to not confuse the two libraries. You will notice that the older library will be called "**SparkFun Micro OLED Breakout**". The example code will include the following line of code: `#include `. - -A full [API Reference](../api_device) is also provided for the library. - - - - - -### Supported Products - -The SparkFun Qwiic OLED Arduino Library supports the following SparkFun products. - - - - - -### Supported Microcontrollers - Arduino Environment - -The following architectures are supported in the Arduino Library. - -* [Artemis](https://www.sparkfun.com/products/15574) -* [SAMD51](https://www.sparkfun.com/products/14713) -* [ESP32](https://www.sparkfun.com/products/20168) -* [STM32](https://www.sparkfun.com/products/17712) -* [SAMD21](https://www.sparkfun.com/products/14812) -* [nrf5280](https://www.sparkfun.com/products/15025) -* [Teensy](https://www.sparkfun.com/products/16402) -* [ATMega328P](https://www.sparkfun.com/products/18158) - -Below are a few of those processors populated on Arduino boards from the [SparkFun catalog](https://www.sparkfun.com/categories/242). You will need to make sure to check the associated hookup guides for additional information about compatible cables, drivers, or board add-ons. - - - -!!! note - Unfortunately, the ATmega32U4 is not supported under this library. We recommend either using a different microcontroller or rolling back to the previous library written for the display. - - -### License - -The SparkFun Qwiic OLED Arduino Library is licensed using the Open Source [MIT License](https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library/blob/main/LICENSE.md#code): - - --8<-- "LICENSE.md:35:55" diff --git a/docs/javascript/README.md b/docs/javascript/README.md deleted file mode 100644 index c67e49c..0000000 --- a/docs/javascript/README.md +++ /dev/null @@ -1,3 +0,0 @@ -javascript directory -==================== -This folder should contain the files for the custom javascript that is enabled in the product documentation \ No newline at end of file diff --git a/docs/single_page.md b/docs/single_page.md deleted file mode 100644 index 0931189..0000000 --- a/docs/single_page.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -hide: - - navigation - - toc -icon: fontawesome/solid/scroll ---- - -# Getting Started - -## Introduction ---8<-- "./docs/introduction.md" - -## Qwiic Micro OLED (0.66", 64x48) ---8<-- "./docs/hug_micro_view.md" - -## Qwiic Transparent Graphical OLED (1.51", 128x56) ---8<-- "./docs/hug_transparent.md" - -## Qwiic OLED (0.91", 128x32) ---8<-- "./docs/hug_0p91.md" - -## Qwiic OLED (1.3", 128x64) ---8<-- "./docs/hug_1p3.md" - -# Software Setup ---8<-- "./docs/software.md" - -# API Reference - -## Device ---8<-- "./docs/api_device.md" - -## Scrolling ---8<-- "./docs/api_scroll.md" - -## Drawing State ---8<-- "./docs/api_draw.md" - -## Graphics ---8<-- "./docs/api_graphics.md" - -## Arduino Print ---8<-- "./docs/api_arduino.md" - -# Arduino Examples - -## Example 1 - Hello ---8<-- "./docs/ex_01_hello.md - -## Example 2 - Shapes ---8<-- "./docs/ex_02_lines.md - -## Example 3 - Bitmaps ---8<-- "./docs/ex_03_bitmaps.md - -## Example 4 - Text ---8<-- "./docs/ex_04_text.md - -## Other Examples ---8<-- "./docs/ex_other.md - -# Troubleshooting ---8<-- "./docs/troubleshooting.md" diff --git a/docs/software.md b/docs/software.md deleted file mode 100644 index a277ec2..0000000 --- a/docs/software.md +++ /dev/null @@ -1,92 +0,0 @@ -# Software Setup - - -## Installation - -!!! arduino - This guide assumes you are using the latest version of the Arduino IDE on your desktop. The following resources available at [SparkFun](https://www.sparkfun.com) provide the details on setting up and configuring Arduino to use this library. - - - [Installing the Arduino IDE](https://learn.sparkfun.com/tutorials/installing-arduino-ide) - - [Installing Board Definitions in the Arduino IDE](https://learn.sparkfun.com/tutorials/installing-board-definitions-in-the-arduino-ide) - - [Installing an Arduino Library](https://learn.sparkfun.com/tutorials/installing-an-arduino-library) - -The SparkFun Qwiic OLED Arduino Library is available within in the Arduino library manager, which is launched via the **Sketch** > **Include Libraries** > **Manage Libraries …** menu option in the Arduino IDE. Just search for ***SparkFun Qwiic OLED Library***. - - -!!! note - If you've never connected a USB-to-serial converter to your computer before, you may need to install drivers. The drivers will depend on what is populated on your Arduino development board. Check out the following tutorials for help with the installation. - - * [How to Install CH340 Drivers](https://learn.sparkfun.com/tutorials/how-to-install-ch340-drivers) - * [How to Install FTDI Drivers](https://learn.sparkfun.com/tutorials/how-to-install-ftdi-drivers) - * [How to Install CP2104 Drivers](https://learn.sparkfun.com/tutorials/esp32-thing-plus-hookup-guide#CP2104) - - -## General Use Pattern - -After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library. - -```C++ -// Include the SparkFun qwiic OLED Library -#include -``` - -The next step is to declare the object for the SparkFun qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the ```setup()``` or ```loop()``` functions. - -The user selects from one of the following classes: - -| Class | Qwiic OLED Device | -| :--- | :--- | -| `QwiicMicroOLED` | [SparkFun Qwiic Micro OLED ]( https://www.sparkfun.com/products/14532)| -| `QwiicNarrowOLED` | [SparkFun Qwiic OLED Display (128x32) ]( https://www.sparkfun.com/products/17153)| -| `QwiicTransparentOLED` | [SparkFun Transparent Graphical OLED]( https://www.sparkfun.com/products/15173)| -| `Qwiic1in3OLED` | [SparkFun Qwiic OLED 1.3" Display (128x32) ]( https://www.sparkfun.com/products/23453)| - -For this example, the Qwiic Micro OLED is used. - -```C++ -QwiicMicroOLED myOLED; -``` - -In the ```setup()``` function of this sketch, like all of the SparkFun qwiic libraries, the device is initialized by calling the ```begin()``` method. This method returns a value of ```true``` on success, or ```false``` on failure. - -```C++ -int width, height; // global variables for use in the sketch -void setup() -{ - Serial.begin(115200); - if(!myOLED.begin()){ - Serial.println("Device failed to initialize"); - while(1); // halt execution - } - Serial.println("Device is initialized"); - -} -``` - -Now that the library is initialized, the desired graphics are drawn. Here we erase the screen and draw simple series of lines that originate at the screen origin and fan out across the height of the display. - -!!! note - Graphics are not send to the OLED device when drawn. Updates are only sent to the device when the `display()` method is called. This minimizes data transfers to the OLED device, delivering a responsive display response. - -```C++ - - myOLED.erase(); // Erase the screen - myOLED.display(); // Send erase to device - - delay(1000); // Slight pause - - // Draw our lines from point (0,0) to (i, screen height) - - for(int i=0; i < width; i+= 6){ - myOLED.line(0, 0, i, height-1); // draw the line - myOLED.display(); // Send the new line to the device for display - } -``` - - - -## Library Provided Examples - -The SparkFun Qwiic OLED Arduino Library, includes a wide variety of examples. These are available from the Examples menu of the Arduino IDE, and in the [`examples`](https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library/blob/main/examples)folder of this repository. - -For a detailed description of the examples, see the Examples section of the documentation. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md deleted file mode 100644 index 1f46c66..0000000 --- a/docs/troubleshooting.md +++ /dev/null @@ -1,13 +0,0 @@ -### General Troubleshooting Help - -!!! note - - Not working as expected and need help?

- - If you need technical assistance and more information on a product that is not working as you expected, we recommend heading on over to the SparkFun Technical Assistance page for some initial troubleshooting.

- - - - If you don't find what you need there, the SparkFun Forums are a great place to find and ask for help. If this is your first visit, you'll need to create a Forum Account to search product forums and post questions.

- - diff --git a/examples/Example-01_Hello/Example-01_Hello.ino b/examples/Example-01_Hello/Example-01_Hello.ino deleted file mode 100644 index e130d21..0000000 --- a/examples/Example-01_Hello/Example-01_Hello.ino +++ /dev/null @@ -1,79 +0,0 @@ -/* - - Example-01_Hello.ino - - This demo shows the basic setup of the OLED library, generating simple graphics and displaying - the results on the target device. - - Micro OLED https://www.sparkfun.com/products/14532 - Transparent OLED https://www.sparkfun.com/products/15173 - "Narrow" OLED https://www.sparkfun.com/products/24606 - Qwiic OLED 1.3in https://www.sparkfun.com/products/23453 - - Written by Kirk Benell @ SparkFun Electronics, March 2022 - - Repository: - https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library - - Documentation: - https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -*/ - -#include //http://librarymanager/All#SparkFun_Qwiic_OLED - -// The Library supports four different types of SparkFun boards. The demo uses the following -// defines to determine which device is being used. Uncomment the device being used for this demo. - -QwiicMicroOLED myOLED; -//QwiicTransparentOLED myOLED; -//QwiicNarrowOLED myOLED; -//Qwiic1in3OLED myOLED; - - -void setup() -{ - Serial.begin(115200); - Serial.println("Running OLED example"); - - Wire.begin(); - - // Initalize the OLED device and related graphics system - if (myOLED.begin() == false) - { - Serial.println("Device begin failed. Freezing..."); - while (true) - ; - } - Serial.println("Begin success"); - - // Do a simple test - fill a rectangle on the screen and then print hello! - - // Fill a rectangle on the screen that has a 4 pixel board - myOLED.rectangleFill(4, 4, myOLED.getWidth() - 8, myOLED.getHeight() - 8); - - String hello = "hello"; // our message - - // Center our message on the screen. Get the screen size of the "hello" string, - // calling the getStringWidth() and getStringHeight() methods on the oled - - // starting x position - screen width minus string width / 2 - int x0 = (myOLED.getWidth() - myOLED.getStringWidth(hello)) / 2; - - // starting y position - screen height minus string height / 2 - int y0 = (myOLED.getHeight() - myOLED.getStringHeight(hello)) / 2; - - // Draw the text - color of black (0) - myOLED.text(x0, y0, hello, 0); - - // There's nothing on the screen yet - Now send the graphics to the device - myOLED.display(); - - // That's it - HELLO! -} - -void loop() -{ - delay(1000); // Do nothing -} diff --git a/examples/Example-02_Shapes/Example-02_Shapes.ino b/examples/Example-02_Shapes/Example-02_Shapes.ino deleted file mode 100644 index ca4d2ee..0000000 --- a/examples/Example-02_Shapes/Example-02_Shapes.ino +++ /dev/null @@ -1,262 +0,0 @@ -/* - Example-01_Hello.ino - - This demo shows the various methods available for drawing shapes using the OLED library - - This library configures and draws graphics to OLED boards that use the - SSD1306 display hardware. The library only supports I2C. - - SparkFun sells these at its website: www.sparkfun.com - - Do you like this library? Help support SparkFun. Buy a board! - - Micro OLED https://www.sparkfun.com/products/14532 - Transparent OLED https://www.sparkfun.com/products/15173 - "Narrow" OLED https://www.sparkfun.com/products/24606 - Qwiic OLED 1.3in https://www.sparkfun.com/products/23453 - - Written by Kirk Benell @ SparkFun Electronics, March 2022 - - Repository: - https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library - - Documentation: - https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -*/ - -#include //http://librarymanager/All#SparkFun_Qwiic_OLED - -// The Library supports four different types of SparkFun boards. The demo uses the following -// defines to determine which device is being used. Uncomment the device being used for this demo. - -QwiicMicroOLED myOLED; -//QwiicTransparentOLED myOLED; -//QwiicNarrowOLED myOLED; -//Qwiic1in3OLED myOLED; - -// Global variables - used to stash our screen size - -int width; -int height; - -void setup() -{ - Serial.begin(115200); - Serial.println("Running OLED example"); - - Wire.begin(); - - // Initalize the OLED device and related graphics system - if (myOLED.begin() == false) - { - Serial.println("Device begin failed. Freezing..."); - while (true) - ; - } - Serial.println("Begin success"); - - // save device dims for the test routines - width = myOLED.getWidth(); - height = myOLED.getHeight(); -} - -void loop() -{ - // Loop over our test functions - for (int i = 0; i < 7; i++) - { - myOLED.erase(); - - if (i == 0) - lineTest1(); - else if (i == 1) - lineTest2(); - else if (i == 2) - lineTestVertical(); - else if (i == 3) - rectangleTest(); - else if (i == 4) - rectangleTestMove(); - else if (i == 5) - rectangleFillTest(); - else if (i == 6) - circleTest(); - - myOLED.display(); - - delay(1000); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// lineTest1() -// -// This test draws a horizontal line on the screen, moving it from the -// top of the screen to the bottom. -// -// This sequence repeats multiple times, starting with a small line and -// growing to the width of the screen. -// -// Since the library uses a "dirty range" methodology to minimize the amount of -// data sent to the device, as the lenght of the line increases, the rate -// of the display updates also decreases. A longer line, results in more data being -// sent to the display. - -void lineTest1(void) -{ - int x, y, i; - - int mid = width / 2; - int delta = mid / 8; - - for (int j = 1; j < 8; j++) - { - - x = delta * j; - - for (i = 0; i < height * 2; i++) - { - - y = i % height; - myOLED.erase(); - myOLED.line(mid - x, y, mid + x, y); - myOLED.display(); - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// lineTest2() -// -// This test draws a series of lines bursting out from the corner of the display. -// -// It demostrates the abilty of the library to draw arbitray straight lines. - -void lineTest2(void) -{ - for (int i = 0; i < width; i += 6) - { - myOLED.line(0, 0, i, height - 1); - myOLED.display(); - } - delay(200); - myOLED.erase(); - for (int i = width - 1; i >= 0; i -= 6) - { - myOLED.line(width - 1, 0, i, height - 1); - myOLED.display(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// lineTestVertIterative() -// -// Draws a series of vertical lines, some horz lines and two diag lines. -// -// Internally, this uses the standard line algorithm (diag), fast horz and fast -// vertical lines functions. -// -// Iterator function - called to animate graphic - -void lineTestVerticalIterative(uint8_t y0, uint8_t y1) -{ - for (int i = 0; i < width; i += 8) - myOLED.line(i, y0, i, y1); - - // end off the vertical lines - myOLED.line(width - 1, y0, width - 1, y1); - - // End lines and cross lines - myOLED.line(0, y0, width - 1, y0); - myOLED.line(0, y1, width - 1, y1); - myOLED.line(0, y0, width - 1, y1); - myOLED.line(0, y1, width - 1, y0); -} - -// Entry point for test -void lineTestVertical(void) -{ - int mid = height / 2; - - for (int i = 0; i < height; i += 4) - { - - myOLED.erase(); - lineTestVerticalIterative(mid - i / 2, mid + i / 2); - myOLED.display(); - delay(10); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// rect_test() -// -// Simple - draw a rectangle test - -void rectangleTest(void) -{ - myOLED.rectangle(4, 4, width - 8, height - 8); -} - -//////////////////////////////////////////////////////////////////////////////// -// rectangleTestMove() -// -// Draws a rectangle, then moves it across the screen -// -void rectangleTestMove(void) -{ - float steps = height; - float xinc = width / steps; - float yinc = height / steps; - int side = 10; - float x = 0; - float y = 0; - - for (int i = 0; i < steps; i++) - { - // Draw the rectangle and send it to device - myOLED.rectangle(x, y, side, side); - myOLED.display(); // sends erased rect and new rect pixels to device - - // Erase the that rect, increment and loop - myOLED.rectangle(x, y, side, side, 0); - - x += xinc; - y += yinc; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// rectangleFillTest() -// -// Draws two filled rectangles, switches to XOR draw mode and overwrites them -// with another rectangle - -void rectangleFillTest(void) -{ - myOLED.rectangleFill(4, 4, width / 2 - 8, height - 8); - - myOLED.rectangleFill(width / 2 + 4, 4, width / 2 - 8, height - 8); - - myOLED.setDrawMode(grROPXOR); // xor - myOLED.rectangleFill(width / 4, 8, width / 2, height - 16); - myOLED.setDrawMode(grROPCopy); // back to copy op (default) -} - -//////////////////////////////////////////////////////////////////////////////// -// circleTest() -// -// Draw a series of circles - filled and not filled -void circleTest(void) -{ - // Let's draw some circles that fit on the device - myOLED.circle(width / 4, height / 2, height / 3); - - myOLED.circleFill(width - width / 4, height / 2, height / 3); - - myOLED.circle(4, height / 2, height / 3); - - myOLED.circleFill(width - width / 2, height / 2, height / 4); -} diff --git a/examples/Example-03_Bitmap/Example-03_Bitmap.ino b/examples/Example-03_Bitmap/Example-03_Bitmap.ino deleted file mode 100644 index 511f08b..0000000 --- a/examples/Example-03_Bitmap/Example-03_Bitmap.ino +++ /dev/null @@ -1,137 +0,0 @@ -/* - Example-03_Bitmap.ino - - This demo shows how to write a simple bitmap to an OLED screen - - This library configures and draws graphics to OLED boards that use the - SSD1306 display hardware. The library only supports I2C. - - SparkFun sells these at its website: www.sparkfun.com - - Do you like this library? Help support SparkFun. Buy a board! - - Micro OLED https://www.sparkfun.com/products/14532 - Transparent OLED https://www.sparkfun.com/products/15173 - "Narrow" OLED https://www.sparkfun.com/products/24606 - Qwiic OLED 1.3in https://www.sparkfun.com/products/23453 - - Written by Kirk Benell @ SparkFun Electronics, March 2022 - - Repository: - https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library - - Documentation: - https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -*/ - -#include //http://librarymanager/All#SparkFun_Qwiic_OLED - -// The Library supports four different types of SparkFun boards. The demo uses the following -// defines to determine which device is being used. Uncomment the device being used for this demo. - -QwiicMicroOLED myOLED; -//QwiicTransparentOLED myOLED; -//QwiicNarrowOLED myOLED; -//Qwiic1in3OLED myOLED; - -// Let's draw a truck - use our built in bitmap -#include "res/qw_bmp_truck.h" -#include "res/qw_bmp_sparkfun.h" - -int width; -int height; - -// For simple frame rate calculations -long drawTotalTime = 0; -int numberOfDraws = 0; - -int iconX = 8; -int iconXChangeAmount = 1; -int iconY = 8; -int iconYChangeAmount = 1; - -void setup() -{ - Serial.begin(115200); - Serial.println("Running OLED example"); - - Wire.begin(); - Wire.setClock(400000); // Optional increase I2C to 400kHz - - // Initalize the OLED device and related graphics system - if (myOLED.begin() == false) - { - Serial.println("Device begin failed. Freezing..."); - while (true) - ; - } - Serial.println("Begin success"); - - // save device dims for the test routines - width = myOLED.getWidth(); - height = myOLED.getHeight(); - - showSplash(); - - drawTotalTime = 0; - numberOfDraws = 0; - - // set a template for our framerate display - Serial.println("- Frame Rate"); -} - -void loop() -{ - // Calculate draw time - long startTime = millis(); - - myOLED.bitmap(iconX, iconY, QW_BMP_TRUCK); - myOLED.display(); - - // Move the icon - iconX += iconXChangeAmount; - iconY += iconYChangeAmount; - - if (iconX + QW_BMP_TRUCK.width >= width) - iconXChangeAmount *= -1; // Change direction - - if (iconX == 0) - iconXChangeAmount *= -1; // Change direction - - if (iconY + QW_BMP_TRUCK.height >= height) - iconYChangeAmount *= -1; // Change direction - - if (iconY == 0) - iconYChangeAmount *= -1; // Change direction - - numberOfDraws++; - drawTotalTime += (millis() - startTime); - - // Output framerate once every 120 frames - if (numberOfDraws % 120 == 0) - { - Serial.print(" Frame rate: "); - Serial.println(numberOfDraws / (float)drawTotalTime * 1000.0); - - numberOfDraws = 0; - drawTotalTime = 0; - } -} - -void showSplash() -{ - int x0 = (width - QW_BMP_SPARKFUN.width) / 2; - if (x0 < 0) - x0 = 0; - - int y0 = (height - QW_BMP_SPARKFUN.height) / 2; - if (y0 < 0) - y0 = 0; - - myOLED.erase(); - myOLED.bitmap(x0, y0, QW_BMP_SPARKFUN); - myOLED.display(); - delay(2000); -} diff --git a/examples/Example-04_Text/Example-04_Text.ino b/examples/Example-04_Text/Example-04_Text.ino deleted file mode 100644 index 7ea723d..0000000 --- a/examples/Example-04_Text/Example-04_Text.ino +++ /dev/null @@ -1,162 +0,0 @@ -/* - Example-04_Text.ino - - This demo shows writing text to an OLED screen using various fonts - - This library configures and draws graphics to OLED boards that use the - SSD1306 display hardware. The library only supports I2C. - - SparkFun sells these at its website: www.sparkfun.com - - Do you like this library? Help support SparkFun. Buy a board! - - Micro OLED https://www.sparkfun.com/products/14532 - Transparent OLED https://www.sparkfun.com/products/15173 - "Narrow" OLED https://www.sparkfun.com/products/24606 - Qwiic OLED 1.3in https://www.sparkfun.com/products/23453 - - Written by Kirk Benell @ SparkFun Electronics, March 2022 - - Repository: - https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library - - Documentation: - https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -*/ - -#include //http://librarymanager/All#SparkFun_Qwiic_OLED - -// The Library supports four different types of SparkFun boards. The demo uses the following -// defines to determine which device is being used. Uncomment the device being used for this demo. - -QwiicMicroOLED myOLED; -//QwiicTransparentOLED myOLED; -//QwiicNarrowOLED myOLED; -//Qwiic1in3OLED myOLED; - -// Fonts -#include -#include -#include -#include -#include - -// An array of fonts to loop over -QwiicFont *demoFonts[] = { - &QW_FONT_5X7, - &QW_FONT_8X16, - &QW_FONT_31X48, - &QW_FONT_LARGENUM, - &QW_FONT_7SEGMENT}; -int nFONTS = sizeof(demoFonts) / sizeof(demoFonts[0]); -int iFont = 0; - -// Some vars for the title. -String strTitle = "<>"; -QwiicFont *pFntTitle = &QW_FONT_5X7; - -void setup() -{ - Serial.begin(115200); - Serial.println("Running OLED example"); - - Wire.begin(); - - // Initalize the OLED device and related graphics system - if (myOLED.begin() == false) - { - Serial.println("Device begin failed. Freezing..."); - while (true) - ; - } - Serial.println("Begin success"); - -} - -void loop() -{ - // next font for display - iFont = (iFont + 1) % nFONTS; - myOLED.setFont(demoFonts[iFont]); - - // Write font name to screen - writeTitle(); - - delay(1000); - - // Write out the full font char set - writeFontChars(); - - delay(2000); -} - -// For the current font, write out all its characters -void writeFontChars() -{ - // get the font - QwiicFont * currFont = myOLED.getFont(); - - // how many chars can a screen handle? (x * y) - uint16_t screenChars = myOLED.getWidth() / (currFont->width + 1); // X - uint8_t nY = myOLED.getHeight() / currFont->height; // Y - - screenChars *= (nY == 0 ? 1 : nY); // need at least 1 row - - // Loop over the characters in the font. - for (int i = 0; i < currFont->n_chars; i++) - { - - if (i % screenChars == 0) - { // next page - delay(400); - myOLED.erase(); - myOLED.setCursor(0, 0); - } - - // if the character is a carriage return, send a blank - otherwise the - // write routine will perform a CR and lead to a confusing display. - myOLED.write((i + currFont->start != '\n') ? i + currFont->start : ' '); - - myOLED.display(); // show the added char - - delay(10); - } -} - -// Simple title for a font -void writeTitle() -{ - - // Get the current font name - String strTitle = myOLED.getFontName(); - - // save our current font, then switch to font for title - QwiicFont * currFont = myOLED.getFont(); - - // Set title font font - myOLED.setFont(pFntTitle); - - // Position to use for the time/banner displayed before each font - - // Get the width of the title in screen size - int width = myOLED.getStringWidth(strTitle); - - // if the string is wider than the screen, set x at 0, otherwise center text - - int xTitle = (width >= myOLED.getWidth() ? 0 : (myOLED.getWidth() - width) / 2); - - // starting y position - width minus string height / 2. No need to chech height, 5x7 font fits everything - int yTitle = (myOLED.getHeight() - myOLED.getStringHeight(strTitle)) / 2; - - myOLED.erase(); - - // Draw the text - myOLED.text(xTitle, yTitle, strTitle); - - // There's nothing on the screen yet - Now send the graphics to the device - myOLED.display(); - - myOLED.setFont(currFont); -} diff --git a/examples/Example-05_ScrollFlip/Example-05_ScrollFlip.ino b/examples/Example-05_ScrollFlip/Example-05_ScrollFlip.ino deleted file mode 100644 index 32135a4..0000000 --- a/examples/Example-05_ScrollFlip/Example-05_ScrollFlip.ino +++ /dev/null @@ -1,154 +0,0 @@ -/* - Example-05_ScrollFlip.ino - - This demo shows the various display options - scrolling, flipping, invert. - - NOTE: Scrolling isn't supported on the Transparent OLED - - This library configures and draws graphics to OLED boards that use the - SSD1306 display hardware. The library only supports I2C. - - SparkFun sells these at its website: www.sparkfun.com - - Do you like this library? Help support SparkFun. Buy a board! - - Micro OLED https://www.sparkfun.com/products/14532 - Transparent OLED https://www.sparkfun.com/products/15173 - "Narrow" OLED https://www.sparkfun.com/products/24606 - Qwiic OLED 1.3in https://www.sparkfun.com/products/23453 - - Written by Kirk Benell @ SparkFun Electronics, March 2022 - - Repository: - https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library - - Documentation: - https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -*/ - -#include //http://librarymanager/All#SparkFun_Qwiic_OLED - -// The Library supports four different types of SparkFun boards. The demo uses the following -// defines to determine which device is being used. Uncomment the device being used for this demo. - -QwiicMicroOLED myOLED; -//QwiicTransparentOLED myOLED; -//QwiicNarrowOLED myOLED; -//Qwiic1in3OLED myOLED; - -int yoffset; - -// Our testing functions -void scrollRight(void) -{ - myOLED.scrollStop(); - myOLED.scrollRight(0, 7, SCROLL_INTERVAL_2_FRAMES); -} - -void scrollRightVertical(void) -{ - myOLED.scrollStop(); - myOLED.scrollVertRight(0, 7, SCROLL_INTERVAL_3_FRAMES); -} - -void scrollLeft(void) -{ - myOLED.scrollStop(); - myOLED.scrollLeft(0, 7, SCROLL_INTERVAL_4_FRAMES); -} - -void scrollLeftVertical(void) -{ - myOLED.scrollStop(); - myOLED.scrollVertLeft(0, 7, SCROLL_INTERVAL_5_FRAMES); -} - -void scrollStop(void) -{ - myOLED.scrollStop(); -} - -void flipHorizontal(void) -{ - for (int i = 0; i < 6; i++) - { - myOLED.flipHorizontal(!(i & 0x01)); - delay(800); - } -} - -void flipVertical(void) -{ - for (int i = 0; i < 6; i++) - { - myOLED.flipVertical(!(i & 0x01)); - delay(800); - } -} - -void invert(void) -{ - for (int i = 0; i < 6; i++) - { - myOLED.invert(!(i & 0x01)); - delay(800); - } -} - -// Use an array of testing functions, with a title, to run the tests -typedef void (*testFn)(void); -typedef struct _testRoutines -{ - void (*testFn)(void); - const char *title; -} testRoutine; - -static const testRoutine testFunctions[] = { - {scrollRight, "Right>"}, - {scrollRightVertical, "^Right-Up>"}, - {scrollLeft, ""}, - {flipHorizontal, "-Flip-Horz-"}, - {flipVertical, "|Flip-Vert|"}, - {invert, "**INVERT**"}}; - -void setup() -{ - Serial.begin(115200); - Serial.println("Running OLED example"); - - Wire.begin(); - - // Initalize the OLED device and related graphics system - if (myOLED.begin() == false) - { - Serial.println("Device begin failed. Freezing..."); - while (true) - ; - } - Serial.println("Begin success"); - - yoffset = (myOLED.getHeight() - myOLED.getStringHeight("a")) / 2; - - delay(1000); -} - -void loop() -{ - // Loop over the test table entries, write title and run test. - for (int i = 0; i < sizeof(testFunctions) / sizeof(testFunctions[0]); i++) - { - if (testFunctions[i].title) - { - myOLED.erase(); - myOLED.text(3, yoffset, testFunctions[i].title); - myOLED.display(); - } - testFunctions[i].testFn(); // run test - - delay(3000); - } -} diff --git a/examples/Example-06_Clock/Example-06_Clock.ino b/examples/Example-06_Clock/Example-06_Clock.ino deleted file mode 100644 index 843f9ea..0000000 --- a/examples/Example-06_Clock/Example-06_Clock.ino +++ /dev/null @@ -1,218 +0,0 @@ -/* - Example-06_Clock.ino - - Draws a clock face on the OLED display. This is a port of the demo for the original Micro OLED library. - - This library configures and draws graphics to OLED boards that use the - SSD1306 display hardware. The library only supports I2C. - - SparkFun sells these at its website: www.sparkfun.com - - Do you like this library? Help support SparkFun. Buy a board! - - Micro OLED https://www.sparkfun.com/products/14532 - Transparent OLED https://www.sparkfun.com/products/15173 - "Narrow" OLED https://www.sparkfun.com/products/24606 - Qwiic OLED 1.3in https://www.sparkfun.com/products/23453 - - Written by - Jim Lindblom @ SparkFun Electronics - Original Creation Date: October 27, 2014 - - Repository: - https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library - - Documentation: - https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -*/ - -#include //http://librarymanager/All#SparkFun_Qwiic_OLED - -// The Library supports four different types of SparkFun boards. The demo uses the following -// defines to determine which device is being used. Uncomment the device being used for this demo. - -QwiicMicroOLED myOLED; -//QwiicTransparentOLED myOLED; -//QwiicNarrowOLED myOLED; -//Qwiic1in3OLED myOLED; - -// Use these variables to set the initial time -int hours = 11; -int minutes = 50; -int seconds = 30; - -// How fast do you want the clock to spin? Set this to 1 for fun. -// Set this to 1000 to get _about_ 1 second timing. -const int CLOCK_SPEED = 1000; - -// Global variables to help draw the clock face: -const int MIDDLE_Y = myOLED.getHeight() / 2; -const int MIDDLE_X = myOLED.getWidth() / 2; - -int CLOCK_RADIUS; -int POS_12_X, POS_12_Y; -int POS_3_X, POS_3_Y; -int POS_6_X, POS_6_Y; -int POS_9_X, POS_9_Y; -int S_LENGTH; -int M_LENGTH; -int H_LENGTH; - -unsigned long lastDraw = 0; - -QwiicFont *pFont; - -void setup() -{ - Serial.begin(115200); - Serial.println("Running OLED example"); - - Wire.begin(); - - // Initalize the OLED device and related graphics system - if (myOLED.begin() == false) - { - Serial.println("Device begin failed. Freezing..."); - while (true) - ; - } - Serial.println("Begin success"); - - pFont = myOLED.getFont(); - - initClockVariables(); - - drawFace(); - drawArms(hours, minutes, seconds); - myOLED.display(); // display the memory buffer drawn -} - -void loop() -{ - // Check if we need to update seconds, minutes, hours: - if (lastDraw + CLOCK_SPEED < millis()) - { - lastDraw += CLOCK_SPEED; - - // Add a second, update minutes/hours if necessary: - updateTime(); - - // Draw the clock: - myOLED.erase(); - - drawFace(); // Draw the face to the buffer - drawArms(hours, minutes, seconds); // Draw arms to the buffer - - myOLED.display(); // Draw the memory buffer - } -} - -void initClockVariables() -{ - // Calculate constants for clock face component positions: - - CLOCK_RADIUS = min(MIDDLE_X, MIDDLE_Y) - 1; - POS_12_X = MIDDLE_X - pFont->width; - POS_12_Y = MIDDLE_Y - CLOCK_RADIUS + 2; - POS_3_X = MIDDLE_X + CLOCK_RADIUS - pFont->width - 1; - POS_3_Y = MIDDLE_Y - pFont->height / 2; - POS_6_X = MIDDLE_X - pFont->width / 2; - POS_6_Y = MIDDLE_Y + CLOCK_RADIUS - pFont->height - 1; - POS_9_X = MIDDLE_X - CLOCK_RADIUS + pFont->width - 2; - POS_9_Y = MIDDLE_Y - pFont->height / 2; - - // Calculate clock arm lengths - S_LENGTH = CLOCK_RADIUS - 2; - M_LENGTH = S_LENGTH * 0.7; - H_LENGTH = S_LENGTH * 0.5; -} - -// Simple function to increment seconds and then increment minutes -// and hours if necessary. -void updateTime() -{ - seconds++; // Increment seconds - if (seconds >= 60) - { // If seconds overflows (>=60) - - seconds = 0; // Set seconds back to 0 - minutes++; // Increment minutes - - if (minutes >= 60) - { // If minutes overflows (>=60) - - minutes = 0; // Set minutes back to 0 - hours++; // Increment hours - - if (hours >= 12) // If hours overflows (>=12) - hours = 0; // Set hours back to 0 - } - } -} - -// Draw the clock's three arms: seconds, minutes, hours. -void drawArms(int h, int m, int s) -{ - double midHours; // this will be used to slightly adjust the hour hand - static int hx, hy, mx, my, sx, sy; - - // Adjust time to shift display 90 degrees ccw - // this will turn the clock the same direction as text: - h -= 3; - m -= 15; - s -= 15; - - if (h <= 0) - h += 12; - - if (m < 0) - m += 60; - - if (s < 0) - s += 60; - - // Calculate and draw new lines: - s = map(s, 0, 60, 0, 360); // map the 0-60, to "360 degrees" - sx = S_LENGTH * cos(PI * ((float)s) / 180); // woo trig! - sy = S_LENGTH * sin(PI * ((float)s) / 180); // woo trig! - - // draw the second hand: - myOLED.line(MIDDLE_X, MIDDLE_Y, MIDDLE_X + sx, MIDDLE_Y + sy); - - m = map(m, 0, 60, 0, 360); // map the 0-60, to "360 degrees" - mx = M_LENGTH * cos(PI * ((float)m) / 180); // woo trig! - my = M_LENGTH * sin(PI * ((float)m) / 180); // woo trig! - - // draw the minute hand - myOLED.line(MIDDLE_X, MIDDLE_Y, MIDDLE_X + mx, MIDDLE_Y + my); - - midHours = minutes / 12; // midHours is used to set the hours hand to middling levels between whole hours - h *= 5; // Get hours and midhours to the same scale - h += midHours; // add hours and midhours - h = map(h, 0, 60, 0, 360); // map the 0-60, to "360 degrees" - hx = H_LENGTH * cos(PI * ((float)h) / 180); // woo trig! - hy = H_LENGTH * sin(PI * ((float)h) / 180); // woo trig! - - // draw the hour hand: - myOLED.line(MIDDLE_X, MIDDLE_Y, MIDDLE_X + hx, MIDDLE_Y + hy); -} - -// Draw an analog clock face -void drawFace() -{ - // Draw the clock border - myOLED.circle(MIDDLE_X, MIDDLE_Y, CLOCK_RADIUS); - - // Draw the clock numbers - - myOLED.setCursor(POS_12_X, POS_12_Y); // points cursor to x=27 y=0 - myOLED.print(12); - myOLED.setCursor(POS_6_X, POS_6_Y); - myOLED.print(6); - myOLED.setCursor(POS_9_X, POS_9_Y); - myOLED.print(9); - myOLED.setCursor(POS_3_X, POS_3_Y); - myOLED.print(3); -} diff --git a/examples/Example-07_Cube/Example-07_Cube.ino b/examples/Example-07_Cube/Example-07_Cube.ino deleted file mode 100644 index 4c8771e..0000000 --- a/examples/Example-07_Cube/Example-07_Cube.ino +++ /dev/null @@ -1,157 +0,0 @@ -/* - Example-07_Cube.ino - - This demo draws a rotating 3D cube - - This library configures and draws graphics to OLED boards that use the - SSD1306 display hardware. The library only supports I2C. - - SparkFun sells these at its website: www.sparkfun.com - - Do you like this library? Help support SparkFun. Buy a board! - - Micro OLED https://www.sparkfun.com/products/14532 - Transparent OLED https://www.sparkfun.com/products/15173 - "Narrow" OLED https://www.sparkfun.com/products/24606 - Qwiic OLED 1.3in https://www.sparkfun.com/products/23453 - - Written by - Jim Lindblom @ SparkFun Electronics - Original Creation Date: October 27, 2014 - - Repository: - https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library - - Documentation: - https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -*/ -#include //http://librarymanager/All#SparkFun_Qwiic_OLED - -// The Library supports four different types of SparkFun boards. The demo uses the following -// defines to determine which device is being used. Uncomment the device being used for this demo. - -QwiicMicroOLED myOLED; -//QwiicTransparentOLED myOLED; -//QwiicNarrowOLED myOLED; -//Qwiic1in3OLED myOLED; - -int width; -int height; - -// For simple frame rate calculations -long drawTotalTime = 0; -int numberOfDraws = 0; - -float d = 3; -float px[] = {-d, d, d, -d, -d, d, d, -d}; -float py[] = {-d, -d, d, d, -d, -d, d, d}; -float pz[] = {-d, -d, -d, -d, d, d, d, d}; - -float p2x[8] = {0}; -float p2y[8] = {0}; -float r[3] = {0}; - -#define SHAPE_SIZE 400 -// Define how fast the cube rotates. Smaller numbers are faster. -// This is the number of ms between draws. -#define ROTATION_SPEED 00 - -void setup() -{ - Serial.begin(115200); - Serial.println("Running OLED example"); - - Wire.begin(); - // Wire.setClock(400000); //Optionally increase I2C bus speed to 400kHz - - // Initalize the OLED device and related graphics system - if (myOLED.begin() == false) - { - Serial.println("Device begin failed. Freezing..."); - while (true) - ; - } - Serial.println("Begin success"); - - width = myOLED.getWidth(); - height = myOLED.getHeight(); - - // For frame rate calc - drawTotalTime = 0; - numberOfDraws = 0; - - // Set a template for our framerate display - Serial.print("- Frame Rate: 00.00"); -} - -void loop() -{ - // Draw the cube - as fast as we can! - drawCube(); -} - -void drawCube() -{ - r[0] = r[0] + PI / 180.0; // Add a degree - r[1] = r[1] + PI / 180.0; // Add a degree - r[2] = r[2] + PI / 180.0; // Add a degree - if (r[0] >= 360.0 * PI / 180.0) - r[0] = 0; - if (r[1] >= 360.0 * PI / 180.0) - r[1] = 0; - if (r[2] >= 360.0 * PI / 180.0) - r[2] = 0; - - // This routine gets called often, so just make these statics - static float px2, py2, pz2, px3, py3, pz3, ax, ay, az; - - for (int i = 0; i < 8; i++) - { - px2 = px[i]; - py2 = cos(r[0]) * py[i] - sin(r[0]) * pz[i]; - pz2 = sin(r[0]) * py[i] + cos(r[0]) * pz[i]; - - px3 = cos(r[1]) * px2 + sin(r[1]) * pz2; - py3 = py2; - pz3 = -sin(r[1]) * px2 + cos(r[1]) * pz2; - - ax = cos(r[2]) * px3 - sin(r[2]) * py3; - ay = sin(r[2]) * px3 + cos(r[2]) * py3; - az = pz3 - 150; - - p2x[i] = width / 2 + ax * SHAPE_SIZE / az; - p2y[i] = height / 2 + ay * SHAPE_SIZE / az; - } - - // Calculate draw time - uint32_t startTime = millis(); - - myOLED.erase(); - for (int i = 0; i < 3; i++) - { - myOLED.line(p2x[i], p2y[i], p2x[i + 1], p2y[i + 1]); - myOLED.line(p2x[i + 4], p2y[i + 4], p2x[i + 5], p2y[i + 5]); - myOLED.line(p2x[i], p2y[i], p2x[i + 4], p2y[i + 4]); - } - - myOLED.line(p2x[3], p2y[3], p2x[0], p2y[0]); - myOLED.line(p2x[7], p2y[7], p2x[4], p2y[4]); - myOLED.line(p2x[3], p2y[3], p2x[7], p2y[7]); - myOLED.display(); - - // Write out our frame rate - drawTotalTime += millis() - startTime; - numberOfDraws++; - - // Output framerate once every 120 frames - if (numberOfDraws % 120 == 0) - { - Serial.print(" Frame rate: "); - Serial.println(numberOfDraws / (float)drawTotalTime * 1000.0); - - numberOfDraws = 0; - drawTotalTime = 0; - } -} diff --git a/examples/Example-08_Multi/Example-08_Multi.ino b/examples/Example-08_Multi/Example-08_Multi.ino deleted file mode 100644 index 841af06..0000000 --- a/examples/Example-08_Multi/Example-08_Multi.ino +++ /dev/null @@ -1,243 +0,0 @@ -/* - Example-08_Multi.ino - - This demo performs multiple examples - - This library configures and draws graphics to OLED boards that use the - SSD1306 display hardware. The library only supports I2C. - - SparkFun sells these at its website: www.sparkfun.com - - Do you like this library? Help support SparkFun. Buy a board! - - Micro OLED https://www.sparkfun.com/products/14532 - Transparent OLED https://www.sparkfun.com/products/15173 - "Narrow" OLED https://www.sparkfun.com/products/24606 - Qwiic OLED 1.3in https://www.sparkfun.com/products/23453 - - Updated from example writtin by Paul Clark @ SparkFun Electronics - Original Creation Date: December 11th, 2020 - - Repository: - https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library - - Documentation: - https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -*/ - -#include //http://librarymanager/All#SparkFun_Qwiic_OLED - -// The Library supports four different types of SparkFun boards. The demo uses the following -// defines to determine which device is being used. Uncomment the device being used for this demo. - -QwiicMicroOLED myOLED; -//QwiicTransparentOLED myOLED; -//QwiicNarrowOLED myOLED; -//Qwiic1in3OLED myOLED; - -int width; -int height; - -void setup() -{ - Serial.begin(115200); - Serial.println("Running OLED example"); - - Wire.begin(); - // Wire.setClock(400000); //Optionally increase I2C bus speed to 400kHz - - // Initalize the OLED device and related graphics system - if (myOLED.begin() == false) - { - Serial.println("Device begin failed. Freezing..."); - while (true) - ; - } - Serial.println("Begin success"); - - width = myOLED.getWidth(); - height = myOLED.getHeight(); - - // Not all platforms have A0 -#ifdef A0 - randomSeed(analogRead(A0)); -#endif -} - -void loop() -{ - pixelExample(); - lineExample(); - shapeExample(); -} - -void pixelExample() -{ - myOLED.erase(); - for (int i = 0; i < 512; i++) - { - myOLED.pixel(random(width), random(height)); - myOLED.display(); - delay(10); - } -} - -void lineExample() -{ - int middleX = width / 2; - int middleY = height / 2; - int xEnd, yEnd; - int lineWidth = min(middleX, middleY); - - myOLED.erase(); - int deg; - - for (int i = 0; i < 3; i++) - { - - for (deg = 0; deg < 360; deg += 15) - { - - xEnd = lineWidth * cos(deg * PI / 180.0); - yEnd = lineWidth * sin(deg * PI / 180.0); - - myOLED.line(middleX, middleY, middleX + xEnd, middleY + yEnd); - myOLED.display(); - delay(10); - } - - for (deg = 0; deg < 360; deg += 15) - { - - xEnd = lineWidth * cos(deg * PI / 180.0); - yEnd = lineWidth * sin(deg * PI / 180.0); - - myOLED.line(middleX, middleY, middleX + xEnd, middleY + yEnd, 0); - myOLED.display(); - delay(10); - } - } -} - -void shapeExample() -{ - // Silly pong demo. It takes a lot of work to fake pong... - int paddleW = 3; // Paddle width - int paddleH = 15; // Paddle height - - // Paddle 0 (left) position coordinates - int paddle0_Y = (height / 2) - (paddleH / 2); - int paddle0_X = 2; - - // Paddle 1 (right) position coordinates - int paddle1_Y = (height / 2) - (paddleH / 2); - int paddle1_X = width - 3 - paddleW; - int ball_rad = 4; // Ball radius - - // Ball position coordinates - int ball_X = paddle0_X + paddleW + ball_rad; - int ball_Y = random(1 + ball_rad, height - ball_rad); // paddle0_Y + ball_rad; - int ballVelocityX = 1; // Ball left/right velocity - int ballVelocityY = 1; // Ball up/down velocity - int paddle0Velocity = -1; // Paddle 0 velocity - int paddle1Velocity = 1; // Paddle 1 velocity - - // Draw the Pong Field - myOLED.erase(); - - // Draw an outline of the screen: - myOLED.rectangle(0, 0, width - 1, height); - - // Draw the center line - myOLED.rectangleFill(width / 2 - 1, 0, 2, height); - - bool firstLoop = true; - - while ((ball_X - ball_rad > 1) && (ball_X + ball_rad < width - 2)) - { - - if (!firstLoop) - { - - // Erase the old ball. In XOR mode, so just draw old values again! - // Draw the Paddles: - myOLED.rectangleFill(paddle0_X, paddle0_Y, paddleW, paddleH); - myOLED.rectangleFill(paddle1_X, paddle1_Y, paddleW, paddleH); - // Draw the ball: - use rect - xor and circle fails b/c of circle algorithm overdraws - myOLED.rectangleFill(ball_X, ball_Y, ball_rad, ball_rad); - } - // Increment ball's position - ball_X += ballVelocityX; - ball_Y += ballVelocityY; - - // Check if the ball is colliding with the left paddle - if (ball_X - ball_rad < paddle0_X + paddleW) - { - - // Check if ball is within paddle's height - if ((ball_Y > paddle0_Y) && (ball_Y < paddle0_Y + paddleH)) - { - - ball_X++; // Move ball over one to the right - ballVelocityX = -ballVelocityX; // Change velocity - } - } - - // Check if the ball hit the right paddle - if (ball_X + ball_rad > paddle1_X) - { - - // Check if ball is within paddle's height - if ((ball_Y > paddle1_Y) && (ball_Y < paddle1_Y + paddleH)) - { - - ball_X--; // Move ball over one to the left - ballVelocityX = -ballVelocityX; // change velocity - } - } - - // Check if the ball hit the top or bottom - if ((ball_Y <= 1) || (ball_Y >= (height - ball_rad - 1))) - { - - // Change up/down velocity direction - ballVelocityY = -ballVelocityY; - } - - // Move the paddles up and down - paddle0_Y += paddle0Velocity; - paddle1_Y += paddle1Velocity; - - // Change paddle 0's direction if it hit top/bottom - if ((paddle0_Y <= 1) || (paddle0_Y > height - 2 - paddleH)) - paddle0Velocity = -paddle0Velocity; - - // Change paddle 1's direction if it hit top/bottom - if ((paddle1_Y <= 1) || (paddle1_Y > height - 2 - paddleH)) - paddle1Velocity = -paddle1Velocity; - - // Draw the Paddles: - myOLED.rectangleFill(paddle0_X, paddle0_Y, paddleW, paddleH); - myOLED.rectangleFill(paddle1_X, paddle1_Y, paddleW, paddleH); - - // Draw the ball: - myOLED.rectangleFill(ball_X, ball_Y, ball_rad, ball_rad); - - // Actually draw everything on the screen: - myOLED.display(); - - // Once the first loop is done, switch to XOR mode. So we just update our - // moving parts - if (firstLoop) - { - firstLoop = false; - myOLED.setDrawMode(grROPXOR); - } - - delay(25); // Delay for visibility - } - delay(1000); - myOLED.setDrawMode(grROPCopy); -} diff --git a/examples/Example-09_CustomOLED/Example-09_CustomOLED.ino b/examples/Example-09_CustomOLED/Example-09_CustomOLED.ino deleted file mode 100644 index d7b0ac6..0000000 --- a/examples/Example-09_CustomOLED/Example-09_CustomOLED.ino +++ /dev/null @@ -1,89 +0,0 @@ -/* - - Example-09_CustomOLED.ino - - This demo shows the basic setup of the OLED library, generating simple graphics and displaying - the results on the target device. - - Micro OLED https://www.sparkfun.com/products/14532 - Transparent OLED https://www.sparkfun.com/products/15173 - "Narrow" OLED https://www.sparkfun.com/products/24606 - Qwiic OLED 1.3in https://www.sparkfun.com/products/23453 - - Written by Kirk Benell @ SparkFun Electronics, March 2022 - - Repository: - https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library - - Documentation: - https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ - - SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -*/ - -#include //http://librarymanager/All#SparkFun_Qwiic_OLED - - -// This demo shows how to use the QwiicCustomOLED class, -// allowing the display width, height etc. to be set manually. - -QwiicCustomOLED myOLED; - -void setup() -{ - delay(1000); - - Serial.begin(115200); - Serial.println("Running OLED example"); - - Wire.begin(); - - // If desired, we can customize the OLED before we begin it. - // Otherwise it will default to 128x64 (1.3" OLED). - myOLED.setXOffset(0); // Set the active area X offset. For the Micro 64x48, set this to 2 - myOLED.setYOffset(0); // Set the active area Y offset - myOLED.setDisplayWidth(128); // Set the active area width. For the Micro 64x48, set this to 64 - myOLED.setDisplayHeight(64); // Set the active area height. For the Micro 64x48, set this to 48 - myOLED.setPinConfig(0x12); // Set COM Pins Hardware Configuration (DAh) - myOLED.setPreCharge(0xF1); // Set Pre-charge Period (D9h) - myOLED.setVcomDeselect(0x40); // Set VCOMH Deselect Level (DBh) - myOLED.setContrast(0xCF); // Set Contrast Control for BANK0 (81h). For the Micro 64x48, set this to 0x8F - - // Initalize the OLED device and related graphics system - if (myOLED.begin(Wire, 0x3D) == false) // The TwoWire port and I2C address are set here - { - Serial.println("Device begin failed. Freezing..."); - while (true) - ; - } - Serial.println("Begin success"); - - // Do a simple test - fill a rectangle on the screen and then print hello! - - // Fill a rectangle on the screen that has a 4 pixel board - myOLED.rectangleFill(4, 4, myOLED.getWidth() - 8, myOLED.getHeight() - 8); - - String hello = "hello"; // our message - - // Center our message on the screen. Get the screen size of the "hello" string, - // calling the getStringWidth() and getStringHeight() methods on the oled - - // starting x position - screen width minus string width / 2 - int x0 = (myOLED.getWidth() - myOLED.getStringWidth(hello)) / 2; - - // starting y position - screen height minus string height / 2 - int y0 = (myOLED.getHeight() - myOLED.getStringHeight(hello)) / 2; - - // Draw the text - color of black (0) - myOLED.text(x0, y0, hello, 0); - - // There's nothing on the screen yet - Now send the graphics to the device - myOLED.display(); - - // That's it - HELLO! -} - -void loop() -{ - delay(1000); // Do nothing -} diff --git a/examples/docs/ex_01_hello.md b/examples/docs/ex_01_hello.md deleted file mode 100644 index e678359..0000000 --- a/examples/docs/ex_01_hello.md +++ /dev/null @@ -1,176 +0,0 @@ -# Example 1 - Hello - -A simple example to show the basic setup and use of the SparkFun Qwiic OLED Library. - -**Key Demo Features** - -* Declaring a Qwiic OLED device object. -* Initializing the Qwiic OLED device -* Drawing a simple graphic - a filled rectangle and a text string -* Using the current font to center text on the screen. -* Displaying the graphics on the screen - - - -## Setup - -After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library. - - -```C++ -// Include the SparkFun Qwiic OLED Library -#include -``` - - -The next step is to declare the object for the SparkFun Qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the ```setup()``` or ```loop()``` functions. - -The user selects from one of the following classes: - -
- - - - - - - - - - - - - - - - - - - - - -
Class - Qwiic OLED Device -
QwiicMicroOLED - SparkFun Qwiic Micro OLED -
QwiicTransparentOLED - SparkFun Transparent Graphical OLED -
QwiicNarrowOLED - SparkFun Qwiic OLED Display (128x32) -
Qwiic1in3OLED - SparkFun Qwiic OLED 1.3" Display (128x32) -
-
- - - -The example code supports all of the SparkFun Qwiic OLED boards. By default, the Qwiic Micro OLED is selected. To select a different board being used, add a single line comment (i.e. `//`) in front of "`QwiicMicroOLED myOLED;`" and uncomment the device being used for the demo board. - - -```C++ -QwiicMicroOLED myOLED; -//QwiicTransparentOLED myOLED; -//QwiicNarrowOLED myOLED; -//Qwiic1in3OLED myOLED; - -``` - - -!!! note - As of version 1.0.2+, users will need to use the class as explained above instead of using a `#define`. - - ```C++ - #define MICRO - //#define NARROW - //#define TRANSPARENT - ``` - - -## Initialization - -In the ```setup()``` function of this sketch, like all of the SparkFun Qwiic Arduino libraries, the device is initialized by calling the ```begin()``` method. This method returns a value of ```true``` on success, or ```false``` on failure. - -```C++ -void setup() -{ - - delay(500); //Give display time to power on - - // Serial on! - Serial.begin(115200); - - Serial.println("\n\r-----------------------------------"); - - Serial.print("Running Example 01 on: "); - Serial.println(String(deviceName)); - - // Initalize the OLED device and related graphics system - if(!myOLED.begin()){ - - Serial.println(" - Device Begin Failed"); - while(1); - } - - Serial.println("- Begin Success"); - - // Do a simple test - fill a rectangle on the screen and then print hello!... - -} -``` - - - -## Drawing Graphics - -Once the device is enabled, the rest of the `setup()` function is devoted to drawing a simple graphic on the target device. - - - -### Filled Rectangle - -First, draw a filled rectangle on the screen - leave a 4 pixel boarder at the end of the screen. Note that the `getWidth()` and `getHeight()` method are used to get the devices screen size. - -```C++ - // Fill a rectangle on the screen that has a 4 pixel board - myOLED.rectangleFill(4, 4, myOLED.getWidth() - 8, myOLED.getHeight() - 8); -``` - - - -### Centered Text - -The next part of our graphic is a message centered in the drawn rectangle. To do the centering, the current font is accessed from the device, and the size of a character in the font is used to calculate the text position on the screen. Once the position is determined, the message is drawn on the display in black (0 for a color value). - -```C++ - String hello = "hello"; // our message - - // Center our message on the screen. Get the screen size of the "hello" string, - // calling the getStringWidth() and getStringHeight() methods on the oled - - // starting x position - screen width minus string width / 2 - int x0 = (myOLED.getWidth() - myOLED.getStringWidth(hello)) / 2; - - // starting y position - screen height minus string height / 2 - int y0 = (myOLED.getHeight() - myOLED.getStringHeight(hello)) / 2; - - // Draw the text - color of black (0) - myOLED.text(x0, y0, hello, 0); -``` - - - -### Displaying the Graphics - -The last step is sending the graphics to the device. This is accomplished by calling the `display()` method. - -```C++ - // There's nothing on the screen yet - Now send the graphics to the device - myOLED.display(); -``` - - -### What You Should See - -And that's it! Select the board and COM port for your development board. Then upload the code! The graphic should display on the OLED device. - -![Hello!](img/ex01_hello.png "Hello") diff --git a/examples/docs/ex_02_lines.md b/examples/docs/ex_02_lines.md deleted file mode 100644 index be69395..0000000 --- a/examples/docs/ex_02_lines.md +++ /dev/null @@ -1,274 +0,0 @@ -# Example 2 - Shapes - -An example that shows drawing simple shapes using the SparkFun Qwiic OLED Library. - -**Key Demo Features** - -* Drawing lines, rectangles and circles -* Demonstrating how graphics size impacts display speed -* Drawing and erasing graphics quickly -* XOR operations using raster operators - - - -## Setup - -After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library. - - -```C++ -// Include the SparkFun Qwiic OLED Library -#include -``` - - -The next step is to declare the object for the SparkFun Qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the ```setup()``` or ```loop()``` functions. - -The user selects from one of the following classes: - -
- - - - - - - - - - - - - - - - - - - - - -
Class - Qwiic OLED Device -
QwiicMicroOLED - SparkFun Qwiic Micro OLED -
QwiicTransparentOLED - SparkFun Transparent Graphical OLED -
QwiicNarrowOLED - SparkFun Qwiic OLED Display (128x32) -
Qwiic1in3OLED - SparkFun Qwiic OLED 1.3" Display (128x32) -
-
- - - -The example code supports all of the SparkFun Qwiic OLED boards. By default, the Qwiic Micro OLED is selected. To select a different board being used, add a single line comment (i.e. `//`) in front of "`QwiicMicroOLED myOLED;`" and uncomment the device being used for the demo board. - - -```C++ -QwiicMicroOLED myOLED; -//QwiicTransparentOLED myOLED; -//QwiicNarrowOLED myOLED; -//Qwiic1in3OLED myOLED; - -``` - - -!!! note - As of version 1.0.2+, users will need to use the class as explained above instead of using a `#define`. - - ```C++ - #define MICRO - //#define NARROW - //#define TRANSPARENT - ``` - - - -## Drawing Shapes - -!!! note - As of version 1.0.2+, the modular functions have a slightly different name. Some functions defined in the example code will have the `_` removed or words spelled out. For example, version v1.0.1 and below defined the function to test the line as `line_test_1()` while version v1.0.2+ defined the function as `lineTest1()`. - -The shapes drawn are broken into a set of functions that perform one test, which is part of the overall example. - - - -###Lines - -This test starts with a short, horizontal line that is animated from the top to bottom of the display. After each iteration, the line size is increased and the animating sequence repeated. - -To animate the line, the display is erased, then the line drawn. Once the line is draw, the updated graphics is sent to the OLED device by calling the `display()` method. - -!!! note - When `display()` is called, only the range of modified pixels is sent to the OLED device, greatly reducing the data transferred for small graphic changes. - - This is demonstrated by this test. When small lines are drawn, the update rate is fast, but as the line length increases, the update rate of the device is noticeably slower. A longer line requires more data to be sent to the device. - -```C++ -void lineTest1(void) -{ - int x, y, i; - - int mid = width / 2; - int delta = mid / 8; - - for (int j = 1; j < 8; j++) - { - - x = delta * j; - - for (i = 0; i < height * 2; i++) - { - - y = i % height; - myOLED.erase(); - myOLED.line(mid - x, y, mid + x, y); - myOLED.display(); - } - } -} -``` - - - -This test is followed up with a series of lines that span from a single point to the bottom of the screen, showing the flexibility of the line to raster algorithm used by the library. - -```C++ -void lineTest2(void) -{ - for (int i = 0; i < width; i += 6) - { - myOLED.line(0, 0, i, height - 1); - myOLED.display(); - } - delay(200); - myOLED.erase(); - for (int i = width - 1; i >= 0; i -= 6) - { - myOLED.line(width - 1, 0, i, height - 1); - myOLED.display(); - } -} -``` - - - -And the last line test draws a series of lines to test all three internal line drawing algorithms. Specifically: - -* Angled lines drawn by the general purpose line algorithm -* Vertical lines drawn by an optimized line routine -* Horizontal lines draw by an optimized line routine - -The test animates to show a growing box, giving an idea of the speed and flexibility of the system. - -```C++ -void lineTestVerticalIterative(uint8_t y0, uint8_t y1) -{ - for (int i = 0; i < width; i += 8) - myOLED.line(i, y0, i, y1); - - // end off the vertical lines - myOLED.line(width - 1, y0, width - 1, y1); - - // End lines and cross lines - myOLED.line(0, y0, width - 1, y0); - myOLED.line(0, y1, width - 1, y1); - myOLED.line(0, y0, width - 1, y1); - myOLED.line(0, y1, width - 1, y0); -} - -// Entry point for test -void lineTestVertical(void) -{ - int mid = height / 2; - - for (int i = 0; i < height; i += 4) - { - - myOLED.erase(); - lineTestVerticalIterative(mid - i / 2, mid + i / 2); - myOLED.display(); - delay(10); - } -} -``` - - - -### Rectangles - -Several rectangle routines are shown in this example. A key test is a fast drawing routine which animates a small rectangle being drawn diagonally across the screen. - -In this test, the rectangle is drawn, sent to the device via using `display()`, then the rectangle is drawn again, but this time in black. This effectively erases the rectangle. The position is incremented and the process loops, causing the rectangle to appear to fly across the screen. - -The animation is quick, since only the portions of the screen that need updated are actually updated. - -The animation algorithm is listed in the `rectangleTestMove() function. - -```C++ -void rectangleTestMove(void) -{ - float steps = height; - float xinc = width / steps; - float yinc = height / steps; - int side = 10; - float x = 0; - float y = 0; - - for (int i = 0; i < steps; i++) - { - // Draw the rectangle and send it to device - myOLED.rectangle(x, y, side, side); - myOLED.display(); // sends erased rect and new rect pixels to device - - // Erase the that rect, increment and loop - myOLED.rectangle(x, y, side, side, 0); - - x += xinc; - y += yinc; - } -} -``` - - - -The next rectangle test draws a series of filled rectangles on the screen. The unique aspect of this test is that is uses the XOR functionally to overlay a rectangle on the device, presenting a alternating color pattern. - -The XOR raster operation is set by calling the `setDrawMode()` method on the OLED device, and providing the `grROPXOR` code. This switch the device into a XOR drawing mode. Graphic operations are restored to normal by calling `setDrawMode()` and providing the `grROPCopy` code, which copies the new pixel value to the destination. - -Filled rectangles and XOR operations: - -```C++ -void rectangleFillTest(void) -{ - myOLED.rectangleFill(4, 4, width / 2 - 8, height - 8); - - myOLED.rectangleFill(width / 2 + 4, 4, width / 2 - 8, height - 8); - - myOLED.setDrawMode(grROPXOR); // xor - myOLED.rectangleFill(width / 4, 8, width / 2, height - 16); - myOLED.setDrawMode(grROPCopy); // back to copy op (default) -} -``` - - - -### Circles - -The final shape drawn by this example is a series of circles and filled circles. Using the geometry of the screen, a set of circles are drawn and displayed. - -```C++ -void circleTest(void) -{ - // Let's draw some circles that fit on the device - myOLED.circle(width / 4, height / 2, height / 3); - - myOLED.circleFill(width - width / 4, height / 2, height / 3); - - myOLED.circle(4, height / 2, height / 3); - - myOLED.circleFill(width - width / 2, height / 2, height / 4); -} -``` diff --git a/examples/docs/ex_03_bitmaps.md b/examples/docs/ex_03_bitmaps.md deleted file mode 100644 index 4836593..0000000 --- a/examples/docs/ex_03_bitmaps.md +++ /dev/null @@ -1,75 +0,0 @@ -# Example 3 - Bitmaps - -An example that shows drawing bitmaps using the SparkFun Qwiic OLED Library. - -**Key Demo Features** - -* Understanding bitmap structure -* Bitmap objects -* Drawing Bitmap - - -## Setup - -After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library. -```C++ -// Include the SparkFun qwiic OLED Library -#include -``` -The next step is to declare the object for the SparkFun qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the ```setup()``` or ```loop()``` functions. - -The user selects from one of the following classes: - -| Class | Qwiic OLED Device | -| :--- | :--- | -| `QwiicMicroOLED` | [SparkFun Qwiic Micro OLED ]( https://www.sparkfun.com/products/14532)| -| `QwiicNarrowOLED` | [SparkFun Qwiic OLED Display (128x32) ]( https://www.sparkfun.com/products/17153)| -| `QwiicTransparentOLED` | [SparkFun Transparent Graphical OLED]( https://www.sparkfun.com/products/15173)| -| `Qwiic1in3OLED` | [SparkFun Qwiic OLED 1.3" Display (128x32) ]( https://www.sparkfun.com/products/23453)| - -The Example code supports all of the SparkFun Qwiic OLED boards. To select the board being used, uncomment the `#define` for the demo board. - -For this example, the Qwiic Micro OLED is used. - -```C++ -#define MICRO -//#define NARROW -//#define TRANSPARENT -``` -Which results in myOLED being declared as: - -```C++ -QwiicMicroOLED myOLED; -``` -## Initialization - -In the ```setup()``` function of this sketch, like all of the SparkFun qwiic libraries, the device is initialized by calling the ```begin()``` method. This method returns a value of ```true``` on success, or ```false``` on failure. - -```C++ -void setup() -{ - - delay(500); //Give display time to power on - - // Serial on! - Serial.begin(115200); - - Serial.println("\n\r-----------------------------------"); - - Serial.print("Running Example 01 on: "); - Serial.println(String(deviceName)); - - // Initalize the OLED device and related graphics system - if(!myOLED.begin()){ - - Serial.println(" - Device Begin Failed"); - while(1); - } - - Serial.println("- Begin Success"); - -``` -## Drawing Bitmaps - - - diff --git a/examples/docs/ex_04_text.md b/examples/docs/ex_04_text.md deleted file mode 100644 index fc7ece7..0000000 --- a/examples/docs/ex_04_text.md +++ /dev/null @@ -1,75 +0,0 @@ -# Example 4 - Text - -An example that shows drawing bitmaps using the SparkFun Qwiic OLED Library. - -**Key Demo Features** - -* Understanding font structure and use -* Drawing text -* Using the Arduino `Print` functionality - - -## Setup - -After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library. -```C++ -// Include the SparkFun qwiic OLED Library -#include -``` -The next step is to declare the object for the SparkFun qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the ```setup()``` or ```loop()``` functions. - -The user selects from one of the following classes: - -| Class | Qwiic OLED Device | -| :--- | :--- | -| `QwiicMicroOLED` | [SparkFun Qwiic Micro OLED ]( https://www.sparkfun.com/products/14532)| -| `QwiicNarrowOLED` | [SparkFun Qwiic OLED Display (128x32) ]( https://www.sparkfun.com/products/17153)| -| `QwiicTransparentOLED` | [SparkFun Transparent Graphical OLED]( https://www.sparkfun.com/products/15173)| -| `Qwiic1in3OLED` | [SparkFun Qwiic OLED 1.3" Display (128x32) ]( https://www.sparkfun.com/products/23453)| - -The Example code supports all of the SparkFun Qwiic OLED boards. To select the board being used, uncomment the `#define` for the demo board. - -For this example, the Qwiic Micro OLED is used. - -```C++ -#define MICRO -//#define NARROW -//#define TRANSPARENT -``` -Which results in myOLED being declared as: - -```C++ -QwiicMicroOLED myOLED; -``` -## Initialization - -In the ```setup()``` function of this sketch, like all of the SparkFun qwiic libraries, the device is initialized by calling the ```begin()``` method. This method returns a value of ```true``` on success, or ```false``` on failure. - -```C++ -void setup() -{ - - delay(500); //Give display time to power on - - // Serial on! - Serial.begin(115200); - - Serial.println("\n\r-----------------------------------"); - - Serial.print("Running Example 01 on: "); - Serial.println(String(deviceName)); - - // Initalize the OLED device and related graphics system - if(!myOLED.begin()){ - - Serial.println(" - Device Begin Failed"); - while(1); - } - - Serial.println("- Begin Success"); - -``` -## Drawing Text - - - diff --git a/examples/docs/ex_other.md b/examples/docs/ex_other.md deleted file mode 100644 index a966fef..0000000 --- a/examples/docs/ex_other.md +++ /dev/null @@ -1,16 +0,0 @@ -# Other Examples - -Descriptions of the other demos that are provided as part of the SparkFun Qwiic OLED Library. - -## Scroll-Flip - - - -## Clock - - -## Cube - - -## Multi - diff --git a/examples/mkdocs.yml b/examples/mkdocs.yml deleted file mode 100644 index 037315b..0000000 --- a/examples/mkdocs.yml +++ /dev/null @@ -1,8 +0,0 @@ -site_name: SparkFun Qwiic OLED Arduino Library - Examples - -nav: - - Example 1 - Hello: "ex_01_hello.md" - - Example 2 - Shapes: "ex_02_lines.md" - - Example 3 - Bitmaps: "ex_03_bitmaps.md" - - Example 4 - Text: "ex_04_text.md" - - Other Examples: "ex_other.md" \ No newline at end of file diff --git a/github/contribute/index.html b/github/contribute/index.html new file mode 100644 index 0000000..4c84d4a --- /dev/null +++ b/github/contribute/index.html @@ -0,0 +1,1911 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Contribute - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Contribute: Help Fix our Mistake!

+

Spot something wrong? Feel free to contribute our open-source design and documentation.

+

Improve our Documentation

+

All of this documentation can be modified by you! Please help us make it better.

+ +

Submit a Correction

+
    +
  1. Fork this repo
  2. +
  3. Add your corrections or improvements to the markdown file
  4. +
  5. File a pull request with your changes, and enjoy making the words worlds world a better place.
      +
    • Once received, the documentation specialist will automatically be notified.
    • +
    • We will review your suggested improvements to make sure they are correct and fit within our documentation standards.
    • +
    +
  6. +
+

Improve our Hardware Design

+

All of our designs are open-source! Please help us make it better.

+ +

Submit a Design Improvement

+
    +
  1. Fork this repo
  2. +
  3. Add your design improvements
  4. +
  5. File a pull request with your changes, and enjoy making the words worlds world a better place.
      +
    • Once received, the engineer in charge of the original design will automatically be notified.
    • +
    • We will review your suggested improvements, if they are within our board design standards and meet our product design requirements, we will flag these changes for our next board revision. (Please note, that even if your suggestion is accepted, these changes may not be immediate. We may have to cycle through our current product inventory first.)
    • +
    +
  6. +
+

Contributors

+

Let's provided some recognition to the contributors for this project!

+

GitHub Contributors Image +
+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/github/file_issue/index.html b/github/file_issue/index.html new file mode 100644 index 0000000..70340ba --- /dev/null +++ b/github/file_issue/index.html @@ -0,0 +1,1989 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Submit Issues - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + + + + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Did we make a mistake?

+

Spot something wrong? Please let us know.

+
+

Attention

+

This is not where customers should seek assistance on a product. If you require technical assistance or have questions about a product that is not working as expected, please head over to the SparkFun Technical Assistance page for some initial troubleshooting. +

+SparkFun Technical Assistance Page +

+

If you can't find what you need there, you'll need a Forum Account to search product forums and post questions.

+
+

Discrepancies in the Documentation

+

All of this documentation can be modified by you! Please help us make it better.

+ +

Spot something wrong?

+

If a section of the documentation is incorrect, please open an issue and let us know.

+

Do you have a suggested correction?

+
    +
  1. With a GitHub account, fork this repo
  2. +
  3. Add your correction(s) or improvement(s) to the markdown file(s)
  4. +
  5. File a pull request with your changes, and enjoy making the words worlds world a better place.
      +
    • Once received, the documentation specialist will automatically be notified.
    • +
    • We will review your suggested improvement(s) to make sure they are correct and fit within our documentation standards.
    • +
    +
  6. +
+

Problems in the Hardware Design

+

All of our designs are open-source! Please help us make it better.

+

Our board design files are contained in the Hardware folder of their respective repositories:

+ +

Does something not make sense?

+

If part of the design is confusing, please open an issue and let us know.

+

Did we forget to include an important function of the board?

+
    +
  • Please keep in mind that we may intentionally exclude certain functions of the board to meet our product design requirements. (For example, our Qwiic Micro boards are intended to fit on a small board layout and only use I2C communication; therefore, we may not have the SPI and interrupt pins available for users.)
  • +
  • If part of the board's functionality is missing, please open an issue and file a feature request.
  • +
+

Do you wish to contribute directly to improving the board design?

+
    +
  1. With a GitHub account, Fork this repo
  2. +
  3. Add your design improvement(s)
  4. +
  5. File a pull request with your changes, and enjoy making the words worlds world a better place.
      +
    • Once received, the engineer in charge of the original design will automatically be notified.
    • +
    • We will review your suggested improvement(s), if they are within our board design standards and meet our product design requirements, we will flag these changes for our next board revision. (Please note, that even if your suggestion is accepted, these changes may not be immediate. We may have to cycle through our current product inventory first.)
    • +
    +
  6. +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hug_0p91/index.html b/hug_0p91/index.html new file mode 100644 index 0000000..4f182d1 --- /dev/null +++ b/hug_0p91/index.html @@ -0,0 +1,2637 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qwiic OLED (0.91", 128x32) - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Qwiic OLED (0.91", 128x32)

+ +

Introduction

+

The SparkFun Qwiic OLED Display can display up to four lines of text and features 128x32 pixels in a small 0.91” (diagonal) frame. As an OLED, this display does not have a back light layer (unlike LCDs) and therefore it’s thinner, consumes less power, and has higher contrast.

+

+ +

+

In this section, we'll go over the hardware and how to hookup the breakout board.

+

Required Materials

+

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

+ +

Microcontroller

+

To get started, you'll need a microcontroller to, well, control everything. We used the RedBoard with the ATmega328P for the Qwiic micro OLED. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

+ +

USB Cable

+

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

+ +

Qwiic

+

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

+ +

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

+ +

Of course, you will also need a Qwiic Micro OLED if you have not added that to you cart already.

+

+ +

+

Hardware Overview

+

In this section, we will highlight the hardware and pins that are broken out on the SparkFun Qwiic OLED Display (0.91 in., 128x32).

+
+ + + + + + + + + +
Top ViewBottom View
Top ViewBottom View
+
+ +

OLED Display (0.91", 128x32)

+

The OLED screen has a pixel resolution of 128x32, a panel size of 30.0mm x 11.5mm x 1.2mm, and an active area of 22.384mm x 5.584mm. The driver chip is the SSD1306. For information can be found in the datasheet linked in the Resources.

+
+ + + + + + + +
OLED Highlighted
OLED Highlighted
+
+ +
+

Note

+

The SparkFun Qwiic OLED Arduino Library works for multiple displays. However, there are some caveats in the size of the display with the text. While you can technically display all fonts in the narrow OLED display, some characters (numbers, letters, and/or symbols depending on the font) will be too big to fully display on the screen. For example, the fonts for the 31x48 (i.e. &QW_FONT_31X48) and large numbers (i.e. &QW_FONT_LARGENUM) are too big to fit within the display.

+

Using the OLED display (0.91", 128x32) we found that we were able to fit:

+
    +
  • 4x lines, 21x characters using the 5x7 (i.e. &QW_FONT_5X7)
  • +
  • 2x lines, 14x characters using the 8x16 (i.e. &QW_FONT_8X16)
  • +
  • 2x lines, 11x characters using the 7 segment (i.e. &QW_FONT_7SEGMENT)
  • +
+
+

Power

+

Power is applied through the vertical Qwiic connectors on the back of the board. The recommended input voltage is 3.3V. The logic levels for the Qwiic OLED Display (0.9", 128x32) is 3.3V.

+
+ + + + + + + +
Power
Power
+
+ +

Qwiic and I2C

+

There are two vertical Qwiic connectors populated on the back of the board. You can use either connectors to provide power and send data through I2C. The Qwiic ecosystem is made for fast prototyping by removing the need for soldering. All you need to do is plug a Qwiic cable into the Qwiic connector and voila!

+
    +
  • SCL — I2C clock
  • +
  • SDA — I2C data
  • +
  • 3.3V — Power
  • +
  • GND — Ground
  • +
+
+ + + + + + + +
Qwiic Connectors
Vertical Qwiic Connectors
+
+ +

The address of the display is 0x3C.

+
+

Note

+

On the back of the board, the power and I2C pins are broken out to test points. These are used in our production department for quality control using custom testbeds. These could be an alternative option to connect to the pins. However, we recommend using the Qwiic connectors to easily connect to the OLED display. Note that the I2C pins are also in a different order compared to a standard I2C Qwiic connector should you decide to solder to the test points.

+

+ + + + + + + +
I2C Test Points
I2C Test Points
+

+
+

Jumpers

+
+

Note

+

If this is your first time working with jumpers, check out the How to Work with Jumper Pads and PCB Traces tutorial for more information.

+
+

The board includes a 1x3 jumper on the back of the board.

+
    +
  • I2C — This three way jumper labeled I2C is connected to two 4.7kΩ pull-up resistors to the I2C data and clock lines. For users that have multiple Qwiic-enabled devices with pull-up resistors enabled, the parallel equivalent resistance will create too strong of a pull-up for the bus to operate correctly. As a general rule of thumb, disable all but one pair of pull-up resistors if multiple devices are connected to the bus.
  • +
+
+ + + + + + + +
Jumpers Highlighted
Jumpers Highlighted
+
+ +

Board Dimensions

+

Version 1.1 is a bit smaller than previous versions since the board includes vertical Qwiic connectors on the back of the board. The overall board size is 1.75 in x 0.5 in. The mounting holes have also moved to toward the top of the board.

+
+ + + + + + + +
Board Dimensions
Board Dimensions
+
+ +

Hardware Hookup

+

In this section, we'll go over how to connect to the display. We will go just a bit further and talk about how to mount the display.

+

Connecting via Qwiic Connector

+

Insert a Qwiic cable between your chosen microcontroller and Qwiic OLED. Then insert a USB cable between the microcontroller and your computer's COM port. For the scope of this tutorial, the USB cable provides power and allows us to upload code to the microcontroller. Of course, you can also debug the display by opening a Serial Terminal.

+
+ + + + + + + +
USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, Qwiic OLED (0.9 in., 12x32)
USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, Qwiic OLED (0.9 in., 12x32)
+
+ +

Once you have finished prototyping, you could continue to use the USB cable and add a 5V power supply or battery pack.

+

Mounting the Qwiic OLED (0.9", 128x32)

+

Grab the board dimensions and cut out a rectangle in the enclosure. For users that want to mount the board so that the OLED display is flush against the enclosure, you will need to look at the dimensions based on the OLED. You will need to add a little tolerance so that the display can fit through the rectangle. For users that need to quickly mount the board, you will could also cut out rectangles based on the vertical Qwiic connector so that the wires can lead into the enclosure. Then cut out the mounting holes so that the board is right side up. In this case, we used a cardboard box as a quick example to demonstrate the Qwiic wires connecting leading into the enclosure.

+
+ + + + + + + + +
5V Battery Pack, USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, and Qwiic OLED (0.9 in., 12x32), stuffed in a cardboard box.5V Battery Pack, USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, and Qwiic OLED (0.9 in., 12x32) Mounted
Qwiic OLED Display Mounted in an Enclosure
+
+ +
+

Note

+

To easily display text and graphics on the board, we recommend mounting the board right side up. There is an option in the example code to flip the text horizontally and vertically should you decide to mount the board upside down, but you would need to also determine the position of the text.

+
+

For a more durable enclosure, you could use wood, metal, or plastic. However, you will need additional tools to cut into the material.

+

Software

+

The Qwiic OLED (0.91", 128x32) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED Library's Software Setup has instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

+ + +

Resources

+

Now that you've successfully got your OLED Display (0.9", 128x36) up and running, it's time to incorporate it into your own project! For more information, check out the resources below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hug_1p3/index.html b/hug_1p3/index.html new file mode 100644 index 0000000..d690b37 --- /dev/null +++ b/hug_1p3/index.html @@ -0,0 +1,1657 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qwiic OLED (1.3", 128x64) - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Qwiic OLED (1.3", 128x64)

+ +

The Qwiic OLED 1.3in has its own hook-up guide.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hug_micro_view/index.html b/hug_micro_view/index.html new file mode 100644 index 0000000..8724b41 --- /dev/null +++ b/hug_micro_view/index.html @@ -0,0 +1,2587 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qwiic Micro OLED (0.66", 64x48) - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Qwiic Micro OLED (0.66", 64x48)

+ +

Introduction

+

The Qwiic Micro OLED is a Qwiic enabled version of our micro OLED display! This small monochrome, blue-on-black OLED display displays incredibly clear images.

+

+ +

+
+ +
+ +

This hookup guide will show you how to get started drawing objects and characters on your OLED.

+

Required Materials

+

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

+ +

Microcontroller

+

To get started, you'll need a microcontroller to, well, control everything. We used the RedBoard with the ATmega328P for the Qwiic micro OLED. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

+ +

USB Cable

+

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

+ +

Qwiic

+

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

+ +

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

+ +

Of course, you will also need a Qwiic Micro OLED if you have not added that to you cart already.

+

+ +

+

Suggested Reading

+

If you aren't familiar with the Qwiic Connection System, we recommend reading here for an overview.

+
+ + + + + + + +
+
Qwiic Connection System +
+
+
+ +

We would also recommend taking a look at the following tutorials if you aren't familiar with them.

+ +

Hardware Overview

+

Listed below are some of the operating ranges and characteristics of the Qwiic Micro OLED.

+
+ + + + + + + + + + + + + + + + + +
Characteristic + Range +
Voltage + 3.3V +
Temperature + -40°C to 85°C +
I2C Address + 0X3D (Default) or 0X3C (Closed Jumper) +
+
+ +

Pins

+

Power and I2C pins are broken out to the 1x4 PTH pins as well as the two horizontal Qwiic connectors.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Pin + Description + Direction +
GND + Ground + In +
3.3V + Power + In +
SDA + I2C Data + In +
SCL + I2C Clock + In +
+
+ +

Jumpers

+

There are several jumpers on board that can be changed to facilitate several different functions. The first of which is the I2C pull-up jumper to disable the 2.2kΩ pull up resistors on the I2C data and clock lines, highlighted below. If multiple boards are connected to the I2C bus, the equivalent resistance goes down, increasing your pull up strength. If multiple boards are connected on the same bus, make sure only one board has the pull-up resistors connected.

+
+ + + + + + + +
I2C Pull-Up Jumper
I2C Pull-Up Jumper
+
+ +

The ADDR jumper (highlighted below) can be used to change the I2C address of the board. The default jumper is open by default, pulling the address pin high and giving us an I2C address of 0X3D. Closing this jumper will ground the address pin, giving us an I2C address of 0X3C.

+
+ + + + + + + +
Address Jumper
Address Jumper
+
+ +

Board Dimensions

+
+

Revision Change

+

For V11, we have optimized the two mounting hole locations to match the mounting holes located on a standard 1.0" x 1.0" Qwiic-sized board. The overall functionality of the Qwiic Micro OLED breakout board is the same as the previous version!

+
+

The overall board size is 1.08" x 1.17". There is a v-score for users that want to remove the mounting holes.

+
+ + + + + + + +
Board Dimensions
Board Dimensions
+
+ +

Hardware Assembly

+

If you haven't yet assembled your Qwiic Shield, now would be the time to head on over to that tutorial. With the shield assembled, SparkFun's Qwiic environment means that connecting the screen could not be easier. Just plug one end of the Qwiic cable into the OLED display, the other into the Qwiic Shield and you'll be ready to start displaying images on your little display.

+
+ + + + +
Qwiic Micro OLED Connected to Arduino and Qwiic Shield
+
+ +

If you have a built-in Qwiic connector, you can skip the hardware assembly of the Qwiic Shield and simply insert a Qwiic cable between the two boards. Have more than one Qwiic-enabled device? You can daisy chain it to the board as well! Below is an example with the SAM-M8Q and the Qwiic Micro OLED daisy chained together to the RedBoard Qwiic.

+
+ + + + +
Qwiic Micro OLED Connected to RedBoard Qwiic and Qwiic GPS(SAM-M8Q)
+
+ +
+

Note

+

The initial launch of the Qwiic micro OLED breakout board had the OLED loosely attached to the breakout board. For users that received those boards, be careful handling it! You can either use your own enclosure for the OLED display, or you can use some double sided foam tape for a less permanent solution.

+

+ + + + +
Taped Screen
+

+

The current production of the boards includes the double sided foam tape.

+
+

Software

+

The SparkFun Micro OLED Breakout (Qwiic) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED library Getting Started guide has library setup instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

+ + +

Resources

+

Now that you've successfully got your OLED displaying things, it's time to incorporate it into your own project!

+

For more on the Qwiic Micro OLED, check out the links below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hug_transparent/index.html b/hug_transparent/index.html new file mode 100644 index 0000000..bf1f79b --- /dev/null +++ b/hug_transparent/index.html @@ -0,0 +1,2888 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qwiic Transparent Graphical OLED (1.51", 128x56) - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Qwiic Transparent Graphical OLED (1.51", 128x56)

+ +

Introduction

+

The future is here! You asked and we delivered - our Qwiic Transparent Graphical OLED Breakout allows you to display custom images on a transparent screen using either I2C or SPI connections.

+

With Qwiic connectors it's quick (ha ha) and easy to get started with your own images. However, we still have broken out 0.1"-spaced pins in case you prefer to use a breadboard. Brilliantly lit in the dark and still visible by daylight, this OLED sports a display area of 128x64 pixels, 128x56 of which are completely transparent. Control of the OLED is based on the HyperDisplay library or SparkFun Qwiic OLED Arduino Library! For the scope of this tutorial, we will be using the SparkFun Qwiic OLED Arduino Library.

+

+ +

+
+ +
+ +

This hookup guide will show you how to get started drawing objects and characters on your OLED.

+

Required Materials

+

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

+ +

Microcontroller

+

To get started, you'll need a microcontroller to, well, control everything. We used the SparkFun Thing Plus - ESP32 WROOOM. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

+ +

USB Cable

+

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

+ +

Qwiic

+

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

+ +

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

+ +

Of course, you will also need A Tranparent Graphical OLED Breakout if you have not added that to you cart already.

+

+ +

+

Suggested Reading

+

If you aren't familiar with the Qwiic Connection System, we recommend reading here for an overview.

+
+ + + + + + + +
+
Qwiic Connection System +
+
+
+ +

We would also recommend taking a look at the following tutorials if you aren't familiar with them.

+ +

Hardware Overview

+

Listed below are some of the operating ranges and characteristics of the Transparent Graphical OLED Breakout.

+
+ + + + + + + + + + + + + + + + + +
Characteristic + Range +
Voltage + 1.65V-3.3V,
typically 3.3V via the Qwiic Cable +
Supply Current + 400 mA +
I2C Address + 0X3C (Default), 0X3D (Closed Jumper) +
+
+ +

Graphical Display

+

The graphical display is where all the fun stuff happens. The glass itself measures 42mm x 27.16mm, with a pixel display that is 35.5 x 18mm. It houses 128x64 pixels, 128x56 of which are transparent.

+
+ + + + + + + +
Display Screen
Graphical Display
+
+ +

Qwiic Connectors

+

There are two Qwiic connectors on the board such that you can daisy-chain the boards should you choose to do so. If you're unfamiliar with our Qwiic Connect System, head on over to our Qwiic page to see the advantages!

+
+ + + + + + + +
Qwiic Connectors
Qwiic Connectors
+
+ +

GPIO Pins

+

When you look at the GPIO pins, you'll notice that the labels are different from one side to the other. One side is labeled for I2C, the other side is labeled for SPI.

+
+ + + + + + + + + +
I2C PinsSPI Pins
I2C LabelsSPI Labels
+
+ +

Power LED

+

This bad boy will light up when the board is powered up correctly.

+
+ + + + + + + +
I2C Pins
Power LED
+
+ +

You can disable the power LED by cutting the LED jumpers on the back of the board.

+
+ + + + + + + +
Power LED Jumpers
Power LED Jumpers
+
+ +

JPX Jumpers

+

The JPX jumpers are used to either change the I2C address or configure the board to use SPI communications. The other two jumpers allow you to disconnect the power LED and to disconnect the I2C pull-up resistors when chaining several Qwiic devices.

+
+ + + + + + + + + + + + + + + + + + + + + +
Jumper + Function +
JP1 + Holds the Chip Select line low when closed. Close for I2C, open for SPI +
JP2 + Selects the address in I2C mode. Closed for 0x30 by default and open for 0x31. Open for SPI mode to release the D/C pin +
JP3 + Used to select I2C or SPI mode. Close for I2C, open for SPI +
JP4 + This jumper should be closed for I2C and open for SPI. This connection allows SDA to be bi-directional +
+
+ +
+ + + + + + + +
JP1-JP4
JPX Jumper
+
+ +

I2C Pull-Up Jumper

+

I2C devices contain open drains so we include resistors on our boards to allow these devices to pull pins high. This becomes a problem if you have a large number of I2C devices chained together. If you plan to daisy chain more than a few Qwiic boards together, you'll need to cut this I2C pull-up jumper.

+
+ + + + + + + +
JP1 to JP4
I2C PU Jumper
+
+ +

Hardware Hookup

+

Now that you know what's available on your breakout board we can check out the options for connecting it to the brains of your project. There are two options to use - either I2C or SPI - and they each have their own advantages and drawbacks. Read on to choose the best option for your setup.

+
+

Warning

+

Reminder! This breakout can only handle up to 3.3V on the pins, so make sure to do some level shifting if you're using a 5V microcontroller.

+
+

I2C (Qwiic)

+

The easiest way to start using the Transparent Graphical OLED is to use a Qwiic Cable along with a Qwiic compatible microcontroller (such as the ESP32 Thing Plus). You can also use the Qwiic Breadboard Cable to attach any I2C capable microcontroller, or take the scenic route and solder in all the I2C wires to the plated-through connections on the board.

+
+ + + + + + + + + +
Qwiic ConnectorI2C Pinout
Top ViewI2C Pinout/i>
+
+ +

So why use I2C? It's easy to connect with the Qwiic system, and you can put up to two of the Transparent Graphical Breakouts on the same bus without using any more microcontroller pins. That simplicity comes at a cost to performance though. The maximum clock speed of the I2C bus is 400 kHz, and there is additional overhead in data transmission to indicate which bytes are data and which are commands. This means that the I2C connection is best for showing static images.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Breakout Pin + Microcontroller Pin Requirements +
GND + Ground pin. Connect these so the two devices agree on voltages +
3V3 + 3.3V supply pin, capable of up to 400 mA output +
SDA + SDA - the bi-directional data line of your chosen I2C port +
SCL + SCL - the clock line of your chosen I2C port +
SA0 + Optional : change the I2C address of the breakout. Make sure to cut JP2 +
RST + Optional : reset the breakout to a known state by pulsing this low +
+
+ +

SPI

+

SPI solves the I2C speed problems. With SPI there is a control signal that indicates data or command and the maximum clock speed is 10 MHz -- giving SPI 50x more speed! However, it doesn't have the same conveniences of the polarized Qwiic connector and low pin usage. You'll need to solder to the pins.

+
+ + + + + + + +
SPI Pinout
SPI Pinout
+
+ +

You can use SPI to connect as many breakouts as you want. For N displays you will need to use at least N + 3 data pins. That's because the MOSI, SCLK, and D/C pins can be shared between displays but each breakout needs its own dedicated Chip Select (CS) pin.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Breakout Pin + Microcontroller Pin Requirements +
CS + A GPIO pin, set low when talking to the breakout +
D/C + A GPIO pin, indicates if bytes are data or commands +
SCLK + The clock output of your chosen SPI port +
MOSI + The data output of your chosen SPI port +
3V3 + 3.3V supply pin, capable of up to 400 mA output +
GND + Ground pin. Connect these so the two devices agree on voltages +
+
+ +
+

Warning

+

Make sure to cut jumpers JP1, JP2, JP3, and JP4 when using SPI mode!

+

+ + + + + + + +
Cut Jumpers for SPI Mode
Cut Jumpers for SPI Mode
+

+
+

Software

+

The Transparent OLED Breakout (Qwiic) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED library Getting Started guide has library setup instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

+ + +

Resources

+

For more information on the Transparent Graphical OLED Breakout, check out some of the links here:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/img/Contributing.JPG b/img/Contributing.JPG deleted file mode 100644 index 5f453b9..0000000 Binary files a/img/Contributing.JPG and /dev/null differ diff --git a/docs/img/OLEDLibBanner.png b/img/OLEDLibBanner.png similarity index 100% rename from docs/img/OLEDLibBanner.png rename to img/OLEDLibBanner.png diff --git a/docs/img/sfe_logo_sm.png b/img/sfe_logo_sm.png similarity index 100% rename from docs/img/sfe_logo_sm.png rename to img/sfe_logo_sm.png diff --git a/index.html b/index.html new file mode 100644 index 0000000..c09e823 --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + + Redirecting... + + + + + +You're being redirected to a new destination. + + diff --git a/introduction/index.html b/introduction/index.html new file mode 100644 index 0000000..4ab657e --- /dev/null +++ b/introduction/index.html @@ -0,0 +1,2104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Introduction - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Introduction

+ +

SparkFun Qwiic OLED Arduino Library

+

The SparkFun Qwiic OLED Arduino Library is a single graphics module that supports all SparkFun OLED boards based on the SSD1306 from Solomon Systech. Prior to this library, three different libraries were used to support our four different OLED boards.

+

The SparkFun Qwiic OLED Library delivers a common implementation for all our Qwiic OLED products, delivering a unified, fast, and efficient solution that implements a familiar and easy to understand user experience.

+

Key Features

+
    +
  • Implements common graphics capabilities: pixel, line, rectangle, filled rectangle, circle, filled circle, bitmap, text and raster operators (i.e. XOR).
  • +
  • Smart data transfer to the device – only sends dirty regions of the graphics buffer to the OLED device, not the entire buffer.
  • +
  • High performance – 2x faster than our previous OLED library, often much higher.
  • +
  • Efficient memory usage. No dynamic memory utilized. Static resources are loaded once, and only on explicit declaration.
  • +
  • Implements a familiar interface, making migration from older libraries straight forward
  • +
+

Getting Started

+

The Software Setup outlines library installation and the general use of the Qwiic OLED library.

+

Detailed examples are included as part of the library installation process and available in the Arduino IDE menu: File > Examples > SparkFun Qwiic OLED Arduino Library. A walk-thru of key examples is contained in the Examples section of this documentation set.

+
+

Note

+

For v1.0.5 of the SparkFun Qwiic OLED Arduino Library, we named the library as SparkFun Qwiic OLED Graphics Library. After v1.0.6, we updated the name to say SparkFun Qwiic OLED Arduino Library. You may have multiple versions in your Arduino libraries folder if you installed the library more than once. To avoid confusion, issues compiling, and to use the latest version, we recommend removing the "SparkFun Qwiic OLED Graphics Library" folder should you decide to use the latest and greatest version. This will probably be located under ..Documents\Arduino\libraries, that is if you are using Windows.

+
+
+

Note

+

Note that we have more than one Arduino Library for the micro OLED. If you have the older Arduino Library, make sure to not confuse the two libraries. You will notice that the older library will be called "SparkFun Micro OLED Breakout". The example code will include the following line of code: #include <SFE_MicroOLED.h>.

+
+

A full API Reference is also provided for the library.

+ + +

Supported Products

+

The SparkFun Qwiic OLED Arduino Library supports the following SparkFun products.

+ +

Supported Microcontrollers - Arduino Environment

+

The following architectures are supported in the Arduino Library.

+ +

Below are a few of those processors populated on Arduino boards from the SparkFun catalog. You will need to make sure to check the associated hookup guides for additional information about compatible cables, drivers, or board add-ons.

+ +
+

Note

+

Unfortunately, the ATmega32U4 is not supported under this library. We recommend either using a different microcontroller or rolling back to the previous library written for the display.

+
+

License

+

The SparkFun Qwiic OLED Arduino Library is licensed using the Open Source MIT License:

+
The MIT License (MIT)
+
+Copyright (c) 2015 SparkFun Electronics
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/index.html b/javascript/index.html new file mode 100644 index 0000000..1175ac1 --- /dev/null +++ b/javascript/index.html @@ -0,0 +1,1629 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + javascript directory - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

javascript directory

+

This folder should contain the files for the custom javascript that is enabled in the product documentation

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/javascript/mathjax.js b/javascript/mathjax.js similarity index 100% rename from docs/javascript/mathjax.js rename to javascript/mathjax.js diff --git a/js/timeago.min.js b/js/timeago.min.js new file mode 100644 index 0000000..a8530a5 --- /dev/null +++ b/js/timeago.min.js @@ -0,0 +1,2 @@ +/* Taken from https://cdnjs.cloudflare.com/ajax/libs/timeago.js/4.0.2/timeago.min.js */ +!function(s,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((s=s||self).timeago={})}(this,function(s){"use strict";var a=["second","minute","hour","day","week","month","year"];function n(s,n){if(0===n)return["just now","right now"];var e=a[Math.floor(n/2)];return 1=m[t]&&t=m[e]&&e 0) { + var locale = getLocale(nodes[0]); + timeago.render(nodes, locale); + } + }) +} else { + var nodes = document.querySelectorAll('.timeago'); + if (nodes.length > 0) { + var locale = getLocale(nodes[0]); + timeago.render(nodes, locale); + } +} diff --git a/keywords.txt b/keywords.txt deleted file mode 100644 index 35c209c..0000000 --- a/keywords.txt +++ /dev/null @@ -1,72 +0,0 @@ -####################################### -# Syntax Coloring Map Quick OLED Library -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -QwiicTransparentOLED KEYWORD1 -QwiicNarrowOLED KEYWORD1 -QwiicMicroOLED KEYWORD1 -Qwiic1in3OLED KEYWORD1 -QwiicCustomOLED KEYWORD1 -QwiicFont KEYWORD1 -grRasterOp_t KEYWORD1 - - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -begin KEYWORD2 -reset KEYWORD2 -getWidth KEYWORD2 -getHeight KEYWORD2 -display KEYWORD2 -displayPower KEYWORD2 -erase KEYWORD2 -invert KEYWORD2 -scrollRight KEYWORD2 -scrollLeft KEYWORD2 -scrollVertRight KEYWORD2 -scrollVertLeft KEYWORD2 -scrollStop KEYWORD2 -flipVertical KEYWORD2 -flipHorizontal KEYWORD2 -setFont KEYWORD2 -getFont KEYWORD2 -setDrawMode KEYWORD2 -getDrawMode KEYWORD2 -pixel KEYWORD2 -line KEYWORD2 -rectangle KEYWORD2 -rectangleFill KEYWORD2 -circle KEYWORD2 -circleFill KEYWORD2 -bitmap KEYWORD2 -text KEYWORD2 -setCursor KEYWORD2 -setColor KEYWORD2 -getColor KEYWORD2 -write KEYWORD2 - -####################################### -# Constants (LITERAL1) -####################################### - -grROPCopy LITERAL1 -grROPNotCopy LITERAL1 -grROPNot LITERAL1 -grROPXOR LITERAL1 -grROPBlack LITERAL1 -grROPWhite LITERAL1 - -SCROLL_INTERVAL_5_FRAMES LITERAL1 -SCROLL_INTERVAL_64_FRAMES LITERAL1 -SCROLL_INTERVAL_128_FRAMES LITERAL1 -SCROLL_INTERVAL_256_FRAMES LITERAL1 -SCROLL_INTERVAL_3_FRAMES LITERAL1 -SCROLL_INTERVAL_4_FRAMES LITERAL1 -SCROLL_INTERVAL_25_FRAMES LITERAL1 -SCROLL_INTERVAL_2_FRAMES LITERAL1 diff --git a/library.json b/library.json deleted file mode 100644 index 7cf9796..0000000 --- a/library.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "SparkFun Qwiic OLED Arduino Library", - "version": "1.0.13", - "keywords": "display oled graphics", - "description": "Library for all SparkFun Qwiic OLED boards", - "repository": - { - "type": "git", - "url": "https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library.git" - }, - "frameworks": "arduino", - "platforms": "*" -} diff --git a/library.properties b/library.properties deleted file mode 100644 index 5dc01c3..0000000 --- a/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=SparkFun Qwiic OLED Arduino Library -version=1.0.13 -author=SparkFun Electronics -maintainer=SparkFun Electronics -sentence=Library for SparkFun SSD1306 based OLED display products. -paragraph=A very fast and efficient Arduino library for the SSD1306 driver IC. Transfer rates are up to 400% faster than alternative libraries; only dirty regions of the graphics buffer are sent to the display. Efficient memory usage. No dynamic memory utilized. Static resources are loaded once, and only on explicit declaration. This library supports the SparkFun Qwiic Micro OLED, 0.91in OLED, Transparent Graphical OLED, smôl OLED Display, and any other board using the SSD1306 IC. -category=Display -url=https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -architectures=* diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index e6e2a66..0000000 --- a/mkdocs.yml +++ /dev/null @@ -1,277 +0,0 @@ -# Documentation page information -site_name: SparkFun Qwiic OLED Arduino Library - Hookup Guide -site_description: SparkFun Arduino Library for Qwiic OLED Boards -site_url: https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library -site_author: SparkFun Electronics - -repo_url: https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -repo_name: sparkfun/SparkFun_Qwiic_OLED_Arduino_Library - -copyright: - Copyright 2023 - SparkFun Electronics®
-
6333 Dry Creek Parkway, Niwot, Colorado 80503 - -# Default edit/view actions to "main" branch, instead of "master" -edit_uri: blob/main/docs/ - - #logo: img/sfe_logo_sm.png - -# Configuration for webpage theme -theme: - # Theme: https://squidfunk.github.io/mkdocs-material/ - name: material - - # Icon in Browser Tab (must be square img - i.e. 32x32 pixels) - favicon: assets/sfe_favicon.png - - # Page Font - font: - text: Roboto - code: Roboto Mono - - # Features to Include (ref. theme documentation) - features: - - # Enable copy button on code blocks - - content.code.copy - - # Enable annotations in code blocks - - content.code.annotate - - # Enable "view source" and "edit this page" buttons - - content.action.edit - # - content.action.view - - # Enable Navigation buttons in the footer (i.e. previous/next) - - navigation.footer - - # Enables anchor tracking (updates page url with the section user is on) - # i.e. https://docs.sparkfun.com//# - - navigation.tracking - - navigation.tabs.sticky - - # Enables tabs for navigating the website - - navigation.tabs - # Keeps tabs visible in the header when scrolling - - navigation.tabs.sticky - - # Adds pop-up button just below the header (when the user starts to scroll up) - # Allows users to easily jump to the beginning of the page - - navigation.top - - # Renders path for page navigation at top of the page (makes page navigation more mobile friendly) - - navigation.path - - - # Adds light/dark theme to the webpage - palette: - # Palette toggle for automatic mode - - media: "(prefers-color-scheme)" - primary: grey - accent: red - toggle: - icon: material/brightness-auto - name: Switch to dark mode - - # Palette toggle for light mode - - media: "(prefers-color-scheme: light)" - primary: grey - accent: red - scheme: default - toggle: - icon: material/brightness-7 - name: Switch to system preference - - # Palette toggle for dark mode - - media: "(prefers-color-scheme: dark)" - primary: grey - accent: red - scheme: slate - toggle: - icon: material/weather-night - name: Switch to light mode - - # Configures icons - icon: - # Sets homepage icon - logo: sfe-logo - - # Sets repo icon to GitHub icon - repo: fontawesome/brands/github - - # Sets icons for "view source" (commented out) and "edit this page" buttons - edit: material/file-document-edit-outline - # view: material/file-code-outline - - # Admonition Icons (callout boxes) - admonition: - note: octicons/tag-16 - abstract: octicons/checklist-16 - info: octicons/info-16 - tip: simple/sparkfun - success: octicons/check-16 - question: octicons/question-16 - warning: octicons/alert-16 - failure: octicons/x-circle-16 - danger: octicons/zap-16 - bug: octicons/bug-16 - example: octicons/beaker-16 - quote: octicons/quote-16 - # Add custom admonitions - github: simple/github - arduino: simple/arduino - python: simple/python - code: fontawesome/regular/file-code - terminal: octicons/terminal-16 - serial: fontawesome/solid/display - hot: material/fire-alert - # Permalink icon - link: octicons/link-16 - - # Adds overrides for stylesheets, html, etc. - custom_dir: overrides - - -# Included MkDocs plugins -# Add the installation of any new plugins to the ./github/workflows/mkdocs.yml file also -plugins: - - search - - typeset - - redirects: - redirect_maps: - 'index.md': 'introduction.md' - # Add revision date - - git-revision-date-localized: - enable_creation_date: true - type: timeago - # Add git committers at bottom of the page - - git-committers: - repository: sparkfun/SparkFun_Qwiic_Buzzer - branch: main - # Add git authors at bottom of the page - - git-authors - # Enables use of Git submodules and larger code base - - monorepo - # For PDF rendering -# - with-pdf: -# author: SparkFun Electronics® -# copyright: Copyright 2023 - SparkFun Electronics® -# cover_subtitle: none -# cover_logo: img/sfe_logo_sm.png -# exclude_pages: [ "hard_copy", "single_page", "file_issue", "contribute" ] - # render_js: true - # headless_chrome_path: headless-chromium -# output_path: board_files/hookup_guide.pdf - - -# Included Markdown extensions -markdown_extensions: - - pymdownx.highlight: - anchor_linenums: true - - pymdownx.inlinehilite - - pymdownx.snippets: - # base_path: ['./docs'] - url_download: true - url_max_size: 0 - url_timeout: 0 - url_request_headers: {} - - pymdownx.superfences - - pymdownx.details - - pymdownx.tabbed: - alternate_style: true - - pymdownx.betterem: - smart_enable: all - - pymdownx.mark - - pymdownx.caret - - pymdownx.tilde - - pymdownx.keys - - tables - - admonition - - md_in_html - - attr_list - - pymdownx.emoji: - emoji_index: !!python/name:materialx.emoji.twemoji - emoji_generator: !!python/name:materialx.emoji.to_svg - options: - custom_icons: - - overrides/.icons - - pymdownx.arithmatex: - generic: true - - toc: - permalink: '' - # Link: 🔗 🔗 - # Chain: ⛓ ⛓ - - - -extra: - # Configures the hyperlink for the logo in the header - homepage: https://www.sparkfun.com/ - - # Configures social icons in the footer - social: - - icon: sfe-logo - link: https://www.sparkfun.com/ - - icon: fontawesome/brands/youtube - link: https://www.youtube.com/sparkfun - - icon: fontawesome/brands/instagram - link: https://www.instagram.com/sparkfun - - icon: fontawesome/brands/github - link: https://www.github.com/sparkfun - - icon: fontawesome/brands/facebook - link: https://www.facebook.com/SparkFun - - icon: fontawesome/brands/x-twitter - link: https://twitter.com/sparkfun - - icon: fontawesome/solid/cookie-bite - link: ./#__consent - name: Change cookie settings - - # Configures Google Analytics - analytics: - provider: google - property: G-7Y7EYCZVC1 - - consent: - cookies: - analytics: - name: Google Analytics - checked: true - title: Cookie consent - description: - We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better. - actions: - - accept - - manage - - reject - -# Configures styling for PDF rendering and webpage layout -extra_css: - - stylesheet/extra.css - -# Enables support for rendering block and inline block equations through MathJax -extra_javascript: -# # Enables support for rendering block and inline block equations through MathJax - - javascript/mathjax.js - - https://polyfill.io/v3/polyfill.min.js?features=es6 - - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js - -# Configures webpage navigation -nav: - - Getting Started: - - Introduction: introduction.md - - Qwiic Micro OLED (0.66", 64x48): hug_micro_view.md - - Qwiic OLED (0.91", 128x32): hug_0p91.md - - Qwiic Transparent Graphical OLED (1.51", 128x56): hug_transparent.md - - Qwiic OLED (1.3", 128x64): hug_1p3.md - - Software Setup: software.md - - API Reference: - - Device: api_device.md - - Scrolling: api_scroll.md - - Drawing State: api_draw.md - - Graphics: api_graphics.md - - Arduino Print: api_arduino.md - - Examples: '!include ./examples/mkdocs.yml' - - Support: - - Troubleshooting: troubleshooting.md - - Submit Issues: github/file_issue.md - - Contribute: github/contribute.md diff --git a/overrides/.icons/sfe-logo.svg b/overrides/.icons/sfe-logo.svg deleted file mode 100644 index 9bf94f2..0000000 --- a/overrides/.icons/sfe-logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/overrides/README.md b/overrides/README.md deleted file mode 100644 index 4932d1a..0000000 --- a/overrides/README.md +++ /dev/null @@ -1,3 +0,0 @@ -overrides directory -==================== -This folder should contain the files used for the webpage customizations of the product documentation diff --git a/overrides/main.html b/overrides/main.html deleted file mode 100644 index cfe40ae..0000000 --- a/overrides/main.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends "base.html" %} - -{% block content %} - - -{% if "single_page.md" %} - - {% include ".icons/material/file-eye-outline.svg" %} - - -{% endif %} - - -{{ super() }} -{% endblock content %} diff --git a/overrides/partials/nav.html b/overrides/partials/nav.html deleted file mode 100644 index 9c8463e..0000000 --- a/overrides/partials/nav.html +++ /dev/null @@ -1,79 +0,0 @@ - - -{% import "partials/nav-item.html" as item with context %} - - -{% set class = "md-nav md-nav--primary" %} -{% if "navigation.tabs" in features %} - {% set class = class ~ " md-nav--lifted" %} -{% endif %} -{% if "toc.integrate" in features %} - {% set class = class ~ " md-nav--integrated" %} -{% endif %} - - - diff --git a/overrides/partials/tabs.html b/overrides/partials/tabs.html deleted file mode 100644 index e83c968..0000000 --- a/overrides/partials/tabs.html +++ /dev/null @@ -1,51 +0,0 @@ - - -{% import "partials/tabs-item.html" as item with context %} - - - diff --git a/overrides/partials/toc-backup.html b/overrides/partials/toc-backup.html deleted file mode 100644 index 670fb01..0000000 --- a/overrides/partials/toc-backup.html +++ /dev/null @@ -1,66 +0,0 @@ - - - -{% set title = lang.t("toc") %} -{% if config.mdx_configs.toc and config.mdx_configs.toc.title %} - {% set title = config.mdx_configs.toc.title %} -{% endif %} - - - diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..0570da1 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"","title":"Home","text":"

Placeholder file for index redirect functionality.

"},{"location":"api_arduino/","title":"Arduino Print","text":"

Methods used to support Arduino Print functionality.

"},{"location":"api_arduino/#setcursor","title":"setCursor()","text":"

This method is called set the \"cursor\" position in the device. The library supports the Arduino Print interface, enabling the use of a print() and println() methods. The set cursor position defines where to start text output for this functionality.

void setCursor(uint8_t x, uint8_t y)\n
Parameter Type Description x uint8_t The X coordinate of the cursor y uint8_t The Y coordinate of the cursor"},{"location":"api_arduino/#setcolor","title":"setColor()","text":"

This method is called to set the current color of the system. This is used by the Arduino Print interface functionality

void setColor(uint8_t clr)\n
Parameter Type Description clr uint8_t The color to set. 0 = black, > 0 = white"},{"location":"api_arduino/#getcolor","title":"getColor()","text":"

This method is called to get the current color of the system. This is used by the Arduino Print interface functionality

uint8_t getColor(void)\n
Parameter Type Description return value uint8_t The current color"},{"location":"api_device/","title":"Device Operations","text":"

Methods to setup the device, get device information and change display options.

"},{"location":"api_device/#initialization","title":"Initialization","text":""},{"location":"api_device/#begin","title":"begin()","text":"

This method is called to initialize the OLED library and connection to the OLED device. This method must be called before calling any graphics methods.

bool begin(TwoWire &wirePort, uint8_t address)\n
Parameter Type Description wirePort TwoWire optional. The Wire port. If not provided, the default port is used address uint8_t optional. I2C Address. If not provided, the default address is used. return value bool true on success, false on startup failure"},{"location":"api_device/#reset","title":"reset()","text":"

When called, this method reset the library state and OLED device to their intial state. Helpful to reset the OLED after waking up a system from a sleep state.

void reset()\n
Parameter Type Description return value bool true on success, false on startup failure"},{"location":"api_device/#geometry","title":"Geometry","text":""},{"location":"api_device/#getwidth","title":"getWidth()","text":"

This method returns the width, in pixels, of the connected OLED device

uint8_t getWidth(void)\n
Parameter Type Description return value uint8_t The width in pixels of the connected OLED device"},{"location":"api_device/#getheight","title":"getHeight()","text":"

This method returns the height, in pixels, of the connected OLED device

uint8_t getHeight(void)\n
Parameter Type Description return value uint8_t The height in pixels of the connected OLED device"},{"location":"api_device/#display-modes","title":"Display Modes","text":""},{"location":"api_device/#invert","title":"invert()","text":"

This method inverts the current graphics on the display. This results of this command happen immediatly.

void invert(bool bInvert)\n
Parameter Type Description bInvert bool true - the screen is inverted. false - the screen is set to normal"},{"location":"api_device/#flipvertical","title":"flipVertical()","text":"

When called, the screen contents are flipped vertically if the flip parameter is true, or restored to normal display if the flip parameter is false.

void flipVertical(bool bFlip)\n
Parameter Type Description bFlip bool true - the screen is flipped vertically. false - the screen is set to normal"},{"location":"api_device/#fliphorizontal","title":"flipHorizontal()","text":"

When called, the screen contents are flipped horizontally if the flip parameter is true, or restored to normal display if the flip parameter is false.

void flipHorizontal(bool bFlip)\n
Parameter Type Description bFlip bool true - the screen is flipped horizontally. false - the screen is set to normal"},{"location":"api_device/#displaypower","title":"displayPower()","text":"

Used to turn the OLED display on or off.

void displayPower(bool bEnable)\n
Parameter Type Description bEnable bool true - the OLED display is powered on (default). false - the OLED dsiplay is powered off."},{"location":"api_draw/","title":"Drawing Settings/State","text":"

Methods for setting the drawing state of the library.

"},{"location":"api_draw/#setfont","title":"setFont()","text":"

This method is called to set the current font in the library. The current font is used when calling the text() method on this device.

The default font for the device is 5x7.

void setFont(QwiicFont& theFont)\nvoid setFont(const QwiicFont * theFont)\n
Parameter Type Description theFont QwiicFont The font to set as current in the device theFont QwiicFont* Pointer to the font to set as current in the device.

For the library, fonts are added to your program by including them via include files which are part of this library.

The following fonts are included:

Font Include File Font Variable Description 5x7 <res/qw_fnt_5x7.h> QW_FONT_5X7 A full, 5 x 7 font 31x48 <res/qw_fnt_31x48.h> QW_FONT_31X48 A full, 31 x 48 font Seven Segment <res/qw_fnt_7segment.h> QW_FONT_7SEGMENT Numbers only 8x16 <res/qw_fnt_8x16.h> QW_FONT_8X16 A full, 8 x 16 font Large Numbers <res/qw_fnt_largenum.h> QW_FONT_LARGENUM Numbers only

For each font, the font variables are objects with the following attributes:

Attribute Value width The font width in pixels height The font height in pixels start The font start character offset n_chars The number of characters map_width The width of the font map

Example use of a font object attribute:

#include <res/qw_fnt_31x48.h>\n\nint myFontWidth = QW_FONT_31X48.width;\n

"},{"location":"api_draw/#getfont","title":"getFont()","text":"

This method returns the current font for the device.

QwiicFont * getFont(void)\n
Parameter Type Description return value QwiicFont* A pointer to the current font. See setFont() for font object details."},{"location":"api_draw/#getfontname","title":"getFontName()","text":"

This method returns the height in pixels of a provided String based on the current device font.

String getFontName(void)\n
Parameter Type Description return value String The name of the current font."},{"location":"api_draw/#getstringwidth","title":"getStringWidth()","text":"

This method returns the width in pixels of a provided String based on the current device font.

unsigned int getStringWidth(String text)\n
Parameter Type Description text String The string used to determine width return value unsigned int The width of the provide string, as determined using the current font."},{"location":"api_draw/#getstringheight","title":"getStringHeight()","text":"

This method returns the height in pixels of a provided String based on the current device font.

unsigned int getStringHeight(String text)\n
Parameter Type Description text String The string used to determine height return value unsigned int The height of the provide string, as determined using the current font."},{"location":"api_draw/#setdrawmode","title":"setDrawMode()","text":"

This method sets the current draw mode for the library. The draw mode determines how pixels are set on the screen during drawing operations.

void setDrawMode(grRasterOp_t rop)\n
Parameter Type Description rop grRasterOp_t The raster operation (ROP) to set the graphics system to.

Raster operations device how source (pixels to draw) are represented on the destination device. The available Raster Operation (ROP) codes are:

ROP Code Description grROPCopy default Drawn pixel values are copied to the device screen grROPNotCopy A not operation is applied to the source value before copying to screen grROPNot A not operation is applied to the destination (screen) value grROPXOR A XOR operation is performed between the source and destination values grROPBlack A value of 0, or black is drawn to the destination grROPWhite A value of 1, or black is drawn to the destination"},{"location":"api_draw/#getdrawmode","title":"getDrawMode()","text":"

This method returns the current draw mode for the library. The draw mode determines how pixels are set on the screen during drawing operations.

grRasterOp_t getDrawMode(void)\n
Parameter Type Description return value grRasterOp_t The current aster operation (ROP) of the graphics system."},{"location":"api_graphics/","title":"Graphics Methods","text":"

Methods used to draw and display graphics.

"},{"location":"api_graphics/#display","title":"display()","text":"

When called, any pending display updates are sent to the connected OLED device. This includes drawn graphics and erase commands.

void display(void)\n
Parameter Type Description NONE"},{"location":"api_graphics/#erase","title":"erase()","text":"

Erases all graphics on the device, placing the display in a blank state. The erase update isn't sent to the device until the next display() call on the device.

void erase(void)\n
Parameter Type Description NONE"},{"location":"api_graphics/#pixel","title":"pixel()","text":"

Set the value of a pixel on the screen.

void pixel(uint8_t x, uint8_t y, uint8_t clr)\n
Parameter Type Description x uint8_t The X coordinate of the pixel to set y uint8_t The Y coordinate of the pixel to set clr uint8_t optional The color value to set the pixel. This defaults to white (1)."},{"location":"api_graphics/#line","title":"line()","text":"

Draw a line on the screen.

Note: If a line is horizontal (y0 = y1) or vertical (x0 = x1), optimized draw algorithms are used by the library.

void line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr)\n
Parameter Type Description x0 uint8_t The start X coordinate of the line y0 uint8_t The start Y coordinate of the line x1 uint8_t The end X coordinate of the line y1 uint8_t The end Y coordinate of the line clr uint8_t optional The color value to draw the line. This defaults to white (1)."},{"location":"api_graphics/#rectangle","title":"rectangle()","text":"

Draw a rectangle on the screen.

void rectangle(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr)\n
Parameter Type Description x0 uint8_t The start X coordinate of the rectangle - upper left corner y0 uint8_t The start Y coordinate of the rectangle - upper left corner width uint8_t The width of the rectangle height uint8_t The height of the rectangle clr uint8_t optional The color value to draw the line. This defaults to white (1)."},{"location":"api_graphics/#rectanglefill","title":"rectangleFill()","text":"

Draw a filled rectangle on the screen.

void rectangleFill(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr)\n
Parameter Type Description x0 uint8_t The start X coordinate of the rectangle - upper left corner y0 uint8_t The start Y coordinate of the rectangle - upper left corner width uint8_t The width of the rectangle height uint8_t The height of the rectangle clr uint8_t optional The color value to draw the line. This defaults to white (1)."},{"location":"api_graphics/#circle","title":"circle()","text":"

Draw a circle on the screen.

void circle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr)\n
Parameter Type Description x0 uint8_t The X coordinate of the circle center y0 uint8_t The Y coordinate of the circle center radius uint8_t The radius of the circle clr uint8_t optional The color value to draw the circle. This defaults to white (1)."},{"location":"api_graphics/#circlefill","title":"circleFill()","text":"

Draw a filled circle on the screen.

void circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr)\n
Parameter Type Description x0 uint8_t The X coordinate of the circle center y0 uint8_t The Y coordinate of the circle center radius uint8_t The radius of the circle clr uint8_t optional The color value to draw the circle. This defaults to white (1)."},{"location":"api_graphics/#bitmap","title":"bitmap()","text":"

Draws a bitmap on the screen.

The bitmap should be 8 bit encoded - each pixel contains 8 y values.

void bitmap(uint8_t x0, uint8_t y0, uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height )\n
Parameter Type Description x0 uint8_t The X coordinate to place the bitmap - upper left corner y0 uint8_t The Y coordinate to place the bitmap - upper left corner pBitmap uint8_t * A pointer to the bitmap array bmp_width uint8_t The width of the bitmap bmp_height uint8_t The height of the bitmap"},{"location":"api_graphics/#bitmap_1","title":"bitmap()","text":"

Draws a bitmap on the screen.

The bitmap should be 8 bit encoded - each pixel contains 8 y values.

The coordinate [x1,y1] allows for only a portion of bitmap to be drawn.

void bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, \n                uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height )\n
Parameter Type Description x0 uint8_t The X coordinate to place the bitmap - upper left corner y0 uint8_t The Y coordinate to place the bitmap - upper left corner x1 uint8_t The end X coordinate of the bitmap - lower right corner y1 uint8_t The end Y coordinate of the bitmap - lower right corner pBitmap uint8_t * A pointer to the bitmap array bmp_width uint8_t The width of the bitmap bmp_height uint8_t The height of the bitmap"},{"location":"api_graphics/#bitmap_2","title":"bitmap()","text":"

Draws a bitmap on the screen using a Bitmap object for the bitmap data.

void bitmap(uint8_t x0, uint8_t y0, QwiicBitmap& bitmap)\n
Parameter Type Description x0 uint8_t The X coordinate to place the bitmap - upper left corner y0 uint8_t The Y coordinate to place the bitmap - upper left corner Bitmap QwiicBitmap A bitmap object"},{"location":"api_graphics/#text","title":"text()","text":"

Draws a string using the current font on the screen.

void text(uint8_t x0, uint8_t y0, const char * text, uint8_t clr)\n
Parameter Type Description x0 uint8_t The X coordinate to start drawing the text y0 uint8_t The Y coordinate to start drawing the text text const char* The string to draw on the screen text String The Arduino string to draw on the screen clr uint8_t optional The color value to draw the circle. This defaults to white (1)."},{"location":"api_scroll/","title":"Scrolling","text":"

Methods for device scrolling

"},{"location":"api_scroll/#scrollstop","title":"scrollStop()","text":"

If the device is in a scrolling mode, calling this method stops the scroll, and restores the device to normal display operation. This action is performed immediately.

void scrollStop(void)\n
Parameter Type Description NONE"},{"location":"api_scroll/#scrollright","title":"scrollRight()","text":"

This method is called to start the device scrolling the displayed graphics to the right. This action is performed immediately.

The screen will scroll until the scrollStop() method is called.

void scrollRight(uint8_t start, uint8_t stop, uint8_t interval)\n
Parameter Type Description start uint8_t The start page address of the scroll - valid values are 0 thru 7 stop uint8_t The stop/end page address of the scroll - valid values are 0 thru 7 interval uint8_t The time interval between scroll step - values listed below

Defined values for the interval parameter:

Defined Symbol Time Interval Between Steps SCROLL_INTERVAL_2_FRAMES 2 SCROLL_INTERVAL_3_FRAMES 3 SCROLL_INTERVAL_4_FRAMES 4 SCROLL_INTERVAL_5_FRAMES 5 SCROLL_INTERVAL_25_FRAMES 25 SCROLL_INTERVAL_64_FRAMES 64 SCROLL_INTERVAL_128_FRAMES 128 SCROLL_INTERVAL_256_FRAMES 256"},{"location":"api_scroll/#scrollvertright","title":"scrollVertRight()","text":"

This method is called to start the device scrolling the displayed graphics vertically and to the right. This action is performed immediately.

The screen will scroll until the scrollStop() method is called.

void scrolVertlRight(uint8_t start, uint8_t stop, uint8_t interval)\n
Parameter Type Description start uint8_t The start page address of the scroll - valid values are 0 thru 7 stop uint8_t The stop/end page address of the scroll - valid values are 0 thru 7 interval uint8_t The time interval between scroll step - values listed in scrollRight"},{"location":"api_scroll/#scrollleft","title":"scrollLeft()","text":"

This method is called start to the device scrolling the displayed graphics to the left. This action is performed immediately.

The screen will scroll until the scrollStop() method is called.

void scrollLeft(uint8_t start, uint8_t stop, uint8_t interval)\n
Parameter Type Description start uint8_t The start page address of the scroll - valid values are 0 thru 7 stop uint8_t The stop/end page address of the scroll - valid values are 0 thru 7 interval uint8_t The time interval between scroll step - values listed in scrollRight"},{"location":"api_scroll/#scrollvertleft","title":"scrollVertLeft()","text":"

This method is called to start the device scrolling the displayed graphics vertically and to the left. This action is performed immediately.

The screen will scroll until the scrollStop() method is called.

void scrolVertlLeft(uint8_t start, uint8_t stop, uint8_t interval)\n
Parameter Type Description start uint8_t The start page address of the scroll - valid values are 0 thru 7 stop uint8_t The stop/end page address of the scroll - valid values are 0 thru 7 interval uint8_t The time interval between scroll step - values listed in scrollRight"},{"location":"hug_0p91/","title":"Qwiic OLED (0.91\", 128x32)","text":""},{"location":"hug_0p91/#introduction","title":"Introduction","text":"

The SparkFun Qwiic OLED Display can display up to four lines of text and features 128x32 pixels in a small 0.91\u201d (diagonal) frame. As an OLED, this display does not have a back light layer (unlike LCDs) and therefore it\u2019s thinner, consumes less power, and has higher contrast.

  • SparkFun Qwiic OLED Display (0.91 in., 128x32) LCD-24606 Purchase from SparkFun

In this section, we'll go over the hardware and how to hookup the breakout board.

"},{"location":"hug_0p91/#required-materials","title":"Required Materials","text":"

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

  • 1x SparkFun RedBoard Plus [DEV-18158]
  • 1x Reversible USB A to C Cable - 0.8m [CAB-15425]
  • 1x Qwiic Cable
    • Flexible Qwiic Cable - 50mm [PRT-17260], for short distances
    • Flexible Qwiic Cable - 500mm [PRT-17257], for those that need to wire the board farther away from your microcontroller
  • 1x SparkFun Qwiic OLED Display (0.91 in., 128x32) [LCD-22495]
"},{"location":"hug_0p91/#microcontroller","title":"Microcontroller","text":"

To get started, you'll need a microcontroller to, well, control everything. We used the RedBoard with the ATmega328P for the Qwiic micro OLED. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

  • SparkFun RedBoard Plus (ATmega328P) DEV-18158

  • SparkFun Thing Plus - Artemis WRL-15574

  • SparkFun Thing Plus - ESP32 WROOM (USB-C) WRL-20168

  • SparkFun Thing Plus - SAMD51 DEV-14713

"},{"location":"hug_0p91/#usb-cable","title":"USB Cable","text":"

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

  • SparkFun 4-in-1 Multi-USB Cable - USB-A Host CAB-21272

  • Reversible USB A to C Cable - 0.8m CAB-15425

  • Reversible USB A to Reversible Micro-B Cable - 0.8m CAB-15428

"},{"location":"hug_0p91/#qwiic","title":"Qwiic","text":"

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

  • SparkFun Qwiic Shield for Arduino DEV-14352

  • SparkFun Qwiic Shield for Teensy DEV-17119

  • SparkFun Qwiic Shield for Arduino Nano DEV-16789

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

  • Flexible Qwiic Cable - 50mm PRT-17260

  • Flexible Qwiic Cable - 100mm PRT-17259

  • Flexible Qwiic Cable - 200mm PRT-17258

  • Flexible Qwiic Cable - 500mm PRT-17257

Of course, you will also need a Qwiic Micro OLED if you have not added that to you cart already.

  • SparkFun Qwiic OLED Display (0.91 in., 128x32) LCD-24606

"},{"location":"hug_0p91/#hardware-overview","title":"Hardware Overview","text":"

In this section, we will highlight the hardware and pins that are broken out on the SparkFun Qwiic OLED Display (0.91 in., 128x32).

Top View Bottom View"},{"location":"hug_0p91/#oled-display-091-128x32","title":"OLED Display (0.91\", 128x32)","text":"

The OLED screen has a pixel resolution of 128x32, a panel size of 30.0mm x 11.5mm x 1.2mm, and an active area of 22.384mm x 5.584mm. The driver chip is the SSD1306. For information can be found in the datasheet linked in the Resources.

OLED Highlighted

Note

The SparkFun Qwiic OLED Arduino Library works for multiple displays. However, there are some caveats in the size of the display with the text. While you can technically display all fonts in the narrow OLED display, some characters (numbers, letters, and/or symbols depending on the font) will be too big to fully display on the screen. For example, the fonts for the 31x48 (i.e. &QW_FONT_31X48) and large numbers (i.e. &QW_FONT_LARGENUM) are too big to fit within the display.

Using the OLED display (0.91\", 128x32) we found that we were able to fit:

  • 4x lines, 21x characters using the 5x7 (i.e. &QW_FONT_5X7)
  • 2x lines, 14x characters using the 8x16 (i.e. &QW_FONT_8X16)
  • 2x lines, 11x characters using the 7 segment (i.e. &QW_FONT_7SEGMENT)
"},{"location":"hug_0p91/#power","title":"Power","text":"

Power is applied through the vertical Qwiic connectors on the back of the board. The recommended input voltage is 3.3V. The logic levels for the Qwiic OLED Display (0.9\", 128x32) is 3.3V.

Power"},{"location":"hug_0p91/#qwiic-and-i2c","title":"Qwiic and I2C","text":"

There are two vertical Qwiic connectors populated on the back of the board. You can use either connectors to provide power and send data through I2C. The Qwiic ecosystem is made for fast prototyping by removing the need for soldering. All you need to do is plug a Qwiic cable into the Qwiic connector and voila!

  • SCL \u2014 I2C clock
  • SDA \u2014 I2C data
  • 3.3V \u2014 Power
  • GND \u2014 Ground
Vertical Qwiic Connectors

The address of the display is 0x3C.

Note

On the back of the board, the power and I2C pins are broken out to test points. These are used in our production department for quality control using custom testbeds. These could be an alternative option to connect to the pins. However, we recommend using the Qwiic connectors to easily connect to the OLED display. Note that the I2C pins are also in a different order compared to a standard I2C Qwiic connector should you decide to solder to the test points.

I2C Test Points

"},{"location":"hug_0p91/#jumpers","title":"Jumpers","text":"

Note

If this is your first time working with jumpers, check out the How to Work with Jumper Pads and PCB Traces tutorial for more information.

The board includes a 1x3 jumper on the back of the board.

  • I2C \u2014 This three way jumper labeled I2C is connected to two 4.7k\u03a9 pull-up resistors to the I2C data and clock lines. For users that have multiple Qwiic-enabled devices with pull-up resistors enabled, the parallel equivalent resistance will create too strong of a pull-up for the bus to operate correctly. As a general rule of thumb, disable all but one pair of pull-up resistors if multiple devices are connected to the bus.
Jumpers Highlighted"},{"location":"hug_0p91/#board-dimensions","title":"Board Dimensions","text":"

Version 1.1 is a bit smaller than previous versions since the board includes vertical Qwiic connectors on the back of the board. The overall board size is 1.75 in x 0.5 in. The mounting holes have also moved to toward the top of the board.

Board Dimensions"},{"location":"hug_0p91/#hardware-hookup","title":"Hardware Hookup","text":"

In this section, we'll go over how to connect to the display. We will go just a bit further and talk about how to mount the display.

"},{"location":"hug_0p91/#connecting-via-qwiic-connector","title":"Connecting via Qwiic Connector","text":"

Insert a Qwiic cable between your chosen microcontroller and Qwiic OLED. Then insert a USB cable between the microcontroller and your computer's COM port. For the scope of this tutorial, the USB cable provides power and allows us to upload code to the microcontroller. Of course, you can also debug the display by opening a Serial Terminal.

USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, Qwiic OLED (0.9 in., 12x32)

Once you have finished prototyping, you could continue to use the USB cable and add a 5V power supply or battery pack.

"},{"location":"hug_0p91/#mounting-the-qwiic-oled-09-128x32","title":"Mounting the Qwiic OLED (0.9\", 128x32)","text":"

Grab the board dimensions and cut out a rectangle in the enclosure. For users that want to mount the board so that the OLED display is flush against the enclosure, you will need to look at the dimensions based on the OLED. You will need to add a little tolerance so that the display can fit through the rectangle. For users that need to quickly mount the board, you will could also cut out rectangles based on the vertical Qwiic connector so that the wires can lead into the enclosure. Then cut out the mounting holes so that the board is right side up. In this case, we used a cardboard box as a quick example to demonstrate the Qwiic wires connecting leading into the enclosure.

Qwiic OLED Display Mounted in an Enclosure

Note

To easily display text and graphics on the board, we recommend mounting the board right side up. There is an option in the example code to flip the text horizontally and vertically should you decide to mount the board upside down, but you would need to also determine the position of the text.

For a more durable enclosure, you could use wood, metal, or plastic. However, you will need additional tools to cut into the material.

"},{"location":"hug_0p91/#software","title":"Software","text":"

The Qwiic OLED (0.91\", 128x32) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED Library's Software Setup has instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

SparkFun Qwiic OLED Library API Reference Guide"},{"location":"hug_0p91/#resources","title":"Resources","text":"

Now that you've successfully got your OLED Display (0.9\", 128x36) up and running, it's time to incorporate it into your own project! For more information, check out the resources below:

  • Schematic (PDF)
  • Eagle Files (ZIP)
  • Board Dimensions (PNG)
  • Datasheet (PDF) (0.91\", 128x32, SSD1306)
  • ReadtheDocs: Qwiic_OLED_Display_Py
  • Qwiic OLED Display Python Package Repo
  • Github Hardware Repo
"},{"location":"hug_1p3/","title":"Qwiic OLED (1.3\", 128x64)","text":"

The Qwiic OLED 1.3in has its own hook-up guide.

"},{"location":"hug_micro_view/","title":"Qwiic Micro OLED (0.66\", 64x48)","text":""},{"location":"hug_micro_view/#introduction","title":"Introduction","text":"

The Qwiic Micro OLED is a Qwiic enabled version of our micro OLED display! This small monochrome, blue-on-black OLED display displays incredibly clear images.

  • SparkFun Micro OLED Breakout (Qwiic) LCD-22495 Purchase from SparkFun

This hookup guide will show you how to get started drawing objects and characters on your OLED.

"},{"location":"hug_micro_view/#required-materials","title":"Required Materials","text":"

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

  • 1x SparkFun RedBoard Plus [DEV-18158]
  • 1x Reversible USB A to C Cable - 0.8m [CAB-15425]
  • 1x Qwiic Cable
    • Flexible Qwiic Cable - 50mm [PRT-17260], for short distances
    • Flexible Qwiic Cable - 500mm [PRT-17257], for those that need to wire the board farther away from your microcontroller
  • 1x SparkFun Micro OLED Breakout (Qwiic) [LCD-22495]
"},{"location":"hug_micro_view/#microcontroller","title":"Microcontroller","text":"

To get started, you'll need a microcontroller to, well, control everything. We used the RedBoard with the ATmega328P for the Qwiic micro OLED. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

  • SparkFun RedBoard Plus (ATmega328P) DEV-18158

  • SparkFun Thing Plus - Artemis WRL-15574

  • SparkFun Thing Plus - ESP32 WROOM (USB-C) WRL-20168

  • SparkFun Thing Plus - SAMD51 DEV-14713

"},{"location":"hug_micro_view/#usb-cable","title":"USB Cable","text":"

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

  • SparkFun 4-in-1 Multi-USB Cable - USB-A Host CAB-21272

  • Reversible USB A to C Cable - 0.8m CAB-15425

  • Reversible USB A to Reversible Micro-B Cable - 0.8m CAB-15428

"},{"location":"hug_micro_view/#qwiic","title":"Qwiic","text":"

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

  • SparkFun Qwiic Shield for Arduino DEV-14352

  • SparkFun Qwiic Shield for Teensy DEV-17119

  • SparkFun Qwiic Shield for Arduino Nano DEV-16789

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

  • Flexible Qwiic Cable - 50mm PRT-17260

  • Flexible Qwiic Cable - 100mm PRT-17259

  • Flexible Qwiic Cable - 200mm PRT-17258

  • Flexible Qwiic Cable - 500mm PRT-17257

Of course, you will also need a Qwiic Micro OLED if you have not added that to you cart already.

  • SparkFun Micro OLED Breakout (Qwiic) LCD-22495

"},{"location":"hug_micro_view/#suggested-reading","title":"Suggested Reading","text":"

If you aren't familiar with the Qwiic Connection System, we recommend reading here for an overview.

Qwiic Connection System

We would also recommend taking a look at the following tutorials if you aren't familiar with them.

  • I2C

  • Qwiic Shield for Arduino & Photon Hookup Guide

"},{"location":"hug_micro_view/#hardware-overview","title":"Hardware Overview","text":"

Listed below are some of the operating ranges and characteristics of the Qwiic Micro OLED.

Characteristic Range Voltage 3.3V Temperature -40\u00b0C to 85\u00b0C I2C Address 0X3D (Default) or 0X3C (Closed Jumper)"},{"location":"hug_micro_view/#pins","title":"Pins","text":"

Power and I2C pins are broken out to the 1x4 PTH pins as well as the two horizontal Qwiic connectors.

Pin Description Direction GND Ground In 3.3V Power In SDA I2C Data In SCL I2C Clock In"},{"location":"hug_micro_view/#jumpers","title":"Jumpers","text":"

There are several jumpers on board that can be changed to facilitate several different functions. The first of which is the I2C pull-up jumper to disable the 2.2k\u03a9 pull up resistors on the I2C data and clock lines, highlighted below. If multiple boards are connected to the I2C bus, the equivalent resistance goes down, increasing your pull up strength. If multiple boards are connected on the same bus, make sure only one board has the pull-up resistors connected.

I2C Pull-Up Jumper

The ADDR jumper (highlighted below) can be used to change the I2C address of the board. The default jumper is open by default, pulling the address pin high and giving us an I2C address of 0X3D. Closing this jumper will ground the address pin, giving us an I2C address of 0X3C.

Address Jumper"},{"location":"hug_micro_view/#board-dimensions","title":"Board Dimensions","text":"

Revision Change

For V11, we have optimized the two mounting hole locations to match the mounting holes located on a standard 1.0\" x 1.0\" Qwiic-sized board. The overall functionality of the Qwiic Micro OLED breakout board is the same as the previous version!

The overall board size is 1.08\" x 1.17\". There is a v-score for users that want to remove the mounting holes.

Board Dimensions"},{"location":"hug_micro_view/#hardware-assembly","title":"Hardware Assembly","text":"

If you haven't yet assembled your Qwiic Shield, now would be the time to head on over to that tutorial. With the shield assembled, SparkFun's Qwiic environment means that connecting the screen could not be easier. Just plug one end of the Qwiic cable into the OLED display, the other into the Qwiic Shield and you'll be ready to start displaying images on your little display.

If you have a built-in Qwiic connector, you can skip the hardware assembly of the Qwiic Shield and simply insert a Qwiic cable between the two boards. Have more than one Qwiic-enabled device? You can daisy chain it to the board as well! Below is an example with the SAM-M8Q and the Qwiic Micro OLED daisy chained together to the RedBoard Qwiic.

Note

The initial launch of the Qwiic micro OLED breakout board had the OLED loosely attached to the breakout board. For users that received those boards, be careful handling it! You can either use your own enclosure for the OLED display, or you can use some double sided foam tape for a less permanent solution.

The current production of the boards includes the double sided foam tape.

"},{"location":"hug_micro_view/#software","title":"Software","text":"

The SparkFun Micro OLED Breakout (Qwiic) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED library Getting Started guide has library setup instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

SparkFun Qwiic OLED Library API Reference Guide"},{"location":"hug_micro_view/#resources","title":"Resources","text":"

Now that you've successfully got your OLED displaying things, it's time to incorporate it into your own project!

For more on the Qwiic Micro OLED, check out the links below:

  • Schematic (PDF)
  • Eagle Files (ZIP)
  • Datasheet (PDF)
  • Bitmap Generator
  • Qwiic System Landing Page
  • Qwiic Micro OLED Python Package
  • GitHub Hardware Repo -- Board design files for the Qwiic Micro OLED.
  • Product Showcase: Qwiic Presence Sensor & OLED
"},{"location":"hug_transparent/","title":"Qwiic Transparent Graphical OLED (1.51\", 128x56)","text":""},{"location":"hug_transparent/#introduction","title":"Introduction","text":"

The future is here! You asked and we delivered - our Qwiic Transparent Graphical OLED Breakout allows you to display custom images on a transparent screen using either I2C or SPI connections.

With Qwiic connectors it's quick (ha ha) and easy to get started with your own images. However, we still have broken out 0.1\"-spaced pins in case you prefer to use a breadboard. Brilliantly lit in the dark and still visible by daylight, this OLED sports a display area of 128x64 pixels, 128x56 of which are completely transparent. Control of the OLED is based on the HyperDisplay library or SparkFun Qwiic OLED Arduino Library! For the scope of this tutorial, we will be using the SparkFun Qwiic OLED Arduino Library.

  • SparkFun Transparent Graphical OLED Breakout (Qwiic) LCD-15173 Purchase from SparkFun

This hookup guide will show you how to get started drawing objects and characters on your OLED.

"},{"location":"hug_transparent/#required-materials","title":"Required Materials","text":"

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

  • 1x SparkFun Thing Plus - ESP32 WROOOM (USB-C) [WRL-20168]
  • 1x Reversible USB A to C Cable - 0.8m [CAB-15425]
  • 1x Qwiic Cable
    • Flexible Qwiic Cable - 50mm [PRT-17260], for short distances
    • Flexible Qwiic Cable - 500mm [PRT-17257], for those that need to wire the board farther away from your microcontroller
  • 1x SparkFun Transparent Graphical OLED Breakout (Qwiic)[LCD-15173]
"},{"location":"hug_transparent/#microcontroller","title":"Microcontroller","text":"

To get started, you'll need a microcontroller to, well, control everything. We used the SparkFun Thing Plus - ESP32 WROOOM. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

  • SparkFun Thing Plus - ESP32 WROOM (USB-C) WRL-20168

  • SparkFun RedBoard Plus (ATmega328P) DEV-18158

  • SparkFun Thing Plus - Artemis WRL-15574

  • SparkFun Thing Plus - SAMD51 DEV-14713

"},{"location":"hug_transparent/#usb-cable","title":"USB Cable","text":"

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

  • SparkFun 4-in-1 Multi-USB Cable - USB-A Host CAB-21272

  • Reversible USB A to C Cable - 0.8m CAB-15425

  • Reversible USB A to Reversible Micro-B Cable - 0.8m CAB-15428

"},{"location":"hug_transparent/#qwiic","title":"Qwiic","text":"

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

  • SparkFun Qwiic Shield for Arduino DEV-14352

  • SparkFun Qwiic Shield for Teensy DEV-17119

  • SparkFun Qwiic Shield for Arduino Nano DEV-16789

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

  • Flexible Qwiic Cable - 50mm PRT-17260

  • Flexible Qwiic Cable - 100mm PRT-17259

  • Flexible Qwiic Cable - 200mm PRT-17258

  • Flexible Qwiic Cable - 500mm PRT-17257

Of course, you will also need A Tranparent Graphical OLED Breakout if you have not added that to you cart already.

  • SparkFun Transparent Graphical OLED Breakout (Qwiic) LCD-15173

"},{"location":"hug_transparent/#suggested-reading","title":"Suggested Reading","text":"

If you aren't familiar with the Qwiic Connection System, we recommend reading here for an overview.

Qwiic Connection System

We would also recommend taking a look at the following tutorials if you aren't familiar with them.

  • I2C

  • Qwiic Shield for Arduino & Photon Hookup Guide

"},{"location":"hug_transparent/#hardware-overview","title":"Hardware Overview","text":"

Listed below are some of the operating ranges and characteristics of the Transparent Graphical OLED Breakout.

Characteristic Range Voltage 1.65V-3.3V,typically 3.3V via the Qwiic Cable Supply Current 400 mA I2C Address 0X3C (Default), 0X3D (Closed Jumper)"},{"location":"hug_transparent/#graphical-display","title":"Graphical Display","text":"

The graphical display is where all the fun stuff happens. The glass itself measures 42mm x 27.16mm, with a pixel display that is 35.5 x 18mm. It houses 128x64 pixels, 128x56 of which are transparent.

Graphical Display"},{"location":"hug_transparent/#qwiic-connectors","title":"Qwiic Connectors","text":"

There are two Qwiic connectors on the board such that you can daisy-chain the boards should you choose to do so. If you're unfamiliar with our Qwiic Connect System, head on over to our Qwiic page to see the advantages!

Qwiic Connectors"},{"location":"hug_transparent/#gpio-pins","title":"GPIO Pins","text":"

When you look at the GPIO pins, you'll notice that the labels are different from one side to the other. One side is labeled for I2C, the other side is labeled for SPI.

I2C Labels SPI Labels"},{"location":"hug_transparent/#power-led","title":"Power LED","text":"

This bad boy will light up when the board is powered up correctly.

Power LED

You can disable the power LED by cutting the LED jumpers on the back of the board.

Power LED Jumpers"},{"location":"hug_transparent/#jpx-jumpers","title":"JPX Jumpers","text":"

The JPX jumpers are used to either change the I2C address or configure the board to use SPI communications. The other two jumpers allow you to disconnect the power LED and to disconnect the I2C pull-up resistors when chaining several Qwiic devices.

Jumper Function JP1 Holds the Chip Select line low when closed. Close for I2C, open for SPI JP2 Selects the address in I2C mode. Closed for 0x30 by default and open for 0x31. Open for SPI mode to release the D/C pin JP3 Used to select I2C or SPI mode. Close for I2C, open for SPI JP4 This jumper should be closed for I2C and open for SPI. This connection allows SDA to be bi-directional JPX Jumper"},{"location":"hug_transparent/#i2c-pull-up-jumper","title":"I2C Pull-Up Jumper","text":"

I2C devices contain open drains so we include resistors on our boards to allow these devices to pull pins high. This becomes a problem if you have a large number of I2C devices chained together. If you plan to daisy chain more than a few Qwiic boards together, you'll need to cut this I2C pull-up jumper.

I2C PU Jumper"},{"location":"hug_transparent/#hardware-hookup","title":"Hardware Hookup","text":"

Now that you know what's available on your breakout board we can check out the options for connecting it to the brains of your project. There are two options to use - either I2C or SPI - and they each have their own advantages and drawbacks. Read on to choose the best option for your setup.

Warning

Reminder! This breakout can only handle up to 3.3V on the pins, so make sure to do some level shifting if you're using a 5V microcontroller.

"},{"location":"hug_transparent/#i2c-qwiic","title":"I2C (Qwiic)","text":"

The easiest way to start using the Transparent Graphical OLED is to use a Qwiic Cable along with a Qwiic compatible microcontroller (such as the ESP32 Thing Plus). You can also use the Qwiic Breadboard Cable to attach any I2C capable microcontroller, or take the scenic route and solder in all the I2C wires to the plated-through connections on the board.

Top View I2C Pinout/i>

So why use I2C? It's easy to connect with the Qwiic system, and you can put up to two of the Transparent Graphical Breakouts on the same bus without using any more microcontroller pins. That simplicity comes at a cost to performance though. The maximum clock speed of the I2C bus is 400 kHz, and there is additional overhead in data transmission to indicate which bytes are data and which are commands. This means that the I2C connection is best for showing static images.

Breakout Pin Microcontroller Pin Requirements GND Ground pin. Connect these so the two devices agree on voltages 3V3 3.3V supply pin, capable of up to 400 mA output SDA SDA - the bi-directional data line of your chosen I2C port SCL SCL - the clock line of your chosen I2C port SA0 Optional : change the I2C address of the breakout. Make sure to cut JP2 RST Optional : reset the breakout to a known state by pulsing this low"},{"location":"hug_transparent/#spi","title":"SPI","text":"

SPI solves the I2C speed problems. With SPI there is a control signal that indicates data or command and the maximum clock speed is 10 MHz -- giving SPI 50x more speed! However, it doesn't have the same conveniences of the polarized Qwiic connector and low pin usage. You'll need to solder to the pins.

SPI Pinout

You can use SPI to connect as many breakouts as you want. For N displays you will need to use at least N + 3 data pins. That's because the MOSI, SCLK, and D/C pins can be shared between displays but each breakout needs its own dedicated Chip Select (CS) pin.

Breakout Pin Microcontroller Pin Requirements CS A GPIO pin, set low when talking to the breakout D/C A GPIO pin, indicates if bytes are data or commands SCLK The clock output of your chosen SPI port MOSI The data output of your chosen SPI port 3V3 3.3V supply pin, capable of up to 400 mA output GND Ground pin. Connect these so the two devices agree on voltages

Warning

Make sure to cut jumpers JP1, JP2, JP3, and JP4 when using SPI mode!

Cut Jumpers for SPI Mode

"},{"location":"hug_transparent/#software","title":"Software","text":"

The Transparent OLED Breakout (Qwiic) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED library Getting Started guide has library setup instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

SparkFun Qwiic OLED Library API Reference Guide"},{"location":"hug_transparent/#resources","title":"Resources","text":"

For more information on the Transparent Graphical OLED Breakout, check out some of the links here:

  • Schematic (PDF)
  • Eagle Files (ZIP)
  • GitHub Hardware Repo
  • SFE Product Showcase
"},{"location":"introduction/","title":"Introduction","text":"

The SparkFun Qwiic OLED Arduino Library is a single graphics module that supports all SparkFun OLED boards based on the SSD1306 from Solomon Systech. Prior to this library, three different libraries were used to support our four different OLED boards.

The SparkFun Qwiic OLED Library delivers a common implementation for all our Qwiic OLED products, delivering a unified, fast, and efficient solution that implements a familiar and easy to understand user experience.

"},{"location":"introduction/#key-features","title":"Key Features","text":"
  • Implements common graphics capabilities: pixel, line, rectangle, filled rectangle, circle, filled circle, bitmap, text and raster operators (i.e. XOR).
  • Smart data transfer to the device \u2013 only sends dirty regions of the graphics buffer to the OLED device, not the entire buffer.
  • High performance \u2013 2x faster than our previous OLED library, often much higher.
  • Efficient memory usage. No dynamic memory utilized. Static resources are loaded once, and only on explicit declaration.
  • Implements a familiar interface, making migration from older libraries straight forward
"},{"location":"introduction/#getting-started","title":"Getting Started","text":"

The Software Setup outlines library installation and the general use of the Qwiic OLED library.

Detailed examples are included as part of the library installation process and available in the Arduino IDE menu: File > Examples > SparkFun Qwiic OLED Arduino Library. A walk-thru of key examples is contained in the Examples section of this documentation set.

Note

For v1.0.5 of the SparkFun Qwiic OLED Arduino Library, we named the library as SparkFun Qwiic OLED Graphics Library. After v1.0.6, we updated the name to say SparkFun Qwiic OLED Arduino Library. You may have multiple versions in your Arduino libraries folder if you installed the library more than once. To avoid confusion, issues compiling, and to use the latest version, we recommend removing the \"SparkFun Qwiic OLED Graphics Library\" folder should you decide to use the latest and greatest version. This will probably be located under ..Documents\\Arduino\\libraries, that is if you are using Windows.

Note

Note that we have more than one Arduino Library for the micro OLED. If you have the older Arduino Library, make sure to not confuse the two libraries. You will notice that the older library will be called \"SparkFun Micro OLED Breakout\". The example code will include the following line of code: #include <SFE_MicroOLED.h>.

A full API Reference is also provided for the library.

SparkFun Qwiic OLED Arduino Library: API Reference"},{"location":"introduction/#supported-products","title":"Supported Products","text":"

The SparkFun Qwiic OLED Arduino Library supports the following SparkFun products.

  • SparkFun Micro OLED Breakout (Qwiic) LCD-22495

  • SparkFun Qwiic OLED Display (0.91 in, 128x32) LCD-24606

  • SparkFun Transparent Graphical OLED Breakout (Qwiic) LCD-15173

  • SparkFun Qwiic OLED (1.3in., 128x64) LCD-23453

"},{"location":"introduction/#supported-microcontrollers-arduino-environment","title":"Supported Microcontrollers - Arduino Environment","text":"

The following architectures are supported in the Arduino Library.

  • Artemis
  • SAMD51
  • ESP32
  • STM32
  • SAMD21
  • nrf5280
  • Teensy
  • ATMega328P

Below are a few of those processors populated on Arduino boards from the SparkFun catalog. You will need to make sure to check the associated hookup guides for additional information about compatible cables, drivers, or board add-ons.

  • SparkFun Thing Plus - Artemis WRL-15574

  • SparkFun Thing Plus - SAMD51 DEV-14713

  • SparkFun Thing Plus - ESP32 WROOM (USB-C) WRL-20168

  • SparkFun Thing Plus - STM32 DEV-17712

  • SparkFun RedBoard Turbo - SAMD21 Development Board DEV-14812

  • SparkFun Pro nRF52840 Mini - Bluetooth Development Board DEV-15025

  • SparkFun MicroMod Teensy Processor DEV-16402

  • SparkFun RedBoard Plus (ATmega328P) DEV-18158

Note

Unfortunately, the ATmega32U4 is not supported under this library. We recommend either using a different microcontroller or rolling back to the previous library written for the display.

"},{"location":"introduction/#license","title":"License","text":"

The SparkFun Qwiic OLED Arduino Library is licensed using the Open Source MIT License:

The MIT License (MIT)\n\nCopyright (c) 2015 SparkFun Electronics\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n
"},{"location":"single_page/","title":"Getting Started","text":""},{"location":"single_page/#introduction","title":"Introduction","text":"

The SparkFun Qwiic OLED Arduino Library is a single graphics module that supports all SparkFun OLED boards based on the SSD1306 from Solomon Systech. Prior to this library, three different libraries were used to support our four different OLED boards.

The SparkFun Qwiic OLED Library delivers a common implementation for all our Qwiic OLED products, delivering a unified, fast, and efficient solution that implements a familiar and easy to understand user experience.

"},{"location":"single_page/#key-features","title":"Key Features","text":"
  • Implements common graphics capabilities: pixel, line, rectangle, filled rectangle, circle, filled circle, bitmap, text and raster operators (i.e. XOR).
  • Smart data transfer to the device \u2013 only sends dirty regions of the graphics buffer to the OLED device, not the entire buffer.
  • High performance \u2013 2x faster than our previous OLED library, often much higher.
  • Efficient memory usage. No dynamic memory utilized. Static resources are loaded once, and only on explicit declaration.
  • Implements a familiar interface, making migration from older libraries straight forward
"},{"location":"single_page/#getting-started_1","title":"Getting Started","text":"

The Software Setup outlines library installation and the general use of the Qwiic OLED library.

Detailed examples are included as part of the library installation process and available in the Arduino IDE menu: File > Examples > SparkFun Qwiic OLED Arduino Library. A walk-thru of key examples is contained in the Examples section of this documentation set.

Note

For v1.0.5 of the SparkFun Qwiic OLED Arduino Library, we named the library as SparkFun Qwiic OLED Graphics Library. After v1.0.6, we updated the name to say SparkFun Qwiic OLED Arduino Library. You may have multiple versions in your Arduino libraries folder if you installed the library more than once. To avoid confusion, issues compiling, and to use the latest version, we recommend removing the \"SparkFun Qwiic OLED Graphics Library\" folder should you decide to use the latest and greatest version. This will probably be located under ..Documents\\Arduino\\libraries, that is if you are using Windows.

Note

Note that we have more than one Arduino Library for the micro OLED. If you have the older Arduino Library, make sure to not confuse the two libraries. You will notice that the older library will be called \"SparkFun Micro OLED Breakout\". The example code will include the following line of code: #include <SFE_MicroOLED.h>.

A full API Reference is also provided for the library.

SparkFun Qwiic OLED Arduino Library: API Reference"},{"location":"single_page/#supported-products","title":"Supported Products","text":"

The SparkFun Qwiic OLED Arduino Library supports the following SparkFun products.

  • SparkFun Micro OLED Breakout (Qwiic) LCD-22495

  • SparkFun Qwiic OLED Display (0.91 in, 128x32) LCD-24606

  • SparkFun Transparent Graphical OLED Breakout (Qwiic) LCD-15173

  • SparkFun Qwiic OLED (1.3in., 128x64) LCD-23453

"},{"location":"single_page/#supported-microcontrollers-arduino-environment","title":"Supported Microcontrollers - Arduino Environment","text":"

The following architectures are supported in the Arduino Library.

  • Artemis
  • SAMD51
  • ESP32
  • STM32
  • SAMD21
  • nrf5280
  • Teensy
  • ATMega328P

Below are a few of those processors populated on Arduino boards from the SparkFun catalog. You will need to make sure to check the associated hookup guides for additional information about compatible cables, drivers, or board add-ons.

  • SparkFun Thing Plus - Artemis WRL-15574

  • SparkFun Thing Plus - SAMD51 DEV-14713

  • SparkFun Thing Plus - ESP32 WROOM (USB-C) WRL-20168

  • SparkFun Thing Plus - STM32 DEV-17712

  • SparkFun RedBoard Turbo - SAMD21 Development Board DEV-14812

  • SparkFun Pro nRF52840 Mini - Bluetooth Development Board DEV-15025

  • SparkFun MicroMod Teensy Processor DEV-16402

  • SparkFun RedBoard Plus (ATmega328P) DEV-18158

Note

Unfortunately, the ATmega32U4 is not supported under this library. We recommend either using a different microcontroller or rolling back to the previous library written for the display.

"},{"location":"single_page/#license","title":"License","text":"

The SparkFun Qwiic OLED Arduino Library is licensed using the Open Source MIT License:

The MIT License (MIT)\n\nCopyright (c) 2015 SparkFun Electronics\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n
"},{"location":"single_page/#qwiic-micro-oled-066-64x48","title":"Qwiic Micro OLED (0.66\", 64x48)","text":""},{"location":"single_page/#introduction_1","title":"Introduction","text":"

The Qwiic Micro OLED is a Qwiic enabled version of our micro OLED display! This small monochrome, blue-on-black OLED display displays incredibly clear images.

  • SparkFun Micro OLED Breakout (Qwiic) LCD-22495 Purchase from SparkFun

This hookup guide will show you how to get started drawing objects and characters on your OLED.

"},{"location":"single_page/#required-materials","title":"Required Materials","text":"

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

  • 1x SparkFun RedBoard Plus [DEV-18158]
  • 1x Reversible USB A to C Cable - 0.8m [CAB-15425]
  • 1x Qwiic Cable
    • Flexible Qwiic Cable - 50mm [PRT-17260], for short distances
    • Flexible Qwiic Cable - 500mm [PRT-17257], for those that need to wire the board farther away from your microcontroller
  • 1x SparkFun Micro OLED Breakout (Qwiic) [LCD-22495]
"},{"location":"single_page/#microcontroller","title":"Microcontroller","text":"

To get started, you'll need a microcontroller to, well, control everything. We used the RedBoard with the ATmega328P for the Qwiic micro OLED. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

  • SparkFun RedBoard Plus (ATmega328P) DEV-18158

  • SparkFun Thing Plus - Artemis WRL-15574

  • SparkFun Thing Plus - ESP32 WROOM (USB-C) WRL-20168

  • SparkFun Thing Plus - SAMD51 DEV-14713

"},{"location":"single_page/#usb-cable","title":"USB Cable","text":"

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

  • SparkFun 4-in-1 Multi-USB Cable - USB-A Host CAB-21272

  • Reversible USB A to C Cable - 0.8m CAB-15425

  • Reversible USB A to Reversible Micro-B Cable - 0.8m CAB-15428

"},{"location":"single_page/#qwiic","title":"Qwiic","text":"

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

  • SparkFun Qwiic Shield for Arduino DEV-14352

  • SparkFun Qwiic Shield for Teensy DEV-17119

  • SparkFun Qwiic Shield for Arduino Nano DEV-16789

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

  • Flexible Qwiic Cable - 50mm PRT-17260

  • Flexible Qwiic Cable - 100mm PRT-17259

  • Flexible Qwiic Cable - 200mm PRT-17258

  • Flexible Qwiic Cable - 500mm PRT-17257

Of course, you will also need a Qwiic Micro OLED if you have not added that to you cart already.

  • SparkFun Micro OLED Breakout (Qwiic) LCD-22495

"},{"location":"single_page/#suggested-reading","title":"Suggested Reading","text":"

If you aren't familiar with the Qwiic Connection System, we recommend reading here for an overview.

Qwiic Connection System

We would also recommend taking a look at the following tutorials if you aren't familiar with them.

  • I2C

  • Qwiic Shield for Arduino & Photon Hookup Guide

"},{"location":"single_page/#hardware-overview","title":"Hardware Overview","text":"

Listed below are some of the operating ranges and characteristics of the Qwiic Micro OLED.

Characteristic Range Voltage 3.3V Temperature -40\u00b0C to 85\u00b0C I2C Address 0X3D (Default) or 0X3C (Closed Jumper)"},{"location":"single_page/#pins","title":"Pins","text":"

Power and I2C pins are broken out to the 1x4 PTH pins as well as the two horizontal Qwiic connectors.

Pin Description Direction GND Ground In 3.3V Power In SDA I2C Data In SCL I2C Clock In"},{"location":"single_page/#jumpers","title":"Jumpers","text":"

There are several jumpers on board that can be changed to facilitate several different functions. The first of which is the I2C pull-up jumper to disable the 2.2k\u03a9 pull up resistors on the I2C data and clock lines, highlighted below. If multiple boards are connected to the I2C bus, the equivalent resistance goes down, increasing your pull up strength. If multiple boards are connected on the same bus, make sure only one board has the pull-up resistors connected.

I2C Pull-Up Jumper

The ADDR jumper (highlighted below) can be used to change the I2C address of the board. The default jumper is open by default, pulling the address pin high and giving us an I2C address of 0X3D. Closing this jumper will ground the address pin, giving us an I2C address of 0X3C.

Address Jumper"},{"location":"single_page/#board-dimensions","title":"Board Dimensions","text":"

Revision Change

For V11, we have optimized the two mounting hole locations to match the mounting holes located on a standard 1.0\" x 1.0\" Qwiic-sized board. The overall functionality of the Qwiic Micro OLED breakout board is the same as the previous version!

The overall board size is 1.08\" x 1.17\". There is a v-score for users that want to remove the mounting holes.

Board Dimensions"},{"location":"single_page/#hardware-assembly","title":"Hardware Assembly","text":"

If you haven't yet assembled your Qwiic Shield, now would be the time to head on over to that tutorial. With the shield assembled, SparkFun's Qwiic environment means that connecting the screen could not be easier. Just plug one end of the Qwiic cable into the OLED display, the other into the Qwiic Shield and you'll be ready to start displaying images on your little display.

If you have a built-in Qwiic connector, you can skip the hardware assembly of the Qwiic Shield and simply insert a Qwiic cable between the two boards. Have more than one Qwiic-enabled device? You can daisy chain it to the board as well! Below is an example with the SAM-M8Q and the Qwiic Micro OLED daisy chained together to the RedBoard Qwiic.

Note

The initial launch of the Qwiic micro OLED breakout board had the OLED loosely attached to the breakout board. For users that received those boards, be careful handling it! You can either use your own enclosure for the OLED display, or you can use some double sided foam tape for a less permanent solution.

The current production of the boards includes the double sided foam tape.

"},{"location":"single_page/#software","title":"Software","text":"

The SparkFun Micro OLED Breakout (Qwiic) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED library Getting Started guide has library setup instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

SparkFun Qwiic OLED Library API Reference Guide"},{"location":"single_page/#resources","title":"Resources","text":"

Now that you've successfully got your OLED displaying things, it's time to incorporate it into your own project!

For more on the Qwiic Micro OLED, check out the links below:

  • Schematic (PDF)
  • Eagle Files (ZIP)
  • Datasheet (PDF)
  • Bitmap Generator
  • Qwiic System Landing Page
  • Qwiic Micro OLED Python Package
  • GitHub Hardware Repo -- Board design files for the Qwiic Micro OLED.
  • Product Showcase: Qwiic Presence Sensor & OLED
"},{"location":"single_page/#qwiic-transparent-graphical-oled-151-128x56","title":"Qwiic Transparent Graphical OLED (1.51\", 128x56)","text":""},{"location":"single_page/#introduction_2","title":"Introduction","text":"

The future is here! You asked and we delivered - our Qwiic Transparent Graphical OLED Breakout allows you to display custom images on a transparent screen using either I2C or SPI connections.

With Qwiic connectors it's quick (ha ha) and easy to get started with your own images. However, we still have broken out 0.1\"-spaced pins in case you prefer to use a breadboard. Brilliantly lit in the dark and still visible by daylight, this OLED sports a display area of 128x64 pixels, 128x56 of which are completely transparent. Control of the OLED is based on the HyperDisplay library or SparkFun Qwiic OLED Arduino Library! For the scope of this tutorial, we will be using the SparkFun Qwiic OLED Arduino Library.

  • SparkFun Transparent Graphical OLED Breakout (Qwiic) LCD-15173 Purchase from SparkFun

This hookup guide will show you how to get started drawing objects and characters on your OLED.

"},{"location":"single_page/#required-materials_1","title":"Required Materials","text":"

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

  • 1x SparkFun Thing Plus - ESP32 WROOOM (USB-C) [WRL-20168]
  • 1x Reversible USB A to C Cable - 0.8m [CAB-15425]
  • 1x Qwiic Cable
    • Flexible Qwiic Cable - 50mm [PRT-17260], for short distances
    • Flexible Qwiic Cable - 500mm [PRT-17257], for those that need to wire the board farther away from your microcontroller
  • 1x SparkFun Transparent Graphical OLED Breakout (Qwiic)[LCD-15173]
"},{"location":"single_page/#microcontroller_1","title":"Microcontroller","text":"

To get started, you'll need a microcontroller to, well, control everything. We used the SparkFun Thing Plus - ESP32 WROOOM. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

  • SparkFun Thing Plus - ESP32 WROOM (USB-C) WRL-20168

  • SparkFun RedBoard Plus (ATmega328P) DEV-18158

  • SparkFun Thing Plus - Artemis WRL-15574

  • SparkFun Thing Plus - SAMD51 DEV-14713

"},{"location":"single_page/#usb-cable_1","title":"USB Cable","text":"

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

  • SparkFun 4-in-1 Multi-USB Cable - USB-A Host CAB-21272

  • Reversible USB A to C Cable - 0.8m CAB-15425

  • Reversible USB A to Reversible Micro-B Cable - 0.8m CAB-15428

"},{"location":"single_page/#qwiic_1","title":"Qwiic","text":"

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

  • SparkFun Qwiic Shield for Arduino DEV-14352

  • SparkFun Qwiic Shield for Teensy DEV-17119

  • SparkFun Qwiic Shield for Arduino Nano DEV-16789

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

  • Flexible Qwiic Cable - 50mm PRT-17260

  • Flexible Qwiic Cable - 100mm PRT-17259

  • Flexible Qwiic Cable - 200mm PRT-17258

  • Flexible Qwiic Cable - 500mm PRT-17257

Of course, you will also need A Tranparent Graphical OLED Breakout if you have not added that to you cart already.

  • SparkFun Transparent Graphical OLED Breakout (Qwiic) LCD-15173

"},{"location":"single_page/#suggested-reading_1","title":"Suggested Reading","text":"

If you aren't familiar with the Qwiic Connection System, we recommend reading here for an overview.

Qwiic Connection System

We would also recommend taking a look at the following tutorials if you aren't familiar with them.

  • I2C

  • Qwiic Shield for Arduino & Photon Hookup Guide

"},{"location":"single_page/#hardware-overview_1","title":"Hardware Overview","text":"

Listed below are some of the operating ranges and characteristics of the Transparent Graphical OLED Breakout.

Characteristic Range Voltage 1.65V-3.3V,typically 3.3V via the Qwiic Cable Supply Current 400 mA I2C Address 0X3C (Default), 0X3D (Closed Jumper)"},{"location":"single_page/#graphical-display","title":"Graphical Display","text":"

The graphical display is where all the fun stuff happens. The glass itself measures 42mm x 27.16mm, with a pixel display that is 35.5 x 18mm. It houses 128x64 pixels, 128x56 of which are transparent.

Graphical Display"},{"location":"single_page/#qwiic-connectors","title":"Qwiic Connectors","text":"

There are two Qwiic connectors on the board such that you can daisy-chain the boards should you choose to do so. If you're unfamiliar with our Qwiic Connect System, head on over to our Qwiic page to see the advantages!

Qwiic Connectors"},{"location":"single_page/#gpio-pins","title":"GPIO Pins","text":"

When you look at the GPIO pins, you'll notice that the labels are different from one side to the other. One side is labeled for I2C, the other side is labeled for SPI.

I2C Labels SPI Labels"},{"location":"single_page/#power-led","title":"Power LED","text":"

This bad boy will light up when the board is powered up correctly.

Power LED

You can disable the power LED by cutting the LED jumpers on the back of the board.

Power LED Jumpers"},{"location":"single_page/#jpx-jumpers","title":"JPX Jumpers","text":"

The JPX jumpers are used to either change the I2C address or configure the board to use SPI communications. The other two jumpers allow you to disconnect the power LED and to disconnect the I2C pull-up resistors when chaining several Qwiic devices.

Jumper Function JP1 Holds the Chip Select line low when closed. Close for I2C, open for SPI JP2 Selects the address in I2C mode. Closed for 0x30 by default and open for 0x31. Open for SPI mode to release the D/C pin JP3 Used to select I2C or SPI mode. Close for I2C, open for SPI JP4 This jumper should be closed for I2C and open for SPI. This connection allows SDA to be bi-directional JPX Jumper"},{"location":"single_page/#i2c-pull-up-jumper","title":"I2C Pull-Up Jumper","text":"

I2C devices contain open drains so we include resistors on our boards to allow these devices to pull pins high. This becomes a problem if you have a large number of I2C devices chained together. If you plan to daisy chain more than a few Qwiic boards together, you'll need to cut this I2C pull-up jumper.

I2C PU Jumper"},{"location":"single_page/#hardware-hookup","title":"Hardware Hookup","text":"

Now that you know what's available on your breakout board we can check out the options for connecting it to the brains of your project. There are two options to use - either I2C or SPI - and they each have their own advantages and drawbacks. Read on to choose the best option for your setup.

Warning

Reminder! This breakout can only handle up to 3.3V on the pins, so make sure to do some level shifting if you're using a 5V microcontroller.

"},{"location":"single_page/#i2c-qwiic","title":"I2C (Qwiic)","text":"

The easiest way to start using the Transparent Graphical OLED is to use a Qwiic Cable along with a Qwiic compatible microcontroller (such as the ESP32 Thing Plus). You can also use the Qwiic Breadboard Cable to attach any I2C capable microcontroller, or take the scenic route and solder in all the I2C wires to the plated-through connections on the board.

Top View I2C Pinout/i>

So why use I2C? It's easy to connect with the Qwiic system, and you can put up to two of the Transparent Graphical Breakouts on the same bus without using any more microcontroller pins. That simplicity comes at a cost to performance though. The maximum clock speed of the I2C bus is 400 kHz, and there is additional overhead in data transmission to indicate which bytes are data and which are commands. This means that the I2C connection is best for showing static images.

Breakout Pin Microcontroller Pin Requirements GND Ground pin. Connect these so the two devices agree on voltages 3V3 3.3V supply pin, capable of up to 400 mA output SDA SDA - the bi-directional data line of your chosen I2C port SCL SCL - the clock line of your chosen I2C port SA0 Optional : change the I2C address of the breakout. Make sure to cut JP2 RST Optional : reset the breakout to a known state by pulsing this low"},{"location":"single_page/#spi","title":"SPI","text":"

SPI solves the I2C speed problems. With SPI there is a control signal that indicates data or command and the maximum clock speed is 10 MHz -- giving SPI 50x more speed! However, it doesn't have the same conveniences of the polarized Qwiic connector and low pin usage. You'll need to solder to the pins.

SPI Pinout

You can use SPI to connect as many breakouts as you want. For N displays you will need to use at least N + 3 data pins. That's because the MOSI, SCLK, and D/C pins can be shared between displays but each breakout needs its own dedicated Chip Select (CS) pin.

Breakout Pin Microcontroller Pin Requirements CS A GPIO pin, set low when talking to the breakout D/C A GPIO pin, indicates if bytes are data or commands SCLK The clock output of your chosen SPI port MOSI The data output of your chosen SPI port 3V3 3.3V supply pin, capable of up to 400 mA output GND Ground pin. Connect these so the two devices agree on voltages

Warning

Make sure to cut jumpers JP1, JP2, JP3, and JP4 when using SPI mode!

Cut Jumpers for SPI Mode

"},{"location":"single_page/#software_1","title":"Software","text":"

The Transparent OLED Breakout (Qwiic) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED library Getting Started guide has library setup instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

SparkFun Qwiic OLED Library API Reference Guide"},{"location":"single_page/#resources_1","title":"Resources","text":"

For more information on the Transparent Graphical OLED Breakout, check out some of the links here:

  • Schematic (PDF)
  • Eagle Files (ZIP)
  • GitHub Hardware Repo
  • SFE Product Showcase
"},{"location":"single_page/#qwiic-oled-091-128x32","title":"Qwiic OLED (0.91\", 128x32)","text":""},{"location":"single_page/#introduction_3","title":"Introduction","text":"

The SparkFun Qwiic OLED Display can display up to four lines of text and features 128x32 pixels in a small 0.91\u201d (diagonal) frame. As an OLED, this display does not have a back light layer (unlike LCDs) and therefore it\u2019s thinner, consumes less power, and has higher contrast.

  • SparkFun Qwiic OLED Display (0.91 in., 128x32) LCD-24606 Purchase from SparkFun

In this section, we'll go over the hardware and how to hookup the breakout board.

"},{"location":"single_page/#required-materials_2","title":"Required Materials","text":"

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

  • 1x SparkFun RedBoard Plus [DEV-18158]
  • 1x Reversible USB A to C Cable - 0.8m [CAB-15425]
  • 1x Qwiic Cable
    • Flexible Qwiic Cable - 50mm [PRT-17260], for short distances
    • Flexible Qwiic Cable - 500mm [PRT-17257], for those that need to wire the board farther away from your microcontroller
  • 1x SparkFun Qwiic OLED Display (0.91 in., 128x32) [LCD-22495]
"},{"location":"single_page/#microcontroller_2","title":"Microcontroller","text":"

To get started, you'll need a microcontroller to, well, control everything. We used the RedBoard with the ATmega328P for the Qwiic micro OLED. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

  • SparkFun RedBoard Plus (ATmega328P) DEV-18158

  • SparkFun Thing Plus - Artemis WRL-15574

  • SparkFun Thing Plus - ESP32 WROOM (USB-C) WRL-20168

  • SparkFun Thing Plus - SAMD51 DEV-14713

"},{"location":"single_page/#usb-cable_2","title":"USB Cable","text":"

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

  • SparkFun 4-in-1 Multi-USB Cable - USB-A Host CAB-21272

  • Reversible USB A to C Cable - 0.8m CAB-15425

  • Reversible USB A to Reversible Micro-B Cable - 0.8m CAB-15428

"},{"location":"single_page/#qwiic_2","title":"Qwiic","text":"

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

  • SparkFun Qwiic Shield for Arduino DEV-14352

  • SparkFun Qwiic Shield for Teensy DEV-17119

  • SparkFun Qwiic Shield for Arduino Nano DEV-16789

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

  • Flexible Qwiic Cable - 50mm PRT-17260

  • Flexible Qwiic Cable - 100mm PRT-17259

  • Flexible Qwiic Cable - 200mm PRT-17258

  • Flexible Qwiic Cable - 500mm PRT-17257

Of course, you will also need a Qwiic Micro OLED if you have not added that to you cart already.

  • SparkFun Qwiic OLED Display (0.91 in., 128x32) LCD-24606

"},{"location":"single_page/#hardware-overview_2","title":"Hardware Overview","text":"

In this section, we will highlight the hardware and pins that are broken out on the SparkFun Qwiic OLED Display (0.91 in., 128x32).

Top View Bottom View"},{"location":"single_page/#oled-display-091-128x32","title":"OLED Display (0.91\", 128x32)","text":"

The OLED screen has a pixel resolution of 128x32, a panel size of 30.0mm x 11.5mm x 1.2mm, and an active area of 22.384mm x 5.584mm. The driver chip is the SSD1306. For information can be found in the datasheet linked in the Resources.

OLED Highlighted

Note

The SparkFun Qwiic OLED Arduino Library works for multiple displays. However, there are some caveats in the size of the display with the text. While you can technically display all fonts in the narrow OLED display, some characters (numbers, letters, and/or symbols depending on the font) will be too big to fully display on the screen. For example, the fonts for the 31x48 (i.e. &QW_FONT_31X48) and large numbers (i.e. &QW_FONT_LARGENUM) are too big to fit within the display.

Using the OLED display (0.91\", 128x32) we found that we were able to fit:

  • 4x lines, 21x characters using the 5x7 (i.e. &QW_FONT_5X7)
  • 2x lines, 14x characters using the 8x16 (i.e. &QW_FONT_8X16)
  • 2x lines, 11x characters using the 7 segment (i.e. &QW_FONT_7SEGMENT)
"},{"location":"single_page/#power","title":"Power","text":"

Power is applied through the vertical Qwiic connectors on the back of the board. The recommended input voltage is 3.3V. The logic levels for the Qwiic OLED Display (0.9\", 128x32) is 3.3V.

Power"},{"location":"single_page/#qwiic-and-i2c","title":"Qwiic and I2C","text":"

There are two vertical Qwiic connectors populated on the back of the board. You can use either connectors to provide power and send data through I2C. The Qwiic ecosystem is made for fast prototyping by removing the need for soldering. All you need to do is plug a Qwiic cable into the Qwiic connector and voila!

  • SCL \u2014 I2C clock
  • SDA \u2014 I2C data
  • 3.3V \u2014 Power
  • GND \u2014 Ground
Vertical Qwiic Connectors

The address of the display is 0x3C.

Note

On the back of the board, the power and I2C pins are broken out to test points. These are used in our production department for quality control using custom testbeds. These could be an alternative option to connect to the pins. However, we recommend using the Qwiic connectors to easily connect to the OLED display. Note that the I2C pins are also in a different order compared to a standard I2C Qwiic connector should you decide to solder to the test points.

I2C Test Points

"},{"location":"single_page/#jumpers_1","title":"Jumpers","text":"

Note

If this is your first time working with jumpers, check out the How to Work with Jumper Pads and PCB Traces tutorial for more information.

The board includes a 1x3 jumper on the back of the board.

  • I2C \u2014 This three way jumper labeled I2C is connected to two 4.7k\u03a9 pull-up resistors to the I2C data and clock lines. For users that have multiple Qwiic-enabled devices with pull-up resistors enabled, the parallel equivalent resistance will create too strong of a pull-up for the bus to operate correctly. As a general rule of thumb, disable all but one pair of pull-up resistors if multiple devices are connected to the bus.
Jumpers Highlighted"},{"location":"single_page/#board-dimensions_1","title":"Board Dimensions","text":"

Version 1.1 is a bit smaller than previous versions since the board includes vertical Qwiic connectors on the back of the board. The overall board size is 1.75 in x 0.5 in. The mounting holes have also moved to toward the top of the board.

Board Dimensions"},{"location":"single_page/#hardware-hookup_1","title":"Hardware Hookup","text":"

In this section, we'll go over how to connect to the display. We will go just a bit further and talk about how to mount the display.

"},{"location":"single_page/#connecting-via-qwiic-connector","title":"Connecting via Qwiic Connector","text":"

Insert a Qwiic cable between your chosen microcontroller and Qwiic OLED. Then insert a USB cable between the microcontroller and your computer's COM port. For the scope of this tutorial, the USB cable provides power and allows us to upload code to the microcontroller. Of course, you can also debug the display by opening a Serial Terminal.

USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, Qwiic OLED (0.9 in., 12x32)

Once you have finished prototyping, you could continue to use the USB cable and add a 5V power supply or battery pack.

"},{"location":"single_page/#mounting-the-qwiic-oled-09-128x32","title":"Mounting the Qwiic OLED (0.9\", 128x32)","text":"

Grab the board dimensions and cut out a rectangle in the enclosure. For users that want to mount the board so that the OLED display is flush against the enclosure, you will need to look at the dimensions based on the OLED. You will need to add a little tolerance so that the display can fit through the rectangle. For users that need to quickly mount the board, you will could also cut out rectangles based on the vertical Qwiic connector so that the wires can lead into the enclosure. Then cut out the mounting holes so that the board is right side up. In this case, we used a cardboard box as a quick example to demonstrate the Qwiic wires connecting leading into the enclosure.

Qwiic OLED Display Mounted in an Enclosure

Note

To easily display text and graphics on the board, we recommend mounting the board right side up. There is an option in the example code to flip the text horizontally and vertically should you decide to mount the board upside down, but you would need to also determine the position of the text.

For a more durable enclosure, you could use wood, metal, or plastic. However, you will need additional tools to cut into the material.

"},{"location":"single_page/#software_2","title":"Software","text":"

The Qwiic OLED (0.91\", 128x32) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED Library's Software Setup has instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

SparkFun Qwiic OLED Library API Reference Guide"},{"location":"single_page/#resources_2","title":"Resources","text":"

Now that you've successfully got your OLED Display (0.9\", 128x36) up and running, it's time to incorporate it into your own project! For more information, check out the resources below:

  • Schematic (PDF)
  • Eagle Files (ZIP)
  • Board Dimensions (PNG)
  • Datasheet (PDF) (0.91\", 128x32, SSD1306)
  • ReadtheDocs: Qwiic_OLED_Display_Py
  • Qwiic OLED Display Python Package Repo
  • Github Hardware Repo
"},{"location":"single_page/#qwiic-oled-13-128x64","title":"Qwiic OLED (1.3\", 128x64)","text":"

The Qwiic OLED 1.3in has its own hook-up guide.

"},{"location":"single_page/#software-setup","title":"Software Setup","text":""},{"location":"single_page/#software-setup_1","title":"Software Setup","text":""},{"location":"single_page/#installation","title":"Installation","text":"

Arduino

This guide assumes you are using the latest version of the Arduino IDE on your desktop. The following resources available at SparkFun provide the details on setting up and configuring Arduino to use this library.

  • Installing the Arduino IDE
  • Installing Board Definitions in the Arduino IDE
  • Installing an Arduino Library

The SparkFun Qwiic OLED Arduino Library is available within in the Arduino library manager, which is launched via the Sketch > Include Libraries > Manage Libraries \u2026 menu option in the Arduino IDE. Just search for SparkFun Qwiic OLED Library.

Note

If you've never connected a USB-to-serial converter to your computer before, you may need to install drivers. The drivers will depend on what is populated on your Arduino development board. Check out the following tutorials for help with the installation.

  • How to Install CH340 Drivers
  • How to Install FTDI Drivers
  • How to Install CP2104 Drivers
"},{"location":"single_page/#general-use-pattern","title":"General Use Pattern","text":"

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library.

// Include the SparkFun qwiic OLED Library\n#include <SparkFun_Qwiic_OLED.h>\n

The next step is to declare the object for the SparkFun qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

The user selects from one of the following classes:

Class Qwiic OLED Device QwiicMicroOLED SparkFun Qwiic Micro OLED QwiicNarrowOLED SparkFun Qwiic OLED Display (128x32) QwiicTransparentOLED SparkFun Transparent Graphical OLED Qwiic1in3OLED SparkFun Qwiic OLED 1.3\" Display (128x32)

For this example, the Qwiic Micro OLED is used.

QwiicMicroOLED myOLED;\n

In the setup() function of this sketch, like all of the SparkFun qwiic libraries, the device is initialized by calling the begin() method. This method returns a value of true on success, or false on failure.

int width, height;  // global variables for use in the sketch\nvoid setup()\n{\n    Serial.begin(115200);\n    if(!myOLED.begin()){\n        Serial.println(\"Device failed to initialize\");\n        while(1);  // halt execution\n    }\n    Serial.println(\"Device is initialized\");\n\n}\n

Now that the library is initialized, the desired graphics are drawn. Here we erase the screen and draw simple series of lines that originate at the screen origin and fan out across the height of the display.

Note

Graphics are not send to the OLED device when drawn. Updates are only sent to the device when the display() method is called. This minimizes data transfers to the OLED device, delivering a responsive display response.

    myOLED.erase();           // Erase the screen\n    myOLED.display();         // Send erase to device\n\n    delay(1000);    // Slight pause\n\n    // Draw our lines from point (0,0) to (i, screen height)\n\n    for(int i=0; i < width; i+= 6){\n        myOLED.line(0, 0, i, height-1);    // draw the line\n        myOLED.display();                  // Send the new line to the device for display\n    }\n
"},{"location":"single_page/#library-provided-examples","title":"Library Provided Examples","text":"

The SparkFun Qwiic OLED Arduino Library, includes a wide variety of examples. These are available from the Examples menu of the Arduino IDE, and in the examplesfolder of this repository.

For a detailed description of the examples, see the Examples section of the documentation.

"},{"location":"single_page/#api-reference","title":"API Reference","text":""},{"location":"single_page/#device","title":"Device","text":""},{"location":"single_page/#device-operations","title":"Device Operations","text":"

Methods to setup the device, get device information and change display options.

"},{"location":"single_page/#initialization","title":"Initialization","text":""},{"location":"single_page/#begin","title":"begin()","text":"

This method is called to initialize the OLED library and connection to the OLED device. This method must be called before calling any graphics methods.

bool begin(TwoWire &wirePort, uint8_t address)\n
Parameter Type Description wirePort TwoWire optional. The Wire port. If not provided, the default port is used address uint8_t optional. I2C Address. If not provided, the default address is used. return value bool true on success, false on startup failure"},{"location":"single_page/#reset","title":"reset()","text":"

When called, this method reset the library state and OLED device to their intial state. Helpful to reset the OLED after waking up a system from a sleep state.

void reset()\n
Parameter Type Description return value bool true on success, false on startup failure"},{"location":"single_page/#geometry","title":"Geometry","text":""},{"location":"single_page/#getwidth","title":"getWidth()","text":"

This method returns the width, in pixels, of the connected OLED device

uint8_t getWidth(void)\n
Parameter Type Description return value uint8_t The width in pixels of the connected OLED device"},{"location":"single_page/#getheight","title":"getHeight()","text":"

This method returns the height, in pixels, of the connected OLED device

uint8_t getHeight(void)\n
Parameter Type Description return value uint8_t The height in pixels of the connected OLED device"},{"location":"single_page/#display-modes","title":"Display Modes","text":""},{"location":"single_page/#invert","title":"invert()","text":"

This method inverts the current graphics on the display. This results of this command happen immediatly.

void invert(bool bInvert)\n
Parameter Type Description bInvert bool true - the screen is inverted. false - the screen is set to normal"},{"location":"single_page/#flipvertical","title":"flipVertical()","text":"

When called, the screen contents are flipped vertically if the flip parameter is true, or restored to normal display if the flip parameter is false.

void flipVertical(bool bFlip)\n
Parameter Type Description bFlip bool true - the screen is flipped vertically. false - the screen is set to normal"},{"location":"single_page/#fliphorizontal","title":"flipHorizontal()","text":"

When called, the screen contents are flipped horizontally if the flip parameter is true, or restored to normal display if the flip parameter is false.

void flipHorizontal(bool bFlip)\n
Parameter Type Description bFlip bool true - the screen is flipped horizontally. false - the screen is set to normal"},{"location":"single_page/#displaypower","title":"displayPower()","text":"

Used to turn the OLED display on or off.

void displayPower(bool bEnable)\n
Parameter Type Description bEnable bool true - the OLED display is powered on (default). false - the OLED dsiplay is powered off."},{"location":"single_page/#scrolling","title":"Scrolling","text":""},{"location":"single_page/#scrolling_1","title":"Scrolling","text":"

Methods for device scrolling

"},{"location":"single_page/#scrollstop","title":"scrollStop()","text":"

If the device is in a scrolling mode, calling this method stops the scroll, and restores the device to normal display operation. This action is performed immediately.

void scrollStop(void)\n
Parameter Type Description NONE"},{"location":"single_page/#scrollright","title":"scrollRight()","text":"

This method is called to start the device scrolling the displayed graphics to the right. This action is performed immediately.

The screen will scroll until the scrollStop() method is called.

void scrollRight(uint8_t start, uint8_t stop, uint8_t interval)\n
Parameter Type Description start uint8_t The start page address of the scroll - valid values are 0 thru 7 stop uint8_t The stop/end page address of the scroll - valid values are 0 thru 7 interval uint8_t The time interval between scroll step - values listed below

Defined values for the interval parameter:

Defined Symbol Time Interval Between Steps SCROLL_INTERVAL_2_FRAMES 2 SCROLL_INTERVAL_3_FRAMES 3 SCROLL_INTERVAL_4_FRAMES 4 SCROLL_INTERVAL_5_FRAMES 5 SCROLL_INTERVAL_25_FRAMES 25 SCROLL_INTERVAL_64_FRAMES 64 SCROLL_INTERVAL_128_FRAMES 128 SCROLL_INTERVAL_256_FRAMES 256"},{"location":"single_page/#scrollvertright","title":"scrollVertRight()","text":"

This method is called to start the device scrolling the displayed graphics vertically and to the right. This action is performed immediately.

The screen will scroll until the scrollStop() method is called.

void scrolVertlRight(uint8_t start, uint8_t stop, uint8_t interval)\n
Parameter Type Description start uint8_t The start page address of the scroll - valid values are 0 thru 7 stop uint8_t The stop/end page address of the scroll - valid values are 0 thru 7 interval uint8_t The time interval between scroll step - values listed in scrollRight"},{"location":"single_page/#scrollleft","title":"scrollLeft()","text":"

This method is called start to the device scrolling the displayed graphics to the left. This action is performed immediately.

The screen will scroll until the scrollStop() method is called.

void scrollLeft(uint8_t start, uint8_t stop, uint8_t interval)\n
Parameter Type Description start uint8_t The start page address of the scroll - valid values are 0 thru 7 stop uint8_t The stop/end page address of the scroll - valid values are 0 thru 7 interval uint8_t The time interval between scroll step - values listed in scrollRight"},{"location":"single_page/#scrollvertleft","title":"scrollVertLeft()","text":"

This method is called to start the device scrolling the displayed graphics vertically and to the left. This action is performed immediately.

The screen will scroll until the scrollStop() method is called.

void scrolVertlLeft(uint8_t start, uint8_t stop, uint8_t interval)\n
Parameter Type Description start uint8_t The start page address of the scroll - valid values are 0 thru 7 stop uint8_t The stop/end page address of the scroll - valid values are 0 thru 7 interval uint8_t The time interval between scroll step - values listed in scrollRight"},{"location":"single_page/#drawing-state","title":"Drawing State","text":""},{"location":"single_page/#drawing-settingsstate","title":"Drawing Settings/State","text":"

Methods for setting the drawing state of the library.

"},{"location":"single_page/#setfont","title":"setFont()","text":"

This method is called to set the current font in the library. The current font is used when calling the text() method on this device.

The default font for the device is 5x7.

void setFont(QwiicFont& theFont)\nvoid setFont(const QwiicFont * theFont)\n
Parameter Type Description theFont QwiicFont The font to set as current in the device theFont QwiicFont* Pointer to the font to set as current in the device.

For the library, fonts are added to your program by including them via include files which are part of this library.

The following fonts are included:

Font Include File Font Variable Description 5x7 <res/qw_fnt_5x7.h> QW_FONT_5X7 A full, 5 x 7 font 31x48 <res/qw_fnt_31x48.h> QW_FONT_31X48 A full, 31 x 48 font Seven Segment <res/qw_fnt_7segment.h> QW_FONT_7SEGMENT Numbers only 8x16 <res/qw_fnt_8x16.h> QW_FONT_8X16 A full, 8 x 16 font Large Numbers <res/qw_fnt_largenum.h> QW_FONT_LARGENUM Numbers only

For each font, the font variables are objects with the following attributes:

Attribute Value width The font width in pixels height The font height in pixels start The font start character offset n_chars The number of characters map_width The width of the font map

Example use of a font object attribute:

#include <res/qw_fnt_31x48.h>\n\nint myFontWidth = QW_FONT_31X48.width;\n

"},{"location":"single_page/#getfont","title":"getFont()","text":"

This method returns the current font for the device.

QwiicFont * getFont(void)\n
Parameter Type Description return value QwiicFont* A pointer to the current font. See setFont() for font object details."},{"location":"single_page/#getfontname","title":"getFontName()","text":"

This method returns the height in pixels of a provided String based on the current device font.

String getFontName(void)\n
Parameter Type Description return value String The name of the current font."},{"location":"single_page/#getstringwidth","title":"getStringWidth()","text":"

This method returns the width in pixels of a provided String based on the current device font.

unsigned int getStringWidth(String text)\n
Parameter Type Description text String The string used to determine width return value unsigned int The width of the provide string, as determined using the current font."},{"location":"single_page/#getstringheight","title":"getStringHeight()","text":"

This method returns the height in pixels of a provided String based on the current device font.

unsigned int getStringHeight(String text)\n
Parameter Type Description text String The string used to determine height return value unsigned int The height of the provide string, as determined using the current font."},{"location":"single_page/#setdrawmode","title":"setDrawMode()","text":"

This method sets the current draw mode for the library. The draw mode determines how pixels are set on the screen during drawing operations.

void setDrawMode(grRasterOp_t rop)\n
Parameter Type Description rop grRasterOp_t The raster operation (ROP) to set the graphics system to.

Raster operations device how source (pixels to draw) are represented on the destination device. The available Raster Operation (ROP) codes are:

ROP Code Description grROPCopy default Drawn pixel values are copied to the device screen grROPNotCopy A not operation is applied to the source value before copying to screen grROPNot A not operation is applied to the destination (screen) value grROPXOR A XOR operation is performed between the source and destination values grROPBlack A value of 0, or black is drawn to the destination grROPWhite A value of 1, or black is drawn to the destination"},{"location":"single_page/#getdrawmode","title":"getDrawMode()","text":"

This method returns the current draw mode for the library. The draw mode determines how pixels are set on the screen during drawing operations.

grRasterOp_t getDrawMode(void)\n
Parameter Type Description return value grRasterOp_t The current aster operation (ROP) of the graphics system."},{"location":"single_page/#graphics","title":"Graphics","text":""},{"location":"single_page/#graphics-methods","title":"Graphics Methods","text":"

Methods used to draw and display graphics.

"},{"location":"single_page/#display","title":"display()","text":"

When called, any pending display updates are sent to the connected OLED device. This includes drawn graphics and erase commands.

void display(void)\n
Parameter Type Description NONE"},{"location":"single_page/#erase","title":"erase()","text":"

Erases all graphics on the device, placing the display in a blank state. The erase update isn't sent to the device until the next display() call on the device.

void erase(void)\n
Parameter Type Description NONE"},{"location":"single_page/#pixel","title":"pixel()","text":"

Set the value of a pixel on the screen.

void pixel(uint8_t x, uint8_t y, uint8_t clr)\n
Parameter Type Description x uint8_t The X coordinate of the pixel to set y uint8_t The Y coordinate of the pixel to set clr uint8_t optional The color value to set the pixel. This defaults to white (1)."},{"location":"single_page/#line","title":"line()","text":"

Draw a line on the screen.

Note: If a line is horizontal (y0 = y1) or vertical (x0 = x1), optimized draw algorithms are used by the library.

void line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr)\n
Parameter Type Description x0 uint8_t The start X coordinate of the line y0 uint8_t The start Y coordinate of the line x1 uint8_t The end X coordinate of the line y1 uint8_t The end Y coordinate of the line clr uint8_t optional The color value to draw the line. This defaults to white (1)."},{"location":"single_page/#rectangle","title":"rectangle()","text":"

Draw a rectangle on the screen.

void rectangle(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr)\n
Parameter Type Description x0 uint8_t The start X coordinate of the rectangle - upper left corner y0 uint8_t The start Y coordinate of the rectangle - upper left corner width uint8_t The width of the rectangle height uint8_t The height of the rectangle clr uint8_t optional The color value to draw the line. This defaults to white (1)."},{"location":"single_page/#rectanglefill","title":"rectangleFill()","text":"

Draw a filled rectangle on the screen.

void rectangleFill(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr)\n
Parameter Type Description x0 uint8_t The start X coordinate of the rectangle - upper left corner y0 uint8_t The start Y coordinate of the rectangle - upper left corner width uint8_t The width of the rectangle height uint8_t The height of the rectangle clr uint8_t optional The color value to draw the line. This defaults to white (1)."},{"location":"single_page/#circle","title":"circle()","text":"

Draw a circle on the screen.

void circle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr)\n
Parameter Type Description x0 uint8_t The X coordinate of the circle center y0 uint8_t The Y coordinate of the circle center radius uint8_t The radius of the circle clr uint8_t optional The color value to draw the circle. This defaults to white (1)."},{"location":"single_page/#circlefill","title":"circleFill()","text":"

Draw a filled circle on the screen.

void circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr)\n
Parameter Type Description x0 uint8_t The X coordinate of the circle center y0 uint8_t The Y coordinate of the circle center radius uint8_t The radius of the circle clr uint8_t optional The color value to draw the circle. This defaults to white (1)."},{"location":"single_page/#bitmap","title":"bitmap()","text":"

Draws a bitmap on the screen.

The bitmap should be 8 bit encoded - each pixel contains 8 y values.

void bitmap(uint8_t x0, uint8_t y0, uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height )\n
Parameter Type Description x0 uint8_t The X coordinate to place the bitmap - upper left corner y0 uint8_t The Y coordinate to place the bitmap - upper left corner pBitmap uint8_t * A pointer to the bitmap array bmp_width uint8_t The width of the bitmap bmp_height uint8_t The height of the bitmap"},{"location":"single_page/#bitmap_1","title":"bitmap()","text":"

Draws a bitmap on the screen.

The bitmap should be 8 bit encoded - each pixel contains 8 y values.

The coordinate [x1,y1] allows for only a portion of bitmap to be drawn.

void bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, \n                uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height )\n
Parameter Type Description x0 uint8_t The X coordinate to place the bitmap - upper left corner y0 uint8_t The Y coordinate to place the bitmap - upper left corner x1 uint8_t The end X coordinate of the bitmap - lower right corner y1 uint8_t The end Y coordinate of the bitmap - lower right corner pBitmap uint8_t * A pointer to the bitmap array bmp_width uint8_t The width of the bitmap bmp_height uint8_t The height of the bitmap"},{"location":"single_page/#bitmap_2","title":"bitmap()","text":"

Draws a bitmap on the screen using a Bitmap object for the bitmap data.

void bitmap(uint8_t x0, uint8_t y0, QwiicBitmap& bitmap)\n
Parameter Type Description x0 uint8_t The X coordinate to place the bitmap - upper left corner y0 uint8_t The Y coordinate to place the bitmap - upper left corner Bitmap QwiicBitmap A bitmap object"},{"location":"single_page/#text","title":"text()","text":"

Draws a string using the current font on the screen.

void text(uint8_t x0, uint8_t y0, const char * text, uint8_t clr)\n
Parameter Type Description x0 uint8_t The X coordinate to start drawing the text y0 uint8_t The Y coordinate to start drawing the text text const char* The string to draw on the screen text String The Arduino string to draw on the screen clr uint8_t optional The color value to draw the circle. This defaults to white (1)."},{"location":"single_page/#arduino-print","title":"Arduino Print","text":""},{"location":"single_page/#arduino-print_1","title":"Arduino Print","text":"

Methods used to support Arduino Print functionality.

"},{"location":"single_page/#setcursor","title":"setCursor()","text":"

This method is called set the \"cursor\" position in the device. The library supports the Arduino Print interface, enabling the use of a print() and println() methods. The set cursor position defines where to start text output for this functionality.

void setCursor(uint8_t x, uint8_t y)\n
Parameter Type Description x uint8_t The X coordinate of the cursor y uint8_t The Y coordinate of the cursor"},{"location":"single_page/#setcolor","title":"setColor()","text":"

This method is called to set the current color of the system. This is used by the Arduino Print interface functionality

void setColor(uint8_t clr)\n
Parameter Type Description clr uint8_t The color to set. 0 = black, > 0 = white"},{"location":"single_page/#getcolor","title":"getColor()","text":"

This method is called to get the current color of the system. This is used by the Arduino Print interface functionality

uint8_t getColor(void)\n
Parameter Type Description return value uint8_t The current color"},{"location":"single_page/#arduino-examples","title":"Arduino Examples","text":""},{"location":"single_page/#example-1-hello","title":"Example 1 - Hello","text":"

--8<-- \"./docs/ex_01_hello.md

"},{"location":"single_page/#example-2-shapes","title":"Example 2 - Shapes","text":"

--8<-- \"./docs/ex_02_lines.md

"},{"location":"single_page/#example-3-bitmaps","title":"Example 3 - Bitmaps","text":"

--8<-- \"./docs/ex_03_bitmaps.md

"},{"location":"single_page/#example-4-text","title":"Example 4 - Text","text":"

--8<-- \"./docs/ex_04_text.md

"},{"location":"single_page/#other-examples","title":"Other Examples","text":"

--8<-- \"./docs/ex_other.md

"},{"location":"single_page/#troubleshooting","title":"Troubleshooting","text":""},{"location":"single_page/#general-troubleshooting-help","title":"General Troubleshooting Help","text":"

Note

Not working as expected and need help?

If you need technical assistance and more information on a product that is not working as you expected, we recommend heading on over to the SparkFun Technical Assistance page for some initial troubleshooting.

SparkFun Technical Assistance Page

If you don't find what you need there, the SparkFun Forums are a great place to find and ask for help. If this is your first visit, you'll need to create a Forum Account to search product forums and post questions.

Create New Forum Account Log Into SparkFun Forums

"},{"location":"software/","title":"Software Setup","text":""},{"location":"software/#installation","title":"Installation","text":"

Arduino

This guide assumes you are using the latest version of the Arduino IDE on your desktop. The following resources available at SparkFun provide the details on setting up and configuring Arduino to use this library.

  • Installing the Arduino IDE
  • Installing Board Definitions in the Arduino IDE
  • Installing an Arduino Library

The SparkFun Qwiic OLED Arduino Library is available within in the Arduino library manager, which is launched via the Sketch > Include Libraries > Manage Libraries \u2026 menu option in the Arduino IDE. Just search for SparkFun Qwiic OLED Library.

Note

If you've never connected a USB-to-serial converter to your computer before, you may need to install drivers. The drivers will depend on what is populated on your Arduino development board. Check out the following tutorials for help with the installation.

  • How to Install CH340 Drivers
  • How to Install FTDI Drivers
  • How to Install CP2104 Drivers
"},{"location":"software/#general-use-pattern","title":"General Use Pattern","text":"

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library.

// Include the SparkFun qwiic OLED Library\n#include <SparkFun_Qwiic_OLED.h>\n

The next step is to declare the object for the SparkFun qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

The user selects from one of the following classes:

Class Qwiic OLED Device QwiicMicroOLED SparkFun Qwiic Micro OLED QwiicNarrowOLED SparkFun Qwiic OLED Display (128x32) QwiicTransparentOLED SparkFun Transparent Graphical OLED Qwiic1in3OLED SparkFun Qwiic OLED 1.3\" Display (128x32)

For this example, the Qwiic Micro OLED is used.

QwiicMicroOLED myOLED;\n

In the setup() function of this sketch, like all of the SparkFun qwiic libraries, the device is initialized by calling the begin() method. This method returns a value of true on success, or false on failure.

int width, height;  // global variables for use in the sketch\nvoid setup()\n{\n    Serial.begin(115200);\n    if(!myOLED.begin()){\n        Serial.println(\"Device failed to initialize\");\n        while(1);  // halt execution\n    }\n    Serial.println(\"Device is initialized\");\n\n}\n

Now that the library is initialized, the desired graphics are drawn. Here we erase the screen and draw simple series of lines that originate at the screen origin and fan out across the height of the display.

Note

Graphics are not send to the OLED device when drawn. Updates are only sent to the device when the display() method is called. This minimizes data transfers to the OLED device, delivering a responsive display response.

    myOLED.erase();           // Erase the screen\n    myOLED.display();         // Send erase to device\n\n    delay(1000);    // Slight pause\n\n    // Draw our lines from point (0,0) to (i, screen height)\n\n    for(int i=0; i < width; i+= 6){\n        myOLED.line(0, 0, i, height-1);    // draw the line\n        myOLED.display();                  // Send the new line to the device for display\n    }\n
"},{"location":"software/#library-provided-examples","title":"Library Provided Examples","text":"

The SparkFun Qwiic OLED Arduino Library, includes a wide variety of examples. These are available from the Examples menu of the Arduino IDE, and in the examplesfolder of this repository.

For a detailed description of the examples, see the Examples section of the documentation.

"},{"location":"troubleshooting/","title":"Troubleshooting","text":""},{"location":"troubleshooting/#general-troubleshooting-help","title":"General Troubleshooting Help","text":"

Note

Not working as expected and need help?

If you need technical assistance and more information on a product that is not working as you expected, we recommend heading on over to the SparkFun Technical Assistance page for some initial troubleshooting.

SparkFun Technical Assistance Page

If you don't find what you need there, the SparkFun Forums are a great place to find and ask for help. If this is your first visit, you'll need to create a Forum Account to search product forums and post questions.

Create New Forum Account Log Into SparkFun Forums

"},{"location":"github/contribute/","title":"Contribute: Help Fix our Mistake!","text":"

Spot something wrong? Feel free to contribute our open-source design and documentation.

"},{"location":"github/contribute/#improve-our-documentation","title":"Improve our Documentation","text":"

All of this documentation can be modified by you! Please help us make it better.

  • These pages are contained in the docs folder of the SparkFun Qwiic OLED Arduino Library repository.
"},{"location":"github/contribute/#submit-a-correction","title":"Submit a Correction","text":"
  1. Fork this repo
  2. Add your corrections or improvements to the markdown file
  3. File a pull request with your changes, and enjoy making the words worlds world a better place.
    • Once received, the documentation specialist will automatically be notified.
    • We will review your suggested improvements to make sure they are correct and fit within our documentation standards.
"},{"location":"github/contribute/#improve-our-hardware-design","title":"Improve our Hardware Design","text":"

All of our designs are open-source! Please help us make it better.

  • Our board design files are contained in the Hardware folder of their respective repositories:

  • SparkFun Micro OLED Breakout (Qwiic)

  • SparkFun Qwiic OLED Display (0.91 in, 128x32)
  • SparkFun Transparent Graphical OLED Breakout (Qwiic)
  • SparkFun Qwiic OLED - (1.3in., 128x64)
"},{"location":"github/contribute/#submit-a-design-improvement","title":"Submit a Design Improvement","text":"
  1. Fork this repo
  2. Add your design improvements
  3. File a pull request with your changes, and enjoy making the words worlds world a better place.
    • Once received, the engineer in charge of the original design will automatically be notified.
    • We will review your suggested improvements, if they are within our board design standards and meet our product design requirements, we will flag these changes for our next board revision. (Please note, that even if your suggestion is accepted, these changes may not be immediate. We may have to cycle through our current product inventory first.)
"},{"location":"github/contribute/#contributors","title":"Contributors","text":"

Let's provided some recognition to the contributors for this project!

"},{"location":"github/file_issue/","title":"Did we make a mistake?","text":"

Spot something wrong? Please let us know.

Attention

This is not where customers should seek assistance on a product. If you require technical assistance or have questions about a product that is not working as expected, please head over to the SparkFun Technical Assistance page for some initial troubleshooting. SparkFun Technical Assistance Page

If you can't find what you need there, you'll need a Forum Account to search product forums and post questions.

"},{"location":"github/file_issue/#discrepancies-in-the-documentation","title":"Discrepancies in the Documentation","text":"

All of this documentation can be modified by you! Please help us make it better.

  • The documentation files for these pages are contained in the docs folder of the SparkFun Qwiic OLED Arduino Library repository.
"},{"location":"github/file_issue/#spot-something-wrong","title":"Spot something wrong?","text":"

If a section of the documentation is incorrect, please open an issue and let us know.

"},{"location":"github/file_issue/#do-you-have-a-suggested-correction","title":"Do you have a suggested correction?","text":"
  1. With a GitHub account, fork this repo
  2. Add your correction(s) or improvement(s) to the markdown file(s)
  3. File a pull request with your changes, and enjoy making the words worlds world a better place.
    • Once received, the documentation specialist will automatically be notified.
    • We will review your suggested improvement(s) to make sure they are correct and fit within our documentation standards.
"},{"location":"github/file_issue/#problems-in-the-hardware-design","title":"Problems in the Hardware Design","text":"

All of our designs are open-source! Please help us make it better.

Our board design files are contained in the Hardware folder of their respective repositories:

  • SparkFun Micro OLED Breakout (Qwiic)
  • SparkFun Qwiic OLED Display (0.91 in, 128x32)
  • SparkFun Transparent Graphical OLED Breakout (Qwiic)
  • SparkFun Qwiic OLED - (1.3in., 128x64)
"},{"location":"github/file_issue/#does-something-not-make-sense","title":"Does something not make sense?","text":"

If part of the design is confusing, please open an issue and let us know.

"},{"location":"github/file_issue/#did-we-forget-to-include-an-important-function-of-the-board","title":"Did we forget to include an important function of the board?","text":"
  • Please keep in mind that we may intentionally exclude certain functions of the board to meet our product design requirements. (For example, our Qwiic Micro boards are intended to fit on a small board layout and only use I2C communication; therefore, we may not have the SPI and interrupt pins available for users.)
  • If part of the board's functionality is missing, please open an issue and file a feature request.
"},{"location":"github/file_issue/#do-you-wish-to-contribute-directly-to-improving-the-board-design","title":"Do you wish to contribute directly to improving the board design?","text":"
  1. With a GitHub account, Fork this repo
  2. Add your design improvement(s)
  3. File a pull request with your changes, and enjoy making the words worlds world a better place.
    • Once received, the engineer in charge of the original design will automatically be notified.
    • We will review your suggested improvement(s), if they are within our board design standards and meet our product design requirements, we will flag these changes for our next board revision. (Please note, that even if your suggestion is accepted, these changes may not be immediate. We may have to cycle through our current product inventory first.)
"},{"location":"javascript/","title":"javascript directory","text":"

This folder should contain the files for the custom javascript that is enabled in the product documentation

"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/","title":"Example 1 - Hello","text":"

A simple example to show the basic setup and use of the SparkFun Qwiic OLED Library.

Key Demo Features

  • Declaring a Qwiic OLED device object.
  • Initializing the Qwiic OLED device
  • Drawing a simple graphic - a filled rectangle and a text string
  • Using the current font to center text on the screen.
  • Displaying the graphics on the screen
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/#setup","title":"Setup","text":"

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library.

// Include the SparkFun Qwiic OLED Library\n#include <SparkFun_Qwiic_OLED.h>\n

The next step is to declare the object for the SparkFun Qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

The user selects from one of the following classes:

Class Qwiic OLED Device QwiicMicroOLED SparkFun Qwiic Micro OLED QwiicTransparentOLED SparkFun Transparent Graphical OLED QwiicNarrowOLED SparkFun Qwiic OLED Display (128x32) Qwiic1in3OLED SparkFun Qwiic OLED 1.3\" Display (128x32)

The example code supports all of the SparkFun Qwiic OLED boards. By default, the Qwiic Micro OLED is selected. To select a different board being used, add a single line comment (i.e. //) in front of \"QwiicMicroOLED myOLED;\" and uncomment the device being used for the demo board.

QwiicMicroOLED myOLED;\n//QwiicTransparentOLED myOLED;\n//QwiicNarrowOLED myOLED;\n//Qwiic1in3OLED myOLED;\n

Note

As of version 1.0.2+, users will need to use the class as explained above instead of using a #define.

#define MICRO\n//#define NARROW\n//#define TRANSPARENT\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/#initialization","title":"Initialization","text":"

In the setup() function of this sketch, like all of the SparkFun Qwiic Arduino libraries, the device is initialized by calling the begin() method. This method returns a value of true on success, or false on failure.

void setup()\n{\n\n    delay(500);   //Give display time to power on\n\n    // Serial on!\n    Serial.begin(115200);\n\n    Serial.println(\"\\n\\r-----------------------------------\");\n\n    Serial.print(\"Running Example 01 on: \");\n    Serial.println(String(deviceName));\n\n    // Initalize the OLED device and related graphics system\n    if(!myOLED.begin()){\n\n        Serial.println(\" - Device Begin Failed\");\n        while(1);\n    }\n\n    Serial.println(\"- Begin Success\");\n\n   // Do a simple test - fill a rectangle on the screen and then print hello!...\n\n}\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/#drawing-graphics","title":"Drawing Graphics","text":"

Once the device is enabled, the rest of the setup() function is devoted to drawing a simple graphic on the target device.

"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/#filled-rectangle","title":"Filled Rectangle","text":"

First, draw a filled rectangle on the screen - leave a 4 pixel boarder at the end of the screen. Note that the getWidth() and getHeight() method are used to get the devices screen size.

    // Fill a rectangle on the screen that has a 4 pixel board\n    myOLED.rectangleFill(4, 4, myOLED.getWidth() - 8, myOLED.getHeight() - 8);\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/#centered-text","title":"Centered Text","text":"

The next part of our graphic is a message centered in the drawn rectangle. To do the centering, the current font is accessed from the device, and the size of a character in the font is used to calculate the text position on the screen. Once the position is determined, the message is drawn on the display in black (0 for a color value).

    String hello = \"hello\"; // our message\n\n    // Center our message on the screen. Get the screen size of the \"hello\" string,\n    // calling the getStringWidth() and getStringHeight() methods on the oled\n\n    // starting x position - screen width minus string width  / 2\n    int x0 = (myOLED.getWidth() - myOLED.getStringWidth(hello)) / 2;\n\n    // starting y position - screen height minus string height / 2\n    int y0 = (myOLED.getHeight() - myOLED.getStringHeight(hello)) / 2;\n\n    // Draw the text - color of black (0)\n    myOLED.text(x0, y0, hello, 0);\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/#displaying-the-graphics","title":"Displaying the Graphics","text":"

The last step is sending the graphics to the device. This is accomplished by calling the display() method.

    // There's nothing on the screen yet - Now send the graphics to the device\n    myOLED.display();\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/#what-you-should-see","title":"What You Should See","text":"

And that's it! Select the board and COM port for your development board. Then upload the code! The graphic should display on the OLED device.

"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_02_lines/","title":"Example 2 - Shapes","text":"

An example that shows drawing simple shapes using the SparkFun Qwiic OLED Library.

Key Demo Features

  • Drawing lines, rectangles and circles
  • Demonstrating how graphics size impacts display speed
  • Drawing and erasing graphics quickly
  • XOR operations using raster operators
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_02_lines/#setup","title":"Setup","text":"

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library.

// Include the SparkFun Qwiic OLED Library\n#include <SparkFun_Qwiic_OLED.h>\n

The next step is to declare the object for the SparkFun Qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

The user selects from one of the following classes:

Class Qwiic OLED Device QwiicMicroOLED SparkFun Qwiic Micro OLED QwiicTransparentOLED SparkFun Transparent Graphical OLED QwiicNarrowOLED SparkFun Qwiic OLED Display (128x32) Qwiic1in3OLED SparkFun Qwiic OLED 1.3\" Display (128x32)

The example code supports all of the SparkFun Qwiic OLED boards. By default, the Qwiic Micro OLED is selected. To select a different board being used, add a single line comment (i.e. //) in front of \"QwiicMicroOLED myOLED;\" and uncomment the device being used for the demo board.

QwiicMicroOLED myOLED;\n//QwiicTransparentOLED myOLED;\n//QwiicNarrowOLED myOLED;\n//Qwiic1in3OLED myOLED;\n

Note

As of version 1.0.2+, users will need to use the class as explained above instead of using a #define.

#define MICRO\n//#define NARROW\n//#define TRANSPARENT\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_02_lines/#drawing-shapes","title":"Drawing Shapes","text":"

Note

As of version 1.0.2+, the modular functions have a slightly different name. Some functions defined in the example code will have the _ removed or words spelled out. For example, version v1.0.1 and below defined the function to test the line as line_test_1() while version v1.0.2+ defined the function as lineTest1().

The shapes drawn are broken into a set of functions that perform one test, which is part of the overall example.

"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_02_lines/#lines","title":"Lines","text":"

This test starts with a short, horizontal line that is animated from the top to bottom of the display. After each iteration, the line size is increased and the animating sequence repeated.

To animate the line, the display is erased, then the line drawn. Once the line is draw, the updated graphics is sent to the OLED device by calling the display() method.

Note

When display() is called, only the range of modified pixels is sent to the OLED device, greatly reducing the data transferred for small graphic changes.

This is demonstrated by this test. When small lines are drawn, the update rate is fast, but as the line length increases, the update rate of the device is noticeably slower. A longer line requires more data to be sent to the device.

void lineTest1(void)\n{\n    int x, y, i;\n\n    int mid = width / 2;\n    int delta = mid / 8;\n\n    for (int j = 1; j < 8; j++)\n    {\n\n        x = delta * j;\n\n        for (i = 0; i < height * 2; i++)\n        {\n\n            y = i % height;\n            myOLED.erase();\n            myOLED.line(mid - x, y, mid + x, y);\n            myOLED.display();\n        }\n    }\n}\n

This test is followed up with a series of lines that span from a single point to the bottom of the screen, showing the flexibility of the line to raster algorithm used by the library.

void lineTest2(void)\n{\n    for (int i = 0; i < width; i += 6)\n    {\n        myOLED.line(0, 0, i, height - 1);\n        myOLED.display();\n    }\n    delay(200);\n    myOLED.erase();\n    for (int i = width - 1; i >= 0; i -= 6)\n    {\n        myOLED.line(width - 1, 0, i, height - 1);\n        myOLED.display();\n    }\n}\n

And the last line test draws a series of lines to test all three internal line drawing algorithms. Specifically:

  • Angled lines drawn by the general purpose line algorithm
  • Vertical lines drawn by an optimized line routine
  • Horizontal lines draw by an optimized line routine

The test animates to show a growing box, giving an idea of the speed and flexibility of the system.

void lineTestVerticalIterative(uint8_t y0, uint8_t y1)\n{\n    for (int i = 0; i < width; i += 8)\n        myOLED.line(i, y0, i, y1);\n\n    // end off the vertical lines\n    myOLED.line(width - 1, y0, width - 1, y1);\n\n    // End lines and cross lines\n    myOLED.line(0, y0, width - 1, y0);\n    myOLED.line(0, y1, width - 1, y1);\n    myOLED.line(0, y0, width - 1, y1);\n    myOLED.line(0, y1, width - 1, y0);\n}\n\n// Entry point for test\nvoid lineTestVertical(void)\n{\n    int mid = height / 2;\n\n    for (int i = 0; i < height; i += 4)\n    {\n\n        myOLED.erase();\n        lineTestVerticalIterative(mid - i / 2, mid + i / 2);\n        myOLED.display();\n        delay(10);\n    }\n}\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_02_lines/#rectangles","title":"Rectangles","text":"

Several rectangle routines are shown in this example. A key test is a fast drawing routine which animates a small rectangle being drawn diagonally across the screen.

In this test, the rectangle is drawn, sent to the device via using display(), then the rectangle is drawn again, but this time in black. This effectively erases the rectangle. The position is incremented and the process loops, causing the rectangle to appear to fly across the screen.

The animation is quick, since only the portions of the screen that need updated are actually updated.

The animation algorithm is listed in the `rectangleTestMove() function.

void rectangleTestMove(void)\n{\n    float steps = height;\n    float xinc = width / steps;\n    float yinc = height / steps;\n    int side = 10;\n    float x = 0;\n    float y = 0;\n\n    for (int i = 0; i < steps; i++)\n    {\n        // Draw the rectangle and send it to device\n        myOLED.rectangle(x, y, side, side);\n        myOLED.display(); // sends erased rect and new rect pixels to device\n\n        // Erase the that rect, increment and loop\n        myOLED.rectangle(x, y, side, side, 0);\n\n        x += xinc;\n        y += yinc;\n    }\n}\n

The next rectangle test draws a series of filled rectangles on the screen. The unique aspect of this test is that is uses the XOR functionally to overlay a rectangle on the device, presenting a alternating color pattern.

The XOR raster operation is set by calling the setDrawMode() method on the OLED device, and providing the grROPXOR code. This switch the device into a XOR drawing mode. Graphic operations are restored to normal by calling setDrawMode() and providing the grROPCopy code, which copies the new pixel value to the destination.

Filled rectangles and XOR operations:

void rectangleFillTest(void)\n{\n    myOLED.rectangleFill(4, 4, width / 2 - 8, height - 8);\n\n    myOLED.rectangleFill(width / 2 + 4, 4, width / 2 - 8, height - 8);\n\n    myOLED.setDrawMode(grROPXOR); // xor\n    myOLED.rectangleFill(width / 4, 8, width / 2, height - 16);\n    myOLED.setDrawMode(grROPCopy); // back to copy op (default)\n}\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_02_lines/#circles","title":"Circles","text":"

The final shape drawn by this example is a series of circles and filled circles. Using the geometry of the screen, a set of circles are drawn and displayed.

void circleTest(void)\n{\n    // Let's draw some circles that fit on the device\n    myOLED.circle(width / 4, height / 2, height / 3);\n\n    myOLED.circleFill(width - width / 4, height / 2, height / 3);\n\n    myOLED.circle(4, height / 2, height / 3);\n\n    myOLED.circleFill(width - width / 2, height / 2, height / 4);\n}\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_03_bitmaps/","title":"Example 3 - Bitmaps","text":"

An example that shows drawing bitmaps using the SparkFun Qwiic OLED Library.

Key Demo Features

  • Understanding bitmap structure
  • Bitmap objects
  • Drawing Bitmap
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_03_bitmaps/#setup","title":"Setup","text":"

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library.

// Include the SparkFun qwiic OLED Library\n#include <SparkFun_Qwiic_OLED.h>\n
The next step is to declare the object for the SparkFun qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

The user selects from one of the following classes:

Class Qwiic OLED Device QwiicMicroOLED SparkFun Qwiic Micro OLED QwiicNarrowOLED SparkFun Qwiic OLED Display (128x32) QwiicTransparentOLED SparkFun Transparent Graphical OLED Qwiic1in3OLED SparkFun Qwiic OLED 1.3\" Display (128x32)

The Example code supports all of the SparkFun Qwiic OLED boards. To select the board being used, uncomment the #define for the demo board.

For this example, the Qwiic Micro OLED is used.

#define MICRO\n//#define NARROW\n//#define TRANSPARENT\n
Which results in myOLED being declared as:

QwiicMicroOLED myOLED;\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_03_bitmaps/#initialization","title":"Initialization","text":"

In the setup() function of this sketch, like all of the SparkFun qwiic libraries, the device is initialized by calling the begin() method. This method returns a value of true on success, or false on failure.

void setup()\n{\n\n    delay(500);   //Give display time to power on\n\n    // Serial on!\n    Serial.begin(115200);\n\n    Serial.println(\"\\n\\r-----------------------------------\");\n\n    Serial.print(\"Running Example 01 on: \");\n    Serial.println(String(deviceName));\n\n    // Initalize the OLED device and related graphics system\n    if(!myOLED.begin()){\n\n        Serial.println(\" - Device Begin Failed\");\n        while(1);\n    }\n\n    Serial.println(\"- Begin Success\");\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_03_bitmaps/#drawing-bitmaps","title":"Drawing Bitmaps","text":""},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_04_text/","title":"Example 4 - Text","text":"

An example that shows drawing bitmaps using the SparkFun Qwiic OLED Library.

Key Demo Features

  • Understanding font structure and use
  • Drawing text
  • Using the Arduino Print functionality
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_04_text/#setup","title":"Setup","text":"

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library.

// Include the SparkFun qwiic OLED Library\n#include <SparkFun_Qwiic_OLED.h>\n
The next step is to declare the object for the SparkFun qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

The user selects from one of the following classes:

Class Qwiic OLED Device QwiicMicroOLED SparkFun Qwiic Micro OLED QwiicNarrowOLED SparkFun Qwiic OLED Display (128x32) QwiicTransparentOLED SparkFun Transparent Graphical OLED Qwiic1in3OLED SparkFun Qwiic OLED 1.3\" Display (128x32)

The Example code supports all of the SparkFun Qwiic OLED boards. To select the board being used, uncomment the #define for the demo board.

For this example, the Qwiic Micro OLED is used.

#define MICRO\n//#define NARROW\n//#define TRANSPARENT\n
Which results in myOLED being declared as:

QwiicMicroOLED myOLED;\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_04_text/#initialization","title":"Initialization","text":"

In the setup() function of this sketch, like all of the SparkFun qwiic libraries, the device is initialized by calling the begin() method. This method returns a value of true on success, or false on failure.

void setup()\n{\n\n    delay(500);   //Give display time to power on\n\n    // Serial on!\n    Serial.begin(115200);\n\n    Serial.println(\"\\n\\r-----------------------------------\");\n\n    Serial.print(\"Running Example 01 on: \");\n    Serial.println(String(deviceName));\n\n    // Initalize the OLED device and related graphics system\n    if(!myOLED.begin()){\n\n        Serial.println(\" - Device Begin Failed\");\n        while(1);\n    }\n\n    Serial.println(\"- Begin Success\");\n
"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_04_text/#drawing-text","title":"Drawing Text","text":""},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_other/","title":"Other Examples","text":"

Descriptions of the other demos that are provided as part of the SparkFun Qwiic OLED Library.

"},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_other/#scroll-flip","title":"Scroll-Flip","text":""},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_other/#clock","title":"Clock","text":""},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_other/#cube","title":"Cube","text":""},{"location":"sparkfun-qwiic-oled-arduino-library-examples/ex_other/#multi","title":"Multi","text":""}]} \ No newline at end of file diff --git a/single_page/index.html b/single_page/index.html new file mode 100644 index 0000000..207aa9f --- /dev/null +++ b/single_page/index.html @@ -0,0 +1,5637 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Getting Started - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Getting Started

+

Introduction

+

SparkFun Qwiic OLED Arduino Library

+

The SparkFun Qwiic OLED Arduino Library is a single graphics module that supports all SparkFun OLED boards based on the SSD1306 from Solomon Systech. Prior to this library, three different libraries were used to support our four different OLED boards.

+

The SparkFun Qwiic OLED Library delivers a common implementation for all our Qwiic OLED products, delivering a unified, fast, and efficient solution that implements a familiar and easy to understand user experience.

+

Key Features

+
    +
  • Implements common graphics capabilities: pixel, line, rectangle, filled rectangle, circle, filled circle, bitmap, text and raster operators (i.e. XOR).
  • +
  • Smart data transfer to the device – only sends dirty regions of the graphics buffer to the OLED device, not the entire buffer.
  • +
  • High performance – 2x faster than our previous OLED library, often much higher.
  • +
  • Efficient memory usage. No dynamic memory utilized. Static resources are loaded once, and only on explicit declaration.
  • +
  • Implements a familiar interface, making migration from older libraries straight forward
  • +
+

Getting Started

+

The Software Setup outlines library installation and the general use of the Qwiic OLED library.

+

Detailed examples are included as part of the library installation process and available in the Arduino IDE menu: File > Examples > SparkFun Qwiic OLED Arduino Library. A walk-thru of key examples is contained in the Examples section of this documentation set.

+
+

Note

+

For v1.0.5 of the SparkFun Qwiic OLED Arduino Library, we named the library as SparkFun Qwiic OLED Graphics Library. After v1.0.6, we updated the name to say SparkFun Qwiic OLED Arduino Library. You may have multiple versions in your Arduino libraries folder if you installed the library more than once. To avoid confusion, issues compiling, and to use the latest version, we recommend removing the "SparkFun Qwiic OLED Graphics Library" folder should you decide to use the latest and greatest version. This will probably be located under ..Documents\Arduino\libraries, that is if you are using Windows.

+
+
+

Note

+

Note that we have more than one Arduino Library for the micro OLED. If you have the older Arduino Library, make sure to not confuse the two libraries. You will notice that the older library will be called "SparkFun Micro OLED Breakout". The example code will include the following line of code: #include <SFE_MicroOLED.h>.

+
+

A full API Reference is also provided for the library.

+ + +

Supported Products

+

The SparkFun Qwiic OLED Arduino Library supports the following SparkFun products.

+ +

Supported Microcontrollers - Arduino Environment

+

The following architectures are supported in the Arduino Library.

+ +

Below are a few of those processors populated on Arduino boards from the SparkFun catalog. You will need to make sure to check the associated hookup guides for additional information about compatible cables, drivers, or board add-ons.

+ +
+

Note

+

Unfortunately, the ATmega32U4 is not supported under this library. We recommend either using a different microcontroller or rolling back to the previous library written for the display.

+
+

License

+

The SparkFun Qwiic OLED Arduino Library is licensed using the Open Source MIT License:

+
The MIT License (MIT)
+
+Copyright (c) 2015 SparkFun Electronics
+
+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.
+
+

Qwiic Micro OLED (0.66", 64x48)

+

Introduction

+

The Qwiic Micro OLED is a Qwiic enabled version of our micro OLED display! This small monochrome, blue-on-black OLED display displays incredibly clear images.

+

+ +

+
+ +
+ +

This hookup guide will show you how to get started drawing objects and characters on your OLED.

+

Required Materials

+

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

+ +

Microcontroller

+

To get started, you'll need a microcontroller to, well, control everything. We used the RedBoard with the ATmega328P for the Qwiic micro OLED. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

+ +

USB Cable

+

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

+ +

Qwiic

+

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

+ +

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

+ +

Of course, you will also need a Qwiic Micro OLED if you have not added that to you cart already.

+

+ +

+

Suggested Reading

+

If you aren't familiar with the Qwiic Connection System, we recommend reading here for an overview.

+
+ + + + + + + +
+
Qwiic Connection System +
+
+
+ +

We would also recommend taking a look at the following tutorials if you aren't familiar with them.

+ +

Hardware Overview

+

Listed below are some of the operating ranges and characteristics of the Qwiic Micro OLED.

+
+ + + + + + + + + + + + + + + + + +
Characteristic + Range +
Voltage + 3.3V +
Temperature + -40°C to 85°C +
I2C Address + 0X3D (Default) or 0X3C (Closed Jumper) +
+
+ +

Pins

+

Power and I2C pins are broken out to the 1x4 PTH pins as well as the two horizontal Qwiic connectors.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Pin + Description + Direction +
GND + Ground + In +
3.3V + Power + In +
SDA + I2C Data + In +
SCL + I2C Clock + In +
+
+ +

Jumpers

+

There are several jumpers on board that can be changed to facilitate several different functions. The first of which is the I2C pull-up jumper to disable the 2.2kΩ pull up resistors on the I2C data and clock lines, highlighted below. If multiple boards are connected to the I2C bus, the equivalent resistance goes down, increasing your pull up strength. If multiple boards are connected on the same bus, make sure only one board has the pull-up resistors connected.

+
+ + + + + + + +
I2C Pull-Up Jumper
I2C Pull-Up Jumper
+
+ +

The ADDR jumper (highlighted below) can be used to change the I2C address of the board. The default jumper is open by default, pulling the address pin high and giving us an I2C address of 0X3D. Closing this jumper will ground the address pin, giving us an I2C address of 0X3C.

+
+ + + + + + + +
Address Jumper
Address Jumper
+
+ +

Board Dimensions

+
+

Revision Change

+

For V11, we have optimized the two mounting hole locations to match the mounting holes located on a standard 1.0" x 1.0" Qwiic-sized board. The overall functionality of the Qwiic Micro OLED breakout board is the same as the previous version!

+
+

The overall board size is 1.08" x 1.17". There is a v-score for users that want to remove the mounting holes.

+
+ + + + + + + +
Board Dimensions
Board Dimensions
+
+ +

Hardware Assembly

+

If you haven't yet assembled your Qwiic Shield, now would be the time to head on over to that tutorial. With the shield assembled, SparkFun's Qwiic environment means that connecting the screen could not be easier. Just plug one end of the Qwiic cable into the OLED display, the other into the Qwiic Shield and you'll be ready to start displaying images on your little display.

+
+ + + + +
Qwiic Micro OLED Connected to Arduino and Qwiic Shield
+
+ +

If you have a built-in Qwiic connector, you can skip the hardware assembly of the Qwiic Shield and simply insert a Qwiic cable between the two boards. Have more than one Qwiic-enabled device? You can daisy chain it to the board as well! Below is an example with the SAM-M8Q and the Qwiic Micro OLED daisy chained together to the RedBoard Qwiic.

+
+ + + + +
Qwiic Micro OLED Connected to RedBoard Qwiic and Qwiic GPS(SAM-M8Q)
+
+ +
+

Note

+

The initial launch of the Qwiic micro OLED breakout board had the OLED loosely attached to the breakout board. For users that received those boards, be careful handling it! You can either use your own enclosure for the OLED display, or you can use some double sided foam tape for a less permanent solution.

+

+ + + + +
Taped Screen
+

+

The current production of the boards includes the double sided foam tape.

+
+

Software

+

The SparkFun Micro OLED Breakout (Qwiic) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED library Getting Started guide has library setup instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

+ + +

Resources

+

Now that you've successfully got your OLED displaying things, it's time to incorporate it into your own project!

+

For more on the Qwiic Micro OLED, check out the links below:

+ +

Qwiic Transparent Graphical OLED (1.51", 128x56)

+

Introduction

+

The future is here! You asked and we delivered - our Qwiic Transparent Graphical OLED Breakout allows you to display custom images on a transparent screen using either I2C or SPI connections.

+

With Qwiic connectors it's quick (ha ha) and easy to get started with your own images. However, we still have broken out 0.1"-spaced pins in case you prefer to use a breadboard. Brilliantly lit in the dark and still visible by daylight, this OLED sports a display area of 128x64 pixels, 128x56 of which are completely transparent. Control of the OLED is based on the HyperDisplay library or SparkFun Qwiic OLED Arduino Library! For the scope of this tutorial, we will be using the SparkFun Qwiic OLED Arduino Library.

+

+ +

+
+ +
+ +

This hookup guide will show you how to get started drawing objects and characters on your OLED.

+

Required Materials

+

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

+ +

Microcontroller

+

To get started, you'll need a microcontroller to, well, control everything. We used the SparkFun Thing Plus - ESP32 WROOOM. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

+ +

USB Cable

+

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

+ +

Qwiic

+

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

+ +

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

+ +

Of course, you will also need A Tranparent Graphical OLED Breakout if you have not added that to you cart already.

+

+ +

+

Suggested Reading

+

If you aren't familiar with the Qwiic Connection System, we recommend reading here for an overview.

+
+ + + + + + + +
+
Qwiic Connection System +
+
+
+ +

We would also recommend taking a look at the following tutorials if you aren't familiar with them.

+ +

Hardware Overview

+

Listed below are some of the operating ranges and characteristics of the Transparent Graphical OLED Breakout.

+
+ + + + + + + + + + + + + + + + + +
Characteristic + Range +
Voltage + 1.65V-3.3V,
typically 3.3V via the Qwiic Cable +
Supply Current + 400 mA +
I2C Address + 0X3C (Default), 0X3D (Closed Jumper) +
+
+ +

Graphical Display

+

The graphical display is where all the fun stuff happens. The glass itself measures 42mm x 27.16mm, with a pixel display that is 35.5 x 18mm. It houses 128x64 pixels, 128x56 of which are transparent.

+
+ + + + + + + +
Display Screen
Graphical Display
+
+ +

Qwiic Connectors

+

There are two Qwiic connectors on the board such that you can daisy-chain the boards should you choose to do so. If you're unfamiliar with our Qwiic Connect System, head on over to our Qwiic page to see the advantages!

+
+ + + + + + + +
Qwiic Connectors
Qwiic Connectors
+
+ +

GPIO Pins

+

When you look at the GPIO pins, you'll notice that the labels are different from one side to the other. One side is labeled for I2C, the other side is labeled for SPI.

+
+ + + + + + + + + +
I2C PinsSPI Pins
I2C LabelsSPI Labels
+
+ +

Power LED

+

This bad boy will light up when the board is powered up correctly.

+
+ + + + + + + +
I2C Pins
Power LED
+
+ +

You can disable the power LED by cutting the LED jumpers on the back of the board.

+
+ + + + + + + +
Power LED Jumpers
Power LED Jumpers
+
+ +

JPX Jumpers

+

The JPX jumpers are used to either change the I2C address or configure the board to use SPI communications. The other two jumpers allow you to disconnect the power LED and to disconnect the I2C pull-up resistors when chaining several Qwiic devices.

+
+ + + + + + + + + + + + + + + + + + + + + +
Jumper + Function +
JP1 + Holds the Chip Select line low when closed. Close for I2C, open for SPI +
JP2 + Selects the address in I2C mode. Closed for 0x30 by default and open for 0x31. Open for SPI mode to release the D/C pin +
JP3 + Used to select I2C or SPI mode. Close for I2C, open for SPI +
JP4 + This jumper should be closed for I2C and open for SPI. This connection allows SDA to be bi-directional +
+
+ +
+ + + + + + + +
JP1-JP4
JPX Jumper
+
+ +

I2C Pull-Up Jumper

+

I2C devices contain open drains so we include resistors on our boards to allow these devices to pull pins high. This becomes a problem if you have a large number of I2C devices chained together. If you plan to daisy chain more than a few Qwiic boards together, you'll need to cut this I2C pull-up jumper.

+
+ + + + + + + +
JP1 to JP4
I2C PU Jumper
+
+ +

Hardware Hookup

+

Now that you know what's available on your breakout board we can check out the options for connecting it to the brains of your project. There are two options to use - either I2C or SPI - and they each have their own advantages and drawbacks. Read on to choose the best option for your setup.

+
+

Warning

+

Reminder! This breakout can only handle up to 3.3V on the pins, so make sure to do some level shifting if you're using a 5V microcontroller.

+
+

I2C (Qwiic)

+

The easiest way to start using the Transparent Graphical OLED is to use a Qwiic Cable along with a Qwiic compatible microcontroller (such as the ESP32 Thing Plus). You can also use the Qwiic Breadboard Cable to attach any I2C capable microcontroller, or take the scenic route and solder in all the I2C wires to the plated-through connections on the board.

+
+ + + + + + + + + +
Qwiic ConnectorI2C Pinout
Top ViewI2C Pinout/i>
+
+ +

So why use I2C? It's easy to connect with the Qwiic system, and you can put up to two of the Transparent Graphical Breakouts on the same bus without using any more microcontroller pins. That simplicity comes at a cost to performance though. The maximum clock speed of the I2C bus is 400 kHz, and there is additional overhead in data transmission to indicate which bytes are data and which are commands. This means that the I2C connection is best for showing static images.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Breakout Pin + Microcontroller Pin Requirements +
GND + Ground pin. Connect these so the two devices agree on voltages +
3V3 + 3.3V supply pin, capable of up to 400 mA output +
SDA + SDA - the bi-directional data line of your chosen I2C port +
SCL + SCL - the clock line of your chosen I2C port +
SA0 + Optional : change the I2C address of the breakout. Make sure to cut JP2 +
RST + Optional : reset the breakout to a known state by pulsing this low +
+
+ +

SPI

+

SPI solves the I2C speed problems. With SPI there is a control signal that indicates data or command and the maximum clock speed is 10 MHz -- giving SPI 50x more speed! However, it doesn't have the same conveniences of the polarized Qwiic connector and low pin usage. You'll need to solder to the pins.

+
+ + + + + + + +
SPI Pinout
SPI Pinout
+
+ +

You can use SPI to connect as many breakouts as you want. For N displays you will need to use at least N + 3 data pins. That's because the MOSI, SCLK, and D/C pins can be shared between displays but each breakout needs its own dedicated Chip Select (CS) pin.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Breakout Pin + Microcontroller Pin Requirements +
CS + A GPIO pin, set low when talking to the breakout +
D/C + A GPIO pin, indicates if bytes are data or commands +
SCLK + The clock output of your chosen SPI port +
MOSI + The data output of your chosen SPI port +
3V3 + 3.3V supply pin, capable of up to 400 mA output +
GND + Ground pin. Connect these so the two devices agree on voltages +
+
+ +
+

Warning

+

Make sure to cut jumpers JP1, JP2, JP3, and JP4 when using SPI mode!

+

+ + + + + + + +
Cut Jumpers for SPI Mode
Cut Jumpers for SPI Mode
+

+
+

Software

+

The Transparent OLED Breakout (Qwiic) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED library Getting Started guide has library setup instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

+ + +

Resources

+

For more information on the Transparent Graphical OLED Breakout, check out some of the links here:

+ +

Qwiic OLED (0.91", 128x32)

+

Introduction

+

The SparkFun Qwiic OLED Display can display up to four lines of text and features 128x32 pixels in a small 0.91” (diagonal) frame. As an OLED, this display does not have a back light layer (unlike LCDs) and therefore it’s thinner, consumes less power, and has higher contrast.

+

+ +

+

In this section, we'll go over the hardware and how to hookup the breakout board.

+

Required Materials

+

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

+ +

Microcontroller

+

To get started, you'll need a microcontroller to, well, control everything. We used the RedBoard with the ATmega328P for the Qwiic micro OLED. However, any of the other microcontrollers that are compatible with the Qwiic OLED Arduino Library will work as well. Below are a few from the list that we provided earlier.

+ +

USB Cable

+

Below are a few USB cables from the SparkFun catalog. Make sure to grab the associated USB cable that is compatible with your microcontroller.

+ +

Qwiic

+

If the controller you choose doesn't have a built-in Qwiic connector, one of the following Qwiic shields that matches your preference of microcontroller is needed:

+ +

You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.

+ +

Of course, you will also need a Qwiic Micro OLED if you have not added that to you cart already.

+

+ +

+

Hardware Overview

+

In this section, we will highlight the hardware and pins that are broken out on the SparkFun Qwiic OLED Display (0.91 in., 128x32).

+
+ + + + + + + + + +
Top ViewBottom View
Top ViewBottom View
+
+ +

OLED Display (0.91", 128x32)

+

The OLED screen has a pixel resolution of 128x32, a panel size of 30.0mm x 11.5mm x 1.2mm, and an active area of 22.384mm x 5.584mm. The driver chip is the SSD1306. For information can be found in the datasheet linked in the Resources.

+
+ + + + + + + +
OLED Highlighted
OLED Highlighted
+
+ +
+

Note

+

The SparkFun Qwiic OLED Arduino Library works for multiple displays. However, there are some caveats in the size of the display with the text. While you can technically display all fonts in the narrow OLED display, some characters (numbers, letters, and/or symbols depending on the font) will be too big to fully display on the screen. For example, the fonts for the 31x48 (i.e. &QW_FONT_31X48) and large numbers (i.e. &QW_FONT_LARGENUM) are too big to fit within the display.

+

Using the OLED display (0.91", 128x32) we found that we were able to fit:

+
    +
  • 4x lines, 21x characters using the 5x7 (i.e. &QW_FONT_5X7)
  • +
  • 2x lines, 14x characters using the 8x16 (i.e. &QW_FONT_8X16)
  • +
  • 2x lines, 11x characters using the 7 segment (i.e. &QW_FONT_7SEGMENT)
  • +
+
+

Power

+

Power is applied through the vertical Qwiic connectors on the back of the board. The recommended input voltage is 3.3V. The logic levels for the Qwiic OLED Display (0.9", 128x32) is 3.3V.

+
+ + + + + + + +
Power
Power
+
+ +

Qwiic and I2C

+

There are two vertical Qwiic connectors populated on the back of the board. You can use either connectors to provide power and send data through I2C. The Qwiic ecosystem is made for fast prototyping by removing the need for soldering. All you need to do is plug a Qwiic cable into the Qwiic connector and voila!

+
    +
  • SCL — I2C clock
  • +
  • SDA — I2C data
  • +
  • 3.3V — Power
  • +
  • GND — Ground
  • +
+
+ + + + + + + +
Qwiic Connectors
Vertical Qwiic Connectors
+
+ +

The address of the display is 0x3C.

+
+

Note

+

On the back of the board, the power and I2C pins are broken out to test points. These are used in our production department for quality control using custom testbeds. These could be an alternative option to connect to the pins. However, we recommend using the Qwiic connectors to easily connect to the OLED display. Note that the I2C pins are also in a different order compared to a standard I2C Qwiic connector should you decide to solder to the test points.

+

+ + + + + + + +
I2C Test Points
I2C Test Points
+

+
+

Jumpers

+
+

Note

+

If this is your first time working with jumpers, check out the How to Work with Jumper Pads and PCB Traces tutorial for more information.

+
+

The board includes a 1x3 jumper on the back of the board.

+
    +
  • I2C — This three way jumper labeled I2C is connected to two 4.7kΩ pull-up resistors to the I2C data and clock lines. For users that have multiple Qwiic-enabled devices with pull-up resistors enabled, the parallel equivalent resistance will create too strong of a pull-up for the bus to operate correctly. As a general rule of thumb, disable all but one pair of pull-up resistors if multiple devices are connected to the bus.
  • +
+
+ + + + + + + +
Jumpers Highlighted
Jumpers Highlighted
+
+ +

Board Dimensions

+

Version 1.1 is a bit smaller than previous versions since the board includes vertical Qwiic connectors on the back of the board. The overall board size is 1.75 in x 0.5 in. The mounting holes have also moved to toward the top of the board.

+
+ + + + + + + +
Board Dimensions
Board Dimensions
+
+ +

Hardware Hookup

+

In this section, we'll go over how to connect to the display. We will go just a bit further and talk about how to mount the display.

+

Connecting via Qwiic Connector

+

Insert a Qwiic cable between your chosen microcontroller and Qwiic OLED. Then insert a USB cable between the microcontroller and your computer's COM port. For the scope of this tutorial, the USB cable provides power and allows us to upload code to the microcontroller. Of course, you can also debug the display by opening a Serial Terminal.

+
+ + + + + + + +
USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, Qwiic OLED (0.9 in., 12x32)
USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, Qwiic OLED (0.9 in., 12x32)
+
+ +

Once you have finished prototyping, you could continue to use the USB cable and add a 5V power supply or battery pack.

+

Mounting the Qwiic OLED (0.9", 128x32)

+

Grab the board dimensions and cut out a rectangle in the enclosure. For users that want to mount the board so that the OLED display is flush against the enclosure, you will need to look at the dimensions based on the OLED. You will need to add a little tolerance so that the display can fit through the rectangle. For users that need to quickly mount the board, you will could also cut out rectangles based on the vertical Qwiic connector so that the wires can lead into the enclosure. Then cut out the mounting holes so that the board is right side up. In this case, we used a cardboard box as a quick example to demonstrate the Qwiic wires connecting leading into the enclosure.

+
+ + + + + + + + +
5V Battery Pack, USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, and Qwiic OLED (0.9 in., 12x32), stuffed in a cardboard box.5V Battery Pack, USB Cable, RedBoard Plus (ATMega328P), Qwiic Cable, and Qwiic OLED (0.9 in., 12x32) Mounted
Qwiic OLED Display Mounted in an Enclosure
+
+ +
+

Note

+

To easily display text and graphics on the board, we recommend mounting the board right side up. There is an option in the example code to flip the text horizontally and vertically should you decide to mount the board upside down, but you would need to also determine the position of the text.

+
+

For a more durable enclosure, you could use wood, metal, or plastic. However, you will need additional tools to cut into the material.

+

Software

+

The Qwiic OLED (0.91", 128x32) uses the SparkFun QWIIC OLED Arduino Library. The SparkFun Qwiic OLED Library's Software Setup has instructions and usage examples. Additionally, the full library API documentation is available in the SparkFun Qwiic OLED Library API Reference guide.

+ + +

Resources

+

Now that you've successfully got your OLED Display (0.9", 128x36) up and running, it's time to incorporate it into your own project! For more information, check out the resources below:

+ +

Qwiic OLED (1.3", 128x64)

+

The Qwiic OLED 1.3in has its own hook-up guide.

+

Software Setup

+

Software Setup

+

Installation

+
+

Arduino

+

This guide assumes you are using the latest version of the Arduino IDE on your desktop. The following resources available at SparkFun provide the details on setting up and configuring Arduino to use this library.

+ +
+

The SparkFun Qwiic OLED Arduino Library is available within in the Arduino library manager, which is launched via the Sketch > Include Libraries > Manage Libraries … menu option in the Arduino IDE. Just search for SparkFun Qwiic OLED Library.

+
+

Note

+

If you've never connected a USB-to-serial converter to your computer before, you may need to install drivers. The drivers will depend on what is populated on your Arduino development board. Check out the following tutorials for help with the installation.

+ +
+

General Use Pattern

+

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library.

+
// Include the SparkFun qwiic OLED Library
+#include <SparkFun_Qwiic_OLED.h>
+
+

The next step is to declare the object for the SparkFun qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

+

The user selects from one of the following classes:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ClassQwiic OLED Device
QwiicMicroOLEDSparkFun Qwiic Micro OLED
QwiicNarrowOLEDSparkFun Qwiic OLED Display (128x32)
QwiicTransparentOLEDSparkFun Transparent Graphical OLED
Qwiic1in3OLEDSparkFun Qwiic OLED 1.3" Display (128x32)
+

For this example, the Qwiic Micro OLED is used.

+
QwiicMicroOLED myOLED;
+
+

In the setup() function of this sketch, like all of the SparkFun qwiic libraries, the device is initialized by calling the begin() method. This method returns a value of true on success, or false on failure.

+
int width, height;  // global variables for use in the sketch
+void setup()
+{
+    Serial.begin(115200);
+    if(!myOLED.begin()){
+        Serial.println("Device failed to initialize");
+        while(1);  // halt execution
+    }
+    Serial.println("Device is initialized");
+
+}
+
+

Now that the library is initialized, the desired graphics are drawn. Here we erase the screen and draw simple series of lines that originate at the screen origin and fan out across the height of the display.

+
+

Note

+

Graphics are not send to the OLED device when drawn. Updates are only sent to the device when the display() method is called. This minimizes data transfers to the OLED device, delivering a responsive display response.

+
+
    myOLED.erase();           // Erase the screen
+    myOLED.display();         // Send erase to device
+
+    delay(1000);    // Slight pause
+
+    // Draw our lines from point (0,0) to (i, screen height)
+
+    for(int i=0; i < width; i+= 6){
+        myOLED.line(0, 0, i, height-1);    // draw the line
+        myOLED.display();                  // Send the new line to the device for display
+    }
+
+

Library Provided Examples

+

The SparkFun Qwiic OLED Arduino Library, includes a wide variety of examples. These are available from the Examples menu of the Arduino IDE, and in the examplesfolder of this repository.

+

For a detailed description of the examples, see the Examples section of the documentation.

+

API Reference

+

Device

+

Device Operations

+

Methods to setup the device, get device information and change display options.

+

Initialization

+

begin()

+

This method is called to initialize the OLED library and connection to the OLED device. This method must be called before calling any graphics methods.

+
bool begin(TwoWire &wirePort, uint8_t address)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
wirePortTwoWireoptional. The Wire port. If not provided, the default port is used
addressuint8_toptional. I2C Address. If not provided, the default address is used.
return valuebooltrue on success, false on startup failure
+

reset()

+

When called, this method reset the library state and OLED device to their intial state. Helpful to reset the OLED after waking up a system from a sleep state.

+
void reset()
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valuebooltrue on success, false on startup failure
+

Geometry

+

getWidth()

+

This method returns the width, in pixels, of the connected OLED device

+
uint8_t getWidth(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valueuint8_tThe width in pixels of the connected OLED device
+

getHeight()

+

This method returns the height, in pixels, of the connected OLED device

+
uint8_t getHeight(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valueuint8_tThe height in pixels of the connected OLED device
+

Display Modes

+

invert()

+

This method inverts the current graphics on the display. This results of this command happen immediatly.

+
void invert(bool bInvert)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
bInvertbooltrue - the screen is inverted. false - the screen is set to normal
+

flipVertical()

+

When called, the screen contents are flipped vertically if the flip parameter is true, or restored to normal display if the flip parameter is false.

+
void flipVertical(bool bFlip)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
bFlipbooltrue - the screen is flipped vertically. false - the screen is set to normal
+

flipHorizontal()

+

When called, the screen contents are flipped horizontally if the flip parameter is true, or restored to normal display if the flip parameter is false.

+
void flipHorizontal(bool bFlip)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
bFlipbooltrue - the screen is flipped horizontally. false - the screen is set to normal
+

displayPower()

+

Used to turn the OLED display on or off.

+
void displayPower(bool bEnable)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
bEnablebooltrue - the OLED display is powered on (default). false - the OLED dsiplay is powered off.
+

Scrolling

+

Scrolling

+

Methods for device scrolling

+

scrollStop()

+

If the device is in a scrolling mode, calling this method stops the scroll, and restores the device to normal display operation. This action is performed immediately.

+
void scrollStop(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
NONE
+

scrollRight()

+

This method is called to start the device scrolling the displayed graphics to the right. This action is performed immediately.

+

The screen will scroll until the scrollStop() method is called.

+
void scrollRight(uint8_t start, uint8_t stop, uint8_t interval)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
startuint8_tThe start page address of the scroll - valid values are 0 thru 7
stopuint8_tThe stop/end page address of the scroll - valid values are 0 thru 7
intervaluint8_tThe time interval between scroll step - values listed below
+

Defined values for the interval parameter:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Defined SymbolTime Interval Between Steps
SCROLL_INTERVAL_2_FRAMES2
SCROLL_INTERVAL_3_FRAMES3
SCROLL_INTERVAL_4_FRAMES4
SCROLL_INTERVAL_5_FRAMES5
SCROLL_INTERVAL_25_FRAMES25
SCROLL_INTERVAL_64_FRAMES64
SCROLL_INTERVAL_128_FRAMES128
SCROLL_INTERVAL_256_FRAMES256
+

scrollVertRight()

+

This method is called to start the device scrolling the displayed graphics vertically and to the right. This action is performed immediately.

+

The screen will scroll until the scrollStop() method is called.

+
void scrolVertlRight(uint8_t start, uint8_t stop, uint8_t interval)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
startuint8_tThe start page address of the scroll - valid values are 0 thru 7
stopuint8_tThe stop/end page address of the scroll - valid values are 0 thru 7
intervaluint8_tThe time interval between scroll step - values listed in scrollRight
+

scrollLeft()

+

This method is called start to the device scrolling the displayed graphics to the left. This action is performed immediately.

+

The screen will scroll until the scrollStop() method is called.

+
void scrollLeft(uint8_t start, uint8_t stop, uint8_t interval)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
startuint8_tThe start page address of the scroll - valid values are 0 thru 7
stopuint8_tThe stop/end page address of the scroll - valid values are 0 thru 7
intervaluint8_tThe time interval between scroll step - values listed in scrollRight
+

scrollVertLeft()

+

This method is called to start the device scrolling the displayed graphics vertically and to the left. This action is performed immediately.

+

The screen will scroll until the scrollStop() method is called.

+
void scrolVertlLeft(uint8_t start, uint8_t stop, uint8_t interval)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
startuint8_tThe start page address of the scroll - valid values are 0 thru 7
stopuint8_tThe stop/end page address of the scroll - valid values are 0 thru 7
intervaluint8_tThe time interval between scroll step - values listed in scrollRight
+

Drawing State

+

Drawing Settings/State

+

Methods for setting the drawing state of the library.

+

setFont()

+

This method is called to set the current font in the library. The current font is used when calling the text() method on this device.

+

The default font for the device is 5x7.

+
void setFont(QwiicFont& theFont)
+void setFont(const QwiicFont * theFont)
+
+ + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
theFontQwiicFontThe font to set as current in the device
theFontQwiicFont*Pointer to the font to set as current in the device.
+

For the library, fonts are added to your program by including them via include files which are part of this library.

+

The following fonts are included:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FontInclude FileFont VariableDescription
5x7<res/qw_fnt_5x7.h>QW_FONT_5X7A full, 5 x 7 font
31x48<res/qw_fnt_31x48.h>QW_FONT_31X48A full, 31 x 48 font
Seven Segment<res/qw_fnt_7segment.h>QW_FONT_7SEGMENTNumbers only
8x16<res/qw_fnt_8x16.h>QW_FONT_8X16A full, 8 x 16 font
Large Numbers<res/qw_fnt_largenum.h>QW_FONT_LARGENUMNumbers only
+

For each font, the font variables are objects with the following attributes:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeValue
widthThe font width in pixels
heightThe font height in pixels
startThe font start character offset
n_charsThe number of characters
map_widthThe width of the font map
+

Example use of a font object attribute: +

#include <res/qw_fnt_31x48.h>
+
+int myFontWidth = QW_FONT_31X48.width;
+

+

getFont()

+

This method returns the current font for the device.

+
QwiicFont * getFont(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valueQwiicFont*A pointer to the current font. See setFont() for font object details.
+

getFontName()

+

This method returns the height in pixels of a provided String based on the current device font.

+
String getFontName(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valueStringThe name of the current font.
+

getStringWidth()

+

This method returns the width in pixels of a provided String based on the current device font.

+
unsigned int getStringWidth(String text)
+
+ + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
textStringThe string used to determine width
return valueunsigned intThe width of the provide string, as determined using the current font.
+

getStringHeight()

+

This method returns the height in pixels of a provided String based on the current device font.

+
unsigned int getStringHeight(String text)
+
+ + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
textStringThe string used to determine height
return valueunsigned intThe height of the provide string, as determined using the current font.
+

setDrawMode()

+

This method sets the current draw mode for the library. The draw mode determines how pixels are set on the screen during drawing operations.

+
void setDrawMode(grRasterOp_t rop)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
ropgrRasterOp_tThe raster operation (ROP) to set the graphics system to.
+

Raster operations device how source (pixels to draw) are represented on the destination device. The available Raster Operation (ROP) codes are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ROP CodeDescription
grROPCopydefault Drawn pixel values are copied to the device screen
grROPNotCopyA not operation is applied to the source value before copying to screen
grROPNotA not operation is applied to the destination (screen) value
grROPXORA XOR operation is performed between the source and destination values
grROPBlackA value of 0, or black is drawn to the destination
grROPWhiteA value of 1, or black is drawn to the destination
+

getDrawMode()

+

This method returns the current draw mode for the library. The draw mode determines how pixels are set on the screen during drawing operations.

+
grRasterOp_t getDrawMode(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valuegrRasterOp_tThe current aster operation (ROP) of the graphics system.
+

Graphics

+

Graphics Methods

+

Methods used to draw and display graphics.

+

display()

+

When called, any pending display updates are sent to the connected OLED device. This includes drawn graphics and erase commands.

+
void display(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
NONE
+

erase()

+

Erases all graphics on the device, placing the display in a blank state. The erase update isn't sent to the device until the next display() call on the device.

+
void erase(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
NONE
+

pixel()

+

Set the value of a pixel on the screen.

+
void pixel(uint8_t x, uint8_t y, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
xuint8_tThe X coordinate of the pixel to set
yuint8_tThe Y coordinate of the pixel to set
clruint8_toptional The color value to set the pixel. This defaults to white (1).
+

line()

+

Draw a line on the screen.

+

Note: If a line is horizontal (y0 = y1) or vertical (x0 = x1), optimized draw algorithms are used by the library.

+
void line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe start X coordinate of the line
y0uint8_tThe start Y coordinate of the line
x1uint8_tThe end X coordinate of the line
y1uint8_tThe end Y coordinate of the line
clruint8_toptional The color value to draw the line. This defaults to white (1).
+

rectangle()

+

Draw a rectangle on the screen.

+
void rectangle(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe start X coordinate of the rectangle - upper left corner
y0uint8_tThe start Y coordinate of the rectangle - upper left corner
widthuint8_tThe width of the rectangle
heightuint8_tThe height of the rectangle
clruint8_toptional The color value to draw the line. This defaults to white (1).
+

rectangleFill()

+

Draw a filled rectangle on the screen.

+
void rectangleFill(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe start X coordinate of the rectangle - upper left corner
y0uint8_tThe start Y coordinate of the rectangle - upper left corner
widthuint8_tThe width of the rectangle
heightuint8_tThe height of the rectangle
clruint8_toptional The color value to draw the line. This defaults to white (1).
+

circle()

+

Draw a circle on the screen.

+
void circle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate of the circle center
y0uint8_tThe Y coordinate of the circle center
radiusuint8_tThe radius of the circle
clruint8_toptional The color value to draw the circle. This defaults to white (1).
+

circleFill()

+

Draw a filled circle on the screen.

+
void circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate of the circle center
y0uint8_tThe Y coordinate of the circle center
radiusuint8_tThe radius of the circle
clruint8_toptional The color value to draw the circle. This defaults to white (1).
+

bitmap()

+

Draws a bitmap on the screen.

+

The bitmap should be 8 bit encoded - each pixel contains 8 y values.

+
void bitmap(uint8_t x0, uint8_t y0, uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height )
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate to place the bitmap - upper left corner
y0uint8_tThe Y coordinate to place the bitmap - upper left corner
pBitmapuint8_t *A pointer to the bitmap array
bmp_widthuint8_tThe width of the bitmap
bmp_heightuint8_tThe height of the bitmap
+

bitmap()

+

Draws a bitmap on the screen.

+

The bitmap should be 8 bit encoded - each pixel contains 8 y values.

+

The coordinate [x1,y1] allows for only a portion of bitmap to be drawn.

+
void bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, 
+                uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height )
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate to place the bitmap - upper left corner
y0uint8_tThe Y coordinate to place the bitmap - upper left corner
x1uint8_tThe end X coordinate of the bitmap - lower right corner
y1uint8_tThe end Y coordinate of the bitmap - lower right corner
pBitmapuint8_t *A pointer to the bitmap array
bmp_widthuint8_tThe width of the bitmap
bmp_heightuint8_tThe height of the bitmap
+

bitmap()

+

Draws a bitmap on the screen using a Bitmap object for the bitmap data.

+
void bitmap(uint8_t x0, uint8_t y0, QwiicBitmap& bitmap)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate to place the bitmap - upper left corner
y0uint8_tThe Y coordinate to place the bitmap - upper left corner
BitmapQwiicBitmapA bitmap object
+

text()

+

Draws a string using the current font on the screen.

+
void text(uint8_t x0, uint8_t y0, const char * text, uint8_t clr)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
x0uint8_tThe X coordinate to start drawing the text
y0uint8_tThe Y coordinate to start drawing the text
textconst char*The string to draw on the screen
textStringThe Arduino string to draw on the screen
clruint8_toptional The color value to draw the circle. This defaults to white (1).
+

Arduino Print

+

Arduino Print

+

Methods used to support Arduino Print functionality.

+

setCursor()

+

This method is called set the "cursor" position in the device. The library supports the Arduino Print interface, enabling the use of a print() and println() methods. The set cursor position defines where to start text output for this functionality.

+
void setCursor(uint8_t x, uint8_t y)
+
+ + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescription
xuint8_tThe X coordinate of the cursor
yuint8_tThe Y coordinate of the cursor
+

setColor()

+

This method is called to set the current color of the system. This is used by the Arduino Print interface functionality

+
void setColor(uint8_t clr)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
clruint8_tThe color to set. 0 = black, > 0 = white
+

getColor()

+

This method is called to get the current color of the system. This is used by the Arduino Print interface functionality

+
uint8_t getColor(void)
+
+ + + + + + + + + + + + + + + +
ParameterTypeDescription
return valueuint8_tThe current color
+

Arduino Examples

+

Example 1 - Hello

+

--8<-- "./docs/ex_01_hello.md

+

Example 2 - Shapes

+

--8<-- "./docs/ex_02_lines.md

+

Example 3 - Bitmaps

+

--8<-- "./docs/ex_03_bitmaps.md

+

Example 4 - Text

+

--8<-- "./docs/ex_04_text.md

+

Other Examples

+

--8<-- "./docs/ex_other.md

+

Troubleshooting

+

General Troubleshooting Help

+
+

Note

+

+ Not working as expected and need help?

+

If you need technical assistance and more information on a product that is not working as you expected, we recommend heading on over to the SparkFun Technical Assistance page for some initial troubleshooting.

+

+

If you don't find what you need there, the SparkFun Forums are a great place to find and ask for help. If this is your first visit, you'll need to create a Forum Account to search product forums and post questions.

+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..a39f66c --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,91 @@ + + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/api_arduino/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/api_device/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/api_draw/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/api_graphics/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/api_scroll/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/hug_0p91/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/hug_1p3/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/hug_micro_view/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/hug_transparent/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/introduction/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/single_page/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/software/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/troubleshooting/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/github/contribute/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/github/file_issue/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/javascript/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/sparkfun-qwiic-oled-arduino-library-examples/ex_02_lines/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/sparkfun-qwiic-oled-arduino-library-examples/ex_03_bitmaps/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/sparkfun-qwiic-oled-arduino-library-examples/ex_04_text/ + 2025-02-20 + + + https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/sparkfun-qwiic-oled-arduino-library-examples/ex_other/ + 2025-02-20 + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000..455299b Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/software/index.html b/software/index.html new file mode 100644 index 0000000..afae53a --- /dev/null +++ b/software/index.html @@ -0,0 +1,1870 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Software Setup - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Software Setup

+

Installation

+
+

Arduino

+

This guide assumes you are using the latest version of the Arduino IDE on your desktop. The following resources available at SparkFun provide the details on setting up and configuring Arduino to use this library.

+ +
+

The SparkFun Qwiic OLED Arduino Library is available within in the Arduino library manager, which is launched via the Sketch > Include Libraries > Manage Libraries … menu option in the Arduino IDE. Just search for SparkFun Qwiic OLED Library.

+
+

Note

+

If you've never connected a USB-to-serial converter to your computer before, you may need to install drivers. The drivers will depend on what is populated on your Arduino development board. Check out the following tutorials for help with the installation.

+ +
+

General Use Pattern

+

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library.

+
// Include the SparkFun qwiic OLED Library
+#include <SparkFun_Qwiic_OLED.h>
+
+

The next step is to declare the object for the SparkFun qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

+

The user selects from one of the following classes:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ClassQwiic OLED Device
QwiicMicroOLEDSparkFun Qwiic Micro OLED
QwiicNarrowOLEDSparkFun Qwiic OLED Display (128x32)
QwiicTransparentOLEDSparkFun Transparent Graphical OLED
Qwiic1in3OLEDSparkFun Qwiic OLED 1.3" Display (128x32)
+

For this example, the Qwiic Micro OLED is used.

+
QwiicMicroOLED myOLED;
+
+

In the setup() function of this sketch, like all of the SparkFun qwiic libraries, the device is initialized by calling the begin() method. This method returns a value of true on success, or false on failure.

+
int width, height;  // global variables for use in the sketch
+void setup()
+{
+    Serial.begin(115200);
+    if(!myOLED.begin()){
+        Serial.println("Device failed to initialize");
+        while(1);  // halt execution
+    }
+    Serial.println("Device is initialized");
+
+}
+
+

Now that the library is initialized, the desired graphics are drawn. Here we erase the screen and draw simple series of lines that originate at the screen origin and fan out across the height of the display.

+
+

Note

+

Graphics are not send to the OLED device when drawn. Updates are only sent to the device when the display() method is called. This minimizes data transfers to the OLED device, delivering a responsive display response.

+
+
    myOLED.erase();           // Erase the screen
+    myOLED.display();         // Send erase to device
+
+    delay(1000);    // Slight pause
+
+    // Draw our lines from point (0,0) to (i, screen height)
+
+    for(int i=0; i < width; i+= 6){
+        myOLED.line(0, 0, i, height-1);    // draw the line
+        myOLED.display();                  // Send the new line to the device for display
+    }
+
+

Library Provided Examples

+

The SparkFun Qwiic OLED Arduino Library, includes a wide variety of examples. These are available from the Examples menu of the Arduino IDE, and in the examplesfolder of this repository.

+

For a detailed description of the examples, see the Examples section of the documentation.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/index.html b/sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/index.html new file mode 100644 index 0000000..f9ccee9 --- /dev/null +++ b/sparkfun-qwiic-oled-arduino-library-examples/ex_01_hello/index.html @@ -0,0 +1,2026 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Example 1 - Hello - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Example 1 - Hello

+

A simple example to show the basic setup and use of the SparkFun Qwiic OLED Library.

+

Key Demo Features

+
    +
  • Declaring a Qwiic OLED device object.
  • +
  • Initializing the Qwiic OLED device
  • +
  • Drawing a simple graphic - a filled rectangle and a text string
  • +
  • Using the current font to center text on the screen.
  • +
  • Displaying the graphics on the screen
  • +
+

Setup

+

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library.

+
// Include the SparkFun Qwiic OLED Library
+#include <SparkFun_Qwiic_OLED.h>
+
+

The next step is to declare the object for the SparkFun Qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

+

The user selects from one of the following classes:

+
+ + + + + + + + + + + + + + + + + + + + + +
Class + Qwiic OLED Device +
QwiicMicroOLED + SparkFun Qwiic Micro OLED +
QwiicTransparentOLED + SparkFun Transparent Graphical OLED +
QwiicNarrowOLED + SparkFun Qwiic OLED Display (128x32) +
Qwiic1in3OLED + SparkFun Qwiic OLED 1.3" Display (128x32) +
+
+ +

The example code supports all of the SparkFun Qwiic OLED boards. By default, the Qwiic Micro OLED is selected. To select a different board being used, add a single line comment (i.e. //) in front of "QwiicMicroOLED myOLED;" and uncomment the device being used for the demo board.

+
QwiicMicroOLED myOLED;
+//QwiicTransparentOLED myOLED;
+//QwiicNarrowOLED myOLED;
+//Qwiic1in3OLED myOLED;
+
+
+

Note

+

As of version 1.0.2+, users will need to use the class as explained above instead of using a #define.

+
#define MICRO
+//#define NARROW
+//#define TRANSPARENT
+
+
+

Initialization

+

In the setup() function of this sketch, like all of the SparkFun Qwiic Arduino libraries, the device is initialized by calling the begin() method. This method returns a value of true on success, or false on failure.

+
void setup()
+{
+
+    delay(500);   //Give display time to power on
+
+    // Serial on!
+    Serial.begin(115200);
+
+    Serial.println("\n\r-----------------------------------");
+
+    Serial.print("Running Example 01 on: ");
+    Serial.println(String(deviceName));
+
+    // Initalize the OLED device and related graphics system
+    if(!myOLED.begin()){
+
+        Serial.println(" - Device Begin Failed");
+        while(1);
+    }
+
+    Serial.println("- Begin Success");
+
+   // Do a simple test - fill a rectangle on the screen and then print hello!...
+
+}
+
+

Drawing Graphics

+

Once the device is enabled, the rest of the setup() function is devoted to drawing a simple graphic on the target device.

+

Filled Rectangle

+

First, draw a filled rectangle on the screen - leave a 4 pixel boarder at the end of the screen. Note that the getWidth() and getHeight() method are used to get the devices screen size.

+
    // Fill a rectangle on the screen that has a 4 pixel board
+    myOLED.rectangleFill(4, 4, myOLED.getWidth() - 8, myOLED.getHeight() - 8);
+
+

Centered Text

+

The next part of our graphic is a message centered in the drawn rectangle. To do the centering, the current font is accessed from the device, and the size of a character in the font is used to calculate the text position on the screen. Once the position is determined, the message is drawn on the display in black (0 for a color value).

+
    String hello = "hello"; // our message
+
+    // Center our message on the screen. Get the screen size of the "hello" string,
+    // calling the getStringWidth() and getStringHeight() methods on the oled
+
+    // starting x position - screen width minus string width  / 2
+    int x0 = (myOLED.getWidth() - myOLED.getStringWidth(hello)) / 2;
+
+    // starting y position - screen height minus string height / 2
+    int y0 = (myOLED.getHeight() - myOLED.getStringHeight(hello)) / 2;
+
+    // Draw the text - color of black (0)
+    myOLED.text(x0, y0, hello, 0);
+
+

Displaying the Graphics

+

The last step is sending the graphics to the device. This is accomplished by calling the display() method.

+
    // There's nothing on the screen yet - Now send the graphics to the device
+    myOLED.display();
+
+

What You Should See

+

And that's it! Select the board and COM port for your development board. Then upload the code! The graphic should display on the OLED device.

+

Hello!

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sparkfun-qwiic-oled-arduino-library-examples/ex_02_lines/index.html b/sparkfun-qwiic-oled-arduino-library-examples/ex_02_lines/index.html new file mode 100644 index 0000000..7a28b41 --- /dev/null +++ b/sparkfun-qwiic-oled-arduino-library-examples/ex_02_lines/index.html @@ -0,0 +1,2061 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Example 2 - Shapes - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Example 2 - Shapes

+

An example that shows drawing simple shapes using the SparkFun Qwiic OLED Library.

+

Key Demo Features

+
    +
  • Drawing lines, rectangles and circles
  • +
  • Demonstrating how graphics size impacts display speed
  • +
  • Drawing and erasing graphics quickly
  • +
  • XOR operations using raster operators
  • +
+

Setup

+

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library.

+
// Include the SparkFun Qwiic OLED Library
+#include <SparkFun_Qwiic_OLED.h>
+
+

The next step is to declare the object for the SparkFun Qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

+

The user selects from one of the following classes:

+
+ + + + + + + + + + + + + + + + + + + + + +
Class + Qwiic OLED Device +
QwiicMicroOLED + SparkFun Qwiic Micro OLED +
QwiicTransparentOLED + SparkFun Transparent Graphical OLED +
QwiicNarrowOLED + SparkFun Qwiic OLED Display (128x32) +
Qwiic1in3OLED + SparkFun Qwiic OLED 1.3" Display (128x32) +
+
+ +

The example code supports all of the SparkFun Qwiic OLED boards. By default, the Qwiic Micro OLED is selected. To select a different board being used, add a single line comment (i.e. //) in front of "QwiicMicroOLED myOLED;" and uncomment the device being used for the demo board.

+
QwiicMicroOLED myOLED;
+//QwiicTransparentOLED myOLED;
+//QwiicNarrowOLED myOLED;
+//Qwiic1in3OLED myOLED;
+
+
+

Note

+

As of version 1.0.2+, users will need to use the class as explained above instead of using a #define.

+
#define MICRO
+//#define NARROW
+//#define TRANSPARENT
+
+
+

Drawing Shapes

+
+

Note

+

As of version 1.0.2+, the modular functions have a slightly different name. Some functions defined in the example code will have the _ removed or words spelled out. For example, version v1.0.1 and below defined the function to test the line as line_test_1() while version v1.0.2+ defined the function as lineTest1().

+
+

The shapes drawn are broken into a set of functions that perform one test, which is part of the overall example.

+

Lines

+

This test starts with a short, horizontal line that is animated from the top to bottom of the display. After each iteration, the line size is increased and the animating sequence repeated.

+

To animate the line, the display is erased, then the line drawn. Once the line is draw, the updated graphics is sent to the OLED device by calling the display() method.

+
+

Note

+

When display() is called, only the range of modified pixels is sent to the OLED device, greatly reducing the data transferred for small graphic changes.

+

This is demonstrated by this test. When small lines are drawn, the update rate is fast, but as the line length increases, the update rate of the device is noticeably slower. A longer line requires more data to be sent to the device.

+
+
void lineTest1(void)
+{
+    int x, y, i;
+
+    int mid = width / 2;
+    int delta = mid / 8;
+
+    for (int j = 1; j < 8; j++)
+    {
+
+        x = delta * j;
+
+        for (i = 0; i < height * 2; i++)
+        {
+
+            y = i % height;
+            myOLED.erase();
+            myOLED.line(mid - x, y, mid + x, y);
+            myOLED.display();
+        }
+    }
+}
+
+

This test is followed up with a series of lines that span from a single point to the bottom of the screen, showing the flexibility of the line to raster algorithm used by the library.

+
void lineTest2(void)
+{
+    for (int i = 0; i < width; i += 6)
+    {
+        myOLED.line(0, 0, i, height - 1);
+        myOLED.display();
+    }
+    delay(200);
+    myOLED.erase();
+    for (int i = width - 1; i >= 0; i -= 6)
+    {
+        myOLED.line(width - 1, 0, i, height - 1);
+        myOLED.display();
+    }
+}
+
+

And the last line test draws a series of lines to test all three internal line drawing algorithms. Specifically:

+
    +
  • Angled lines drawn by the general purpose line algorithm
  • +
  • Vertical lines drawn by an optimized line routine
  • +
  • Horizontal lines draw by an optimized line routine
  • +
+

The test animates to show a growing box, giving an idea of the speed and flexibility of the system.

+
void lineTestVerticalIterative(uint8_t y0, uint8_t y1)
+{
+    for (int i = 0; i < width; i += 8)
+        myOLED.line(i, y0, i, y1);
+
+    // end off the vertical lines
+    myOLED.line(width - 1, y0, width - 1, y1);
+
+    // End lines and cross lines
+    myOLED.line(0, y0, width - 1, y0);
+    myOLED.line(0, y1, width - 1, y1);
+    myOLED.line(0, y0, width - 1, y1);
+    myOLED.line(0, y1, width - 1, y0);
+}
+
+// Entry point for test
+void lineTestVertical(void)
+{
+    int mid = height / 2;
+
+    for (int i = 0; i < height; i += 4)
+    {
+
+        myOLED.erase();
+        lineTestVerticalIterative(mid - i / 2, mid + i / 2);
+        myOLED.display();
+        delay(10);
+    }
+}
+
+

Rectangles

+

Several rectangle routines are shown in this example. A key test is a fast drawing routine which animates a small rectangle being drawn diagonally across the screen.

+

In this test, the rectangle is drawn, sent to the device via using display(), then the rectangle is drawn again, but this time in black. This effectively erases the rectangle. The position is incremented and the process loops, causing the rectangle to appear to fly across the screen.

+

The animation is quick, since only the portions of the screen that need updated are actually updated.

+

The animation algorithm is listed in the `rectangleTestMove() function.

+
void rectangleTestMove(void)
+{
+    float steps = height;
+    float xinc = width / steps;
+    float yinc = height / steps;
+    int side = 10;
+    float x = 0;
+    float y = 0;
+
+    for (int i = 0; i < steps; i++)
+    {
+        // Draw the rectangle and send it to device
+        myOLED.rectangle(x, y, side, side);
+        myOLED.display(); // sends erased rect and new rect pixels to device
+
+        // Erase the that rect, increment and loop
+        myOLED.rectangle(x, y, side, side, 0);
+
+        x += xinc;
+        y += yinc;
+    }
+}
+
+

The next rectangle test draws a series of filled rectangles on the screen. The unique aspect of this test is that is uses the XOR functionally to overlay a rectangle on the device, presenting a alternating color pattern.

+

The XOR raster operation is set by calling the setDrawMode() method on the OLED device, and providing the grROPXOR code. This switch the device into a XOR drawing mode. Graphic operations are restored to normal by calling setDrawMode() and providing the grROPCopy code, which copies the new pixel value to the destination.

+

Filled rectangles and XOR operations:

+
void rectangleFillTest(void)
+{
+    myOLED.rectangleFill(4, 4, width / 2 - 8, height - 8);
+
+    myOLED.rectangleFill(width / 2 + 4, 4, width / 2 - 8, height - 8);
+
+    myOLED.setDrawMode(grROPXOR); // xor
+    myOLED.rectangleFill(width / 4, 8, width / 2, height - 16);
+    myOLED.setDrawMode(grROPCopy); // back to copy op (default)
+}
+
+

Circles

+

The final shape drawn by this example is a series of circles and filled circles. Using the geometry of the screen, a set of circles are drawn and displayed.

+
void circleTest(void)
+{
+    // Let's draw some circles that fit on the device
+    myOLED.circle(width / 4, height / 2, height / 3);
+
+    myOLED.circleFill(width - width / 4, height / 2, height / 3);
+
+    myOLED.circle(4, height / 2, height / 3);
+
+    myOLED.circleFill(width - width / 2, height / 2, height / 4);
+}
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sparkfun-qwiic-oled-arduino-library-examples/ex_03_bitmaps/index.html b/sparkfun-qwiic-oled-arduino-library-examples/ex_03_bitmaps/index.html new file mode 100644 index 0000000..9552036 --- /dev/null +++ b/sparkfun-qwiic-oled-arduino-library-examples/ex_03_bitmaps/index.html @@ -0,0 +1,1860 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Example 3 - Bitmaps - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Example 3 - Bitmaps

+

An example that shows drawing bitmaps using the SparkFun Qwiic OLED Library.

+

Key Demo Features

+
    +
  • Understanding bitmap structure
  • +
  • Bitmap objects
  • +
  • Drawing Bitmap
  • +
+

Setup

+

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library. +

// Include the SparkFun qwiic OLED Library
+#include <SparkFun_Qwiic_OLED.h>
+
+The next step is to declare the object for the SparkFun qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

+

The user selects from one of the following classes:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ClassQwiic OLED Device
QwiicMicroOLEDSparkFun Qwiic Micro OLED
QwiicNarrowOLEDSparkFun Qwiic OLED Display (128x32)
QwiicTransparentOLEDSparkFun Transparent Graphical OLED
Qwiic1in3OLEDSparkFun Qwiic OLED 1.3" Display (128x32)
+

The Example code supports all of the SparkFun Qwiic OLED boards. To select the board being used, uncomment the #define for the demo board.

+

For this example, the Qwiic Micro OLED is used.

+

#define MICRO
+//#define NARROW
+//#define TRANSPARENT
+
+Which results in myOLED being declared as:

+
QwiicMicroOLED myOLED;
+
+

Initialization

+

In the setup() function of this sketch, like all of the SparkFun qwiic libraries, the device is initialized by calling the begin() method. This method returns a value of true on success, or false on failure.

+
void setup()
+{
+
+    delay(500);   //Give display time to power on
+
+    // Serial on!
+    Serial.begin(115200);
+
+    Serial.println("\n\r-----------------------------------");
+
+    Serial.print("Running Example 01 on: ");
+    Serial.println(String(deviceName));
+
+    // Initalize the OLED device and related graphics system
+    if(!myOLED.begin()){
+
+        Serial.println(" - Device Begin Failed");
+        while(1);
+    }
+
+    Serial.println("- Begin Success");
+
+

Drawing Bitmaps

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sparkfun-qwiic-oled-arduino-library-examples/ex_04_text/index.html b/sparkfun-qwiic-oled-arduino-library-examples/ex_04_text/index.html new file mode 100644 index 0000000..28ef2e7 --- /dev/null +++ b/sparkfun-qwiic-oled-arduino-library-examples/ex_04_text/index.html @@ -0,0 +1,1860 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Example 4 - Text - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Example 4 - Text

+

An example that shows drawing bitmaps using the SparkFun Qwiic OLED Library.

+

Key Demo Features

+
    +
  • Understanding font structure and use
  • +
  • Drawing text
  • +
  • Using the Arduino Print functionality
  • +
+

Setup

+

After installing this library in your local Arduino environment, begin with a standard Arduino sketch, and include the header file for this library. +

// Include the SparkFun qwiic OLED Library
+#include <SparkFun_Qwiic_OLED.h>
+
+The next step is to declare the object for the SparkFun qwiic OLED device used. Like most Arduino sketches, this is done at a global scope (after the include file declaration), not within the setup() or loop() functions.

+

The user selects from one of the following classes:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ClassQwiic OLED Device
QwiicMicroOLEDSparkFun Qwiic Micro OLED
QwiicNarrowOLEDSparkFun Qwiic OLED Display (128x32)
QwiicTransparentOLEDSparkFun Transparent Graphical OLED
Qwiic1in3OLEDSparkFun Qwiic OLED 1.3" Display (128x32)
+

The Example code supports all of the SparkFun Qwiic OLED boards. To select the board being used, uncomment the #define for the demo board.

+

For this example, the Qwiic Micro OLED is used.

+

#define MICRO
+//#define NARROW
+//#define TRANSPARENT
+
+Which results in myOLED being declared as:

+
QwiicMicroOLED myOLED;
+
+

Initialization

+

In the setup() function of this sketch, like all of the SparkFun qwiic libraries, the device is initialized by calling the begin() method. This method returns a value of true on success, or false on failure.

+
void setup()
+{
+
+    delay(500);   //Give display time to power on
+
+    // Serial on!
+    Serial.begin(115200);
+
+    Serial.println("\n\r-----------------------------------");
+
+    Serial.print("Running Example 01 on: ");
+    Serial.println(String(deviceName));
+
+    // Initalize the OLED device and related graphics system
+    if(!myOLED.begin()){
+
+        Serial.println(" - Device Begin Failed");
+        while(1);
+    }
+
+    Serial.println("- Begin Success");
+
+

Drawing Text

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sparkfun-qwiic-oled-arduino-library-examples/ex_other/index.html b/sparkfun-qwiic-oled-arduino-library-examples/ex_other/index.html new file mode 100644 index 0000000..a305c1c --- /dev/null +++ b/sparkfun-qwiic-oled-arduino-library-examples/ex_other/index.html @@ -0,0 +1,1817 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Other Examples - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Other Examples

+

Descriptions of the other demos that are provided as part of the SparkFun Qwiic OLED Library.

+

Scroll-Flip

+

Clock

+

Cube

+

Multi

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/docs/img/ex01_hello.png b/sparkfun-qwiic-oled-arduino-library-examples/img/ex01_hello.png similarity index 100% rename from examples/docs/img/ex01_hello.png rename to sparkfun-qwiic-oled-arduino-library-examples/img/ex01_hello.png diff --git a/src/SparkFun_Qwiic_OLED.h b/src/SparkFun_Qwiic_OLED.h deleted file mode 100644 index 752af45..0000000 --- a/src/SparkFun_Qwiic_OLED.h +++ /dev/null @@ -1,883 +0,0 @@ -// SparkFun_Qwiic_OLED.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -#pragma once - -// Arduino wrapper for the OLED library. Provides an Arduino experience and platform support -// for the Qwiic OLED driver. - -// include the underlying SDK implementation headers for the OLED devices -#include "qwiic_oled_1in3.h" -#include "qwiic_oled_custom.h" -#include "qwiic_oledmicro.h" -#include "qwiic_olednarrow.h" -#include "qwiic_oledtransp.h" - -#include -#include - -// Friendly typenames -typedef QwFont QwiicFont; -typedef QwBitmap QwiicBitmap; - -#define COLOR_WHITE 1 -#define COLOR_BLACK 0 - -// The Plan: -// -// For each supported device the following is needed -// -// - A commmon Arduino interface/implementation. One impl, one area to maintain -// - Classes that are specialized for each device -// - No abstract methods that a subclass must implement -// -// The solution -// A templated base class that device specific sub-classes derive from. -// - -// flag - internal - to determine if an address is passed into begin or not - -#define kNoAddressSet 0 - -// Define the template and fill in the interface methods in-line. - -template class QwiicOLEDBaseClass : public Print // NOTE: implementing Arduino Print -{ - protected: - // our device driver - SSD1306DeviceType m_device; - - private: - QwI2C m_i2cBus; // our i2c object - - // for the Aruduino print functionaliyt - uint8_t m_cursorX; - uint8_t m_cursorY; - - uint8_t m_color; - - public: - /////////////////////////////////////////////////////////////////////// - // begin() - // - // This method is called to initialize the OLED library and connection to - // the OLED device. This method must be called before calling any graphics methods. - // - // This method follows the standard startup pattern in SparkFun Arduino - // libraries. - // - // Parameter Description - // --------- ---------------------------- - // wirePort optional. The Wire port. If not provided, the default port is used - // address optional. I2C Address. If not provided, the default address is used. - // retval true on success, false on startup failure - - bool begin(TwoWire &wirePort = Wire, uint8_t address = kNoAddressSet) - { - - // defaults for Arduino Print - setCursor(0, 0); - setColor(COLOR_WHITE); - - m_i2cBus.init(wirePort); - - m_device.setCommBus(m_i2cBus, (address == kNoAddressSet ? m_device.default_address : address)); - - // call init on the device - bool bStatus = m_device.init(); - - // Want to start cursor at Y height of the current font, if we have a font. - // - // Get our font height ... a default font is set during init ... - if (bStatus) - { - QwiicFont *pFont = m_device.font(); - if (pFont) - m_cursorY = pFont->height; - } - - return bStatus; - } - - /////////////////////////////////////////////////////////////////////// - // getWidth() - // - // This method returns the width, in pixels, of the connected OLED device - // - // Parameter Description - // --------- ----------------------------- - // retval The width in pixels of the connected OLED device - - uint8_t getWidth(void) - { - return m_device.width(); - } - - /////////////////////////////////////////////////////////////////////// - // getHeight() - // - // This method returns the height, in pixels, of the connected OLED device - // - // Parameter Description - // --------- ----------------------------- - // retval The height in pixels of the connected OLED device - - uint8_t getHeight(void) - { - return m_device.height(); - } - - /////////////////////////////////////////////////////////////////////// - // reset() - // - // When called, the system and OLED are reset back to an initial state - // - // Parameter Description - // --------- ----------------------------- - // clearDisplay true - clear the internal buffers during reset - // retval true on success, false on failure - - bool reset(bool clearDisplay) - { - return m_device.reset(clearDisplay); - } - - /////////////////////////////////////////////////////////////////////// - // display() - // - // When called, any pending display updates are sent to the connected OLED - // device. This includes drawn graphics and erase commands. - // - // To display any graphics, this method must be called. - - void display(void) - { - m_device.display(); - } - - /////////////////////////////////////////////////////////////////////// - // erase() - // - // Erases all graphics on the device, placing the display in a blank state. - // The erase update isn't sent to the device until the next display() call - // on the device. - - void erase(void) - { - m_device.erase(); - } - - /////////////////////////////////////////////////////////////////////// - // invert() - // - // This method inverts the current graphics on the display. This results - // of this command happen immediatly. - // - // Parameter Description - // --------- ----------------------------- - // bInvert true - the screen is inverted. false - the screen is set to normal - - void invert(bool bInvert) - { - m_device.invert(bInvert); - } - - /////////////////////////////////////////////////////////////////////// - // flipVertical() - // - // When called, the screen contents are flipped vertically if the flip parameter - // is true, or restored to normal display if the flip parameter is false. - // - // Parameter Description - // --------- ----------------------------- - // bFlip true - the screen is flipped vertically. false - the screen is set to normal - - void flipVertical(bool bFlip) - { - m_device.flipVert(bFlip); - } - - /////////////////////////////////////////////////////////////////////// - // flipHorizontal() - // - // When called, the screen contents are flipped horizontally if the flip parameter - // is true, or restored to normal display if the flip parameter is false. - // - // Parameter Description - // --------- ----------------------------- - // bFlip true - the screen is flipped horizontally. false - the screen is set to normal - - void flipHorizontal(bool bFlip) - { - m_device.flipHorz(bFlip); - } - - /////////////////////////////////////////////////////////////////////// - // scrollStop() - // - // If the device is in a scrolling mode, calling this method stops the scroll, - // and restores the device to normal display operation. This action is performed immediately. - - void scrollStop(void) - { - m_device.stopScroll(); - } - - /////////////////////////////////////////////////////////////////////// - // scrollRight() - // - // This method is called to start the device scrolling the displayed graphics to the right. - // This action is performed immediately. - // - // The screen will scroll until the scrollStop() method is called. - // - // Parameter Description - // --------- ----------------------------- - // start The start page address of the scroll - valid values are 0 thru 7 - // stop The stop/end page address of the scroll - valid values are 0 thru 7 - // interval The time interval between scroll step - values listed below - // - // Defined values for the interval parameter: - // - // Defined Symbol Time Interval Between Steps - // ---------------------------- --------------------------- - // SCROLL_INTERVAL_2_FRAMES 2 - // SCROLL_INTERVAL_3_FRAMES 3 - // SCROLL_INTERVAL_4_FRAMES 4 - // SCROLL_INTERVAL_5_FRAMES 5 - // SCROLL_INTERVAL_25_FRAMES 25 - // SCROLL_INTERVAL_64_FRAMES 64 - // SCROLL_INTERVAL_128_FRAMES 128 - // SCROLL_INTERVAL_256_FRAMES 256 - - void scrollRight(uint8_t start, uint8_t stop, uint8_t interval) - { - m_device.scroll(SCROLL_RIGHT, start, stop, interval); - } - - /////////////////////////////////////////////////////////////////////// - // scrollVertRight() - // - // This method is called to start the device scrolling the displayed graphics verticall and to the right. - // This action is performed immediately. - // - // The screen will scroll until the scrollStop() method is called. - // - // Parameter Description - // --------- ----------------------------- - // start The start page address of the scroll - valid values are 0 thru 7 - // stop The stop/end page address of the scroll - valid values are 0 thru 7 - // interval The time interval between scroll step - values listed in scrollRight() - - void scrollVertRight(uint8_t start, uint8_t stop, uint8_t interval) - { - m_device.scroll(SCROLL_VERT_RIGHT, start, stop, interval); - } - - /////////////////////////////////////////////////////////////////////// - // scrollLeft() - // - // This method is called start to the device scrolling the displayed graphics to the left. - // This action is performed immediately. - // - // The screen will scroll until the scrollStop() method is called. - // - // Parameter Description - // --------- ----------------------------- - // start The start page address of the scroll - valid values are 0 thru 7 - // stop The stop/end page address of the scroll - valid values are 0 thru 7 - // interval The time interval between scroll step - values listed in scrollRight() - - void scrollLeft(uint8_t start, uint8_t stop, uint8_t interval) - { - m_device.scroll(SCROLL_LEFT, start, stop, interval); - } - - /////////////////////////////////////////////////////////////////////// - // scrollVertLeft() - // - // This method is called to start the device scrolling the displayed graphics verticall and to the left. - // This action is performed immediately. - // - // The screen will scroll until the scrollStop() method is called. - // - // Parameter Description - // --------- ----------------------------- - // start The start page address of the scroll - valid values are 0 thru 7 - // stop The stop/end page address of the scroll - valid values are 0 thru 7 - // interval The time interval between scroll step - values listed in scrollRight() - - void scrollVertLeft(uint8_t start, uint8_t stop, uint8_t interval) - { - m_device.scroll(SCROLL_VERT_LEFT, start, stop, interval); - } - - /////////////////////////////////////////////////////////////////////// - // displayPower() - // - // Used to turn the OLED display on an off. - // - // Default value is on. - // - // Parameter Description - // --------- ----------------------------- - // enable Turn the display on or off - default is on - - void displayPower(bool enable = true) - { - - m_device.displayPower(enable); - } - /////////////////////////////////////////////////////////////////////// - // setFont() - // - // This method is called to set the current font in the library. The current font is used - // when calling the text() method on this device. - // - // The default font for the device is 5x7. - // - // Parameter Description - // --------- ----------------------------- - // theFont The font to set as current in the device. A Font object or pointer is accepted - // - // For the library, fonts are added to your program by including them via include files which - // are part of this library. - // - // The following fonts are included: - // - // Font Include File Font Variable Description - // ----------- --------------------- ---------------- --------------------- - // 5x7 QW_FONT_5X7 A full, 5 x 7 font - // 31x48 QW_FONT_31X48 A full, 31 x 48 font - // Seven Segment QW_FONT_7SEGMENT Numbers only - // 8x16 QW_FONT_8X16 A full, 8 x 16 font - // Large Numbers QW_FONT_LARGENUM Numbers only - // - // For each font, the font variables are objects with the following attributes: - // - // Attribute Value - // ---------- ------------------------------------- - // width The font width in pixels - // height The font height in pixels - // start The font start character offset - // n_chars The number of characters - // map_width The width of the font map - // - // Example use of a font object attribute: - // - // #include - // - // int myFontWidth = QW_FONT_31X48.width; - // - - void setFont(QwiicFont &theFont) - { - m_device.setFont(theFont); - } - void setFont(const QwiicFont *theFont) - { - m_device.setFont(theFont); - } - - /////////////////////////////////////////////////////////////////////// - // getFont() - // - // This method returns the current font for the device. - // - // Parameter Description - // --------- ----------------------------- - // retval A pointer to the current font. See setFont() for font object details. - - QwiicFont *getFont(void) - { - return m_device.font(); - } - - /////////////////////////////////////////////////////////////////////// - // getFontName() - // - // This method returns the name of the current font for the device. - - String getFontName(void) - { - QwiicFont *pFont = m_device.font(); - - if (!pFont) - return String(""); - - return String(pFont->name); - } - /////////////////////////////////////////////////////////////////////// - // getStringWidth() - // - // Returns the width of the provide string using the current font. - // - // Parameter Description - // --------- ----------------------------- - // text The string used to determine width - // retval The width of the provide string, as determined using the current font. - - unsigned int getStringWidth(String &text) - { - return getStringWidth(text.c_str()); - } - - unsigned int getStringWidth(const char *text) - { - - uint16_t height, width; - - return (m_device.getStringSize(text, width, height) ? width : 0); - } - - /////////////////////////////////////////////////////////////////////// - // getStringHeight() - // - // Returns the height of the provide string using the current font. - // - // Parameter Description - // --------- ----------------------------- - // text The string used to determine height - // retval The height of the provide string, as determined using the current font. - - unsigned int getStringHeight(String &text) - { - return getStringHeight(text.c_str()); - } - - unsigned int getStringHeight(const char *text) - { - - uint16_t height, width; - - return (m_device.getStringSize(text, width, height) ? height : 0); - } - /////////////////////////////////////////////////////////////////////// - // setDrawMode() - // - // This method sets the current draw mode for the library. The draw mode - // determines how pixels are set on the screen during drawing operations. - // - // Parameter Description - // --------- ----------------------------- - // rop The raster operation (ROP) to set the graphics system to. - // - // Raster operations device how source (pixels to draw) are represented on the - // destination device. The available Raster Operation (ROP) codes are: - // - // ROP Code Description - // --------- ------------------------------------- - // grROPCopy default Drawn pixel values are copied to the device screen - // grROPNotCopy A not operation is applied to the source value before copying to screen - // grROPNot A not operation is applied to the destination (screen) value - // grROPXOR A XOR operation is performed between the source and destination values - // grROPBlack A value of 0, or black is drawn to the destination - // grROPWhite A value of 1, or black is drawn to the destination - - void setDrawMode(grRasterOp_t rop) - { - m_device.setRasterOp(rop); - } - - /////////////////////////////////////////////////////////////////////// - // setDrawMode() - // - // This method returns the current draw mode for the library. The draw mode - // determines how pixels are set on the screen during drawing operations. - // - // Parameter Description - // --------- ----------------------------- - // retval The current aster operation (ROP) of the graphics system. - - grRasterOp_t getDrawMode(void) - { - return m_device.rasterOp(); - } - - /////////////////////////////////////////////////////////////////////// - // Drawing methods - /////////////////////////////////////////////////////////////////////// - // - // pixel() - // - // Set the value of a pixel on the screen. - // - // Parameter Description - // --------- ----------------------------- - // x The X coordinate of the pixel to set - // y The Y coordinate of the pixel to set - // clr optional The color value to set the pixel. This defaults to white (1). - - void pixel(uint8_t x, uint8_t y, uint8_t clr = COLOR_WHITE) - { - m_device.pixel(x, y, clr); - } - - /////////////////////////////////////////////////////////////////////// - // line() - // - // Draw a line on the screen. - // - // Note: If a line is horizontal (y0 = y1) or vertical (x0 = x1), optimized - // draw algorithms are used by the library. - // - // Parameter Description - // --------- ----------------------------- - // x0 The start X coordinate of the line - // y0 The start Y coordinate of the line - // x1 The end X coordinate of the line - // y1 The end Y coordinate of the line - // clr optional The color value to draw the line. This defaults to white (1). - - void line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr = COLOR_WHITE) - { - m_device.line(x0, y0, x1, y1, clr); - } - - /////////////////////////////////////////////////////////////////////// - // rectangle() - // - // Draw a rectangle on the screen. - // - // Parameter Description - // --------- ----------------------------- - // x0 The start X coordinate of the rectangle - upper left corner - // y0 The start Y coordinate of the rectangle - upper left corner - // width The width of the rectangle - // height The height of the rectangle - // clr optional The color value to draw the rectangle. This defaults to white (1). - - void rectangle(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr = COLOR_WHITE) - { - m_device.rectangle(x0, y0, width, height, clr); - } - - /////////////////////////////////////////////////////////////////////// - // rectangleFill() - // - // Draw a filled rectangle on the screen. - // - // Parameter Description - // --------- ----------------------------- - // x0 The start X coordinate of the rectangle - upper left corner - // y0 The start Y coordinate of the rectangle - upper left corner - // width The width of the rectangle - // height The height of the rectangle - // clr optional The color value to draw the filled rectangle. This defaults to white (1). - - void rectangleFill(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr = COLOR_WHITE) - { - m_device.rectangleFill(x0, y0, width, height, clr); - } - - /////////////////////////////////////////////////////////////////////// - // circle() - // - // Draw a circle on the screen. - // - // Parameter Description - // --------- ----------------------------- - // x0 The X coordinate of the circle center - // y0 The Y coordinate of the circle center - // radius The radius of the circle - // clr optional The color value to draw the circle. This defaults to white (1). - - void circle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr = COLOR_WHITE) - { - m_device.circle(x0, y0, radius, clr); - } - - /////////////////////////////////////////////////////////////////////// - // circleFill() - // - // Draw a circle on the screen. - // - // Parameter Description - // --------- ----------------------------- - // x0 The X coordinate of the circle center - // y0 The Y coordinate of the circle center - // radius The radius of the circle - // clr optional The color value to draw the circle. This defaults to white (1). - - void circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr = COLOR_WHITE) - { - m_device.circleFill(x0, y0, radius, clr); - } - - /////////////////////////////////////////////////////////////////////// - // bitmap() - // - // Draws a bitmap on the screen. - // - // Parameter Description - // --------- ----------------------------- - // x0 The X coordinate to place the bitmap - upper left corner - // y0 The Y coordinate to place the bitmap - upper left corner - // x1 The end X coordinate of area to draw - lower right corner - // Range will not exceed bitmap width - // y1 The end Y coordinate of area to draw - lower right corner - // Range will not exceed bitmap height - // pBitmap A pointer to the bitmap array - // bmp_width The width of the bitmap - // bmp_height The height of the bitmap - - void bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height) - { - m_device.bitmap(x0, y0, x1, y1, pBitmap, bmp_width, bmp_height); - } - - /////////////////////////////////////////////////////////////////////// - // bitmap() - // - // Draws a bitmap on the screen. - // - // Parameter Description - // --------- ----------------------------- - // x0 The X coordinate to place the bitmap - upper left corner - // y0 The Y coordinate to place the bitmap - upper left corner - // pBitmap A pointer to the bitmap array - // bmp_width The width of the bitmap - // bmp_height The height of the bitmap - - void bitmap(uint8_t x0, uint8_t y0, uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height) - { - - m_device.bitmap(x0, y0, pBitmap, bmp_width, bmp_height); - } - /////////////////////////////////////////////////////////////////////// - // bitmap() - // - // Draws a bitmap object on the screen. - // - // Parameter Description - // --------- ----------------------------- - // x0 The X coordinate to place the bitmap - upper left corner - // y0 The Y coordinate to place the bitmap - upper left corner - // bitmap A bitmap object - - void bitmap(uint8_t x0, uint8_t y0, QwiicBitmap &bitmap) - { - m_device.bitmap(x0, y0, bitmap); - } - - /////////////////////////////////////////////////////////////////////// - // text() - // - // Draws a string using the current font on the screen. - // - // Parameter Description - // --------- ----------------------------- - // x0 The X coordinate to start drawing the text - // y0 The Y coordinate to start drawing the text - // text The string to draw on the screen - // clr optional The color value to draw the text. This defaults to white (1). - - void text(uint8_t x0, uint8_t y0, const char *text, uint8_t clr = COLOR_WHITE) - { - m_device.text(x0, y0, text, clr); - } - - void text(uint8_t x0, uint8_t y0, String &text, uint8_t clr = COLOR_WHITE) - { - - m_device.text(x0, y0, text.c_str(), clr); - } - - /////////////////////////////////////////////////////////////////////// - // Methods to support Arduino Print capability - /////////////////////////////////////////////////////////////////////// - // - // setCursor() - // - // This method is called set the "cursor" position in the device. The library - // supports the Arduino Print interface, enabling the use of a print() and - // println() methods. The set cursor position defines where to start text - // output for this functionality. - // - // Parameter Description - // --------- ----------------------------- - // x The X coordinate of the cursor - // y The Y coordinate of the cursor - - void setCursor(uint8_t x, uint8_t y) - { - - if (x < 0 || x >= m_device.width() || y < 0 || y >= m_device.height()) - return; - - m_cursorX = x; - m_cursorY = y; - } - - /////////////////////////////////////////////////////////////////////// - // setColor() - // - // This method is called to set the current color of the system. This is - // used by the Arduino Print interface functionality - // - // Parameter Description - // --------- ----------------------------- - // clr The color to set. 0 = black, > 0 = white - - void setColor(uint8_t clr) - { - m_color = (clr > 0 ? COLOR_WHITE : COLOR_BLACK); - } - - /////////////////////////////////////////////////////////////////////// - // getColor() - // - // This method is called to get the current color of the system. This is - // used by the Arduino Print interface functionality - // - // Parameter Description - // --------- ----------------------------- - // retval The current color. 0 = black, > 0 = white - - uint8_t getColor(void) - { - return m_color; - } - - /////////////////////////////////////////////////////////////////////// - // write() - // - // For the Arduino Print interface - // - - virtual size_t write(uint8_t theChar) - { - QwiicFont *pFont = m_device.font(); - - if (!pFont) // no Font?! No dice - return 0; - - switch (theChar) - { - case '\n': // Carriage return - m_cursorX = 0; - m_cursorY += pFont->height; - case '\r': // Line feed - do nothing - break; - default: - - char buffer[2] = {theChar, '\0'}; // text() needs a c string - m_device.text(m_cursorX, m_cursorY, buffer, m_color); - - m_cursorX += pFont->width + 1; - - if (m_cursorX > m_device.width() - pFont->width) - { // overflow - m_cursorX = 0; - m_cursorY += pFont->height; - } - break; - } - if (m_cursorY >= m_device.height()) // check for overflow - m_cursorY = 0; - - return 1; - } -}; - -/////////////////////////////////////////////////////////////////////// -// For our actual implementations - just subclass from the above Arduino template - -class QwiicMicroOLED : public QwiicOLEDBaseClass -{ - // nothing here - see above -}; - -class QwiicNarrowOLED : public QwiicOLEDBaseClass -{ - // nothing here - see above -}; - -class QwiicTransparentOLED : public QwiicOLEDBaseClass -{ - // nothing here - see above -}; - -class Qwiic1in3OLED : public QwiicOLEDBaseClass -{ - // nothing here - see above -}; - -class QwiicCustomOLED : public QwiicOLEDBaseClass -{ - public: - void setXOffset(uint8_t xOffset) - { - m_device.setXOffset(xOffset); - } - void setYOffset(uint8_t yOffset) - { - m_device.setYOffset(yOffset); - } - void setDisplayWidth(uint8_t displayWidth) - { - m_device.setDisplayWidth(displayWidth); - } - void setDisplayHeight(uint8_t displayHeight) - { - m_device.setDisplayHeight(displayHeight); - } - void setPinConfig(uint8_t pinConfig) - { - m_device.setPinConfig(pinConfig); - } - void setPreCharge(uint8_t preCharge) - { - m_device.setPreCharge(preCharge); - } - void setVcomDeselect(uint8_t vcomDeselect) - { - m_device.setVcomDeselect(vcomDeselect); - } - void setContrast(uint8_t contrast) - { - m_device.setContrast(contrast); - } -}; diff --git a/src/qwiic_grbuffer.cpp b/src/qwiic_grbuffer.cpp deleted file mode 100644 index 7f7c42e..0000000 --- a/src/qwiic_grbuffer.cpp +++ /dev/null @@ -1,655 +0,0 @@ - -// qwiic_grbuffer.cpp -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -//////////////////////////////////////////////////////////////////////////////////// -// Overview: -// -// Buffer graphics device implementation. -// -// The buffer device implements a base graphics class for this library, providing device setup -// and raster-based graphic commands that provide base functionality. -// -// A subclass is required to use this class. At a minimum, the subclass must implement a -// drawPixel() method, which the graphics routines in this class use to render graphics. -// -// This class also performs runtime object vtable inspection to determine the methods -// to call for drawing, and set fallbacks as needed. The vtable is mapped to a draw -// interface structure, which is used to call the desired graphics operations. Besides -// providing flexiblity, this implementation might provide a slight performance gain -// for virtual method dispatch. -// - -#include "qwiic_grbuffer.h" -#include -#include -#include - -// default font -#include "res/qw_fnt_5x7.h" - -// Handy helper -const uint8_t byte_bits[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; - -//////////////////////////////////////////////////////////////////////////////////// -// vTable/IDraw Interface Routines -//////////////////////////////////////////////////////////////////////////////////// -// Support for our drawing interface/vtable inspection -// -// function to get the vTable from an object reference - -_QwIDraw_vtable *GetIDrawVTable(_QwIDraw *obj) -{ - _QwIDraw_vtable **vtable_ptr = (_QwIDraw_vtable **)obj; - return *vtable_ptr; -} - -//////////////////////////////////////////////////////////////////////////////////// -// initDrawFunctions() -// -// This method pulls out the vtable of this object and determines what methods are -// defined in the QwIDraw interface. -// -// Using what is defined, the functions in m_idraw interface are set. This class uses -// the draw functions in this interface to skip call time vtable method lookup and call the -// target method directly. -// -// Ideally this pattern/implementation increase performace a slight bit. Also it -// allows runtime method implementation determination in this class, which can then -// setup fallbacks if need. -// - -bool QwGrBufferDevice::initDrawFunctions(void) -{ - // Get our vtable, and that of a null _QwIDraw object/interface. - // Use these to determine if a method was overriden/implemented and - // set defaults ... etc - - _QwIDraw null_obj_; // dummy object - - // copy in the vtable to our draw interface - m_idraw = *GetIDrawVTable(this); - - // Null vtable - has defaults setup - _QwIDraw_vtable *null_vtable = GetIDrawVTable(&null_obj_); - - // Review implemented methods - take actions as needed - - // If we don't have a pixel set method, this is a fatal error - if (m_idraw.drawPixel == null_vtable->drawPixel) - { - // ERROR - drawPixel is required - fprintf(stderr, "[ERROR][QwGrBufferDevice] Render class must implement drawPixel method\n"); - return false; - } - - // If the horz line function wasn't implemented (function pointer == null function) = set it to line - - if (m_idraw.drawLineHorz == null_vtable->drawLineHorz) - m_idraw.drawLineHorz = m_idraw.drawLine; - - // If the vert line function wasn't implemented (function pointer == null function) = set it to line - if (m_idraw.drawLineVert == null_vtable->drawLineVert) - m_idraw.drawLineVert = m_idraw.drawLine; - - // if rect_filled isn't implemented, just sub in rect - it' something ... - if (m_idraw.drawRectFilled == null_vtable->drawRectFilled) - m_idraw.drawRectFilled = m_idraw.drawRect; - - // if circle_filled isn't implemented, just sub in circle - it' something ... - if (m_idraw.drawCircleFilled == null_vtable->drawCircleFilled) - m_idraw.drawCircleFilled = m_idraw.drawCircle; - - return true; -} -//////////////////////////////////////////////////////////////////////////////////// -// init() -// -// Intialize the class. User called as part of the startup process of the library. -// - -bool QwGrBufferDevice::init(void) -{ - // Initialize our Font - initFont(); - - // setup the draw function table and return status - - return initDrawFunctions(); -} -//////////////////////////////////////////////////////////////////////////////////// -// Font related things -//////////////////////////////////////////////////////////////////////////////////// -// initFont() -// -// Set the default font if one hasn't been set yet - -void QwGrBufferDevice::initFont(void) -{ - if (!m_currentFont) - m_currentFont = &QW_FONT_5X7; -} -//////////////////////////////////////////////////////////////////////////////////// -// font() -// -// Return the current font. - -QwFont *QwGrBufferDevice::font(void) -{ - if (m_currentFont == nullptr) // device hasn't been init'd - maybe ? Go default - initFont(); - - return m_currentFont; -} - -//////////////////////////////////////////////////////////////////////////////////////// -// seFont() -// -// Object ref version - -void QwGrBufferDevice::setFont(QwFont &font) -{ - // just call the pointer version of this method - setFont(&font); -} -//////////////////////////////////////////////////////////////////////////////////////// -// setFont() -// -// Object pointer version - -void QwGrBufferDevice::setFont(const QwFont *font) -{ - if (font) - m_currentFont = (QwFont *)font; - else if (!m_currentFont) // null passed, we have no default set - init font. - initFont(); -} - -//////////////////////////////////////////////////////////////////////////////////////// -// get_string_size() -// -// Return the size (width, height) in pixels of the given string using the current font - -bool QwGrBufferDevice::getStringSize(const char *text, uint16_t &width, uint16_t &height) -{ - if (!m_currentFont) // no font? - initFont(); - - // no font, no text - no dice - if (!m_currentFont || !text) - return false; - - int sLen = strlen(text); - - width = sLen * m_currentFont->width; - - // The 5x7 font width is off by one - historical - was same in orig lib, which fonts - // are used. - if (m_currentFont == &QW_FONT_5X7) - width += sLen; - - height = (sLen > 0 ? m_currentFont->height : 0); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////// -// Public Graphics Methods -//////////////////////////////////////////////////////////////////////////////////////// -// -// pixel() -// -// Set a pixel on the screen - -void QwGrBufferDevice::pixel(uint8_t x, uint8_t y, uint8_t clr) -{ - // in range? - if (x >= m_viewport.width || y >= m_viewport.height) - return; - - // Call the pixel draw method in the draw interface. - (*m_idraw.drawPixel)(this, x, y, clr); -} -//////////////////////////////////////////////////////////////////////////////////////// -// line() -// -// Method that rasterizes a line, setting pixels in the buffer device via -// the pixel command. -// -// Parameters -// -// (x0, y0) - Line origin -// (x1, y1) - Line end - -void QwGrBufferDevice::line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr) -{ - // if we have a vertical or horizonal line, call the optimized drawing functions - - if (x0 == x1) - (*m_idraw.drawLineVert)(this, x0, y0, x1, y1, clr); - else if (y0 == y1) - (*m_idraw.drawLineHorz)(this, x0, y0, x1, y1, clr); - else - (*m_idraw.drawLine)(this, x0, y0, x1, y1, clr); -} - -////////////////////////////////////////////////////////////////////////////////////////// -// drawLine() -// -// Core, internal line drawing method - performs a line rasterization algorithm - -void QwGrBufferDevice::drawLine(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr) -{ - // The rasterization method uses an increment of 1 to walk the desired line - // to determine which pixels are being set in the buffer device. - // - // To ensure a detailed rasterization, the dimention with the largest value is used. - - // deltas for each dimension - uint8_t dx = abs(x1 - x0); - uint8_t dy = abs(y1 - y0); - - // zero len line - turns out that's a point - if (!dx && !dy) - { - (*m_idraw.drawPixel)(this, x0, y0, clr); - return; - } - // If this is a steep line, switch the axis to increment along - bool isSteep = dy > dx; - - if (isSteep) - { - swap_int(x0, y0); - swap_int(x1, y1); - swap_int(dx, dy); - } - - // let's be positive about our increment - if negative, swap our vertex - if (x0 > x1) - { - swap_int(x0, x1); - swap_int(y0, y1); - } - - // value used to determine when to bump up Y as we walk the line - int8_t err = dx / 2; - int8_t ystep = y0 < y1 ? 1 : -1; // is y going up or down? - - // Crank over our x range of the line and draw our pixels - for (; x0 <= x1; x0++) - { - - if (isSteep) - (*m_idraw.drawPixel)(this, y0, x0, clr); - else - (*m_idraw.drawPixel)(this, x0, y0, clr); - - // do we need to bump up y? or if the slow is shallow, stay of - // the same value? - err -= dy; - if (err < 0) - { - y0 += ystep; - err += dx; - } - } -} -//////////////////////////////////////////////////////////////////////////////////////// -// rectangle() -// -// Draw a rectangle on screen. - -void QwGrBufferDevice::rectangle(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr) -{ - // Is this a line? - if (width <= 1 || height <= 1) - { - // this is a line - line(x0, y0, x0 + width - 1, y0 + height - 1); - return; - } - - // bounds check - if (x0 >= m_viewport.width || y0 >= m_viewport.height) - return; // not on screen - - // Send to drawing routine. - - (*m_idraw.drawRect)(this, x0, y0, width, height, clr); -} - -//////////////////////////////////////////////////////////////////////////////////////// -// drawRect() -// -// Does the actual drawing/logic - -void QwGrBufferDevice::drawRect(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr) -{ - // A rect is really just a series of vert and horz lines - - uint8_t x1 = x0 + width - 1; - uint8_t y1 = y0 + height - 1; - - (*m_idraw.drawLineHorz)(this, x0, y0, x1, y0, clr); - (*m_idraw.drawLineHorz)(this, x0, y1, x1, y1, clr); - - // If the height is less than 2, no need for vert lines b/c the line itself is 1 pixel - - if (y1 - y0 < 3) - return; - - // Vertical lines - note - do not draw over our horz lines b/c of potential xor turds - (*m_idraw.drawLineVert)(this, x0, y0 + 1, x0, y1, clr); - (*m_idraw.drawLineVert)(this, x1, y0 + 1, x1, y1, clr); -} -//////////////////////////////////////////////////////////////////////////////////////// -// rectangleFill() - -void QwGrBufferDevice::rectangleFill(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr) -{ - // Is this a line? - if (width <= 1 || height <= 1) - { - // this is a line - line(x0, y0, x0 + width - 1, y0 + height - 1); - return; - } - // bounds check - if (x0 >= m_viewport.width || y0 >= m_viewport.height) - return; // not on screen - - // Send to drawing routine. - - (*m_idraw.drawRectFilled)(this, x0, y0, width, height, clr); -} -//////////////////////////////////////////////////////////////////////////////////////// -// drawRectFill() -// -// Does the actual drawing/logic - -void QwGrBufferDevice::drawRectFilled(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr) -{ - uint8_t x1 = x0 + width - 1; - uint8_t y1 = y0 + height - 1; - - // Just draw vertical lines - for (int i = x0; i <= x1; i++) - (*m_idraw.drawLineVert)(this, i, y0, i, y1, clr); -} -//////////////////////////////////////////////////////////////////////////////////////// -// circle() -// - -void QwGrBufferDevice::circle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr) -{ - // Anything visible on screen? - if (!radius || x0 - (int8_t)radius >= m_viewport.width || y0 - (int8_t)radius >= m_viewport.height) - return; - - // Is this just a pixel - if (radius == 1) - { - (*m_idraw.drawPixel)(this, x0, y0, clr); - return; - } - - (*m_idraw.drawCircle)(this, x0, y0, radius, clr); -} -//////////////////////////////////////////////////////////////////////////////////////// -// drawCircle() -// -// Draw a circle - -void QwGrBufferDevice::drawCircle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr) -{ - int8_t f = 1 - radius; - int8_t ddF_x = 1; - int8_t ddF_y = -2 * radius; - int8_t x = 0; - int8_t y = radius; - - (*m_idraw.drawPixel)(this, x0, y0 + radius, clr); - (*m_idraw.drawPixel)(this, x0, y0 - radius, clr); - (*m_idraw.drawPixel)(this, x0 + radius, y0, clr); - (*m_idraw.drawPixel)(this, x0 - radius, y0, clr); - - while (x < y) - { - - if (f >= 0) - { - y--; - ddF_y += 2; - f += ddF_y; - } - x++; - ddF_x += 2; - f += ddF_x; - - (*m_idraw.drawPixel)(this, x0 + x, y0 + y, clr); - (*m_idraw.drawPixel)(this, x0 - x, y0 + y, clr); - (*m_idraw.drawPixel)(this, x0 + x, y0 - y, clr); - (*m_idraw.drawPixel)(this, x0 - x, y0 - y, clr); - - (*m_idraw.drawPixel)(this, x0 + y, y0 + x, clr); - (*m_idraw.drawPixel)(this, x0 - y, y0 + x, clr); - (*m_idraw.drawPixel)(this, x0 + y, y0 - x, clr); - (*m_idraw.drawPixel)(this, x0 - y, y0 - x, clr); - } -} -//////////////////////////////////////////////////////////////////////////////////////// -// circle_fill() -// -// Draw a filled circle - -void QwGrBufferDevice::circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr) -{ - // Anything visible on screen? - if (!radius || x0 - (int8_t)radius >= m_viewport.width || y0 - (int8_t)radius >= m_viewport.height) - return; - - if (radius == 1) - { - (*m_idraw.drawPixel)(this, x0, y0, clr); - return; - } - - (*m_idraw.drawCircleFilled)(this, x0, y0, radius, clr); -} - -//////////////////////////////////////////////////////////////////////////////////////// -// drawCircleFilled() -// -void QwGrBufferDevice::drawCircleFilled(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr) -{ - int8_t f = 1 - radius; - int8_t ddF_x = 1; - int8_t ddF_y = -2 * radius; - int8_t x = 0; - int8_t y = radius; - - (*m_idraw.drawLineVert)(this, x0, y0 - radius, x0, y0 + radius, clr); - - while (x < y) - { - - if (f >= 0) - { - y--; - ddF_y += 2; - f += ddF_y; - } - x++; - ddF_x += 2; - f += ddF_x; - - (*m_idraw.drawLineVert)(this, x0 + x, y0 - y, x0 + x, y0 + y, clr); - (*m_idraw.drawLineVert)(this, x0 - x, y0 - y, x0 - x, y0 + y, clr); - - (*m_idraw.drawLineVert)(this, x0 + y, y0 - x, x0 + y, y0 + x, clr); - (*m_idraw.drawLineVert)(this, x0 - y, y0 - x, x0 - y, y0 + x, clr); - } -} -//////////////////////////////////////////////////////////////////////////////////////// -// bitmap() -// -// Draw a bitmap on the screen - -void QwGrBufferDevice::bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t *pBitmap, uint8_t bmp_width, - uint8_t bmp_height) -{ - (*m_idraw.drawBitmap)(this, x0, y0, x1, y1, pBitmap, bmp_width, bmp_height); -} - -//////////////////////////////////////////////////////////////////////////////////////// -// bitmap() -// -// Draw a bitmap on the screen - -void QwGrBufferDevice::bitmap(uint8_t x0, uint8_t y0, uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height) -{ - (*m_idraw.drawBitmap)(this, x0, y0, bmp_width, bmp_height, pBitmap, bmp_width, bmp_height); -} - -//////////////////////////////////////////////////////////////////////////////////////// -// bitmap() - use a bitmap object -// -void QwGrBufferDevice::bitmap(uint8_t x0, uint8_t y0, QwBitmap &theBMP) -{ - // just pass to graphics device - (*m_idraw.drawBitmap)(this, x0, y0, theBMP.width, theBMP.height, (uint8_t *)theBMP.data(), theBMP.width, - theBMP.height); -} -//////////////////////////////////////////////////////////////////////////////////////// -// text() -// -// Draw a string on the screen using the current font - -void QwGrBufferDevice::text(uint8_t x0, uint8_t y0, const char *text, uint8_t clr) -{ - if (!text || x0 >= m_viewport.width || y0 >= m_viewport.height) - return; - - (m_idraw.drawText)(this, x0, y0, text, clr); -} -//////////////////////////////////////////////////////////////////////////////////////// -// draw_test() -// -// Draw text - one pixel at a time. Based on the algorithm in the Micro OLED -// Arduino library -// -void QwGrBufferDevice::drawText(uint8_t x0, uint8_t y0, const char *text, uint8_t clr) -{ - // check things - if (!m_currentFont || !text) - return; - - int slen = strlen(text); - - if (!slen) // empty string? - return; - - uint8_t nRows = m_currentFont->height / kByteNBits; - if (!nRows) - nRows = 1; - - // 5x7 font is special - need to add a margin - uint8_t margin5x7 = (nRows == 1); // For the 5x7 font - - // used in loop - uint16_t nRowLen = m_currentFont->map_width / m_currentFont->width; // how long is a - uint16_t rowBytes = m_currentFont->map_width * nRows; - - // get font data - const uint8_t *pFont = m_currentFont->data(); - - // vars for the loops ... - uint16_t charOffset, fontIndex; - uint8_t rowOffset, currChar, i, j, row; - - // walk the string ... note: doing all loop incs here - to handle continue statement below - - for (int k = 0; k < slen; k++, text++, x0 += m_currentFont->width + margin5x7) - { - - // index into the font data - takes into account font size, rows span ... etc - charOffset = *text - m_currentFont->start; - - // does the char location exceed the number of chars in the font? - if (charOffset >= m_currentFont->n_chars) - continue; // neeeexxxtt! - - // offset into the font data array - start location - fontIndex = (charOffset / nRowLen * rowBytes) + ((charOffset % nRowLen) * m_currentFont->width); - - // Now walk the rows of this font entry (it can span bytes) - for (row = 0; row < nRows; row++) - { - - rowOffset = row * kByteNBits; // y offset for multi row fonts - used in pixel draw - - // walk the width of the font - for (i = 0; i < m_currentFont->width + margin5x7; i++) - { - - // this is done in a weird way because the 5x7 font has no margin - if (margin5x7 && i == m_currentFont->width) - continue; // skip to next - - // finally - data! - currChar = pgm_read_byte(pFont + fontIndex + i + (row * m_currentFont->map_width)); - - // draw bits - for (j = 0; j < kByteNBits; j++) - if (currChar & byte_bits[j]) - (*m_idraw.drawPixel)(this, x0 + i, y0 + j + rowOffset, clr); - - } // walk font width - - } // row loop - - } // string loop -} diff --git a/src/qwiic_grbuffer.h b/src/qwiic_grbuffer.h deleted file mode 100644 index 5d5fe48..0000000 --- a/src/qwiic_grbuffer.h +++ /dev/null @@ -1,280 +0,0 @@ - -// qwiic_grbuffer.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. -// - -// A Graphics System base class for qwiic display devices - simple bmp based devices. - -#pragma once - -// required on some platforms -#include - -// Include resource definitions -#include "res/qwiic_resdef.h" - -// RECT! -struct QwRect -{ - uint16_t x; - uint16_t y; - uint16_t width; - uint16_t height; -}; - -////////////////////////////////////////////////////////////////////////////////// -// Utils -// -// Bit level tools/helpers -// -// Handy const = save some compute used bit shifting -extern const uint8_t byte_bits[8]; - -// something more readable -#define kByteNBits 8 - -// Mod 8 is really just the lower 3 bits of a value. This might be faster than -// standard mod operator - maybe -#define mod_byte(_value_) (_value_ & 0x07) - -// Some rouintes need a int swap function. Many ways to do this- all the cool kids -// use bitwise ops - namely the xor. -// -#define swap_int(_a_, _b_) (((_a_) ^= (_b_)), ((_b_) ^= (_a_)), ((_a_) ^= (_b_))) - -/////////////////////////////////////////////////////////////////////////////////////////// -// _QwIDraw -// -// IDraw interface for the graphics system. Defines methods used to draw 2D primatives. -// -// Seperated out to enable easy vtable access and method dispatch short circuiting - -class _QwIDraw -{ - - // Pixel Methods - virtual void drawPixel(uint8_t x, uint8_t y, uint8_t clr) - { - } // A subclass must implement this - - // Line Methods - virtual void drawLine(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr) - { - } - virtual void drawLineHorz(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr) - { - } - virtual void drawLineVert(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr) - { - } - - // Rectangles - virtual void drawRect(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr) - { - } - virtual void drawRectFilled(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr) - { - } - - // Circles - virtual void drawCircle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr) - { - } - virtual void drawCircleFilled(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr) - { - } - - // Bitmaps - virtual void drawBitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t *pBitmap, uint8_t bmp_width, - uint8_t bmp_height) - { - } - - virtual void drawText(uint8_t x0, uint8_t y0, const char *text, uint8_t clr) - { - } -}; - -// Drawing fuction typedefs -typedef void (*QwDrawPntFn)(void *, uint8_t, uint8_t, uint8_t); -typedef void (*QwDrawTwoPntFn)(void *, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t); -typedef void (*QwDrawCircleFn)(void *, uint8_t, uint8_t, uint8_t, uint8_t); -typedef void (*QwDrawBitmapFn)(void *, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t *, uint8_t, uint8_t); -typedef void (*QwDrawTextFn)(void *, uint8_t, uint8_t, const char *, uint8_t); - -// Define the vtable struct for IDraw -struct _QwIDraw_vtable -{ - QwDrawPntFn drawPixel; - QwDrawTwoPntFn drawLine; - QwDrawTwoPntFn drawLineHorz; - QwDrawTwoPntFn drawLineVert; - QwDrawTwoPntFn drawRect; - QwDrawTwoPntFn drawRectFilled; - QwDrawCircleFn drawCircle; - QwDrawCircleFn drawCircleFilled; - QwDrawBitmapFn drawBitmap; - QwDrawTextFn drawText; -}; - -/////////////////////////////////////////////////////////////////////////////////////////// -// QwGrBufferDevice -// -// Buffer class - defines basics for a memory buffer drawing class. Note it subclasses -// from QwIDraw - -class QwGrBufferDevice : protected _QwIDraw -{ - - public: - // Constructors - QwGrBufferDevice() : m_currentFont{nullptr} {}; - QwGrBufferDevice(uint8_t width, uint8_t height) : QwGrBufferDevice(0, 0, width, height){}; - QwGrBufferDevice(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height) : QwGrBufferDevice() - { - setViewport(x0, y0, width, height); - }; - - // Buffer location on the device - void setViewport(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height) - { - m_viewport.x = x0; - m_viewport.y = y0; - m_viewport.width = width; - m_viewport.height = height; - }; - - QwRect viewport(void) - { - return m_viewport; - }; - uint16_t originX(void) - { - return m_viewport.x; - }; - uint16_t originY(void) - { - return m_viewport.y; - }; - uint16_t width(void) - { - return m_viewport.width; - }; - uint16_t height(void) - { - return m_viewport.height; - }; - - // Lifecycle - virtual bool init(void); - - // Font methods - void initFont(void); - void setFont(QwFont &font); - void setFont(const QwFont *font); - QwFont *font(void); - - // Returns the size of a string - in pixels - using current font - bool getStringSize(const char *text, uint16_t &width, uint16_t &height); - - // Public Interface - Graphics interface - void line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr = 1); - - void circle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr = 1); - void circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr = 1); - - void pixel(uint8_t x, uint8_t y, uint8_t clr = 1); - - void rectangle(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr = 1); - void rectangleFill(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr = 1); - - void bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t *pBitmap, uint8_t bmp_width, - uint8_t bmp_height); - - // draw full bitmap - void bitmap(uint8_t x0, uint8_t y0, uint8_t *pBitmap, uint8_t bmp_width, uint8_t bmp_height); - - // Bitmap draw - using a bitmap object - void bitmap(uint8_t x0, uint8_t y0, QwBitmap &bitmap); - - void text(uint8_t x0, uint8_t y0, const char *text, uint8_t clr = 1); - - // subclass interface - virtual void display(void) = 0; - virtual void erase(void) = 0; - - protected: - QwRect m_viewport; - - // Internal, fast draw routines - These implement QwIDraw - - // Pixels - // At a minimum, a sub-class must implement a pixel set function - virtual void drawPixel(uint8_t x, uint8_t y, uint8_t clr) = 0; // A subclass must implement this - - // Lines - // Sub-class implementation is optional - virtual void drawLine(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr); - - // Rects - virtual void drawRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr); - virtual void drawRectFilled(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr); - - // Circle - virtual void drawCircle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr); - virtual void drawCircleFilled(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t clr); - - // Text - virtual void drawText(uint8_t x0, uint8_t y0, const char *text, uint8_t clr); - - // Our drawing interface - open to sub-classes ... - _QwIDraw_vtable m_idraw; - - // Current Font - QwFont *m_currentFont; - - private: - bool initDrawFunctions(void); -}; \ No newline at end of file diff --git a/src/qwiic_grssd1306.cpp b/src/qwiic_grssd1306.cpp deleted file mode 100644 index ce30fca..0000000 --- a/src/qwiic_grssd1306.cpp +++ /dev/null @@ -1,1016 +0,0 @@ - -// qwiic_grssd1306.cpp -// -// This is a library written for SparkFun Qwiic OLED boards that use the -// SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT -// License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -#include "qwiic_grssd1306.h" - -///////////////////////////////////////////////////////////////////////////// -// Class that implements graphics support for devices that use the SSD1306 -// -///////////////////////////////////////////////////////////////////////////// -// Device Commands -// -// The commands are codes used to communicate with the SSD1306 device and are -// from the devices datasheet. -// - -#define kCmdSetContrast 0x81 -#define kCmdDisplayAllOnResume 0xA4 -#define kCmdDisplayAllOn 0xA5 -#define kCmdNormalDisplay 0xA6 -#define kCmdInvertDisplay 0xA7 -#define kCmdDisplayOff 0xAE -#define kCmdDisplayOn 0xAF -#define kCmdSetDisplayOffset 0xD3 -#define kCmdSetComPins 0xDA -#define kCmdSetVComDeselect 0xDB -#define kCmdSetDisplayClockDiv 0xD5 -#define kCmdSetPreCharge 0xD9 -#define kCmdSetMultiplex 0xA8 -#define kCmdSetLowColumn 0x00 -#define kCmdSetHighColumn 0x10 -#define kCmdSetStartLine 0x40 -#define kCmdMemoryMode 0x20 -#define kCmdComScanInc 0xC0 -#define kCmdComScanDec 0xC8 -#define kCmdSegRemap 0xA0 -#define kCmdChargePump 0x8D -#define kCmdExternalVCC 0x01 -#define kCmdSwitchCapVCC 0x02 -#define kCmdPageAddress 0x22 -#define kCmdColumnAddress 0x21 -#define kCmdActivateScroll 0x2F -#define kCmdDeactivateScroll 0x2E -#define kCmdSetVerticalScrollArea 0xA3 -#define kCmdRightHorizontalScroll 0x26 -#define kCmdLeftHorizontalScroll 0x27 -#define kCmdVerticalRightHorzScroll 0x29 -#define kCmdVerticalLeftHorzScroll 0x2A -#define kCmdPageModePageBase 0xB0 -#define kCmdPageModeColTopBase 0x10 -#define kCmdPageModeColLowBase 0x0F - -////////////////////////////////////////////////////////////////////////////////// -// Screen Buffer -// -// A key feature of this library is that it only sends "dirty" pixels to the -// device, minimizing data transfer over the I2C bus. To accomplish this, the -// dirty range of each graphics buffer page (see device memory layout in the -// datasheet) is maintained during drawing operation. Whe data is sent to the -// device, only the pixels in these regions are sent to the device, not the -// entire page of data. -// -// The below macros are used to manage the record keeping of dirty page ranges. -// Given that these actions are taking place in the draw loop, macros are used -// for performance considerations. -// -// These macros work with the pageState_t struct type. -// -// Define unique values just outside of the screen buffer (SSD1306) page range -// (0 base) Note: A page is 128 bits in length - -#define kPageMin -1 // outside bounds - low value -#define kPageMax 128 // outside bounds - high value - -// clean/ no settings in the page -#define pageIsClean(_page_) (_page_.xmin == kPageMax) - -// Macro to reset page descriptor -#define pageSetClean(_page_) \ - do \ - { \ - _page_.xmin = kPageMax; \ - _page_.xmax = kPageMin; \ - } while (false) - -// Macro to check and adjust record bounds based on a single location -#define pageCheckBounds(_page_, _x_) \ - do \ - { \ - if (_x_ < _page_.xmin) \ - _page_.xmin = _x_; \ - if (_x_ > _page_.xmax) \ - _page_.xmax = _x_; \ - } while (false) - -// Macro to check and adjust record bounds using another page descriptor -#define pageCheckBoundsDesc(_page_, _page2_) \ - do \ - { \ - if (_page2_.xmin < _page_.xmin) \ - _page_.xmin = _page2_.xmin; \ - if (_page2_.xmax > _page_.xmax) \ - _page_.xmax = _page2_.xmax; \ - } while (false) - -// Macro to check and adjust record bounds using bounds values -#define pageCheckBoundsRange(_page_, _x0_, _x1_) \ - do \ - { \ - if (_x0_ < _page_.xmin) \ - _page_.xmin = _x0_; \ - if (_x1_ > _page_.xmax) \ - _page_.xmax = _x1_; \ - } while (false) - -////////////////////////////////////////////////////////////////////////////////// -// Communication -// -// When communicating with the device, you either send commands or data. Define -// our codes for these two options - these are basically i2c registers/offsets. -// -// See datasheet for details -// -#define kDeviceSendCommand 0x00 -#define kDeviceSendData 0x40 - -//////////////////////////////////////////////////////////////////////////////////// -// Pixel write/set operations -// -// Using LAMBDAs to create fast raster write/set operations. Using this pattern -// eleminates the need for switch/if statements in each draw routine. This is -// basically classic ROPs' -// -// NOTE - the order in the arrays is based on grRasterOp_t enum -// -// The Graphic operator functions (ROPS) -// - Copy - copy the pixel value in to the buffer (default) -// - Not Copy - copy the not of the pixel value to buffer -// - Not - Set the buffer value to not it's current value -// - XOR - XOR of color and current pixel value -// - Black - Set value to always be black -// - White - set value to always be white - -typedef void (*rasterOPsFn)(uint8_t *dest, uint8_t src, uint8_t mask); - -static const rasterOPsFn m_rasterOps[] = { - // COPY - [](uint8_t *dst, uint8_t src, uint8_t mask) -> void { *dst = (~mask & *dst) | (src & mask); }, - // NOT COPY - [](uint8_t *dst, uint8_t src, uint8_t mask) -> void { *dst = (~mask & *dst) | ((!src) & mask); }, - // NOT DEST - [](uint8_t *dst, uint8_t src, uint8_t mask) -> void { *dst = (~mask & *dst) | ((!(*dst)) & mask); }, - // XOR - [](uint8_t *dst, uint8_t src, uint8_t mask) -> void { *dst = (~mask & *dst) | ((*dst ^ src) & mask); }, - // Always Black - [](uint8_t *dst, uint8_t src, uint8_t mask) -> void { *dst = ~mask & *dst; }, - // Always White - [](uint8_t *dst, uint8_t src, uint8_t mask) -> void { *dst = mask | *dst; }}; - -//////////////////////////////////////////////////////////////////////////////////// -// setup defaults - called from constructors -// -// Just a bunch of member variable inits - -void QwGrSSD1306::setupDefaults(void) -{ - default_address = {0}; - m_pBuffer = {nullptr}; - m_color = {1}; - m_rop = {grROPCopy}; - m_i2cBus = {nullptr}; - m_i2cAddress = {0}; - m_initHWComPins = {kDefaultPinConfig}; - m_initPreCharge = {kDefaultPreCharge}; - m_initVCOMDeselect = {kDefaultVCOMDeselect}; - m_initContrast = {kDefaultContrast}; - m_isInitialized = {false}; -} -//////////////////////////////////////////////////////////////////////////////////// -// init() -// -// Called by user when the device/system is up and ready to be "initialized." -// -// This implementation performs the basic setup for the SSD1306 device -// -// The startup sequence is as follows: -// -// - Make sure a device is connected -// - Call super class -// - Shutdown the device (display off), initial device setup, turn on -// device -// - Init the local graphics buffers/system -// -// When this method is complete, the driver and device are ready for use -// -bool QwGrSSD1306::init(void) -{ - if (m_isInitialized) - return true; - - // do we have a bus yet? Buffer? Note - buffer is set by subclass of this - // object - if (!m_i2cBus || !m_i2cAddress || !m_pBuffer) - return false; - - // Is the device connected? - if (!m_i2cBus->ping(m_i2cAddress)) - return false; - - // Super-class - if (!this->QwGrBufferDevice::init()) - return false; // something isn't right - - // setup the oled device - setupOLEDDevice(); - - // Finish up setting up this object - - // Number of pages used for this device? - m_nPages = m_viewport.height / kByteNBits; // height / number of pixels per byte. - // TODO - support multiples != 8 - - // init the graphics buffers - initBuffers(); - - m_isInitialized = true; // we're ready to rock - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////// -// reset() -// -// Return the OLED system to its initial state -// -// Returns true on success, false on failure - -bool QwGrSSD1306::reset(bool clearDisplay) -{ - // If we are not in an init state, just call init - if (!m_isInitialized) - return init(); - - // is the device connected? - if (!m_i2cBus->ping(m_i2cAddress)) - return false; - - // setup oled - setupOLEDDevice(clearDisplay); - - // Init internal/drawing buffers and device screen buffer - if (clearDisplay) - initBuffers(); - - return true; -} -//////////////////////////////////////////////////////////////////////////////////// -// Configuration API -// -// This allows sub-classes to setup for their device, while preserving -// encapsulation. -// -// These should be called/set before calling init -// -// For details of each of these settings -- see the datasheet -// -void QwGrSSD1306::setCommPins(uint8_t pin_code) -{ - m_initHWComPins = pin_code; -} - -void QwGrSSD1306::setPreCharge(uint8_t pre_charge) -{ - m_initPreCharge = pre_charge; -} - -void QwGrSSD1306::setVcomDeselect(uint8_t vcom_d) -{ - m_initVCOMDeselect = vcom_d; -} - -void QwGrSSD1306::setContrast(uint8_t contrast) -{ - if (!m_isInitialized) - m_initContrast = contrast; - else - sendDevCommand(kCmdSetContrast, contrast); -} - -//////////////////////////////////////////////////////////////////////////////////// -// setupOLEDDevice() -// -// Method sends the init/setup commands to the OLED device, placing -// it in a state for use by this driver/library. - -void QwGrSSD1306::setupOLEDDevice(bool clearDisplay) -{ - // Start the device setup - sending commands to device. See command defs in - // header, and device datasheet - if (clearDisplay) - sendDevCommand(kCmdDisplayOff); - - sendDevCommand(kCmdSetDisplayClockDiv, 0x80); - sendDevCommand(kCmdSetMultiplex, m_viewport.height - 1); - sendDevCommand(kCmdSetDisplayOffset, 0x0); - - sendDevCommand(kCmdSetStartLine | 0x0); - sendDevCommand(kCmdChargePump, 0x14); - sendDevCommand(kCmdMemoryMode, 0b10); // Page Addressing mode - - sendDevCommand(kCmdNormalDisplay); - sendDevCommand(kCmdDisplayAllOnResume); - sendDevCommand(kCmdSegRemap | 0x1); - - sendDevCommand(kCmdComScanDec); - sendDevCommand(kCmdSetComPins, m_initHWComPins); - sendDevCommand(kCmdSetContrast, m_initContrast); - - sendDevCommand(kCmdSetPreCharge, m_initPreCharge); - sendDevCommand(kCmdSetVComDeselect, m_initVCOMDeselect); - sendDevCommand(kCmdDeactivateScroll); - - if (clearDisplay) - sendDevCommand(kCmdDisplayOn); -} -//////////////////////////////////////////////////////////////////////////////////// -// setCommBus() -// -// Method to set the bus object that is used to communicate with the device -// -// TODO - In the *future*, generalize to match SDK - -void QwGrSSD1306::setCommBus(QwI2C &theBus, uint8_t id_bus) -{ - m_i2cBus = &theBus; - m_i2cAddress = id_bus; -} - -//////////////////////////////////////////////////////////////////////////////////// -// setBuffer() -// -// Protected method - used by sub-class to set the graphics buffer array. -// -// The subclass knows the size of the specific device, so it statically defines -// the graphics buffer array. The buffer is often set in the subclasses -// on_initialize() method. -// -// -void QwGrSSD1306::setBuffer(uint8_t *pBuffer) -{ - if (pBuffer) - m_pBuffer = pBuffer; -} - -//////////////////////////////////////////////////////////////////////////////////// -// clearScreenBuffer() -// -// Clear out all the on-device memory. -// -void QwGrSSD1306::clearScreenBuffer(void) -{ - // Clear out the screen buffer on the device - uint8_t emptyPage[kPageMax] = {0}; - - for (int i = 0; i < kMaxPageNumber; i++) - { - setScreenBufferAddress(i, 0); // start of page - sendDevData((uint8_t *)emptyPage, kPageMax); // clear out page - } -} -//////////////////////////////////////////////////////////////////////////////////// -// initBuffers() -// -// Will clear the local graphics buffer, and the devices screen buffer. Also -// resets page state descriptors to a "clean" state. - -void QwGrSSD1306::initBuffers(void) -{ - int i; - - // clear out the local graphics buffer - if (m_pBuffer) - memset(m_pBuffer, 0, m_viewport.width * m_nPages); - - // Set page descs to "clean" state - for (i = 0; i < m_nPages; i++) - { - pageSetClean(m_pageState[i]); - pageSetClean(m_pageErase[i]); - } - - m_pendingErase = false; - - // clear out the screen buffer - clearScreenBuffer(); -} -//////////////////////////////////////////////////////////////////////////////////// -// resendGraphics() -// -// Re-send the region in the graphics buffer (local) that contains drawn -// graphics. This region is defined by the contents of the m_pageErase -// descriptors. -// -// Copy these to the page state, and call display -// - -void QwGrSSD1306::resendGraphics(void) -{ - // Set the page state dirty bounds to the bounds of erase state - for (int i = 0; i < m_nPages; i++) - m_pageState[i] = m_pageErase[i]; - - display(); // push bits to screen buffer -} -//////////////////////////////////////////////////////////////////////////////////// -// Screen Control -//////////////////////////////////////////////////////////////////////////////////// -// flip_vert() -// -// Flip the onscreen graphics vertically. - -void QwGrSSD1306::flipVert(bool bFlip) -{ - sendDevCommand((bFlip ? kCmdComScanInc : kCmdComScanDec)); -} -//////////////////////////////////////////////////////////////////////////////////// -// flip_horz() -// -// Flip the onscreen graphcis horizontally. This requires a resend of the -// graphics data to the device/screen buffer. -// - -void QwGrSSD1306::flipHorz(bool bFlip) -{ - sendDevCommand(kCmdSegRemap | (bFlip ? 0x0 : 0x1)); - clearScreenBuffer(); - resendGraphics(); -} -//////////////////////////////////////////////////////////////////////////////////// -// invert() -// -// Inverts the display contents on device -// - -void QwGrSSD1306::invert(bool bInvert) -{ - sendDevCommand((bInvert ? kCmdInvertDisplay : kCmdNormalDisplay)); -} - -//////////////////////////////////////////////////////////////////////////////////// -void QwGrSSD1306::stopScroll(void) -{ - sendDevCommand(kCmdDeactivateScroll); - - // After sending a deactivate command, the ram data in the device needs to be - // re-written. See datasheet - // - // First clear out the entire screen buffer (on device mem). The device uses - // this off screen area to scroll - if you don't erase it, when scroll starts - // back up, old graphics turds will appear ... - // - // Second - Send over the graphics again to the display - - clearScreenBuffer(); - resendGraphics(); -} - -//////////////////////////////////////////////////////////////////////////////////// -// scroll() -// -// Set scroll parametes on the device and start scrolling -// -void QwGrSSD1306::scroll(uint16_t scroll_type, uint8_t start, uint8_t stop, uint8_t interval) -{ - // parameter sanity? - if (stop < start) - return; - - // Setup a default command list - uint8_t n_commands = 7; - uint8_t commands[7] = {kCmdRightHorizontalScroll, // default scroll right - 0x00, // dummy byte - start, // start page address - interval, // interval between scroll steps - in terms of frame fequency - stop, // end page address - 0x00, // dummy byte for non vert, for vert it's scroll offset - 0xFF}; // Dummy byte for non vert - set to FFX, not used for vert. - - // Which way to scroll - switch (scroll_type) - { - case SCROLL_RIGHT: - break; // set in initializer of command array - case SCROLL_LEFT: - commands[0] = kCmdLeftHorizontalScroll; - break; - case SCROLL_VERT_LEFT: - commands[0] = kCmdVerticalLeftHorzScroll; - break; - case SCROLL_VERT_RIGHT: - commands[0] = kCmdVerticalRightHorzScroll; - break; - } - - // If we are scrolling vertically, modify the command list, and set the - // vertical scroll area on display - if (scroll_type & SCROLL_VERTICAL) - { - commands[5] = 0x01; // set the scrolling offset - n_commands--; // don't use the last byte of command buffer - - // Set on display scroll area - sendDevCommand(kCmdSetVerticalScrollArea, 0x00); - sendDevCommand(m_viewport.height); - } - - // send the scroll commands to the device - - // Do not use scroll_stop() - that method resets the display - memory ...etc - - // to it's start state - the graphics displayed before scrolling was initially - // started. - // - // Here, we just stop scrolling and keep device memory state as is. This - // allows scrolling to change paraterms during a scroll session - gives a - // smooth presentation on screen. - sendDevCommand(kCmdDeactivateScroll); - sendDevCommand(commands, n_commands); - sendDevCommand(kCmdActivateScroll); -} - -//////////////////////////////////////////////////////////////////////////////////// -// displayPower() -// -// Used to set the power of the screen. - -void QwGrSSD1306::displayPower(bool enable) -{ - if (!m_isInitialized) - return; - - sendDevCommand((enable ? kCmdDisplayOn : kCmdDisplayOff)); -} -//////////////////////////////////////////////////////////////////////////////////// -// Drawing Methods -//////////////////////////////////////////////////////////////////////////////////// -// erase() -// -// Erase the graphics that are on screen and anything that's been draw but -// haven't been sent to the screen. -// - -void QwGrSSD1306::erase(void) -{ - if (!m_pBuffer) - return; - - // Cleanup the dirty parts of each page in the graphics buffer. - for (uint8_t i = 0; i < m_nPages; i++) - { - // m_pageState - // The current "dirty" areas of the graphics [local] buffer. - // Areas that haven't been sent to the screen/device but are - // "dirty" - // - // Add the areas with pixels set and have been sent to the - // device - this is the contents of m_pageErase - - pageCheckBoundsDesc(m_pageState[i], m_pageErase[i]); - - // if this page is clean, there is nothing to update - if (pageIsClean(m_pageState[i])) - continue; - - // clear out memory that is dirty on this page - memset(m_pBuffer + i * m_viewport.width + m_pageState[i].xmin, 0, - m_pageState[i].xmax - m_pageState[i].xmin + 1); // add one b/c values are 0 based - - // clear out any pending dirty range for this page - it's erased - pageSetClean(m_pageState[i]); - } - - // Indicate that the data transfer to the device should include the erase - // region - m_pendingErase = true; -} - -//////////////////////////////////////////////////////////////////////////////////// -// -// draw_pixel() -// -// Used to set a pixel in the graphics buffer - uses the current write operator -// function -// - -void QwGrSSD1306::drawPixel(uint8_t x, uint8_t y, uint8_t clr) -{ - // quick sanity check on range - if (x >= m_viewport.width || y >= m_viewport.height) - return; // out of bounds - - uint8_t bit = byte_bits[mod_byte(y)]; - - m_rasterOps[m_rop](m_pBuffer + x + y / kByteNBits * m_viewport.width, // pixel offset - (clr ? bit : 0), bit); // which bit to set in byte - - pageCheckBounds(m_pageState[y / kByteNBits], - x); // update dirty range for page -} -//////////////////////////////////////////////////////////////////////////////////// -// draw_line_horz() -// -// Fast horizontal line drawing routine -// - -void QwGrSSD1306::drawLineHorz(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr) -{ - // Basically we set a bit within a range in a page of our graphics buffer. - - // in range - if (y0 >= m_viewport.height) - return; - - if (x0 > x1) - swap_int(x0, x1); - - if (x1 >= m_viewport.width) - x1 = m_viewport.width - 1; - - uint8_t bit = byte_bits[mod_byte(y0)]; // bit to set - rasterOPsFn curROP = m_rasterOps[m_rop]; // current raster op - - // Get the start of this line in the graphics buffer - uint8_t *pBuffer = m_pBuffer + x0 + y0 / kByteNBits * m_viewport.width; - - // walk up x and set the target pixel using the pixel operator function - for (int i = x0; i <= x1; i++, pBuffer++) - curROP(pBuffer, (clr ? bit : 0), bit); - - // Mark the page dirty for the range drawn - pageCheckBoundsRange(m_pageState[y0 / kByteNBits], x0, x1); -} -//////////////////////////////////////////////////////////////////////////////////// -// draw_line_vert() -// -// Fast vertical line drawing routine - also supports fast filled rects -// -void QwGrSSD1306::drawLineVert(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr) -{ - if (x0 >= m_viewport.width) // out of bounds - return; - - // want an accending order - if (y0 > y1) - swap_int(y0, y1); - - // keep on screen - if (y1 >= m_viewport.height) - y1 = m_viewport.height - 1; - - uint8_t startBit, endBit, setBits; - - // Get the start and end pages we are writing to - uint8_t page0 = y0 / kByteNBits; - uint8_t page1 = y1 / kByteNBits; - - // loop over the pages. For each page determine the range of pixels - // to set in the target page byte and then set them using the current - // pixel operator function - - // Note: This function can also be used to draw filled rects - just iterate - // in the x direction. The base rect fill (in grBuffer) calls this - // method x1-x0 times, and each of those calls has some overhead. So - // just iterating over each page - x1-x0 times here - saves overhead - // costs. - // - // To make this work, make sure x0 > x1. Also, this method is wired in - // as the draw_rect_filled entry in the draw interface. This is done - // above in the init process. - - int xinc; - if (x0 > x1) - swap_int(x0, x1); - - rasterOPsFn curROP = m_rasterOps[m_rop]; // current raster op - - for (int i = page0; i <= page1; i++) - { - startBit = mod_byte(y0); // start bit in this byte - - // last bit of this byte to set? Does the line end in this byte, or continue - // on... - endBit = y0 + kByteNBits - startBit > y1 ? mod_byte(y1) : kByteNBits - 1; - - // Set the bits from startBit to endBit - setBits = (0xFF >> ((kByteNBits - endBit) - 1)) << startBit; // what bits are being set in this byte - - // set the bits in the graphics buffer using the current byte operator - // function - - // Note - We iterate over x to fill in a rect if specified. - for (xinc = x0; xinc <= x1; xinc++) - curROP(m_pBuffer + i * m_viewport.width + xinc, (clr ? setBits : 0), setBits); - - y0 += endBit - startBit + 1; // increment Y0 to next page - - pageCheckBoundsRange(m_pageState[i], x0, - x1); // mark dirty range in page desc - } -} -//////////////////////////////////////////////////////////////////////////////////////// -// draw_rect_fill() -// -// Does the actual drawing/logic - -void QwGrSSD1306::drawRectFilled(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr) -{ - uint8_t x1 = x0 + width - 1; - uint8_t y1 = y0 + height - 1; - - // just call vert line - drawLineVert(x0, y0, x1, y1, clr); -} -//////////////////////////////////////////////////////////////////////////////////// -// draw_bitmap() -// -// Draw a 8 bit encoded (aka same y layout as this device) bitmap to the screen -// - -void QwGrSSD1306::drawBitmap(uint8_t x0, uint8_t y0, uint8_t dst_width, uint8_t dst_height, uint8_t *pBitmap, - uint8_t bmp_width, uint8_t bmp_height) -{ - // some simple checks - if (x0 >= m_viewport.width || y0 >= m_viewport.height || !bmp_width || !bmp_height) - return; - - // Bounds check - if (x0 + dst_width > m_viewport.width) // out of bounds - dst_width = m_viewport.width - x0; - - if (bmp_width < dst_width) - dst_width = bmp_width; - - if (y0 + dst_height > m_viewport.height) // out of bounds - dst_height = m_viewport.height - y0; - - if (bmp_height < dst_height) - dst_height = bmp_height; - - // current position in the bitmap - uint8_t bmp_x = 0; - uint8_t bmp_y = 0; - - uint8_t page0, page1; - uint8_t startBit, endBit, grSetBits, grStartBit; - - uint8_t bmp_mask[2], bmp_data, bmpPage; - uint8_t remainingBits, neededBits; - - uint8_t y1 = y0 + dst_height - 1; - - page0 = y0 / kByteNBits; - page1 = y1 / kByteNBits; - - rasterOPsFn curROP = m_rasterOps[m_rop]; // current raster op - - // The Plan: - // - Walk down the graphics buffer range (y) one page at a time - // - For each page - // - Determine needed number of bits for the destination - // - Determine what bits to pull from the bitmap - // - Create a mask to pull out bits - from one or two bytes - // - Loop over the x dimension - // - pull bits from bitmap, build byte of data of bitmap bits, in - // right order for the destination (graphics buffer) - // - Write the bitmap bits to the graphis buffer using the - // current operator - - // Loop over the memory pages in the graphics buffer - for (int iPage = page0; iPage <= page1; iPage++) - { - // First, get the number of destination bits in the current page - grStartBit = mod_byte(y0); // start bit - - // last bit of this byte to set? Does the copy region end in this byte, or - // continue on... - endBit = y0 + kByteNBits - grStartBit > y1 ? mod_byte(y1) : kByteNBits - 1; - - // Set the bits from startBit to endBit - grSetBits = (0xFF >> (kByteNBits - endBit - 1)) << grStartBit; // what bits are being set in this byte - - // how many bits of data do we need to transfer from the bitmap? - neededBits = endBit - grStartBit + 1; - - // Okay, we have how much data to transfer to the current page. Now build - // the data from the bitmap. - - // First, build bit masks for pulling the data out of the bmp array. The - // data might straddle two bytes, so build two masks - - // as above, get the start and end bites for the current position in the - // bmp. - startBit = mod_byte(bmp_y); - endBit = (kByteNBits - startBit > neededBits ? startBit + neededBits : kByteNBits) - 1; - - // Set the bits from startBit to endBit - bmp_mask[0] = (0xFF >> (kByteNBits - endBit - 1)) << startBit; - - // any remaining bits to get? - remainingBits = neededBits - (endBit - startBit + 1); // +1 - needsBits is 1's based - bmp_mask[1] = 0xFF >> (kByteNBits - remainingBits); - - // What row in the source bitmap - bmpPage = bmp_y / kByteNBits; - - // we have the mask for the bmp - loop over the width of the copy region, - // pulling out bmp data and writing it to the graphics buffer - for (bmp_x = 0; bmp_x < dst_width; bmp_x++) - { - // get data bits out of current bitmap location and shift if needed - bmp_data = (pBitmap[bmp_width * bmpPage + bmp_x] & bmp_mask[0]) >> startBit; - - if (remainingBits) // more data to add from the next byte in this column - bmp_data |= (pBitmap[bmp_width * (bmpPage + 1) + bmp_x] & bmp_mask[1]) << (neededBits - remainingBits); - - // Write the bmp data to the graphics buffer - using current write op. - // Note, if the location in the buffer didn't start at bit 0, we shift - // bmp_data - curROP(m_pBuffer + iPage * m_viewport.width + bmp_x + x0, bmp_data << grStartBit, grSetBits); - } - // move up our y values (graphics buffer and bitmap) by the number of bits - // transferred - y0 += neededBits; - bmp_y += neededBits; - - pageCheckBoundsRange(m_pageState[iPage], x0, - x0 + dst_width); // mark dirty range in page desc - } -} - -//////////////////////////////////////////////////////////////////////////////////// -// Device Update Methods -//////////////////////////////////////////////////////////////////////////////////// -// setScreenBufferAddress() -// -// Sets the target screen buffer address for graphics buffer transfer to the -// device. -// -// The positon is specified by page and column -// -// The system runs in "page mode" - data is streamed along a page, based -// on the set starting position. -// -// This class takes advantage of this to just write the "dirty" ranges in a -// page. -// - -bool QwGrSSD1306::setScreenBufferAddress(uint8_t page, uint8_t column) -{ - if (page >= m_nPages || column >= m_viewport.width) - return false; - - // send the page address - sendDevCommand(kCmdPageModePageBase | page); - - // For the column start address, add the viewport x offset. Some devices - // (Micro OLED) don't start at column 0 in the screen buffer - sendDevCommand((kCmdPageModeColTopBase | (column >> 4)) + m_viewport.x); - sendDevCommand(kCmdPageModeColLowBase & column); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////// -// display() -// -// Send the "dirty" areas of the graphics buffer to the device's screen buffer. -// Only send the areas that need to be updated. The update region is based on -// new graphics to display, and any currently displayed items that need to be -// erased. - -void QwGrSSD1306::display() -{ - // Loop over our page descriptors - if a page is dirty, send the graphics - // buffer dirty region to the device for the current page - - pageState_t transferRange; - - for (int i = 0; i < m_nPages; i++) - { - // We keep the erase rect seperate from dirty rect. Make temp copy of - // dirty rect page range, expand to include erase rect page range. - - transferRange = m_pageState[i]; - - // If an erase has happend, we need to transfer/include erase update range - if (m_pendingErase) - pageCheckBoundsDesc(transferRange, m_pageErase[i]); - - if (pageIsClean(transferRange)) // both dirty and erase range for this - // page were null - continue; // next - - // set the start address to write the updated data to the devices screen - // buffer - setScreenBufferAddress(i, transferRange.xmin); - - // send the dirty data to the device - sendDevData(m_pBuffer + (i * m_viewport.width) + transferRange.xmin, // this page start + xmin - transferRange.xmax - transferRange.xmin + 1); // dirty region xmax - xmin. Add 1 b/c 0 based - - // If we sent the erase bounds, zero out the erase bounds - this area is now - // clear - if (m_pendingErase) - pageSetClean(m_pageErase[i]); - - // add the just send dirty range (non erase rec) to the erase rect - pageCheckBoundsDesc(m_pageErase[i], m_pageState[i]); - - // this page is no longer dirty - mark it clean - pageSetClean(m_pageState[i]); - } - m_pendingErase = false; // no longer pending -} - -//////////////////////////////////////////////////////////////////////////////////// -// Device communication methods -//////////////////////////////////////////////////////////////////////////////////// -// sendDeviceCommand() -// -// send a single command to the device via the current bus object - -void QwGrSSD1306::sendDevCommand(uint8_t command) -{ - m_i2cBus->writeRegisterByte(m_i2cAddress, kDeviceSendCommand, command); -} - -//////////////////////////////////////////////////////////////////////////////////// -// sendDeviceCommand() -// -// send a single command and value to the device via the current bus object. - -void QwGrSSD1306::sendDevCommand(uint8_t *commands, uint8_t n_commands) -{ - if (!commands || n_commands == 0) - return; - - m_i2cBus->writeRegisterRegion(m_i2cAddress, kDeviceSendCommand, commands, n_commands); -} - -//////////////////////////////////////////////////////////////////////////////////// -// sendDeviceCommand() -// -// send a single command and value to the device via the current bus object. -// - -void QwGrSSD1306::sendDevCommand(uint8_t command, uint8_t value) -{ - uint8_t buffer[] = {command, value}; - - sendDevCommand(buffer, 2); -} -//////////////////////////////////////////////////////////////////////////////////// -// sendDeviceData() -// -// send a single command to the device via the current bus object - -void QwGrSSD1306::sendDevData(uint8_t *pData, uint8_t nData) -{ - m_i2cBus->writeRegisterRegion(m_i2cAddress, kDeviceSendData, pData, nData); -} \ No newline at end of file diff --git a/src/qwiic_grssd1306.h b/src/qwiic_grssd1306.h deleted file mode 100644 index aca583f..0000000 --- a/src/qwiic_grssd1306.h +++ /dev/null @@ -1,290 +0,0 @@ -// qwiic_gr1306.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -/* - * Header file for the SSD1306 bitmap graphics driver device. - */ - -#pragma once - -#include "qwiic_grbuffer.h" -#include "qwiic_i2c.h" -#include "res/qwiic_resdef.h" - -///////////////////////////////////////////////////////////////////////////// -// Device Config -///////////////////////////////////////////////////////////////////////////// -// -// Defaults -// Each device can have a different Hardware pin configuration, which must -// be set in the device. These are the pins that connect the display to -// the SSD1306. -// -#define kDefaultPinConfig 0x12 -#define kDefaultPreCharge 0xF1 -#define kDefaultVCOMDeselect 0x40 -#define kDefaultContrast 0x8F - -///////////////////////////////////////////////////////////////////////////// -// The graphics Raster Operator functions (ROPS) -///////////////////////////////////////////////////////////////////////////// -// - Copy - copy the pixel value in to the buffer (default) -// - Not Copy - copy the not of the pixel value to buffer -// - Not - Set the buffer value to not it's current value -// - XOR - XOR of color and current pixel value -// - Black - Set value to always be black -// - White - set value to always be white - -typedef enum gr_op_funcs_ -{ - grROPCopy = 0, - grROPNotCopy = 1, - grROPNot = 2, - grROPXOR = 3, - grROPBlack = 4, - grROPWhite = 5 -} grRasterOp_t; - -///////////////////////////////////////////////////////////////////////////// -// Flags for scrolling -///////////////////////////////////////////////////////////////////////////// - -#define SCROLL_VERTICAL 0x01 -#define SCROLL_RIGHT 0x02 -#define SCROLL_LEFT 0x04 -#define SCROLL_VERT_RIGHT SCROLL_VERTICAL | SCROLL_RIGHT -#define SCROLL_VERT_LEFT SCROLL_VERTICAL | SCROLL_LEFT - -#define SCROLL_INTERVAL_5_FRAMES 0x00 -#define SCROLL_INTERVAL_64_FRAMES 0x01 -#define SCROLL_INTERVAL_128_FRAMES 0x02 -#define SCROLL_INTERVAL_256_FRAMES 0x03 -#define SCROLL_INTERVAL_3_FRAMES 0x04 -#define SCROLL_INTERVAL_4_FRAMES 0x05 -#define SCROLL_INTERVAL_25_FRAMES 0x06 -#define SCROLL_INTERVAL_2_FRAMES 0x07 - -///////////////////////////////////////////////////////////////////////////// -// Buffer Management -///////////////////////////////////////////////////////////////////////////// -// -// The memory/back buffer of the SSD1306 is based on the concept of pages - -// each page is a stream of bytes, and defined as follows: -// -// - X pixel position is an offset in a byte array -// - Y pixel position is a bit in a byte, so a page can have 8 Y locations -// -// A pixel value of 1, turn on the corresponding pixel, 0 turns it off. -// -// The device has different data transfer modes - see the data sheet - mostly -// outline how received a recieved byte is placed in the device framebuffer and the -// next update locaton set. -// -// This implementation uses the Page mode for buffer transfer. This is defined by: -// - A start position is set - a page number and column in that page. -// - As data is transferred, it is written to the screenbuffer, based on this start -// position -// - If the end of the page is reached, the next entry location is the start of that page -// -// >> Implementation << -// -// This implementation uses the concept of "dirty rects" at the page level to minimize data -// transfers to the device. The min and max x locations set for each page is recorded as -// graphics are draw to the graphics buffer. When the transfering the display buffer to -// the devices screen buffer, the following takes place: -// -// For each page: -// - if page is dirty -// - Set the screen buffer current location to this page, xmin dirty value -// - Write buffer bytes to the device - starting at xmin for the page, ending at xmax -// - Mark the buffer as "clean" -// -// -// Define variables to manage page state - -#define kMaxPageNumber 8 - -typedef struct -{ - int16_t xmin; - int16_t xmax; -} pageState_t; - -///////////////////////////////////////////////////////////////////////////// -// QwGrSSD1306 -// A buffer graphics device to support the SSD1306 graphics hardware - -class QwGrSSD1306 : public QwGrBufferDevice -{ - private: - void setupDefaults(void); - - public: - QwGrSSD1306() - { - setupDefaults(); // default constructor - always called - } - QwGrSSD1306(uint8_t width, uint8_t height) : QwGrSSD1306(0, 0, width, height){}; - - // call super class - QwGrSSD1306(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height) : QwGrBufferDevice(x0, y0, width, height) - { - setupDefaults(); - }; - - // Public draw methods - void display(void); // send graphics buffer to the devices screen buffer - void erase(void); - - // Device setup - virtual bool init(void); - - bool isInitialized(void) - { - return m_isInitialized; - }; - bool reset(bool clearDisplay = true); - - // method to set the communication bus this object should use - void setCommBus(QwI2C &theBus, uint8_t id_bus); - - // Set the current color/pixel write operation - void setColor(uint8_t color); - - // Settings/operational methods - void setContrast(uint8_t); - - // default address of the device - expect the sub to fill in. - uint8_t default_address; - - void setRasterOp(grRasterOp_t rop) - { - m_rop = rop; - } - - grRasterOp_t rasterOp(void) - { - return m_rop; - } - // screen control - void invert(bool); - void flipVert(bool); - void flipHorz(bool); - - // screen scrolling - void stopScroll(void); - void scroll(uint16_t scroll_type, uint8_t start, uint8_t stop, uint8_t interval = SCROLL_INTERVAL_2_FRAMES); - - void displayPower(bool enable = true); - - protected: - // Subclasses of this class define the specifics of the device, including size. - // Subclass needs to define the graphics buffer array - stack based - and pass in - void setBuffer(uint8_t *pBuffer); - - /////////////////////////////////////////////////////////////////////////// - // Internal, fast draw routines - this are used in the overall - // draw interface (_QwIDraw) for this object/device/system. - // - // >> Pixels << - void drawPixel(uint8_t x, uint8_t y, uint8_t clr); - - // >> Fast Lines << - void drawLineHorz(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr); - void drawLineVert(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t clr); - - // fast rect fill - void drawRectFilled(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height, uint8_t clr); - - // >> Fast Bitmap << - void drawBitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t *pBitmap, uint8_t bmp_width, - uint8_t bmp_height); - - /////////////////////////////////////////////////////////////////////////// - // configuration methods for sub-classes. Settings unique to a device - void setCommPins(uint8_t); - void setPreCharge(uint8_t); - void setVcomDeselect(uint8_t); - - private: - // Internal buffer management methods - bool setScreenBufferAddress(uint8_t page, uint8_t column); - void initBuffers(void); // clear graphics and screen buffer - void clearScreenBuffer(void); - void resendGraphics(void); - void setupOLEDDevice(bool clearDisplay = true); - - // device communication methods - void sendDevCommand(uint8_t command); - void sendDevCommand(uint8_t command, uint8_t value); - void sendDevCommand(uint8_t *commands, uint8_t n); - void sendDevData(uint8_t *pData, uint8_t nData); - - ///////////////////////////////////////////////////////////////////////////// - // instance vars - - // Buffer variables - uint8_t *m_pBuffer; // Pointer to the graphics buffer - uint8_t m_nPages; // number of pages for current device - pageState_t m_pageState[kMaxPageNumber]; // page state descriptors - pageState_t m_pageErase[kMaxPageNumber]; // keep track of erase boundaries - bool m_pendingErase; - - // display variables - uint8_t m_color; // current color (really 0 or 1) - grRasterOp_t m_rop; // current raster operation code - - // I2C things - QwI2C *m_i2cBus; // pointer to our i2c bus object - uint8_t m_i2cAddress; // address of the device - - // Stash values for settings that are unique to each device. - uint8_t m_initHWComPins; - uint8_t m_initPreCharge; - uint8_t m_initVCOMDeselect; - uint8_t m_initContrast; - - bool m_isInitialized; // general init flag -}; diff --git a/src/qwiic_i2c.cpp b/src/qwiic_i2c.cpp deleted file mode 100644 index 1dbe5d1..0000000 --- a/src/qwiic_i2c.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// qwiic_i2c.cpp -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -// Class provide an abstract interface to the I2C device - -#include "qwiic_i2c.h" - - -// What is the max buffer size for this platform. - -#if defined(SERIAL_BUFFER_SIZE) -#define kMaxTransferBuffer SERIAL_BUFFER_SIZE - -#elif defined(I2C_BUFFER_LENGTH) -#define kMaxTransferBuffer I2C_BUFFER_LENGTH - -#elif defined(BUFFER_LENGTH) -#define kMaxTransferBuffer BUFFER_LENGTH - -#else // just the standard Arduino value -#define kMaxTransferBuffer 32 - -#endif - -// What we use for transfer chunk size - -const static uint16_t kChunkSize = kMaxTransferBuffer - 1; - -////////////////////////////////////////////////////////////////////////////////////////////////// -// Constructor - -QwI2C::QwI2C(void) -{ - m_i2cPort = nullptr; -} -////////////////////////////////////////////////////////////////////////////////////////////////// -// init() -// -// Methods to init/setup this device. The caller can provide a Wire Port, or this class -// will use the default - -bool QwI2C::init(TwoWire& wirePort) -{ - // if we don't have a wire port already - if (!m_i2cPort) - m_i2cPort = &wirePort; - - return true; -} -////////////////////////////////////////////////////////////////////////////////////////////////// -// - -bool QwI2C::init(void) -{ - // do we already have a wire port? - if (!m_i2cPort) - return init(Wire); // no wire, send in Wire - - return true; -} - -////////////////////////////////////////////////////////////////////////////////////////////////// -// ping() -// -// Is a device connected? -bool QwI2C::ping(uint8_t i2c_address) -{ - m_i2cPort->beginTransmission(i2c_address); - return m_i2cPort->endTransmission() == 0; -} - -////////////////////////////////////////////////////////////////////////////////////////////////// -// writeRegisterByte() -// -// Write a byte to a register - -bool QwI2C::writeRegisterByte(uint8_t i2c_address, uint8_t offset, uint8_t dataToWrite) -{ - m_i2cPort->beginTransmission(i2c_address); - m_i2cPort->write(offset); - m_i2cPort->write(dataToWrite); - return m_i2cPort->endTransmission() == 0; -} -////////////////////////////////////////////////////////////////////////////////////////////////// -// writeRegisterRegion() -// -// Write a block of data to a device. This routine will chunk over the data if needed - -int QwI2C::writeRegisterRegion(uint8_t i2c_address, uint8_t offset, uint8_t* data, uint16_t length) -{ - uint16_t nSent; - uint16_t nRemaining = length; - uint16_t nToWrite; - - while (nRemaining > 0) { - - m_i2cPort->beginTransmission(i2c_address); - m_i2cPort->write(offset); - - nToWrite = (nRemaining > kChunkSize ? kChunkSize : nRemaining); - nSent = m_i2cPort->write(data, nToWrite); - - nRemaining -= nToWrite; // Note - use nToWrite, not nSent, or lock on esp32 - data += nSent; // move up to remaining data in buffer - -#if defined(ARDUINO_ARCH_ESP32) - // if we are on ESP32, release bus no matter what - if (m_i2cPort->endTransmission()) -#else - // only release bus if we've sent all data - if (m_i2cPort->endTransmission(nRemaining <= 0)) -#endif - return -1; // the client didn't ACK - } - - return length - nRemaining; -} diff --git a/src/qwiic_i2c.h b/src/qwiic_i2c.h deleted file mode 100644 index 261498c..0000000 --- a/src/qwiic_i2c.h +++ /dev/null @@ -1,77 +0,0 @@ -// qwiic_i2c.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -// Header for I2C driver object - -#pragma once - -// Simple object to encapsulate basic I2C operations. -// -// This is following a pattern for future implementations -// -// This class is focused on Aurduino.. - -#include -#include - -class QwI2C { - -public: - QwI2C(void); - - bool init(void); - bool init(TwoWire& wirePort); - - // see if a device exists - bool ping(uint8_t address); - - bool writeRegisterByte(uint8_t address, uint8_t offset, uint8_t data); - - // Write a block of bytes to the device -- - int writeRegisterRegion(uint8_t address, uint8_t offset, uint8_t* data, uint16_t length); - -private: - TwoWire* m_i2cPort; -}; \ No newline at end of file diff --git a/src/qwiic_oled_1in3.h b/src/qwiic_oled_1in3.h deleted file mode 100644 index 65d8c88..0000000 --- a/src/qwiic_oled_1in3.h +++ /dev/null @@ -1,99 +0,0 @@ -// qwiic_oled_1in3.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// 1.3" OLED https://www.sparkfun.com/products/23453 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -// Implementation for the 1.3" OLED device - -#pragma once - -#include "qwiic_grssd1306.h" - -////////////////////////////////////////////////////////////////// -// Set the defaults for the SparkFun Qwiic MicroOLED - -#define kOLED1in3Width 128 -#define kOLED1in3Height 64 - -#define kOLED1in3XOffset 0 -#define kOLED1in3YOffset 0 - -// Parameters for this device -#define kOLED1in3PinConfig 0x12 -#define kOLED1in3PreCharge 0xF1 -#define kOLED1in3VCOM 0x40 -#define kOLED1in3Contrast 0xCF - -#define kOLED1in3DefaultAddress 0x3D -#define kOLED1in3AltAddress 0x3C - -class QwOLED1in3 : public QwGrSSD1306 { - -public: - // Constructor - setup the viewport and default address for this device. - QwOLED1in3() - : QwGrSSD1306(kOLED1in3XOffset, kOLED1in3YOffset, kOLED1in3Width, kOLED1in3Height) - { - default_address = kOLED1in3DefaultAddress; - }; - - // set up the specific device settings - bool init(void) - { - - setBuffer(m_graphicsBuffer); // The buffer to use - - setCommPins(kOLED1in3PinConfig); - setPreCharge(kOLED1in3PreCharge); - setVcomDeselect(kOLED1in3VCOM); - setContrast(kOLED1in3Contrast); - - // Call the super class to do all the work - return this->QwGrSSD1306::init(); - }; - -private: - // Graphics buffer for this device. - uint8_t m_graphicsBuffer[kOLED1in3Width * kOLED1in3Height / 8]; -}; \ No newline at end of file diff --git a/src/qwiic_oled_custom.h b/src/qwiic_oled_custom.h deleted file mode 100644 index fb508df..0000000 --- a/src/qwiic_oled_custom.h +++ /dev/null @@ -1,130 +0,0 @@ -// qwiic_oled_custom.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// 1.3" OLED https://www.sparkfun.com/products/23453 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -// Implementation for the 1.3" OLED device - -#pragma once - -#include "qwiic_grssd1306.h" - -////////////////////////////////////////////////////////////////// -// Set the defaults for the SparkFun Qwiic MicroOLED - -#define kOLEDCustomDefaultWidth 128 -#define kOLEDCustomDefaultHeight 64 - -#define kOLEDCustomDefaultXOffset 0 -#define kOLEDCustomDefaultYOffset 0 - -// Parameters for this device -#define kOLEDCustomDefaultPinConfig 0x12 -#define kOLEDCustomDefaultPreCharge 0xF1 -#define kOLEDCustomDefaultVCOM 0x40 -#define kOLEDCustomDefaultContrast 0xCF - -#define kOLEDCustomDefaultDefaultAddress 0x3D -#define kOLEDCustomDefaultAltAddress 0x3C - -class QwOLEDCustom : public QwGrSSD1306 { - -public: - // Constructor - setup the viewport and default address for this device. - QwOLEDCustom() - : QwGrSSD1306(kOLEDCustomDefaultXOffset, kOLEDCustomDefaultYOffset, kOLEDCustomDefaultWidth, kOLEDCustomDefaultHeight) - { - default_address = kOLEDCustomDefaultDefaultAddress; - }; - - ~QwOLEDCustom() - { - if (m_graphicsBuffer != nullptr) - { - delete[] m_graphicsBuffer; - m_graphicsBuffer = nullptr; - } - }; - - // set up the specific device settings - bool init(void) - { - this->QwGrSSD1306::setViewport(m_xOffset, m_yOffset, m_displayWidth, m_displayHeight); - - this->QwGrSSD1306::setCommPins(m_pinConfig); - this->QwGrSSD1306::setPreCharge(m_preCharge); - this->QwGrSSD1306::setVcomDeselect(m_vcomDeselect); - this->QwGrSSD1306::setContrast(m_contrast); - - if (m_graphicsBuffer != nullptr) - delete[] m_graphicsBuffer; - m_graphicsBuffer = new uint8_t[(uint16_t)m_displayWidth * (uint16_t)m_displayHeight / 8]; - this->QwGrSSD1306::setBuffer(m_graphicsBuffer); // The buffer to use - - // Call the super class to do all the work - return this->QwGrSSD1306::init(); - }; - - void setXOffset(uint8_t xOffset){ m_xOffset = xOffset; } - void setYOffset(uint8_t yOffset){ m_yOffset = yOffset; } - void setDisplayWidth(uint8_t displayWidth){ m_displayWidth = displayWidth; } - void setDisplayHeight(uint8_t displayHeight){ m_displayHeight = displayHeight; } - void setPinConfig(uint8_t pinConfig){ m_pinConfig = pinConfig; } - void setPreCharge(uint8_t preCharge){ m_preCharge = preCharge; } - void setVcomDeselect(uint8_t vcomDeselect){ m_vcomDeselect = vcomDeselect; } - void setContrast(uint8_t contrast){ m_contrast = contrast; } - -private: - uint8_t m_xOffset = kOLEDCustomDefaultXOffset; - uint8_t m_yOffset = kOLEDCustomDefaultYOffset; - uint8_t m_displayWidth = kOLEDCustomDefaultWidth; - uint8_t m_displayHeight = kOLEDCustomDefaultHeight; - uint8_t m_pinConfig = kOLEDCustomDefaultPinConfig; - uint8_t m_preCharge = kOLEDCustomDefaultPreCharge; - uint8_t m_vcomDeselect = kOLEDCustomDefaultVCOM; - uint8_t m_contrast = kOLEDCustomDefaultContrast; - - // Graphics buffer for this device. - uint8_t *m_graphicsBuffer = nullptr; -}; \ No newline at end of file diff --git a/src/qwiic_oledmicro.h b/src/qwiic_oledmicro.h deleted file mode 100644 index e95e9ed..0000000 --- a/src/qwiic_oledmicro.h +++ /dev/null @@ -1,96 +0,0 @@ -// qwiic_oledmicro.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -// Implementation for the Qwiic Micro OLED Device - -#pragma once - -#include "qwiic_grssd1306.h" - -////////////////////////////////////////////////////////////////// -// Set the defaults for the SparkFun Qwiic MicroOLED - -#define kOLEDMicroWidth 64 -#define kOLEDMicroHeight 48 - -// The viewport x is off by 2 on this device - starts at value 2 -#define kOLEDMicroXOffset 2 -#define kOLEDMicroYOffset 0 - -// Parameters for this device -#define kOLEDMicroPinConfig 0x12 -#define kOLEDMicroPreCharge 0xF1 -#define kOLEDMicroVCOM 0x40 - -#define kOLEDMicroDefaultAddress 0x3D -#define kOLEDMicroAltAddress 0x3C - -class QwOLEDMicro : public QwGrSSD1306 { - -public: - // Constructor - setup the viewport and default address for this device. - QwOLEDMicro() - : QwGrSSD1306(kOLEDMicroXOffset, kOLEDMicroYOffset, kOLEDMicroWidth, kOLEDMicroHeight) - { - default_address = kOLEDMicroDefaultAddress; - }; - - // set up the specific device settings - bool init(void) - { - setBuffer(m_graphicsBuffer); // The buffer to use - - setCommPins(kOLEDMicroPinConfig); - setPreCharge(kOLEDMicroPreCharge); - setVcomDeselect(kOLEDMicroVCOM); - - // Call the super class to do all the work - return this->QwGrSSD1306::init(); - }; - -private: - // Graphics buffer for this device. - uint8_t m_graphicsBuffer[kOLEDMicroWidth * kOLEDMicroHeight / 8]; -}; \ No newline at end of file diff --git a/src/qwiic_olednarrow.h b/src/qwiic_olednarrow.h deleted file mode 100644 index 40c3f10..0000000 --- a/src/qwiic_olednarrow.h +++ /dev/null @@ -1,92 +0,0 @@ -// qwiic_olednarrow.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// - -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -// Implementation for the Qwiic Narrow OLED Device (128x32) - -#pragma once - -#include "qwiic_grssd1306.h" - -////////////////////////////////////////////////////////////////// -// Set the defaults for the SparkFun Qwiic "Narrow" OLED - -#define kOLEDNarrowWidth 128 -#define kOLEDNarrowHeight 32 - -// Parameters for this device -#define kOLEDNarrowPinConfig 0x02 -#define kOLEDNarrowPreCharge 0xF1 -#define kOLEDNarrowVCOM 0x40 - -#define kOLEDNarrowDefaultAddress 0x3C - -class QwOLEDNarrow : public QwGrSSD1306 { - -public: - // Constructor - setup the viewport and default address for this device. - QwOLEDNarrow() - : QwGrSSD1306(kOLEDNarrowWidth, kOLEDNarrowHeight) - { - default_address = kOLEDNarrowDefaultAddress; - }; - - // set up the specific values - bool init(void) - { - - setBuffer(m_graphicsBuffer); - - setCommPins(kOLEDNarrowPinConfig); - setPreCharge(kOLEDNarrowPreCharge); - setVcomDeselect(kOLEDNarrowVCOM); - - // Call the super class to do all the work - return this->QwGrSSD1306::init(); - }; - -private: - // Graphics buffer for this device. - uint8_t m_graphicsBuffer[kOLEDNarrowWidth * kOLEDNarrowHeight / 8]; -}; \ No newline at end of file diff --git a/src/qwiic_oledtransp.h b/src/qwiic_oledtransp.h deleted file mode 100644 index cf33b13..0000000 --- a/src/qwiic_oledtransp.h +++ /dev/null @@ -1,96 +0,0 @@ -// qwiic_oledtransp.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -// Implementation for the Transparent OLED device - -#pragma once - -#include "qwiic_grssd1306.h" - -////////////////////////////////////////////////////////////////// -// Set the defaults for the SparkFun Qwiic MicroOLED - -#define kOLEDTransWidth 128 -#define kOLEDTransHeight 64 - -// The viewport x is off by 2 on this device - starts at value 2 -#define kOLEDTransXOffset 0 -#define kOLEDTransYOffset 0 - -// Parameters for this device -#define kOLEDTransPinConfig 0x12 -#define kOLEDTransPreCharge 0x25 -#define kOLEDTransVCOM 0x40 - -#define kOLEDTransDefaultAddress 0x3C - -class QwOLEDTransparent : public QwGrSSD1306 { - -public: - // Constructor - setup the viewport and default address for this device. - QwOLEDTransparent() - : QwGrSSD1306(kOLEDTransXOffset, kOLEDTransYOffset, kOLEDTransWidth, kOLEDTransHeight) - { - default_address = kOLEDTransDefaultAddress; - }; - - // set up the specific device settings - bool init(void) - { - - setBuffer(m_graphicsBuffer); // The buffer to use - - setCommPins(kOLEDTransPinConfig); - setPreCharge(kOLEDTransPreCharge); - setVcomDeselect(kOLEDTransVCOM); - - // Call the super class to do all the work - return this->QwGrSSD1306::init(); - }; - -private: - // Graphics buffer for this device. - uint8_t m_graphicsBuffer[kOLEDTransWidth * kOLEDTransHeight / 8]; -}; \ No newline at end of file diff --git a/src/res/_bmp_sparkfun.h b/src/res/_bmp_sparkfun.h deleted file mode 100644 index f4dc09b..0000000 --- a/src/res/_bmp_sparkfun.h +++ /dev/null @@ -1,70 +0,0 @@ -/****************************************************************************** -font5x7.h -Definition for small font - -This file was imported from the MicroView library, written by GeekAmmo -(https://github.com/geekammo/MicroView-Arduino-Library), and released under -the terms of the GNU General Public License as published by the Free Software -Foundation, either version 3 of the License, or (at your option) any later -version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Modified by: -Emil Varughese @ Edwin Robotics Pvt. Ltd. -July 27, 2015 -https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/ - -******************************************************************************/ -#pragma once - -/* -#if defined(ARDUINO_ARCH_MBED) - // ARDUINO_ARCH_MBED (APOLLO3 v2) does not support or require pgmspace.h / PROGMEM - static const uint8_t bmp_truck[] = { -#elif defined(__AVR__) || defined(__arm__) || defined(__ARDUINO_ARC__) - #include - static const uint8_t bmp_truck[] PROGMEM = { -#else - #include - static const uint8_t bmp_truck[] PROGMEM = { -#endif -*/ - -#define BMP_SPARKFUN_WIDTH 64 -#define BMP_SPARKFUN_HEIGHT 48 - -// SparkFun Electronics LOGO -static const uint8_t bmp_sparkfun_data[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x0F, 0x07, 0x07, 0x06, 0x06, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x07, 0x0F, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xFC, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xE0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xFD, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x07, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - diff --git a/src/res/_bmp_truck.h b/src/res/_bmp_truck.h deleted file mode 100644 index d9ecf41..0000000 --- a/src/res/_bmp_truck.h +++ /dev/null @@ -1,82 +0,0 @@ -/****************************************************************************** -font5x7.h -Definition for small font - -This file was imported from the MicroView library, written by GeekAmmo -(https://github.com/geekammo/MicroView-Arduino-Library), and released under -the terms of the GNU General Public License as published by the Free Software -Foundation, either version 3 of the License, or (at your option) any later -version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Modified by: -Emil Varughese @ Edwin Robotics Pvt. Ltd. -July 27, 2015 -https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/ - -******************************************************************************/ -#pragma once - -/* -#if defined(ARDUINO_ARCH_MBED) - // ARDUINO_ARCH_MBED (APOLLO3 v2) does not support or require pgmspace.h / PROGMEM - static const uint8_t bmp_truck[] = { -#elif defined(__AVR__) || defined(__arm__) || defined(__ARDUINO_ARC__) - #include - static const uint8_t bmp_truck[] PROGMEM = { -#else - #include - static const uint8_t bmp_truck[] PROGMEM = { -#endif -*/ - -#define BMP_TRUCK_WIDTH 19 -#define BMP_TRUCK_HEIGHT 16 - -static const uint8_t bmp_truck_data[] = { - 0xFF, - 0x01, - 0xC1, - 0x41, - 0x41, - 0x41, - 0x71, - 0x11, - 0x11, - 0x11, - 0x11, - 0x11, - 0x71, - 0x41, - 0x41, - 0xC1, - 0x81, - 0x01, - 0xFF, - 0xFF, - 0x80, - 0x83, - 0x82, - 0x86, - 0x8F, - 0x8F, - 0x86, - 0x82, - 0x82, - 0x82, - 0x86, - 0x8F, - 0x8F, - 0x86, - 0x83, - 0x81, - 0x80, - 0xFF, -}; diff --git a/src/res/_fnt_31x48.h b/src/res/_fnt_31x48.h deleted file mode 100644 index 8e041cd..0000000 --- a/src/res/_fnt_31x48.h +++ /dev/null @@ -1,717 +0,0 @@ -/****************************************************************************** -fontlargeletter.h -Definition for large letter only font - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Created by: -DaAwesomeP -August 13, 2015 -https://github.com/DaAwesomeP/SparkFun_Micro_OLED_Arduino_Library/ - -******************************************************************************/ - -#pragma once - - -// Define the font attributes -#define FONT_31X48_WIDTH 31 -#define FONT_31X48_HEIGHT 48 -#define FONT_31X48_START 65 -#define FONT_31X48_NCHAR 58 -#define FONT_31X48_MAP_WIDTH 62 -#define FONT_31X48_NAME "31 x 48" - -#if defined(ARDUINO_ARCH_MBED) - // ARDUINO_ARCH_MBED (APOLLO3 v2) does not support or require pgmspace.h / PROGMEM - static const uint8_t font31x48_data [] = { -#elif defined(__AVR__) || defined(__arm__) || defined(__ARDUINO_ARC__) - static const uint8_t font31x48_data [] PROGMEM = { -#else - static const uint8_t font31x48_data [] PROGMEM = { -#endif - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF8, 0xF8, 0xF8, 0xF8, - 0xF8, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, - 0x78, 0xF8, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0xFF, 0xFF, 0x3F, 0x07, 0x00, 0x00, 0x07, 0x3F, - 0xFF, 0xFF, 0xFC, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xE0, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x8F, - 0xBF, 0xFF, 0xFF, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x3F, 0x3F, - 0x7B, 0xFB, 0xF1, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0xFF, 0xFF, - 0x7F, 0x1F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x1F, 0x7F, 0xFF, 0xFF, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x08, 0x0F, 0x0F, 0x0F, 0x0F, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x0F, 0x0F, 0x0F, 0x0F, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x03, 0x03, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xF8, 0x78, - 0x7C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x7C, 0x7C, 0xF8, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x78, 0x78, 0x78, 0x78, - 0x78, 0x78, 0x78, 0xF8, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0F, 0x07, 0x07, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x0F, 0x7F, 0xFF, 0xFF, 0xFC, 0xF0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x1F, 0x7F, 0xFF, 0xFF, 0xF8, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF8, 0xFC, 0xF8, 0x78, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, - 0xC0, 0xF0, 0xF8, 0xFF, 0xFF, 0x7F, 0x1F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, - 0x0F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x03, - 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, - 0xF8, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, - 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, - 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, - 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1E, 0x1E, 0x1E, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0x78, 0x78, 0x78, - 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xF8, 0x78, 0x7C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x7C, - 0xF8, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, - 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, - 0xFF, 0xFF, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x03, 0x07, 0x03, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0xF8, 0xF8, - 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1F, 0x7F, 0xFF, 0xFF, 0xF8, 0xE0, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0F, 0x0F, - 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0xF8, 0xF8, 0xF8, - 0xF8, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x78, - 0x78, 0x78, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xF0, 0xF8, - 0xF8, 0xF8, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, - 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x07, - 0x0F, 0x0F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x0F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xF8, 0x78, 0x38, 0x18, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x80, 0xC0, - 0xE0, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x0F, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x7E, 0x3F, 0x1F, 0x3F, 0x7F, 0xFF, - 0xFC, 0xF8, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, - 0x0F, 0x1F, 0x7F, 0xFE, 0xFC, 0xF8, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x07, 0x0F, 0x0F, 0x0F, 0x0E, 0x0C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, - 0xF8, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0xF8, 0xF8, - 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, - 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, - 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x0F, 0x7F, - 0xFF, 0xFC, 0xF0, 0x80, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0xFF, 0x7F, 0x0F, 0x01, 0xFF, 0xFF, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x0F, 0x3F, - 0xFF, 0xFC, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x0F, - 0x7F, 0xFF, 0xFC, 0xF8, 0xFF, 0x7F, 0x0F, 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x07, - 0x1F, 0x7F, 0xFF, 0xFC, 0xE0, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x0F, 0x3F, 0xFF, 0xFE, 0xF8, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0xE0, 0xF0, 0xF0, 0xF8, 0xF8, 0x7C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x7C, 0xF8, - 0xF8, 0xF0, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, - 0xF8, 0xF8, 0xF8, 0xF8, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0xF8, 0xF0, - 0xF0, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC7, - 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x7C, 0x7C, 0x3E, 0x3F, 0x1F, 0x1F, 0x0F, - 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x3F, 0xFF, 0xFF, 0xFF, 0xF0, 0xC0, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0x3F, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x07, 0x0F, 0x0F, 0x1F, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x0F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF0, 0xF8, 0xF8, 0x7C, 0x3C, 0x3C, 0x3C, 0x3C, - 0x3C, 0x3C, 0x7C, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, - 0x78, 0x78, 0xF8, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xFF, - 0xFF, 0xFF, 0xFF, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0xFC, 0xFC, 0xFC, 0xFC, 0xDE, 0x1E, - 0x1F, 0x0F, 0x0F, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x3F, 0xFF, - 0xFF, 0xFF, 0xF0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, - 0xFF, 0xFF, 0xFF, 0x3F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x3F, 0xFF, 0xFE, 0xF8, - 0xF0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, - 0x07, 0x0F, 0x0F, 0x1F, 0x1E, 0x1E, 0x7E, 0xFE, 0xFE, 0xFE, 0xFF, 0x8F, 0x0F, 0x07, 0x03, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x0F, - 0x0F, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x0F, 0x1F, 0x1E, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF0, 0xF8, 0x78, 0x3C, 0x3C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, 0x3C, 0x78, 0xF8, 0xF0, 0xF0, 0xE0, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, - 0xF8, 0xF8, 0xF8, 0xF8, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xE0, 0xC0, 0x80, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x07, 0x07, 0x03, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x1F, 0x1E, - 0x1E, 0x3E, 0x3E, 0x3C, 0x7C, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0xF0, 0xF8, 0xF8, 0xF8, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x07, 0x0F, 0x0F, 0x0F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, - 0x0F, 0x0F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, - 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x38, 0xF8, 0xF8, 0xF8, 0xF0, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, - 0xF8, 0xF8, 0xF8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x3F, 0xFF, 0xFF, 0xFC, 0xF0, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xFC, 0xFF, 0xFF, 0x3F, 0x0F, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x3F, 0xFF, 0xFF, 0xFC, 0xE0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0xFF, 0xFF, 0x3F, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x3F, 0xFF, 0xFF, 0xF8, 0xC0, - 0xC0, 0xF8, 0xFF, 0xFF, 0x3F, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x0F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, - 0x1E, 0x1E, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xF8, 0xF8, 0xF8, - 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0x38, 0x00, 0x00, 0x00, 0x08, 0x18, 0x78, - 0xF8, 0xF8, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xC0, 0xF0, 0xF8, 0xF8, 0x78, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFC, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x07, 0x1F, 0x3F, 0xFE, 0xFC, 0xF0, 0xE0, 0x80, 0x80, 0xE0, 0xF0, 0xFC, 0xFE, 0x3F, 0x1F, 0x07, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, - 0x00, 0x00, 0xC0, 0xFC, 0xFF, 0xFF, 0x0F, 0x07, 0xFF, 0xFF, 0xFC, 0xC0, 0x00, 0x00, 0x00, 0xFC, - 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xC0, 0xF1, 0xFF, 0xFF, 0x7F, 0x7F, 0xFF, 0xFF, 0xF1, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFC, 0xC0, 0xFC, - 0xFF, 0x7F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x07, 0x7F, 0xFF, 0xFC, 0xC0, 0xF8, 0xFF, 0xFF, 0xFF, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xFC, 0xFE, 0x3F, 0x1F, - 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x1F, 0x3F, 0xFE, 0xFC, 0xF0, 0xE0, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x0C, 0x0F, 0x0F, 0x0F, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0F, 0x0F, 0x0F, 0x0C, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x08, 0x38, 0x78, 0xF8, 0xF8, 0xF0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0xF8, 0xF8, 0x78, 0x38, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, - 0x78, 0x78, 0x78, 0x78, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x03, 0x0F, 0x3F, 0x7F, 0xFE, 0xF8, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xC0, - 0xF0, 0xF8, 0xFE, 0x7F, 0x3F, 0x0F, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0xF8, - 0xFC, 0x7E, 0x3F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0F, 0x3F, 0xFF, 0xFE, 0xFE, 0xFF, 0x3F, 0x0F, 0x03, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFE, 0x7F, 0x1F, 0x0F, 0x07, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xFC, - 0x7E, 0x3F, 0x1F, 0x0F, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1F, 0x7F, 0xFE, 0xFC, 0xF0, 0xC0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x3F, 0xFF, 0xFC, 0xF8, 0xE0, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x1F, 0x7F, 0xFE, - 0xF8, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, - 0x3F, 0xFF, 0xFC, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x0F, 0x0F, 0x0F, 0x0E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xE0, 0xF8, 0xF8, 0x78, 0x78, 0xF8, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xFC, 0xFF, - 0x3F, 0x07, 0x01, 0x00, 0x00, 0x01, 0x0F, 0x3F, 0xFF, 0xFC, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xFE, 0xFF, 0x1F, 0x07, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1F, 0xFF, 0xFE, 0xF0, 0xC0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3F, 0x3F, - 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0E, 0x0E, 0x1E, 0x3C, 0x78, 0x70, 0x60, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0x7C, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x1E, - 0x1E, 0x7C, 0xFC, 0xF8, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x78, 0x38, 0x1C, 0x0C, 0x0E, 0x0E, 0x0E, 0x0E, 0x1E, - 0x1E, 0x3C, 0xFC, 0xF8, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x81, 0xC1, 0xE1, 0xE1, 0xE0, 0xF0, 0xF0, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, - 0xFF, 0xFF, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xFF, 0xFF, - 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xFF, - 0xFF, 0xFF, 0x7F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0F, 0x0F, - 0x1F, 0x1E, 0x1C, 0x1C, 0x1C, 0x1C, 0x0C, 0x0E, 0x0E, 0x07, 0x03, 0x00, 0x03, 0x0F, 0x1F, 0x1F, - 0x1F, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, - 0x03, 0x07, 0x0E, 0x0E, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1E, 0x1E, 0x0F, 0x0F, 0x07, 0x03, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xF8, 0xF8, 0x7C, 0x3C, 0x1E, 0x0E, 0x0E, - 0x0E, 0x0E, 0x0E, 0x0E, 0x1E, 0x1C, 0x3C, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0x3C, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, - 0x0E, 0x0E, 0x1C, 0x1C, 0x78, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0x7F, 0xFF, 0xFF, 0xFF, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF0, 0xF0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x7F, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x1E, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1E, 0x0E, - 0x0F, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x07, 0x07, 0x0F, 0x0F, 0x1E, 0x1E, 0x1C, 0x1C, 0x1C, 0x1C, 0x0C, 0x0E, 0x07, 0x03, 0x01, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xE0, 0xF8, 0xFC, 0xFE, 0x3E, 0x1F, 0x0F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xF8, 0xF8, 0x7C, - 0x3C, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x1E, 0x1C, 0x7C, 0xF8, 0xF8, 0xF0, 0xE0, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0xFF, - 0xFF, 0xFF, 0xFF, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x7F, 0x7F, 0x7F, 0x7F, 0x78, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0xFF, 0xFF, 0xFF, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x0F, 0x1E, 0x1E, 0x1C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1E, 0x0E, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, - 0xF0, 0xF8, 0xFC, 0x3C, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0C, 0x1C, 0x38, 0x78, 0xE0, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0C, 0x0E, 0x0E, 0x0E, 0x0E, 0x1E, 0x1E, 0x7E, 0xFC, 0xFC, - 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xF0, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x87, 0x87, 0x8F, 0x0F, 0x0E, - 0x0E, 0x0E, 0x0E, 0x0E, 0x06, 0x07, 0x03, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x0F, 0x1F, 0x1E, 0x3C, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x3C, 0x1E, 0x1F, 0x0F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, - 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0xFC, 0xFC, 0xFC, 0xFC, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0xFC, 0xFC, 0xFC, - 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, - 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, - 0x0E, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x3C, 0x1E, 0x1F, 0x0F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0xF8, 0xFC, 0x7C, 0x3C, 0x1C, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, - 0xDF, 0x8F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x01, 0x01, 0x00, 0x03, 0x07, 0x0F, 0x3F, - 0x7F, 0xFC, 0xF8, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x07, 0x0F, 0x0F, 0x0F, 0x0E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, - 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0E, 0x0E, 0x0E, - 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFC, 0xFC, 0xFC, 0xE0, 0x78, 0x1C, 0x0E, - 0x0E, 0x0E, 0x3E, 0xFE, 0xFC, 0xF8, 0xE0, 0xF8, 0x1C, 0x0C, 0x0E, 0x0E, 0x1E, 0xFE, 0xFC, 0xFC, - 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xFC, 0xFC, 0xFC, 0xFC, 0xE0, 0x70, - 0x38, 0x1C, 0x0C, 0x0E, 0x0E, 0x0E, 0x0E, 0x1E, 0x1E, 0x7E, 0xFC, 0xFC, 0xF8, 0xE0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, - 0xF0, 0xF8, 0xF8, 0x7C, 0x3C, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x1E, 0x1C, 0x7C, 0xFC, - 0xF8, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xFC, 0xFC, - 0xFC, 0xFC, 0xE0, 0x70, 0x38, 0x1C, 0x0C, 0x0E, 0x0E, 0x0E, 0x0E, 0x1E, 0x1E, 0x3C, 0xFC, 0xF8, - 0xF8, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, - 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x7F, 0xFF, 0xFF, 0xFF, 0xE0, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xFF, 0xFF, 0xFF, 0x3F, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x7F, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x1E, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1E, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x07, 0x0E, 0x0E, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1E, 0x1E, 0x0F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0x3C, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x1C, - 0x1C, 0x78, 0xE0, 0xFE, 0xFE, 0xFE, 0xFE, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1C, 0xFC, 0xFC, 0xFC, 0xF8, 0x80, 0xE0, 0xF0, 0x78, 0x7C, 0x3C, 0x1E, 0x1E, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, - 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x7F, 0xFF, - 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x07, - 0x0F, 0x0F, 0x1E, 0x1E, 0x1C, 0x1C, 0x1C, 0x1C, 0x0C, 0x0E, 0x07, 0x03, 0x01, 0xFF, 0xFF, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, - 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF8, 0xF8, 0xF8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xF8, 0xF8, 0x7C, 0x1C, 0x1E, 0x0E, 0x0E, - 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x1C, 0x3C, 0xFC, 0xF8, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x1F, 0x3F, 0x3F, 0x7E, 0x78, 0xF8, 0xF0, 0xF0, 0xF0, 0xE0, - 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x03, 0x03, 0x07, 0x8F, 0xFF, 0xFF, 0xFE, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x07, 0x07, 0x0F, 0x0E, 0x1E, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x0E, - 0x0E, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0F, 0x0F, 0x1F, 0x1E, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x3C, 0xFC, 0xFC, 0xFC, 0xF0, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xFC, 0xFC, 0xFC, 0x3C, - 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x3F, 0xFF, 0xFF, 0xFE, 0xF0, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xFE, 0xFF, 0xFF, 0x3F, 0x07, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x1F, 0xFF, 0xFF, 0xFE, 0xF0, 0x80, - 0xC0, 0xF8, 0xFE, 0xFF, 0x7F, 0x1F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x0F, 0x1F, 0x1E, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x0C, 0x0E, 0x06, 0x07, 0x01, 0x03, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0xC0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xC0, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0C, 0x3C, 0x7C, - 0xFC, 0xF8, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0xF8, 0xFC, - 0x7C, 0x1C, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, - 0x00, 0x00, 0x00, 0xE0, 0xFE, 0xFE, 0x1E, 0x3E, 0xFE, 0xFE, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xF0, - 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x07, 0x0F, 0x1F, 0xFE, 0xFC, 0xF0, 0xF8, 0xFC, 0xBE, 0x1F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xF0, 0xC0, 0xF8, - 0xFF, 0x7F, 0x0F, 0x01, 0x00, 0x00, 0x01, 0x0F, 0xFF, 0xFF, 0xF8, 0x80, 0xFC, 0xFF, 0xFF, 0xFF, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xFC, 0x7E, - 0x3F, 0x1F, 0x07, 0x03, 0x03, 0x07, 0x1F, 0x3F, 0xFE, 0xF8, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0F, 0x0F, 0x0F, 0x0E, 0x0C, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0C, 0x3C, 0xFC, 0xFC, 0xFC, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0xFC, 0xFC, 0x3C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x9C, - 0xDC, 0xFC, 0xFC, 0xFC, 0x7C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x07, 0x1F, 0x7F, 0xFF, 0xFC, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, - 0xFC, 0xFF, 0xFF, 0x1F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0x7E, 0x3F, 0x1F, 0x0F, 0x07, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x0F, 0x3F, 0xFF, 0xFE, 0xF8, 0xC0, 0x80, 0xF0, 0xFC, 0xFF, 0x7F, 0x0F, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, - 0xF0, 0xF8, 0xFC, 0x7E, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC7, 0xFF, 0xFF, 0xFF, 0x3F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, - 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x38, 0x38, 0x3C, 0x3C, - 0x1E, 0x1F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, -}; - - - diff --git a/src/res/_fnt_5x7.h b/src/res/_fnt_5x7.h deleted file mode 100644 index 44c1e61..0000000 --- a/src/res/_fnt_5x7.h +++ /dev/null @@ -1,302 +0,0 @@ -/****************************************************************************** -font5x7.h -Definition for small font - -This file was imported from the MicroView library, written by GeekAmmo -(https://github.com/geekammo/MicroView-Arduino-Library), and released under -the terms of the GNU General Public License as published by the Free Software -Foundation, either version 3 of the License, or (at your option) any later -version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Modified by: -Emil Varughese @ Edwin Robotics Pvt. Ltd. -July 27, 2015 -https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/ - -******************************************************************************/ -#pragma once - -// Define the font attributes -#define FONT_5X7_WIDTH 5 -#define FONT_5X7_HEIGHT 8 -#define FONT_5X7_START 0 -#define FONT_5X7_NCHAR 255 -#define FONT_5X7_MAP_WIDTH 1275 -#define FONT_5X7_NAME "5 x 7" - -// Standard ASCII 5x7 font -#if defined(ARDUINO_ARCH_MBED) - // ARDUINO_ARCH_MBED (APOLLO3 v2) does not support or require pgmspace.h / PROGMEM - static const uint8_t font5x7_data[] = { -#elif defined(__AVR__) || defined(__arm__) || defined(__ARDUINO_ARC__) -// #include - static const uint8_t font5x7_data[] PROGMEM = { -#else -// #include - static const uint8_t font5x7_data[] PROGMEM = { -#endif - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, - 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, - 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, - 0x18, 0x3C, 0x7E, 0x3C, 0x18, - 0x1C, 0x57, 0x7D, 0x57, 0x1C, - 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, - 0x00, 0x18, 0x3C, 0x18, 0x00, - 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, - 0x00, 0x18, 0x24, 0x18, 0x00, - 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, - 0x30, 0x48, 0x3A, 0x06, 0x0E, - 0x26, 0x29, 0x79, 0x29, 0x26, - 0x40, 0x7F, 0x05, 0x05, 0x07, - 0x40, 0x7F, 0x05, 0x25, 0x3F, - 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, - 0x7F, 0x3E, 0x1C, 0x1C, 0x08, - 0x08, 0x1C, 0x1C, 0x3E, 0x7F, - 0x14, 0x22, 0x7F, 0x22, 0x14, - 0x5F, 0x5F, 0x00, 0x5F, 0x5F, - 0x06, 0x09, 0x7F, 0x01, 0x7F, - 0x00, 0x66, 0x89, 0x95, 0x6A, - 0x60, 0x60, 0x60, 0x60, 0x60, - 0x94, 0xA2, 0xFF, 0xA2, 0x94, - 0x08, 0x04, 0x7E, 0x04, 0x08, - 0x10, 0x20, 0x7E, 0x20, 0x10, - 0x08, 0x08, 0x2A, 0x1C, 0x08, - 0x08, 0x1C, 0x2A, 0x08, 0x08, - 0x1E, 0x10, 0x10, 0x10, 0x10, - 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, - 0x30, 0x38, 0x3E, 0x38, 0x30, - 0x06, 0x0E, 0x3E, 0x0E, 0x06, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x5F, 0x00, 0x00, - 0x00, 0x07, 0x00, 0x07, 0x00, - 0x14, 0x7F, 0x14, 0x7F, 0x14, - 0x24, 0x2A, 0x7F, 0x2A, 0x12, - 0x23, 0x13, 0x08, 0x64, 0x62, - 0x36, 0x49, 0x56, 0x20, 0x50, - 0x00, 0x08, 0x07, 0x03, 0x00, - 0x00, 0x1C, 0x22, 0x41, 0x00, - 0x00, 0x41, 0x22, 0x1C, 0x00, - 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, - 0x08, 0x08, 0x3E, 0x08, 0x08, - 0x00, 0x80, 0x70, 0x30, 0x00, - 0x08, 0x08, 0x08, 0x08, 0x08, - 0x00, 0x00, 0x60, 0x60, 0x00, - 0x20, 0x10, 0x08, 0x04, 0x02, - 0x3E, 0x51, 0x49, 0x45, 0x3E, - 0x00, 0x42, 0x7F, 0x40, 0x00, - 0x72, 0x49, 0x49, 0x49, 0x46, - 0x21, 0x41, 0x49, 0x4D, 0x33, - 0x18, 0x14, 0x12, 0x7F, 0x10, - 0x27, 0x45, 0x45, 0x45, 0x39, - 0x3C, 0x4A, 0x49, 0x49, 0x31, - 0x41, 0x21, 0x11, 0x09, 0x07, - 0x36, 0x49, 0x49, 0x49, 0x36, - 0x46, 0x49, 0x49, 0x29, 0x1E, - 0x00, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x40, 0x34, 0x00, 0x00, - 0x00, 0x08, 0x14, 0x22, 0x41, - 0x14, 0x14, 0x14, 0x14, 0x14, - 0x00, 0x41, 0x22, 0x14, 0x08, - 0x02, 0x01, 0x59, 0x09, 0x06, - 0x3E, 0x41, 0x5D, 0x59, 0x4E, - 0x7C, 0x12, 0x11, 0x12, 0x7C, - 0x7F, 0x49, 0x49, 0x49, 0x36, - 0x3E, 0x41, 0x41, 0x41, 0x22, - 0x7F, 0x41, 0x41, 0x41, 0x3E, - 0x7F, 0x49, 0x49, 0x49, 0x41, - 0x7F, 0x09, 0x09, 0x09, 0x01, - 0x3E, 0x41, 0x41, 0x51, 0x73, - 0x7F, 0x08, 0x08, 0x08, 0x7F, - 0x00, 0x41, 0x7F, 0x41, 0x00, - 0x20, 0x40, 0x41, 0x3F, 0x01, - 0x7F, 0x08, 0x14, 0x22, 0x41, - 0x7F, 0x40, 0x40, 0x40, 0x40, - 0x7F, 0x02, 0x1C, 0x02, 0x7F, - 0x7F, 0x04, 0x08, 0x10, 0x7F, - 0x3E, 0x41, 0x41, 0x41, 0x3E, - 0x7F, 0x09, 0x09, 0x09, 0x06, - 0x3E, 0x41, 0x51, 0x21, 0x5E, - 0x7F, 0x09, 0x19, 0x29, 0x46, - 0x26, 0x49, 0x49, 0x49, 0x32, - 0x03, 0x01, 0x7F, 0x01, 0x03, - 0x3F, 0x40, 0x40, 0x40, 0x3F, - 0x1F, 0x20, 0x40, 0x20, 0x1F, - 0x3F, 0x40, 0x38, 0x40, 0x3F, - 0x63, 0x14, 0x08, 0x14, 0x63, - 0x03, 0x04, 0x78, 0x04, 0x03, - 0x61, 0x59, 0x49, 0x4D, 0x43, - 0x00, 0x7F, 0x41, 0x41, 0x41, - 0x02, 0x04, 0x08, 0x10, 0x20, - 0x00, 0x41, 0x41, 0x41, 0x7F, - 0x04, 0x02, 0x01, 0x02, 0x04, - 0x40, 0x40, 0x40, 0x40, 0x40, - 0x00, 0x03, 0x07, 0x08, 0x00, - 0x20, 0x54, 0x54, 0x78, 0x40, - 0x7F, 0x28, 0x44, 0x44, 0x38, - 0x38, 0x44, 0x44, 0x44, 0x28, - 0x38, 0x44, 0x44, 0x28, 0x7F, - 0x38, 0x54, 0x54, 0x54, 0x18, - 0x00, 0x08, 0x7E, 0x09, 0x02, - 0x18, 0xA4, 0xA4, 0x9C, 0x78, - 0x7F, 0x08, 0x04, 0x04, 0x78, - 0x00, 0x44, 0x7D, 0x40, 0x00, - 0x20, 0x40, 0x40, 0x3D, 0x00, - 0x7F, 0x10, 0x28, 0x44, 0x00, - 0x00, 0x41, 0x7F, 0x40, 0x00, - 0x7C, 0x04, 0x78, 0x04, 0x78, - 0x7C, 0x08, 0x04, 0x04, 0x78, - 0x38, 0x44, 0x44, 0x44, 0x38, - 0xFC, 0x18, 0x24, 0x24, 0x18, - 0x18, 0x24, 0x24, 0x18, 0xFC, - 0x7C, 0x08, 0x04, 0x04, 0x08, - 0x48, 0x54, 0x54, 0x54, 0x24, - 0x04, 0x04, 0x3F, 0x44, 0x24, - 0x3C, 0x40, 0x40, 0x20, 0x7C, - 0x1C, 0x20, 0x40, 0x20, 0x1C, - 0x3C, 0x40, 0x30, 0x40, 0x3C, - 0x44, 0x28, 0x10, 0x28, 0x44, - 0x4C, 0x90, 0x90, 0x90, 0x7C, - 0x44, 0x64, 0x54, 0x4C, 0x44, - 0x00, 0x08, 0x36, 0x41, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, - 0x00, 0x41, 0x36, 0x08, 0x00, - 0x02, 0x01, 0x02, 0x04, 0x02, - 0x3C, 0x26, 0x23, 0x26, 0x3C, - 0x1E, 0xA1, 0xA1, 0x61, 0x12, - 0x3A, 0x40, 0x40, 0x20, 0x7A, - 0x38, 0x54, 0x54, 0x55, 0x59, - 0x21, 0x55, 0x55, 0x79, 0x41, - 0x21, 0x54, 0x54, 0x78, 0x41, - 0x21, 0x55, 0x54, 0x78, 0x40, - 0x20, 0x54, 0x55, 0x79, 0x40, - 0x0C, 0x1E, 0x52, 0x72, 0x12, - 0x39, 0x55, 0x55, 0x55, 0x59, - 0x39, 0x54, 0x54, 0x54, 0x59, - 0x39, 0x55, 0x54, 0x54, 0x58, - 0x00, 0x00, 0x45, 0x7C, 0x41, - 0x00, 0x02, 0x45, 0x7D, 0x42, - 0x00, 0x01, 0x45, 0x7C, 0x40, - 0xF0, 0x29, 0x24, 0x29, 0xF0, - 0xF0, 0x28, 0x25, 0x28, 0xF0, - 0x7C, 0x54, 0x55, 0x45, 0x00, - 0x20, 0x54, 0x54, 0x7C, 0x54, - 0x7C, 0x0A, 0x09, 0x7F, 0x49, - 0x32, 0x49, 0x49, 0x49, 0x32, - 0x32, 0x48, 0x48, 0x48, 0x32, - 0x32, 0x4A, 0x48, 0x48, 0x30, - 0x3A, 0x41, 0x41, 0x21, 0x7A, - 0x3A, 0x42, 0x40, 0x20, 0x78, - 0x00, 0x9D, 0xA0, 0xA0, 0x7D, - 0x39, 0x44, 0x44, 0x44, 0x39, - 0x3D, 0x40, 0x40, 0x40, 0x3D, - 0x3C, 0x24, 0xFF, 0x24, 0x24, - 0x48, 0x7E, 0x49, 0x43, 0x66, - 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, - 0xFF, 0x09, 0x29, 0xF6, 0x20, - 0xC0, 0x88, 0x7E, 0x09, 0x03, - 0x20, 0x54, 0x54, 0x79, 0x41, - 0x00, 0x00, 0x44, 0x7D, 0x41, - 0x30, 0x48, 0x48, 0x4A, 0x32, - 0x38, 0x40, 0x40, 0x22, 0x7A, - 0x00, 0x7A, 0x0A, 0x0A, 0x72, - 0x7D, 0x0D, 0x19, 0x31, 0x7D, - 0x26, 0x29, 0x29, 0x2F, 0x28, - 0x26, 0x29, 0x29, 0x29, 0x26, - 0x30, 0x48, 0x4D, 0x40, 0x20, - 0x38, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x38, - 0x2F, 0x10, 0xC8, 0xAC, 0xBA, - 0x2F, 0x10, 0x28, 0x34, 0xFA, - 0x00, 0x00, 0x7B, 0x00, 0x00, - 0x08, 0x14, 0x2A, 0x14, 0x22, - 0x22, 0x14, 0x2A, 0x14, 0x08, - 0xAA, 0x00, 0x55, 0x00, 0xAA, - 0xAA, 0x55, 0xAA, 0x55, 0xAA, - 0x00, 0x00, 0x00, 0xFF, 0x00, - 0x10, 0x10, 0x10, 0xFF, 0x00, - 0x14, 0x14, 0x14, 0xFF, 0x00, - 0x10, 0x10, 0xFF, 0x00, 0xFF, - 0x10, 0x10, 0xF0, 0x10, 0xF0, - 0x14, 0x14, 0x14, 0xFC, 0x00, - 0x14, 0x14, 0xF7, 0x00, 0xFF, - 0x00, 0x00, 0xFF, 0x00, 0xFF, - 0x14, 0x14, 0xF4, 0x04, 0xFC, - 0x14, 0x14, 0x17, 0x10, 0x1F, - 0x10, 0x10, 0x1F, 0x10, 0x1F, - 0x14, 0x14, 0x14, 0x1F, 0x00, - 0x10, 0x10, 0x10, 0xF0, 0x00, - 0x00, 0x00, 0x00, 0x1F, 0x10, - 0x10, 0x10, 0x10, 0x1F, 0x10, - 0x10, 0x10, 0x10, 0xF0, 0x10, - 0x00, 0x00, 0x00, 0xFF, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0xFF, 0x10, - 0x00, 0x00, 0x00, 0xFF, 0x14, - 0x00, 0x00, 0xFF, 0x00, 0xFF, - 0x00, 0x00, 0x1F, 0x10, 0x17, - 0x00, 0x00, 0xFC, 0x04, 0xF4, - 0x14, 0x14, 0x17, 0x10, 0x17, - 0x14, 0x14, 0xF4, 0x04, 0xF4, - 0x00, 0x00, 0xFF, 0x00, 0xF7, - 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0xF7, 0x00, 0xF7, - 0x14, 0x14, 0x14, 0x17, 0x14, - 0x10, 0x10, 0x1F, 0x10, 0x1F, - 0x14, 0x14, 0x14, 0xF4, 0x14, - 0x10, 0x10, 0xF0, 0x10, 0xF0, - 0x00, 0x00, 0x1F, 0x10, 0x1F, - 0x00, 0x00, 0x00, 0x1F, 0x14, - 0x00, 0x00, 0x00, 0xFC, 0x14, - 0x00, 0x00, 0xF0, 0x10, 0xF0, - 0x10, 0x10, 0xFF, 0x10, 0xFF, - 0x14, 0x14, 0x14, 0xFF, 0x14, - 0x10, 0x10, 0x10, 0x1F, 0x00, - 0x00, 0x00, 0x00, 0xF0, 0x10, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x38, 0x44, 0x44, 0x38, 0x44, - 0x7C, 0x2A, 0x2A, 0x3E, 0x14, - 0x7E, 0x02, 0x02, 0x06, 0x06, - 0x02, 0x7E, 0x02, 0x7E, 0x02, - 0x63, 0x55, 0x49, 0x41, 0x63, - 0x38, 0x44, 0x44, 0x3C, 0x04, - 0x40, 0x7E, 0x20, 0x1E, 0x20, - 0x06, 0x02, 0x7E, 0x02, 0x02, - 0x99, 0xA5, 0xE7, 0xA5, 0x99, - 0x1C, 0x2A, 0x49, 0x2A, 0x1C, - 0x4C, 0x72, 0x01, 0x72, 0x4C, - 0x30, 0x4A, 0x4D, 0x4D, 0x30, - 0x30, 0x48, 0x78, 0x48, 0x30, - 0xBC, 0x62, 0x5A, 0x46, 0x3D, - 0x3E, 0x49, 0x49, 0x49, 0x00, - 0x7E, 0x01, 0x01, 0x01, 0x7E, - 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, - 0x44, 0x44, 0x5F, 0x44, 0x44, - 0x40, 0x51, 0x4A, 0x44, 0x40, - 0x40, 0x44, 0x4A, 0x51, 0x40, - 0x00, 0x00, 0xFF, 0x01, 0x03, - 0xE0, 0x80, 0xFF, 0x00, 0x00, - 0x08, 0x08, 0x6B, 0x6B, 0x08, - 0x36, 0x12, 0x36, 0x24, 0x36, - 0x06, 0x0F, 0x09, 0x0F, 0x06, - 0x00, 0x00, 0x18, 0x18, 0x00, - 0x00, 0x00, 0x10, 0x10, 0x00, - 0x30, 0x40, 0xFF, 0x01, 0x01, - 0x00, 0x1F, 0x01, 0x01, 0x1E, - 0x00, 0x19, 0x1D, 0x17, 0x12, - 0x00, 0x3C, 0x3C, 0x3C, 0x3C, - 0x00, 0x00, 0x00, 0x00, 0x00 -}; - diff --git a/src/res/_fnt_7segment.h b/src/res/_fnt_7segment.h deleted file mode 100644 index 5b2f8d1..0000000 --- a/src/res/_fnt_7segment.h +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** -7segment.h -Definition for 7-segment font - -This file was imported from the MicroView library, written by GeekAmmo -(https://github.com/geekammo/MicroView-Arduino-Library), and released under -the terms of the GNU General Public License as published by the Free Software -Foundation, either version 3 of the License, or (at your option) any later -version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Modified by: -Emil Varughese @ Edwin Robotics Pvt. Ltd. -July 27, 2015 -https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/ - -******************************************************************************/ - -#pragma once - -// Define the font attributes -#define FONT_7SEG_WIDTH 10 -#define FONT_7SEG_HEIGHT 16 -#define FONT_7SEG_START 46 -#define FONT_7SEG_NCHAR 13 -#define FONT_7SEG_MAP_WIDTH 130 -#define FONT_7SEG_NAME "7 Segment" - -#if defined(ARDUINO_ARCH_MBED) - // ARDUINO_ARCH_MBED (APOLLO3 v2) does not support or require pgmspace.h / PROGMEM - static const uint8_t segment7_data [] = { -#elif defined(__AVR__) || defined(__arm__) || defined(__ARDUINO_ARC__) - static const uint8_t segment7_data [] PROGMEM = { -#else - static const uint8_t segment7_data [] PROGMEM = { -#endif - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x78, 0xFC, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0xFC, 0x78, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7E, 0x00, 0x00, 0x02, 0x83, 0x83, 0x83, 0x83, 0x02, - 0xFC, 0x78, 0x00, 0x00, 0x02, 0x83, 0x83, 0x83, 0x83, 0x02, 0xFC, 0x78, 0x7E, 0xFF, 0x00, 0x80, - 0x80, 0x80, 0x80, 0x00, 0xFF, 0x7E, 0x78, 0xFC, 0x02, 0x83, 0x83, 0x83, 0x83, 0x02, 0x00, 0x00, - 0x78, 0xFC, 0x02, 0x83, 0x83, 0x83, 0x83, 0x02, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x02, 0xFC, 0x78, 0x78, 0xFC, 0x02, 0x83, 0x83, 0x83, 0x83, 0x02, 0xFC, 0x78, 0x78, 0xFC, - 0x02, 0x83, 0x83, 0x83, 0x83, 0x02, 0xFC, 0x78, 0x00, 0x00, 0x00, 0X00, 0x18, 0x3C, 0x3C, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xF0, 0xF0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x3F, 0x40, 0xC0, 0xC0, 0xC0, 0xC0, 0x40, 0x3F, 0x1E, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7E, 0x1C, 0x3E, 0x41, 0xC1, 0xC1, 0xC1, - 0xC1, 0x41, 0x00, 0x00, 0x00, 0x00, 0x41, 0xC1, 0xC1, 0xC1, 0xC1, 0x41, 0x3E, 0x1C, 0x00, 0x00, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0x7E, 0x00, 0x00, 0x41, 0xC1, 0xC1, 0xC1, 0xC1, 0x41, - 0x3E, 0x1C, 0x1C, 0x3E, 0x41, 0xC1, 0xC1, 0xC1, 0xC1, 0x41, 0x3E, 0x1C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7E, 0x1C, 0x3E, 0x41, 0xC1, 0xC1, 0xC1, 0xC1, 0x41, 0x3E, 0x1C, - 0x00, 0x00, 0x41, 0xC1, 0xC1, 0xC1, 0xC1, 0x41, 0x3E, 0x1C, 0x00, 0x00, 0x00, 0X00, 0x18, 0x3C, - 0x3C, 0x18, 0x00, 0x00 - -}; - - diff --git a/src/res/_fnt_8x16.h b/src/res/_fnt_8x16.h deleted file mode 100644 index dabff9d..0000000 --- a/src/res/_fnt_8x16.h +++ /dev/null @@ -1,143 +0,0 @@ -/****************************************************************************** -font8x16.h -Definition for medium font - -This file was imported from the MicroView library, written by GeekAmmo -(https://github.com/geekammo/MicroView-Arduino-Library), and released under -the terms of the GNU General Public License as published by the Free Software -Foundation, either version 3 of the License, or (at your option) any later -version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Modified by: -Emil Varughese @ Edwin Robotics Pvt. Ltd. -July 27, 2015 -https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/ -******************************************************************************/ - -#pragma once - - - -// Define the font attributes -#define FONT_8X16_WIDTH 8 -#define FONT_8X16_HEIGHT 16 -#define FONT_8X16_START 32 -#define FONT_8X16_NCHAR 96 -#define FONT_8X16_MAP_WIDTH 256 -#define FONT_8X16_NAME "8 x 16" - -#if defined(ARDUINO_ARCH_MBED) - // ARDUINO_ARCH_MBED (APOLLO3 v2) does not support or require pgmspace.h / PROGMEM - static const uint8_t font8x16_data[] = { -#elif defined(__AVR__) || defined(__arm__) || defined(__ARDUINO_ARC__) - static const uint8_t font8x16_data[] PROGMEM = { -#else - static const uint8_t font8x16_data[] PROGMEM = { -#endif - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xBE, 0x90, 0xD0, 0xBE, 0x90, 0x00, - 0x00, 0x1C, 0x62, 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x0C, 0x12, 0x92, 0x4C, 0xB0, 0x88, 0x06, 0x00, - 0x80, 0x7C, 0x62, 0xB2, 0x1C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xE0, 0x18, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, - 0x00, 0x24, 0x18, 0x7E, 0x18, 0x24, 0x00, 0x00, 0x80, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x06, 0x00, 0x00, - 0xF8, 0x04, 0xC2, 0x32, 0x0C, 0xF8, 0x00, 0x00, 0x00, 0x04, 0x04, 0xFE, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x82, 0x42, 0x22, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x22, 0x22, 0x22, 0xDC, 0x00, 0x00, - 0xC0, 0xA0, 0x98, 0x84, 0xFE, 0x80, 0x80, 0x00, 0x00, 0x1E, 0x12, 0x12, 0x22, 0xC2, 0x00, 0x00, - 0xF8, 0x44, 0x22, 0x22, 0x22, 0xC0, 0x00, 0x00, 0x00, 0x02, 0x02, 0xC2, 0x32, 0x0A, 0x06, 0x00, - 0x00, 0x8C, 0x52, 0x22, 0x52, 0x8C, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x26, 0xF8, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, - 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x00, 0x00, 0x02, 0x82, 0x42, 0x22, 0x1C, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x04, 0x0F, 0x04, 0x03, 0x00, 0x00, 0x04, 0x02, 0x01, 0x03, 0x04, 0x04, 0x03, 0x00, - 0x03, 0x04, 0x04, 0x04, 0x05, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x06, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x06, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x07, 0x04, 0x04, 0x00, 0x00, - 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, - 0x01, 0x02, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x04, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, - 0x04, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF8, 0x04, 0x72, 0x8A, 0xFA, 0x84, 0x78, 0x00, 0x00, 0xC0, 0x38, 0x06, 0x38, 0xC0, 0x00, 0x00, - 0x00, 0xFE, 0x22, 0x22, 0x22, 0xDC, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, - 0xFE, 0x02, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00, 0x00, 0xFE, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, - 0x00, 0xFE, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x22, 0xE2, 0x00, 0x00, - 0xFE, 0x20, 0x20, 0x20, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x02, 0xFE, 0x00, 0x00, 0xFE, 0x40, 0xB0, 0x08, 0x04, 0x02, 0x00, 0x00, - 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x0C, 0x70, 0x80, 0x70, 0x0C, 0xFE, 0x00, - 0xFE, 0x0C, 0x30, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00, - 0xFE, 0x42, 0x42, 0x42, 0x22, 0x1C, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00, - 0x00, 0xFE, 0x42, 0x42, 0xA2, 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x42, 0x42, 0x80, 0x00, 0x00, - 0x02, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x02, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, - 0x06, 0x38, 0xC0, 0x00, 0xC0, 0x38, 0x06, 0x00, 0x3E, 0xC0, 0xF0, 0x0E, 0xF0, 0xC0, 0x3E, 0x00, - 0x00, 0x06, 0x98, 0x60, 0x98, 0x06, 0x00, 0x00, 0x00, 0x06, 0x18, 0xE0, 0x18, 0x06, 0x00, 0x00, - 0x02, 0x02, 0xC2, 0x32, 0x0A, 0x06, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x02, 0x00, - 0x00, 0x06, 0x18, 0x60, 0x80, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, - 0x40, 0x30, 0x0C, 0x0C, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x02, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x06, 0x00, - 0x00, 0x07, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, - 0x07, 0x04, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x04, 0x07, 0x04, 0x04, 0x00, 0x00, - 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00, - 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0C, 0x12, 0x11, 0x10, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x06, 0x01, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, - 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, - 0x00, 0xE0, 0x10, 0x10, 0x10, 0xFE, 0x00, 0x00, 0x00, 0xE0, 0x90, 0x90, 0x90, 0xE0, 0x00, 0x00, - 0x00, 0x20, 0xFC, 0x22, 0x22, 0x22, 0x02, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, - 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x10, 0x10, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x10, 0x10, 0xF2, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x80, 0x40, 0x20, 0x10, 0x00, 0x00, - 0x00, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x20, 0x10, 0xF0, 0x20, 0x10, 0xF0, 0x00, - 0x00, 0xF0, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xE0, 0x00, 0x00, - 0x00, 0xF0, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, - 0x00, 0xF0, 0x20, 0x10, 0x10, 0x70, 0x00, 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x20, 0xFC, 0x20, 0x20, 0x20, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0x70, 0x80, 0x00, 0x80, 0x70, 0x00, 0x00, 0xF0, 0x00, 0xC0, 0x30, 0xC0, 0x00, 0xF0, 0x00, - 0x00, 0x30, 0xC0, 0xC0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0xC0, 0x00, 0x80, 0x70, 0x00, 0x00, - 0x00, 0x10, 0x10, 0x90, 0x50, 0x30, 0x00, 0x00, 0x00, 0x80, 0x80, 0x7E, 0x02, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x7E, 0x80, 0x80, 0x00, 0x00, - 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00, - 0x00, 0x07, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, - 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x24, 0x24, 0x22, 0x1F, 0x00, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, - 0x00, 0x3F, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x3F, 0x00, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x04, 0x03, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x00, 0x01, 0x06, 0x01, 0x00, - 0x00, 0x06, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x20, 0x20, 0x31, 0x0E, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x06, 0x05, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - - diff --git a/src/res/_fnt_largenum.h b/src/res/_fnt_largenum.h deleted file mode 100644 index b1e8e70..0000000 --- a/src/res/_fnt_largenum.h +++ /dev/null @@ -1,96 +0,0 @@ -/****************************************************************************** -fontlargenumber.h -Definition for large font - -This file was imported from the MicroView library, written by GeekAmmo -(https://github.com/geekammo/MicroView-Arduino-Library), and released under -the terms of the GNU General Public License as published by the Free Software -Foundation, either version 3 of the License, or (at your option) any later -version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Modified by: -Emil Varughese @ Edwin Robotics Pvt. Ltd. -July 27, 2015 -https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/ - -******************************************************************************/ -#pragma once - - -// Define the font attributes -#define FONT_LARGENUM_WIDTH 12 -#define FONT_LARGENUM_HEIGHT 48 -#define FONT_LARGENUM_START 48 -#define FONT_LARGENUM_NCHAR 11 -#define FONT_LARGENUM_MAP_WIDTH 132 -#define FONT_LARGENUM_NAME "Large Number" - -#if defined(ARDUINO_ARCH_MBED) - // ARDUINO_ARCH_MBED (APOLLO3 v2) does not support or require pgmspace.h / PROGMEM - static const uint8_t fontlargenum_data[] = { -#elif defined(__AVR__) || defined(__arm__) || defined(__ARDUINO_ARC__) - static const uint8_t fontlargenum_data[] PROGMEM = { -#else - static const uint8_t fontlargenum_data[] PROGMEM = { -#endif - 0x00, 0xC0, 0xF8, 0x7C, 0x3E, 0x3E, 0xFC, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, - 0x78, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7C, 0x3C, 0x3E, 0x3E, 0xFE, 0xFC, - 0xE0, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x3E, 0x3E, 0x3E, 0xFE, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x3E, - 0x3E, 0x3E, 0x3E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xFC, 0x3E, 0x3E, 0x3E, - 0xFC, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0xFE, 0xFE, 0x00, 0x00, - 0x00, 0x00, 0xC0, 0xF8, 0xFE, 0x3E, 0x7E, 0xFC, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, - 0x7E, 0x3E, 0xFE, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xC0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xF9, 0xFF, 0xFF, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x07, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x3F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFC, - 0x7F, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0xFE, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3F, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFE, 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, - 0xFC, 0xFF, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFE, 0x3F, 0x03, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x3E, 0x7E, 0xFC, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x80, 0xF0, 0x7C, 0x7C, 0xF8, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xF8, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x9F, 0xFF, 0xF8, 0xFE, 0x1F, - 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0xFC, - 0x7F, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFE, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xE7, 0xE0, - 0xE0, 0xE0, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, - 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFC, 0x3F, - 0x03, 0x03, 0x1F, 0xFF, 0xFC, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x3E, 0x3E, 0x0F, 0x01, - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFE, 0x0F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x7F, 0x00, 0x00, 0x00, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xC0, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x80, - 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xFC, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1F, 0x3F, 0x7C, 0x7C, 0x3F, 0x1F, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7F, 0x7F, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7C, - 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7E, 0x7C, 0x7C, 0x7E, 0x1F, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1F, 0x3E, 0x7C, 0x7C, 0x3E, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1F, - 0x7F, 0x7C, 0x7C, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1F, 0x3F, 0x7E, 0x7C, 0x7E, 0x3F, 0x1F, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x3E, 0x7C, 0x7C, 0x7E, 0x3F, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - - diff --git a/src/res/qw_bmp_sparkfun.h b/src/res/qw_bmp_sparkfun.h deleted file mode 100644 index ef7cad0..0000000 --- a/src/res/qw_bmp_sparkfun.h +++ /dev/null @@ -1,67 +0,0 @@ -// qw_bmp_sparkun.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -#pragma once - -#include "qwiic_resdef.h" - -class QwBMPSparkFun final : public bmpSingleton { - -public: - const uint8_t* data(void) - { - -#include "_bmp_sparkfun.h" - - return bmp_sparkfun_data; - } - - QwBMPSparkFun() - : bmpSingleton(BMP_SPARKFUN_WIDTH, BMP_SPARKFUN_HEIGHT) - { - } -}; - -#define QW_BMP_SPARKFUN QwBMPSparkFun::instance() \ No newline at end of file diff --git a/src/res/qw_bmp_truck.h b/src/res/qw_bmp_truck.h deleted file mode 100644 index 8b9e797..0000000 --- a/src/res/qw_bmp_truck.h +++ /dev/null @@ -1,67 +0,0 @@ -// qw_bmp_truck.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -#pragma once - -#include "qwiic_resdef.h" - -class QwBMPTruck final : public bmpSingleton { - -public: - const uint8_t* data(void) - { - -#include "_bmp_truck.h" - - return bmp_truck_data; - } - - QwBMPTruck() - : bmpSingleton(BMP_TRUCK_WIDTH, BMP_TRUCK_HEIGHT) - { - } -}; - -#define QW_BMP_TRUCK QwBMPTruck::instance() \ No newline at end of file diff --git a/src/res/qw_fnt_31x48.h b/src/res/qw_fnt_31x48.h deleted file mode 100644 index 95e5abe..0000000 --- a/src/res/qw_fnt_31x48.h +++ /dev/null @@ -1,74 +0,0 @@ -// qw_fnt_31x48.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -#pragma once - -#include "qwiic_resdef.h" - -class QwFont31x48 final : public fontSingleton { - -public: - const uint8_t* data(void) - { - // include font data (static const), and attribute defines. - // Doing this here makes the data variable a static (aka only one instance ever) - // variable in this method. -#include "_fnt_31x48.h" - - return font31x48_data; - } - - QwFont31x48() - : fontSingleton(FONT_31X48_WIDTH, - FONT_31X48_HEIGHT, - FONT_31X48_START, - FONT_31X48_NCHAR, - FONT_31X48_MAP_WIDTH, - FONT_31X48_NAME) - { - } -}; - -#define QW_FONT_31X48 QwFont31x48::instance() \ No newline at end of file diff --git a/src/res/qw_fnt_5x7.h b/src/res/qw_fnt_5x7.h deleted file mode 100644 index 93e83e3..0000000 --- a/src/res/qw_fnt_5x7.h +++ /dev/null @@ -1,74 +0,0 @@ -// qw_fnt_5x7.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -#pragma once - -#include "qwiic_resdef.h" - -class QwFont5x7 final : public fontSingleton { - -public: - const uint8_t* data(void) - { - // include font data (static const), and attribute defines. - // Doing this here makes the data variable a static (aka only one instance ever) - // variable in this method. -#include "_fnt_5x7.h" - - return font5x7_data; - } - - QwFont5x7() - : fontSingleton(FONT_5X7_WIDTH, - FONT_5X7_HEIGHT, - FONT_5X7_START, - FONT_5X7_NCHAR, - FONT_5X7_MAP_WIDTH, - FONT_5X7_NAME) - { - } -}; - -#define QW_FONT_5X7 QwFont5x7::instance() \ No newline at end of file diff --git a/src/res/qw_fnt_7segment.h b/src/res/qw_fnt_7segment.h deleted file mode 100644 index ab3dafb..0000000 --- a/src/res/qw_fnt_7segment.h +++ /dev/null @@ -1,74 +0,0 @@ -// qw_fnt_7segment.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -#pragma once - -#include "qwiic_resdef.h" - -class QwFont7Segment final : public fontSingleton { - -public: - const uint8_t* data(void) - { - // include font data (static const), and attribute defines. - // Doing this here makes the data variable a static (aka only one instance ever) - // variable in this method. -#include "_fnt_7segment.h" - - return segment7_data; - } - - QwFont7Segment() - : fontSingleton(FONT_7SEG_WIDTH, - FONT_7SEG_HEIGHT, - FONT_7SEG_START, - FONT_7SEG_NCHAR, - FONT_7SEG_MAP_WIDTH, - FONT_7SEG_NAME) - { - } -}; - -#define QW_FONT_7SEGMENT QwFont7Segment::instance() \ No newline at end of file diff --git a/src/res/qw_fnt_8x16.h b/src/res/qw_fnt_8x16.h deleted file mode 100644 index ab28ef2..0000000 --- a/src/res/qw_fnt_8x16.h +++ /dev/null @@ -1,74 +0,0 @@ -// qw_fnt_8x16.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -#pragma once - -#include "qwiic_resdef.h" - -class QwFont8x16 final : public fontSingleton { - -public: - const uint8_t* data(void) - { - // include font data (static const), and attribute defines. - // Doing this here makes the data variable a static (aka only one instance ever) - // variable in this method. -#include "_fnt_8x16.h" - - return font8x16_data; - } - - QwFont8x16() - : fontSingleton(FONT_8X16_WIDTH, - FONT_8X16_HEIGHT, - FONT_8X16_START, - FONT_8X16_NCHAR, - FONT_8X16_MAP_WIDTH, - FONT_8X16_NAME) - { - } -}; - -#define QW_FONT_8X16 QwFont8x16::instance() \ No newline at end of file diff --git a/src/res/qw_fnt_largenum.h b/src/res/qw_fnt_largenum.h deleted file mode 100644 index 6a2e471..0000000 --- a/src/res/qw_fnt_largenum.h +++ /dev/null @@ -1,74 +0,0 @@ -// qw_fnt_largenum.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -#pragma once - -#include "qwiic_resdef.h" - -class QwFontLargeNum final : public fontSingleton { - -public: - const uint8_t* data(void) - { - // include font data (static const), and attribute defines. - // Doing this here makes the data variable a static (aka only one instance ever) - // variable in this method. -#include "_fnt_largenum.h" - - return fontlargenum_data; - } - - QwFontLargeNum() - : fontSingleton(FONT_LARGENUM_WIDTH, - FONT_LARGENUM_HEIGHT, - FONT_LARGENUM_START, - FONT_LARGENUM_NCHAR, - FONT_LARGENUM_MAP_WIDTH, - FONT_LARGENUM_NAME) - { - } -}; - -#define QW_FONT_LARGENUM QwFontLargeNum::instance() \ No newline at end of file diff --git a/src/res/qw_pgm_arduino.h b/src/res/qw_pgm_arduino.h deleted file mode 100644 index 54e3883..0000000 --- a/src/res/qw_pgm_arduino.h +++ /dev/null @@ -1,59 +0,0 @@ - -// qw_pgm_arduino.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -// File to declare pgmspace in a platform abstract (sort of ) way - -#pragma once - -#if defined(TARGET_Apollo3) -// do nothing -#elif defined(__AVR__) || defined(__arm__) || defined(__ARDUINO_ARC__) - #include - -#else - #include -#endif - diff --git a/src/res/qwiic_resdef.h b/src/res/qwiic_resdef.h deleted file mode 100644 index f9e84f3..0000000 --- a/src/res/qwiic_resdef.h +++ /dev/null @@ -1,205 +0,0 @@ -// qwiic_resdef.h -// -// This is a library written for SparkFun Qwiic OLED boards that use the SSD1306. -// -// SparkFun sells these at its website: www.sparkfun.com -// -// Do you like this library? Help support SparkFun. Buy a board! -// -// Micro OLED https://www.sparkfun.com/products/14532 -// Transparent OLED https://www.sparkfun.com/products/15173 -// "Narrow" OLED https://www.sparkfun.com/products/17153 -// -// -// Written by Kirk Benell @ SparkFun Electronics, March 2022 -// -// This library configures and draws graphics to OLED boards that use the -// SSD1306 display hardware. The library only supports I2C. -// -// Repository: -// https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -// -// Documentation: -// https://sparkfun.github.io/SparkFun_Qwiic_OLED_Arduino_Library/ -// -// -// SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT). -// -// SPDX-License-Identifier: MIT -// -// The MIT License (MIT) -// -// Copyright (c) 2022 SparkFun Electronics -// 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. - -// -// Define resource objects/structures to manage fonts and bitmaps - -// -#pragma once - -// NOTE: The way I'm including the font/resource defines, some platforms have -// include file issues - -#include "qw_pgm_arduino.h" - -#include - -//////////////////////////////////////////////////////////////////////// -// Notes Template singletons for managing resources -//////////////////////////////////////////////////////////////////////// -// -// The common use/storage of bitmap and font data is creating a static -// array and placing it in a header file. -// -// This pattern is fine for simple uses, where the bitmap is only included -// in a single file. BUT if the bitmap header is included in multiple files, -// multiple copies of the bitmap are created. -// -// You could just make the bitmap array a const - but then multiple includes -// will lead to symbol collision at link time - confusing the user. -// -// These simple classes help place the bitmap data in a singleton class AND -// only create one copy/instance of the bitmap data no matter how many times a -// resource header file is included. -// -// The Plan: -// - Define a base resource class -// - attributes as public instance vars -// - Define a constructor that init's the instance vars -// - Resource data access via virtual accessor - make it const -// -// - Create a template that subclasses the resource class, and defines a singleton -// - It ensures only once of these classes is ever created. -// -// - In a seperate header file - one for each resource, define the resource -// - For example - for a bitmap - the data array, #defines for width and height -// - The data array is declard as const static -// -// - In another header file - create a subclass of our singleton -// ex: -// class QwBMPTruck final : public bitmapSingleton { -// -// - Override the base class data accessor method -// - In the body of this method, include the resource defined header file -// - This defines the resource data as a static in this method. So only one copy is made -// ex: -// const uint8_t * bitmap(void){ -// #include "bmp_truck.h" -// return bmp_truck_data; -// } -// -// - After this resource access method, define the constructor of this class -// - This is done after so it can use the attribute #defines of the included resource def header -// - Have the constructor call it's superclass constructor, passing in resource attributes -// ex: -// QwBMPTruck(): bitmapSingleton(BMP_TRUCK_WIDTH, BMP_TRUCK_HEIGHT){} -// -// - Lastly, define a macro that makes the syntax of access easy. This macro calls the instance -// method of the singleton, getting access to the object that contains the data of the resource -// ex: -// #define QW_BMP_TRUCK QwBMPTruck::instance() -// -// To the user, they just have a bitmap, referenced as QW_BMP_TRUCK and can do the following -// ex: -// uint8_t width = QW_BMP_TRUCK.width; -// uint8_t height = QW_BMP_TRUCK.height; -// -// And internal methods get the data of this bitmap object using the bitmap() method -// ex: -// const uint8_t * pData = QW_BMP_TRUCK.data(); -// -// It shoulds complicated - it isn't. Just look at examples in ths folder and copy when -// adding new resources. -// -/////////////////////////////////////////////////////////////////////////////////////////////////// -// Simple Bitmap class definition - -class QwBitmap { - -public: - uint8_t width; - uint8_t height; - virtual const uint8_t* data(void) { return nullptr; }; - -protected: - QwBitmap(uint8_t w, uint8_t h) - : width { w } - , height { h } - { - } -}; - -// Template that creates a singleton for bitmaps. -template -class bmpSingleton : public QwBitmap { -public: - static T& instance(void) - { - static T instance; - return instance; - } - - bmpSingleton(const bmpSingleton&) = delete; - bmpSingleton& operator=(const bmpSingleton) = delete; - -protected: - bmpSingleton() { } - using QwBitmap::QwBitmap; // inherit contructor -}; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// Font things - class to hold font attributes - -class QwFont { - -public: - uint8_t width; - uint8_t height; - uint8_t start; - uint8_t n_chars; - uint16_t map_width; - const char* name; - - virtual const uint8_t* data(void) { return nullptr; }; - -protected: - QwFont(uint8_t w, uint8_t h, uint8_t st_chr, uint8_t n_chr, uint16_t m_w, const char* f_name) - : width { w } - , height { h } - , start { st_chr } - , n_chars { n_chr } - , map_width { m_w } - , name { f_name } - { - } -}; - -// Template that creates a singleton for bitmaps. -template -class fontSingleton : public QwFont { -public: - static T& instance(void) - { - static T instance; - return instance; - } - - fontSingleton(const fontSingleton&) = delete; - fontSingleton& operator=(const fontSingleton) = delete; - -protected: - fontSingleton() { } - using QwFont::QwFont; // inherit constructor -}; diff --git a/docs/stylesheet/extra.css b/stylesheet/extra.css similarity index 100% rename from docs/stylesheet/extra.css rename to stylesheet/extra.css diff --git a/troubleshooting/index.html b/troubleshooting/index.html new file mode 100644 index 0000000..67979b5 --- /dev/null +++ b/troubleshooting/index.html @@ -0,0 +1,1762 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Troubleshooting - SparkFun Qwiic OLED Arduino Library - Hookup Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Troubleshooting

+ +

General Troubleshooting Help

+
+

Note

+

+ Not working as expected and need help?

+

If you need technical assistance and more information on a product that is not working as you expected, we recommend heading on over to the SparkFun Technical Assistance page for some initial troubleshooting.

+

+

If you don't find what you need there, the SparkFun Forums are a great place to find and ask for help. If this is your first visit, you'll need to create a Forum Account to search product forums and post questions.

+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file