mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
Updated README and TODO files
This commit is contained in:
parent
9a3433c52a
commit
4fceab4533
4 changed files with 71 additions and 355 deletions
17
Makefile
17
Makefile
|
@ -71,10 +71,6 @@ define n
|
||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
ifeq ("$(wildcard $(config))","")
|
|
||||||
$(error "Configuration files are missing. Did you ./configure?")
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Module-scope variables.
|
# Module-scope variables.
|
||||||
$(foreach mod, $(modules), $(eval \
|
$(foreach mod, $(modules), $(eval \
|
||||||
mod-$(mod)-c = $(notdir $(wildcard src/$(mod)/*.c)) $n\
|
mod-$(mod)-c = $(notdir $(wildcard src/$(mod)/*.c)) $n\
|
||||||
|
@ -131,6 +127,9 @@ endef
|
||||||
all: $(config) $(target-std) $(target-lib) $(target-g1a)
|
all: $(config) $(target-std) $(target-lib) $(target-g1a)
|
||||||
@ printf '\e[32;1mmsg \u00bb\e[0m All done!\n'
|
@ printf '\e[32;1mmsg \u00bb\e[0m All done!\n'
|
||||||
|
|
||||||
|
$(config):
|
||||||
|
$(error "Configuration files are missing. Did you ./configure?")
|
||||||
|
|
||||||
build:
|
build:
|
||||||
$(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n')
|
$(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n')
|
||||||
$(if $(VERBOSE),,@) mkdir -p $@
|
$(if $(VERBOSE),,@) mkdir -p $@
|
||||||
|
@ -212,10 +211,7 @@ mrproper: clean
|
||||||
|
|
||||||
distclean: mrproper
|
distclean: mrproper
|
||||||
|
|
||||||
install:
|
install: $(target-std) $(target-lib)
|
||||||
p7 send -f $(target-g1a)
|
|
||||||
|
|
||||||
install_lib: $(target-std) $(target-lib)
|
|
||||||
mkdir -p $(folder)
|
mkdir -p $(folder)
|
||||||
install -m 644 $^ $(folder)
|
install -m 644 $^ $(folder)
|
||||||
install -m 644 -T demo/gintdemo.ld $(folder)/linker.ld
|
install -m 644 -T demo/gintdemo.ld $(folder)/linker.ld
|
||||||
|
@ -223,4 +219,7 @@ install_lib: $(target-std) $(target-lib)
|
||||||
install -m 644 include/*.h $(folder)/gint
|
install -m 644 include/*.h $(folder)/gint
|
||||||
@ printf '\e[32;1mmsg \u00bb\e[0m All installed!\n'
|
@ printf '\e[32;1mmsg \u00bb\e[0m All installed!\n'
|
||||||
|
|
||||||
.PHONY: all clean mrproper distclean install install_lib help
|
install_demo:
|
||||||
|
p7 send -f $(target-g1a)
|
||||||
|
|
||||||
|
.PHONY: all clean mrproper distclean install install_demo help
|
||||||
|
|
87
README.md
87
README.md
|
@ -2,54 +2,77 @@ gint project
|
||||||
============
|
============
|
||||||
|
|
||||||
gint (pronounce 'guin') is a low-level library for fx-9860G calculators. It
|
gint (pronounce 'guin') is a low-level library for fx-9860G calculators. It
|
||||||
provides the tools needed to develop programs under Linux using the gcc
|
provides a mostly free-standing runtime support for the platform, and can be
|
||||||
toolchain (sh3eb-elf).
|
used to develop add-ins under Linux along with the gcc toolchain (`sh3eb-elf`
|
||||||
|
target) and the [fxSDK](http://git.planet-casio.com/lephe/fxsdk).
|
||||||
|
|
||||||
By the way, gint is free software; you may use it for any purpose, share it,
|
gint is free software: you may use it for any purpose, share it, modify it and
|
||||||
modify it and share you changes. No credit of any kind is needed, though
|
share your changes. No credit of any kind is required, though appreciated.
|
||||||
appreciated.
|
|
||||||
|
|
||||||
|
|
||||||
|
Programming interface
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Because of its free-standing design, gint's API provides direct and efficient
|
||||||
|
access to the low-level MPU features, among which:
|
||||||
|
* Extensive keyboard control, including replication of the system behavior for
|
||||||
|
office applications and event-driven decisions for games
|
||||||
|
* Hardware timers running at over 10 MHz, allowing microsecond-level control
|
||||||
|
* Unlimited mappings of callbacks to Real-Time Clock events (requires build)
|
||||||
|
* Access to processor register for debugging information, determination of
|
||||||
|
processor speed (overclock is on the TODO list), backlight management...
|
||||||
|
|
||||||
|
The library also offers powerful higher-level features:
|
||||||
|
* A gray engine that works by rapidly swapping monochrome images
|
||||||
|
* Blazingly fast drawing functions when working with the fxSDK
|
||||||
|
* C Standard functions such as the `printf()` family.
|
||||||
|
|
||||||
|
|
||||||
Interrupt handler
|
Interrupt handler
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The interrupt handler is the lowest-level part of the library. It directly
|
The interrupt handler is the lowest-level part of the library. It directly
|
||||||
accesses the peripheral modules and performs keyboard analyzes, swaps screen
|
accesses the peripheral modules and workarounds the system to perform keyboard
|
||||||
buffers, etc.
|
analyzes directly on hardware or timer management.
|
||||||
|
|
||||||
gint does not allow user programs to use their own handlers. However, it is
|
|
||||||
possible to map interrupt-driven events to user callbacks using the public API
|
|
||||||
(which is not possible with the system's interrupt handler). This may be
|
|
||||||
particularly useful for timers and RTC (the 16 Hz interrupt can be used as a
|
|
||||||
basis for a physical engine).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Public Interface
|
|
||||||
----------------
|
|
||||||
|
|
||||||
gint's API provides access to keyboard, timers, clock and more. It does some
|
|
||||||
powerful drawing and offers reliable multi-getkey, a gray engine, facilitates
|
|
||||||
register access and implements a few standard functions.
|
|
||||||
|
|
||||||
|
gint does not allow user programs to use their own handlers, but it allows them
|
||||||
|
to complete the original handler if they want to use interrupts that are not
|
||||||
|
supported by the library. It is also possible to map various interrupt-driven
|
||||||
|
events to user-provided callbacks using the API, which is not allowed by the
|
||||||
|
operating system. This is particularly useful for timers and the Real-Time
|
||||||
|
Clock (the 16 Hz interrupt can be used to run a physical engine, while the 1 Hz
|
||||||
|
interrupt can be used in a real-time management game).
|
||||||
|
|
||||||
|
|
||||||
Building and installing
|
Building and installing
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
There are some dependencies:
|
To build and install gint, you will need the following components:
|
||||||
* The `sh3eb-elf` toolchain somewhere in the PATH
|
* The `sh3eb-elf` toolchain linked somewhere in the PATH
|
||||||
* The fxSDK installed and available in the PATH
|
* The [fxSDK](http://git.planet-casio.com/lephe/fxsdk) installed and available
|
||||||
|
in the PATH
|
||||||
|
|
||||||
The easiest way to build gint is simply to enter a terminal and execute `make`.
|
The classical way to build gint is to enter a terminal and use the usual:
|
||||||
This will build the following components :
|
|
||||||
|
$ ./configure
|
||||||
|
$ make
|
||||||
|
# make install
|
||||||
|
|
||||||
|
This will build and install the following components in the storage folder of
|
||||||
|
the fxSDK:
|
||||||
* `libgint.a`, the gint library
|
* `libgint.a`, the gint library
|
||||||
* `libc.a`, a (very) few standard procedures
|
* `libc.a`, the partial standard library
|
||||||
|
* The libgint headers for development
|
||||||
|
|
||||||
|
The following additional files will be generated in the working directory:
|
||||||
* `gintdemo.g1a`, a test application
|
* `gintdemo.g1a`, a test application
|
||||||
|
|
||||||
The common `clean`, `mrproper`, and `distclean` rules will clean the directory.
|
The usual `clean`, `mrproper`, and `distclean` rules will clean the directory.
|
||||||
|
There are configuration options, which can be obtained using
|
||||||
|
`./configure --help`. Most of them customize size limits, if a project needs to
|
||||||
|
extend them. The true free-standing program may build the library using the
|
||||||
|
`--no-syscalls` switch, but some features will be disabled (dynamic
|
||||||
|
allocation...).
|
||||||
|
|
||||||
|
|
||||||
Source organization
|
Source organization
|
||||||
|
@ -65,8 +88,6 @@ components:
|
||||||
* Other source files in `/src/module`: contain multiple functions that always
|
* Other source files in `/src/module`: contain multiple functions that always
|
||||||
work together, or are lightweight enough not to be separated. Their names
|
work together, or are lightweight enough not to be separated. Their names
|
||||||
often begin with `module_`.
|
often begin with `module_`.
|
||||||
* Other files in `/src/module`: the `display` module contains a font, I think.
|
* Other files in `/src/module`: the `display` module contains a font.
|
||||||
|
|
||||||
The demo application is in the `demo` directory.
|
The demo application is in the `demo` directory.
|
||||||
|
|
||||||
The `doc` folder contains some documentation.
|
|
||||||
|
|
16
TODO
16
TODO
|
@ -3,19 +3,21 @@ Bugs to fix:
|
||||||
- Lost keyboard control at startup (could not reproduce)
|
- Lost keyboard control at startup (could not reproduce)
|
||||||
|
|
||||||
Simple improvements:
|
Simple improvements:
|
||||||
- bopti: Monochrome bitmaps blending modes
|
|
||||||
- bopti: Partial transparency
|
|
||||||
- demo: Try 284x124 at (-60, -28) (all disadvantages)
|
- demo: Try 284x124 at (-60, -28) (all disadvantages)
|
||||||
- display: Rectangle-based drawing functions
|
- display: Rectangle-based drawing functions
|
||||||
- tales: Test all font encodings
|
- tales: Test all font encodings
|
||||||
- time: Compute CLOCKS_PER_SEC
|
- time: Compute CLOCKS_PER_SEC
|
||||||
- core: Add VBR handlers debugging information (if possible)
|
- core: Add VBR handlers debugging information (if possible)
|
||||||
|
Larger improvements:
|
||||||
|
- errno: Introduce errno and use it more or less everywhere
|
||||||
|
- bopti: Monochrome bitmaps blending modes
|
||||||
|
- bopti: Handle partial transparency
|
||||||
- core: Implement all callbacks and a complete user API
|
- core: Implement all callbacks and a complete user API
|
||||||
|
Other whole modules:
|
||||||
Modules to implement:
|
- Serial communication through 3-pin
|
||||||
- Serial communication
|
- USB communication
|
||||||
- Sound playback and synthesizing
|
- Sound playback and synthesizing (if possible)
|
||||||
- Handle errors within errno
|
- Overclock (relaunch clocks when overclocking)
|
||||||
|
|
||||||
Things to investigate:
|
Things to investigate:
|
||||||
- Packed bit fields alignment
|
- Packed bit fields alignment
|
||||||
|
|
306
doc/bopti.md
306
doc/bopti.md
|
@ -1,306 +0,0 @@
|
||||||
|
|
||||||
# gint documentation: bitmap rendering #
|
|
||||||
|
|
||||||
|
|
||||||
*Warning: this is a draft. The current implementation of bopti is different*
|
|
||||||
*from this description, though similar.*
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Basics
|
|
||||||
|
|
||||||
The bitmap drawing module, *bopti*, is based on video-ram (vram) bitwise
|
|
||||||
operations. The images are made of layers that describe (more or less) which
|
|
||||||
pixels of the image an operation applies to. Rendering the image consists in
|
|
||||||
applying an operation function to the existing vram pixels.
|
|
||||||
|
|
||||||
*bopti* makes an extensive use of longword operations and 4-alignment to take
|
|
||||||
advantage of the bit-based structure of the monochrome vram and enhance
|
|
||||||
performance. Among all possible optimizations, avoiding direct pixel access has
|
|
||||||
proven to be the most efficient.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Operations
|
|
||||||
|
|
||||||
Operations are functions applied to update a vram longword in accordance with
|
|
||||||
an operation mask. Bits that are set in the mask indicate pixels which have to
|
|
||||||
be updated by the operation. Bits that are reset indicate pixels that must not
|
|
||||||
be changed.
|
|
||||||
|
|
||||||
All the point is, the functions must not access the bit information in the mask
|
|
||||||
or the vram data individually. They must operate globally using longword
|
|
||||||
bitwise instructions, so that performance is maintained.
|
|
||||||
|
|
||||||
Consider for instance a logical and operation (`(a, b) -> a & b`).
|
|
||||||
Operating on pixels would need to move some data, test the value of a bit in
|
|
||||||
the mask, edit the vram data, and eventually shift both the data and the mask,
|
|
||||||
for all of the 32 pixels.
|
|
||||||
One could not expect this from happening in less than 150 processor cycles
|
|
||||||
(in comparison, using generic-purpose `setPixel()`-like functions would be at
|
|
||||||
least 10 times as long). The smarter method operates directly on the longword
|
|
||||||
parameters, and performs `data = data & ~mask`, which is 2 processor cycles
|
|
||||||
long.
|
|
||||||
|
|
||||||
The following operations are defined by *bopti*:
|
|
||||||
|
|
||||||
- `Draw `: Draws black pixels.
|
|
||||||
- `Alpha `: Erases non-transparent pixels.
|
|
||||||
- `Change `: Changes the pixels' color.
|
|
||||||
- `Lighten `: Lightens gray pixels.
|
|
||||||
- `Lighten2`: Lightens gray pixels more.
|
|
||||||
- `Darken `: Darkens gray pixels.
|
|
||||||
- `Darken2 `: Darkens gray pixels more.
|
|
||||||
|
|
||||||
To perform an operation, *bopti* uses the mask data, which is taken from a
|
|
||||||
layer, and calls the associated operation function. Every operation has its
|
|
||||||
default layer mask (except `change`), but this setting may be overridden.
|
|
||||||
*bopti* allows user programs to use any monochrome image as a mask for an
|
|
||||||
operation. For instance, a black rectangle may be drawn by any of the operation
|
|
||||||
functions, resulting in various results.
|
|
||||||
|
|
||||||
An additional operation, `fill`, is defined by the library. It does all the job
|
|
||||||
necessary to render the full image, which often falls back to performing the
|
|
||||||
operations that correspond to the kind of image.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Operation on gray pixels
|
|
||||||
|
|
||||||
*Detailed article: [Gray engine](gray-engine)*
|
|
||||||
|
|
||||||
Gray pixels are made of four colors represented by pairs of bits. Arguments
|
|
||||||
`light` and `dark` of gray operation functions are longwords containing the
|
|
||||||
least significant and most significant of these bits, respectively.
|
|
||||||
|
|
||||||
white = 0 [00]
|
|
||||||
lightgray = 1 [01]
|
|
||||||
darkgray = 2 [10]
|
|
||||||
black = 3 [11]
|
|
||||||
|
|
||||||
The `Lighten` operation affects pixels as if decrementing their value (white
|
|
||||||
pixels are not changed), and `darken` does the opposite (black pixels are not
|
|
||||||
changed).
|
|
||||||
Operations `Lighten2` and `darken2` do the same two times.
|
|
||||||
|
|
||||||
From this description, and considering two bits `light` and `dark`, it follows
|
|
||||||
that:
|
|
||||||
|
|
||||||
```c
|
|
||||||
lighten2 (light, dark) = (0, light & dark)
|
|
||||||
lighten (light, dark) = (light & dark, light & ~dark)
|
|
||||||
darken (light, dark) = (light | dark, light | ~dark)
|
|
||||||
darken2 (light, dark) = (1, light | dark)
|
|
||||||
```
|
|
||||||
|
|
||||||
This does not take account of a possible operation mask. See section
|
|
||||||
[Operation functions](#operation-functions) for more flexible functions.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Partial transparency
|
|
||||||
|
|
||||||
*bopti* allows monochrome images to have semi-transparent pixels. Consider for
|
|
||||||
example a white background. An opaque black pixel will render black, while a
|
|
||||||
1/3-transparent black pixel will render dark gray, and a 2/3-transparent black
|
|
||||||
pixel will render light gray. Which means that:
|
|
||||||
|
|
||||||
* 1/3-transparent white pixels form the mask for `lighten2`
|
|
||||||
* 2/3-transparent white pixels form the mask for `lighten`
|
|
||||||
* 2/3-transparent black pixels form the mask for `darken`
|
|
||||||
* 1/3-transparent black pixels form the mask for `darken2`
|
|
||||||
|
|
||||||
Partial transparency on gray pixels is not allowed. Apart from the complexity
|
|
||||||
of the generic partial transparency rendering operation, semi-transparent gray
|
|
||||||
pixels are not of any use.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Operation functions
|
|
||||||
|
|
||||||
Operations on monochrome buffers are defined as functions of two parameters:
|
|
||||||
the vram data longword to update, `data`, and the operation mask, `x`. Every
|
|
||||||
of these functions must satisfy `f(data, 0) = data`.
|
|
||||||
|
|
||||||
Operations on gray buffers take three arguments: `light` and `dark`, which are
|
|
||||||
longwords from the [gray buffers](gray-engine), and the operation mask `x`.
|
|
||||||
They update both longwords and return them. These functions must satisfy
|
|
||||||
`f(light, dark, 0) = (light, dark)`.
|
|
||||||
|
|
||||||
The functions for each of the operations are the following:
|
|
||||||
|
|
||||||
~~~c
|
|
||||||
# Draw function
|
|
||||||
draw(data, x) = data | x
|
|
||||||
|
|
||||||
# Alpha function
|
|
||||||
alpha(data, x) = data & ~x
|
|
||||||
|
|
||||||
# Change function
|
|
||||||
change(data, x) = data ^ x
|
|
||||||
|
|
||||||
# Lighten function
|
|
||||||
lighten(light, dark, x) = (light & (dark | ~x), (light | ~x) & (x ^ dark))
|
|
||||||
|
|
||||||
# Lighten2 function
|
|
||||||
lighten2(light, dark, x) = (light & ~x, (light | ~x) & dark)
|
|
||||||
|
|
||||||
# Darken function
|
|
||||||
darken(light, dark, x) = (light | (dark & x), (light & x) | (x ^ dark))
|
|
||||||
|
|
||||||
# Darken2 function
|
|
||||||
darken2(light, dark, x) = (light | x, (light & x) | dark)
|
|
||||||
~~~
|
|
||||||
|
|
||||||
One could easily check that these functions do their jobs when `x = 1` and
|
|
||||||
leave the data unchanged when `x = 0`.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Image format
|
|
||||||
|
|
||||||
Images are made of *layers*, each of which describe the mask for an operation.
|
|
||||||
When an image is rendered, *bopti* draws some of those layers in the vram
|
|
||||||
using the operation functions.
|
|
||||||
|
|
||||||
* Non-transparent monochrome images only have one layer, which describes the
|
|
||||||
mask for the `draw` operation.
|
|
||||||
* Transparent monochrome images have two layers. The first describes the mask
|
|
||||||
for the `draw` operation, while the other is the `alpha` operation mask (which
|
|
||||||
means that it indicates which pixels are not transparent).
|
|
||||||
* Non-transparent gray images also have two layers: one for each
|
|
||||||
[gray buffer](gray-engine). Both are for the `draw` operation.
|
|
||||||
* Transparent gray images have three layers. Two of them constitute the two-bit
|
|
||||||
color information for the `draw` operation, and the third is the `alpha`
|
|
||||||
operation mask.
|
|
||||||
* Semi-transparent monochrome images also have three layers. Two are used to
|
|
||||||
store the two-bit transparency level information (0 is opaque, 3 is fully
|
|
||||||
transparent), and the third indicates the color.
|
|
||||||
|
|
||||||
Layers are encoded as a bit map. The image is split into a *grid*, which is
|
|
||||||
made of 32-pixel *columns*, and an *end*.
|
|
||||||
|
|
||||||
32 32 32 end
|
|
||||||
+------+------+------+---+
|
|
||||||
| | | | |
|
|
||||||
| | | | |
|
|
||||||
| | | | |
|
|
||||||
+------+------+------+---+
|
|
||||||
|
|
||||||
Bitmap
|
|
||||||
|
|
||||||
The first bytes of the layer data is the column data. Each column is encoded
|
|
||||||
as a 32-bit integer array from top to bottom. Columns are written from left to
|
|
||||||
right. The end is encoded as an 8-bit or 16-bit integer array depending on its
|
|
||||||
size, and written from top to bottom. Additionally, 0 to 3 NUL (0x00) bytes are
|
|
||||||
added to make the layer size a multiple of 4 (to allow 32-bit access to the
|
|
||||||
column data of the following layer).
|
|
||||||
|
|
||||||
In case of big images (see the image structure below), the end is expanded to
|
|
||||||
a 32-pixel column to improve performance.
|
|
||||||
|
|
||||||
The image itself is a structure of the following kind (in case of small
|
|
||||||
images):
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct Image
|
|
||||||
{
|
|
||||||
unsigned char magic;
|
|
||||||
unsigned char format;
|
|
||||||
|
|
||||||
unsigned char width;
|
|
||||||
unsigned char height;
|
|
||||||
|
|
||||||
const uint32_t data[];
|
|
||||||
|
|
||||||
} __attribute__((aligned(4)));
|
|
||||||
```
|
|
||||||
|
|
||||||
For bigger images (`width` > 255 or `height` > 255), both `width` and `height`
|
|
||||||
are set to `0` and the actual size information is written on two shorts just
|
|
||||||
where the data resides:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct BigImage
|
|
||||||
{
|
|
||||||
unsigned char magic;
|
|
||||||
unsigned char format;
|
|
||||||
|
|
||||||
unsigned char null_width; /* contains 0 */
|
|
||||||
unsigned char null_height; /* contains 0 */
|
|
||||||
|
|
||||||
unsigned short width;
|
|
||||||
unsigned short height;
|
|
||||||
|
|
||||||
const uint32_t data[];
|
|
||||||
|
|
||||||
} __attribute__((aligned(4)));
|
|
||||||
```
|
|
||||||
|
|
||||||
This does not create a memory loss because a two-byte gap was needed to make
|
|
||||||
the data 4-aligned.
|
|
||||||
|
|
||||||
* The `magic` number, which is common to all the file formats of *gint*,
|
|
||||||
identifies the file type and version of the structure. *bopti* will not render
|
|
||||||
an image which is not encoded for its specific version.
|
|
||||||
|
|
||||||
* The `format` attribute describes the layer distribution, as specified by the
|
|
||||||
following enum:
|
|
||||||
|
|
||||||
```c
|
|
||||||
enum ImageFormat
|
|
||||||
{
|
|
||||||
ImageFormat_Mono = 0x01,
|
|
||||||
ImageFormat_MonoAlpha = 0x09,
|
|
||||||
ImageFormat_Gray = 0x06,
|
|
||||||
ImageFormat_GrayAlpha = 0x0e,
|
|
||||||
ImageFormat_GreaterAlpha = 0x31,
|
|
||||||
|
|
||||||
ImageFormat_ColorMask = 0x07,
|
|
||||||
ImageFormat_AlphaMask = 0x38,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
`Alpha` refers to uniform transparency. The only format that supports
|
|
||||||
partial transparency is `GreaterAlpha`, and it is always encoded as
|
|
||||||
monochrome (because using gray pixels would lead to 9 different colors,
|
|
||||||
which is rather unoptimized). Gray images with partial transparency
|
|
||||||
will be refused by *fxconv*.
|
|
||||||
|
|
||||||
|
|
||||||
* The `width` and `height` attributes are exactly what you expect.
|
|
||||||
|
|
||||||
* The `data` is simply made of all the layers put one after another. Layers are
|
|
||||||
put in the following order:
|
|
||||||
|
|
||||||
[0] Monochrome `draw` layer
|
|
||||||
[1] Dark gray `draw` layer
|
|
||||||
[2] Light gray `draw` layer
|
|
||||||
[3] Uniform `alpha` layer
|
|
||||||
[4] First semi-`alpha` layer
|
|
||||||
[5] Second semi-`alpha` layer
|
|
||||||
|
|
||||||
Not every format uses the six layers, of course. The layers used by
|
|
||||||
each format may be found by reading the position of the `1`'s in the
|
|
||||||
corresponding `enum ImageFormat` entry. Layers that are not needed are
|
|
||||||
skipped.
|
|
Loading…
Reference in a new issue