mirror of
https://github.com/go-vgo/robotgo.git
synced 2025-06-01 14:43:55 +00:00
Compare commits
285 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a8c387a070 | ||
![]() |
3eef3b5879 | ||
![]() |
b731094f61 | ||
![]() |
8d4679db07 | ||
![]() |
02c668a946 | ||
![]() |
5c2864485d | ||
![]() |
f101b10497 | ||
![]() |
73c07dc991 | ||
![]() |
fc47bc8216 | ||
![]() |
912ddcbfe4 | ||
![]() |
57b5e5bca2 | ||
![]() |
8031f7f526 | ||
![]() |
36bc85ad19 | ||
![]() |
5fc2bd4c73 | ||
![]() |
47abfac5ee | ||
![]() |
df0731c4df | ||
![]() |
03432155c1 | ||
![]() |
6a1f060a8c | ||
![]() |
e924f25fe1 | ||
![]() |
d300eedf54 | ||
![]() |
c07f3f0171 | ||
![]() |
0b18fa5058 | ||
![]() |
471f7ba05f | ||
![]() |
a84a195c4c | ||
![]() |
c8df366f89 | ||
![]() |
70f811ce53 | ||
![]() |
ecc260ea31 | ||
![]() |
78d01703b8 | ||
![]() |
47cde13dab | ||
![]() |
8db59aac2d | ||
![]() |
217d6cf1f1 | ||
![]() |
75fd24ea0a | ||
![]() |
bed6776ca2 | ||
![]() |
1923d7bb48 | ||
![]() |
ead43d062e | ||
![]() |
3258566802 | ||
![]() |
0de26ecee4 | ||
![]() |
c48e3d072c | ||
![]() |
b1ad7db6be | ||
![]() |
0110b85d40 | ||
![]() |
3e5b10f720 | ||
![]() |
cb51e2aa10 | ||
![]() |
85f2702683 | ||
![]() |
5b9871b063 | ||
![]() |
b201ab9f80 | ||
![]() |
d3e364fa26 | ||
![]() |
1f437d12e4 | ||
![]() |
c5110d0ac8 | ||
![]() |
f98b4c52bd | ||
![]() |
f1db2ede4a | ||
![]() |
d90493e63e | ||
![]() |
63eb594ea5 | ||
![]() |
8a990ac042 | ||
![]() |
bf1758b424 | ||
![]() |
9424b71a73 | ||
![]() |
6c137427db | ||
![]() |
ffbf4f875b | ||
![]() |
05c54c6f25 | ||
![]() |
3171c5bdff | ||
![]() |
b718cf4a8c | ||
![]() |
bfc28d12fa | ||
![]() |
e9421b58b6 | ||
![]() |
4d780b9908 | ||
![]() |
39818d41fa | ||
![]() |
eacf74f488 | ||
![]() |
61b77ce3e1 | ||
![]() |
01e4fffcb8 | ||
![]() |
e2f5f54804 | ||
![]() |
f22f063926 | ||
![]() |
722feb7ba3 | ||
![]() |
dbf0d84f12 | ||
![]() |
b8a6b1778e | ||
![]() |
a780825c09 | ||
![]() |
de675b4dd2 | ||
![]() |
ef191f2dfd | ||
![]() |
44b2715de0 | ||
![]() |
90f41269da | ||
![]() |
8a5ca54915 | ||
![]() |
5b0ac98ef3 | ||
![]() |
c2b5c864d2 | ||
![]() |
0c4055bfee | ||
![]() |
af32110521 | ||
![]() |
5c3cbd6e17 | ||
![]() |
3182fb9d73 | ||
![]() |
6fa2f418fa | ||
![]() |
8e7a413ec6 | ||
![]() |
8ce3a5dff0 | ||
![]() |
8ea126d35b | ||
![]() |
c62f7fd81e | ||
![]() |
92fd032685 | ||
![]() |
ffcf6b26cd | ||
![]() |
451bb91209 | ||
![]() |
cbca6d08c7 | ||
![]() |
d249cdcd9e | ||
![]() |
4140463ed1 | ||
![]() |
186bceb9d0 | ||
![]() |
01212c5684 | ||
![]() |
07dd53a897 | ||
![]() |
9afa311121 | ||
![]() |
94be6c56c1 | ||
![]() |
e0583e83ec | ||
![]() |
6a2ffab625 | ||
![]() |
679aef0f70 | ||
![]() |
cc6f1934f9 | ||
![]() |
4bdacf4187 | ||
![]() |
c8d35acd24 | ||
![]() |
e4848b4608 | ||
![]() |
f47571eaae | ||
![]() |
dd149367b3 | ||
![]() |
da736a93ee | ||
![]() |
73a40e7861 | ||
![]() |
5e5c4ddbfa | ||
![]() |
23d3df9027 | ||
![]() |
bb76af18f0 | ||
![]() |
b13320884a | ||
![]() |
df1617d894 | ||
![]() |
b20007917d | ||
![]() |
f830c8ed13 | ||
![]() |
736fa1cc26 | ||
![]() |
9f8d308eaa | ||
![]() |
95be5f752f | ||
![]() |
4bc64ebf67 | ||
![]() |
bdae1a7759 | ||
![]() |
c9e1c3db67 | ||
![]() |
e8b3975205 | ||
![]() |
f4f4a3d319 | ||
![]() |
3052272818 | ||
![]() |
6313e52156 | ||
![]() |
f911550742 | ||
![]() |
2f936e1f49 | ||
![]() |
7aa5beb8f7 | ||
![]() |
4eea01b88d | ||
![]() |
7103f6b891 | ||
![]() |
bb90d71b5f | ||
![]() |
0ef48f1c4d | ||
![]() |
be6984fd34 | ||
![]() |
2f2ed595f6 | ||
![]() |
5079db2df7 | ||
![]() |
469cd4da5e | ||
![]() |
a8faa0e906 | ||
![]() |
0293ab5d0c | ||
![]() |
fc5dac6f8a | ||
![]() |
4bf054f47a | ||
![]() |
c3cda41c2d | ||
![]() |
e9b5a9251e | ||
![]() |
47ca6812fe | ||
![]() |
4ad733fe83 | ||
![]() |
f428ffb1fb | ||
![]() |
a1cb2ebef2 | ||
![]() |
31c248aedd | ||
![]() |
db2eda3e1f | ||
![]() |
ee25e577e5 | ||
![]() |
62c61cf52a | ||
![]() |
1934220f50 | ||
![]() |
673c9a68a3 | ||
![]() |
e08e05307e | ||
![]() |
e53c75ff95 | ||
![]() |
c5cdd0a33f | ||
![]() |
8ba7338861 | ||
![]() |
7df3bc3800 | ||
![]() |
8744c88f5f | ||
![]() |
e533734f0b | ||
![]() |
a2e387b448 | ||
![]() |
bfa6b232be | ||
![]() |
51ca08e484 | ||
![]() |
debc2719ee | ||
![]() |
985c590284 | ||
![]() |
94c4b98edd | ||
![]() |
895aed8f22 | ||
![]() |
6bf430b1cd | ||
![]() |
1d2ec44308 | ||
![]() |
60bf136aa1 | ||
![]() |
e7c518eb2a | ||
![]() |
e755317599 | ||
![]() |
efc7c90b9f | ||
![]() |
c493c4981d | ||
![]() |
f110d5bf9e | ||
![]() |
ade0381d15 | ||
![]() |
0dcc87c355 | ||
![]() |
3d7cce3a31 | ||
![]() |
60ddc20e02 | ||
![]() |
16e0808dbd | ||
![]() |
3278758575 | ||
![]() |
389f7c6802 | ||
![]() |
ffa27a50cc | ||
![]() |
e1c5590f30 | ||
![]() |
93a9f8194f | ||
![]() |
a917683d97 | ||
![]() |
34d0fbf4bc | ||
![]() |
3e97de3745 | ||
![]() |
2f79ebe879 | ||
![]() |
ab66b269b8 | ||
![]() |
a00655dbe4 | ||
![]() |
45b85e1ec3 | ||
![]() |
c395a0dcd6 | ||
![]() |
5d651eb627 | ||
![]() |
c0ef98e712 | ||
![]() |
d14fae83be | ||
![]() |
8aa3348a2a | ||
![]() |
ebdc6878e5 | ||
![]() |
a9d995fdf6 | ||
![]() |
be9b02c588 | ||
![]() |
264f658a46 | ||
![]() |
6c1e845183 | ||
![]() |
84d85b1995 | ||
![]() |
4a043157ad | ||
![]() |
1fac32d382 | ||
![]() |
74c3f6e08e | ||
![]() |
76b123142f | ||
![]() |
b543a49322 | ||
![]() |
fafd2bfcd4 | ||
![]() |
b439c59d85 | ||
![]() |
5d460e5100 | ||
![]() |
d82ca8cee4 | ||
![]() |
3655e795d7 | ||
![]() |
f0b614d78e | ||
![]() |
c61fe44788 | ||
![]() |
2d52e2c008 | ||
![]() |
75cfe774b3 | ||
![]() |
00fa7ff5fc | ||
![]() |
4599d66f5b | ||
![]() |
2502329583 | ||
![]() |
82cde2281e | ||
![]() |
99963bc6fc | ||
![]() |
c5446b655d | ||
![]() |
ed45411f5c | ||
![]() |
b6ef01a929 | ||
![]() |
149d0f8307 | ||
![]() |
e81c9ec843 | ||
![]() |
cd7ed72bf2 | ||
![]() |
72167ef467 | ||
![]() |
5c0f1d340b | ||
![]() |
70f6c276ac | ||
![]() |
8ad853dca2 | ||
![]() |
9d145c042c | ||
![]() |
427d2b4d61 | ||
![]() |
ce43fa6621 | ||
![]() |
76abeff3ff | ||
![]() |
80ee9fcc43 | ||
![]() |
18243a2192 | ||
![]() |
168a26ff5d | ||
![]() |
969478625a | ||
![]() |
540bf594ff | ||
![]() |
b8b8450f67 | ||
![]() |
bafa051f92 | ||
![]() |
921059926e | ||
![]() |
8defbda0cd | ||
![]() |
63f914ae62 | ||
![]() |
477a7b473c | ||
![]() |
897af2a0db | ||
![]() |
acfb61e8ce | ||
![]() |
caf3fbb982 | ||
![]() |
481fbb72a5 | ||
![]() |
4021a8bb92 | ||
![]() |
30f4520541 | ||
![]() |
a860bbcff9 | ||
![]() |
b81aad6085 | ||
![]() |
ce0972d699 | ||
![]() |
83ebdf3efd | ||
![]() |
0b2e9034b2 | ||
![]() |
4705e668bc | ||
![]() |
bf3f823fd7 | ||
![]() |
112fc4c6bb | ||
![]() |
ec4d4dd0d8 | ||
![]() |
adc7bd42d1 | ||
![]() |
7685ce8a3b | ||
![]() |
cf237175a7 | ||
![]() |
a93a984215 | ||
![]() |
d2f905e308 | ||
![]() |
0b6cc4867e | ||
![]() |
f6abdbe21b | ||
![]() |
337cd3f73a | ||
![]() |
627f5c9d3b | ||
![]() |
348b39cd04 | ||
![]() |
ca337b8505 | ||
![]() |
cc2d0198ea | ||
![]() |
28fd0b9af6 | ||
![]() |
48f1adce7e | ||
![]() |
108c6395f8 | ||
![]() |
6c249c12a3 | ||
![]() |
fe42b2a74c | ||
![]() |
b2702100cb | ||
![]() |
25c764cd1d | ||
![]() |
21eeb19818 | ||
![]() |
47245e8862 |
@ -5,26 +5,24 @@ jobs:
|
||||
docker:
|
||||
# using custom image, see .circleci/images/primary/Dockerfile
|
||||
# - image: govgo/robotgoci:1.10.3
|
||||
- image: golang:1.17.5
|
||||
- image: golang:1.23.0
|
||||
working_directory: /gopath/src/github.com/go-vgo/robotgo
|
||||
steps:
|
||||
- checkout
|
||||
# specify any bash command here prefixed with `run: `
|
||||
- run: apt update
|
||||
- run: apt -y install gcc libc6-dev
|
||||
libx11-dev xorg-dev libxtst-dev libpng++-dev
|
||||
xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev
|
||||
libxkbcommon-dev
|
||||
- run:
|
||||
apt -y install gcc libc6-dev
|
||||
libx11-dev xorg-dev libxtst-dev
|
||||
xsel xclip
|
||||
# libpng++-dev
|
||||
# xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev libxkbcommon-dev
|
||||
- run: apt -y install xvfb
|
||||
#
|
||||
# override:
|
||||
# './...' is a relative pattern which means all subdirectories
|
||||
# - run: go get -u github.com/go-vgo/robotgo
|
||||
# - run: go get -u golang.org/x/sys/unix
|
||||
# - run: go get -u github.com/shirou/gopsutil
|
||||
- run: go get -v -t -d ./...
|
||||
- run: xvfb-run go test -v ./...
|
||||
#
|
||||
# codecov.io
|
||||
# - run: xvfb-run go test -v -covermode=count -coverprofile=coverage.out
|
||||
# - run: bash <(curl -s https://codecov.io/bash)
|
||||
|
@ -1,22 +1,19 @@
|
||||
# FROM golang:1.10.1
|
||||
FROM golang:1.17.5-stretch AS build
|
||||
FROM golang:1.24.2-stretch AS build
|
||||
# FROM govgo/go:1.11.1
|
||||
|
||||
RUN apt update && apt install -y --no-install-recommends \
|
||||
# customize dependencies
|
||||
libx11-dev xorg-dev \
|
||||
# libgtkglextmm-x11-dev
|
||||
# libghc6-x11-dev
|
||||
# libgl1-mesa-swx11-dev
|
||||
# xorg-dev
|
||||
libxtst-dev libpng++-dev \
|
||||
libxtst-dev \
|
||||
# Bitmap
|
||||
libpng++-dev \
|
||||
# Event:
|
||||
xcb libxcb-xkb-dev \
|
||||
x11-xkb-utils libx11-xcb-dev \
|
||||
libxkbcommon-x11-dev libxkbcommon-dev \
|
||||
# Clipboard:
|
||||
xsel xclip && \
|
||||
# RUN apt install -y xclip
|
||||
#
|
||||
apt remove --purge --auto-remove && \
|
||||
apt clean && \
|
||||
|
5
.github/issue_template.md
vendored
5
.github/issue_template.md
vendored
@ -1,11 +1,12 @@
|
||||
1. Please **speak English**, this is the language everybody of us can speak and write.
|
||||
1. Please **speak English (English only)**, this is the language everybody of us can speak and write.
|
||||
2. Please take a moment to **search** that an issue **doesn't already exist**.
|
||||
3. Please make sure `Golang, GCC` is installed correctly before installing RobotGo.
|
||||
4. Please ask questions or config/deploy problems on our Gitter channel: https://gitter.im/go-vgo/robotgo
|
||||
<!-- 4. Please ask questions or config/deploy problems on our Gitter channel: https://gitter.im/go-vgo/robotgo -->
|
||||
5. Please give all relevant information below for bug reports, incomplete details will be handled as an invalid report.
|
||||
|
||||
**You MUST delete the content above including this line before posting, otherwise your issue will be invalid.**
|
||||
|
||||
|
||||
- Robotgo version (or commit ref):
|
||||
- Go version:
|
||||
- Gcc version:
|
||||
|
3
.github/pull_request_template.md
vendored
3
.github/pull_request_template.md
vendored
@ -5,10 +5,11 @@ The pull request will be closed without any reasons if it does not satisfy any o
|
||||
3. Please read contributing guidelines: [CONTRIBUTING](https://github.com/go-vgo/robotgo/blob/master/CONTRIBUTING.md)
|
||||
4. Describe what your pull request does and which issue you're targeting (if any and **Please use English**)
|
||||
5. ... if it is not related to any particular issues, explain why we should not reject your pull request.
|
||||
6. The Commits must use English, must be test and No useless submissions.
|
||||
6. The Commits must **use English**, must be test and No useless submissions.
|
||||
|
||||
**You MUST delete the content above including this line before posting, otherwise your pull request will be invalid.**
|
||||
|
||||
|
||||
**Please provide Issues links to:**
|
||||
|
||||
- Issues: #1
|
||||
|
8
.github/workflows/go.yml
vendored
8
.github/workflows/go.yml
vendored
@ -10,10 +10,10 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Set up Go 1.17
|
||||
- name: Set up Go 1.24.0
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.24.0
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
@ -22,10 +22,6 @@ jobs:
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
# if [ -f Gopkg.toml ]; then
|
||||
# curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||
# dep ensure
|
||||
# fi
|
||||
|
||||
- name: Build
|
||||
run: go build -v .
|
||||
|
@ -15,7 +15,9 @@ go:
|
||||
# - 1.14.x
|
||||
# - 1.15.x
|
||||
# - 1.16.x
|
||||
- 1.17.x
|
||||
# - 1.17.x
|
||||
# - 1.18.x
|
||||
- 1.19.x
|
||||
# - tip
|
||||
|
||||
addons:
|
||||
|
@ -24,7 +24,7 @@ This process gives everyone a chance to validate the design, helps prevent dupli
|
||||
|
||||
## Testing redux
|
||||
|
||||
Before sending code out for review, run all the tests for the whole tree to make sure the changes don't break other usage and keep the compatibility on upgrade. You must be test on Mac, Windows, Linux and other. You should install the CLI for Circle CI, as we are using the server for continous testing.
|
||||
Before sending code out for review, run all the tests for the whole tree to make sure the changes don't break other usage and keep the compatibility on upgrade. You must be test on Mac, Windows, Linux and other. You should install the CLI for Circle CI, as we are using the server for continuous testing.
|
||||
|
||||
## Code review
|
||||
|
||||
|
241
README.md
241
README.md
@ -4,31 +4,33 @@
|
||||
<!--[](https://travis-ci.org/go-vgo/robotgo)
|
||||
[](https://codecov.io/gh/go-vgo/robotgo)-->
|
||||
<!--<a href="https://circleci.com/gh/go-vgo/robotgo/tree/dev"><img src="https://img.shields.io/circleci/project/go-vgo/robotgo/dev.svg" alt="Build Status"></a>-->
|
||||
|
||||
[](https://github.com/go-vgo/robotgo/commits/master)
|
||||
[](https://circleci.com/gh/go-vgo/robotgo)
|
||||
[](https://travis-ci.org/go-vgo/robotgo)
|
||||

|
||||
[](https://goreportcard.com/report/github.com/go-vgo/robotgo)
|
||||
[](https://godoc.org/github.com/go-vgo/robotgo)
|
||||
[](https://pkg.go.dev/github.com/go-vgo/robotgo?tab=doc)
|
||||
[](https://github.com/go-vgo/robotgo/releases/latest)
|
||||
[](https://gitter.im/go-vgo/robotgo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
<!-- [](https://github.com/go-vgo/robotgo/releases/latest) -->
|
||||
<!-- <a href="https://github.com/go-vgo/robotgo/releases"><img src="https://img.shields.io/badge/%20version%20-%206.0.0%20-blue.svg?style=flat-square" alt="Releases"></a> -->
|
||||
|
||||
> Golang Desktop Automation. Control the mouse, keyboard, bitmap and image, read the screen, process, Window Handle and global event listener.
|
||||
> Golang Desktop Automation. Control the mouse, keyboard, read the screen, process, Window Handle, image and bitmap and global event listener.
|
||||
|
||||
RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x86-amd64.
|
||||
|
||||
[Chinese Simplified](https://github.com/go-vgo/robotgo/blob/master/README_zh.md)
|
||||
|
||||
## Contents
|
||||
|
||||
- [Docs](#docs)
|
||||
- [Binding](#binding)
|
||||
- [Requirements](#requirements)
|
||||
- [Installation](#installation)
|
||||
- [Update](#update)
|
||||
- [Examples](#examples)
|
||||
- [Cross-Compiling](#crosscompiling)
|
||||
- [Type Conversion and keys](https://github.com/go-vgo/robotgo/blob/master/docs/keys.md)
|
||||
- [Cross-Compiling](https://github.com/go-vgo/robotgo/blob/master/docs/install.md#crosscompiling)
|
||||
- [Authors](#authors)
|
||||
- [Plans](#plans)
|
||||
- [Donate](#donate)
|
||||
@ -36,12 +38,12 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8
|
||||
- [License](#license)
|
||||
|
||||
## Docs
|
||||
- [GoDoc](https://godoc.org/github.com/go-vgo/robotgo) <br>
|
||||
|
||||
- [API Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) (Deprecated, no updated)
|
||||
- [Chinese Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md) (Deprecated, no updated)
|
||||
|
||||
- [GoDoc](https://godoc.org/github.com/go-vgo/robotgo) <br>
|
||||
- [API Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) (Deprecated, no updated)
|
||||
|
||||
## Binding:
|
||||
|
||||
[ADB](https://github.com/vcaesar/adb), packaging android adb API.
|
||||
|
||||
[Robotn](https://github.com/vcaesar/robotn), binding JavaScript and other, support more language.
|
||||
@ -51,64 +53,96 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8
|
||||
Now, Please make sure `Golang, GCC` is installed correctly before installing RobotGo.
|
||||
|
||||
### ALL:
|
||||
|
||||
```
|
||||
Golang
|
||||
|
||||
GCC
|
||||
```
|
||||
|
||||
#### For Mac OS X:
|
||||
#### For MacOS:
|
||||
```
|
||||
brew install go
|
||||
```
|
||||
|
||||
Xcode Command Line Tools (And Privacy setting: [#277](https://github.com/go-vgo/robotgo/issues/277) )
|
||||
Xcode Command Line Tools (And Privacy setting: [#277](https://github.com/go-vgo/robotgo/issues/277))
|
||||
|
||||
```
|
||||
xcode-select --install
|
||||
```
|
||||
|
||||
#### For Windows:
|
||||
|
||||
[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended)
|
||||
```
|
||||
winget install Golang.go
|
||||
```
|
||||
|
||||
```
|
||||
Or the other GCC (But you should compile the "libpng" with yourself.
|
||||
Or you can removed the bitmap.go.
|
||||
|
||||
In the plans, the bitmap.go will moves to the bitmap dir, but break the API. )
|
||||
winget install MartinStorsjo.LLVM-MinGW.UCRT
|
||||
```
|
||||
|
||||
Or [MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) or others Mingw [llvm-mingw](https://github.com/mstorsjo/llvm-mingw);
|
||||
|
||||
Download the Mingw, then set system environment variables `C:\mingw64\bin` to the Path.
|
||||
[Set environment variables to run GCC from command line](https://www.youtube.com/results?search_query=Set+environment+variables+to+run+GCC+from+command+line).
|
||||
|
||||
`Or the other GCC` (But you should compile the "libpng" with yourself when use the [bitmap](https://github.com/vcaesar/bitmap).)
|
||||
|
||||
#### For everything else:
|
||||
|
||||
```
|
||||
GCC, libpng
|
||||
GCC
|
||||
|
||||
X11 with the XTest extension (also known as the Xtst library)
|
||||
X11 with the XTest extension (the Xtst library)
|
||||
|
||||
Event:
|
||||
"Clipboard": xsel xclip
|
||||
|
||||
|
||||
"Bitmap": libpng (Just used by the "bitmap".)
|
||||
|
||||
"Event-Gohook": xcb, xkb, libxkbcommon (Just used by the "hook".)
|
||||
|
||||
xcb, xkb, libxkbcommon
|
||||
```
|
||||
|
||||
##### Ubuntu:
|
||||
|
||||
```yml
|
||||
# sudo apt install golang
|
||||
sudo snap install go --classic
|
||||
|
||||
# gcc
|
||||
sudo apt install gcc libc6-dev
|
||||
|
||||
sudo apt install libx11-dev xorg-dev libxtst-dev libpng++-dev
|
||||
# x11
|
||||
sudo apt install libx11-dev xorg-dev libxtst-dev
|
||||
|
||||
# Clipboard
|
||||
sudo apt install xsel xclip
|
||||
|
||||
#
|
||||
# Bitmap
|
||||
sudo apt install libpng++-dev
|
||||
|
||||
# GoHook
|
||||
sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev libxkbcommon-dev
|
||||
|
||||
sudo apt install xsel xclip
|
||||
```
|
||||
|
||||
##### Fedora:
|
||||
|
||||
```yml
|
||||
sudo dnf install libxkbcommon-devel libXtst-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel
|
||||
# x11
|
||||
sudo dnf install libXtst-devel
|
||||
|
||||
# Clipboard
|
||||
sudo dnf install xsel xclip
|
||||
|
||||
#
|
||||
# Bitmap
|
||||
sudo dnf install libpng-devel
|
||||
|
||||
sudo dnf install xsel xclip
|
||||
# GoHook
|
||||
sudo dnf install libxkbcommon-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel
|
||||
|
||||
```
|
||||
|
||||
## Installation:
|
||||
@ -128,6 +162,7 @@ go get github.com/go-vgo/robotgo
|
||||
png.h: No such file or directory? Please see [issues/47](https://github.com/go-vgo/robotgo/issues/47).
|
||||
|
||||
## Update:
|
||||
|
||||
```
|
||||
go get -u github.com/go-vgo/robotgo
|
||||
```
|
||||
@ -135,7 +170,6 @@ go get -u github.com/go-vgo/robotgo
|
||||
Note go1.10.x C file compilation cache problem, [golang #24355](https://github.com/golang/go/issues/24355).
|
||||
`go mod vendor` problem, [golang #26366](https://github.com/golang/go/issues/26366).
|
||||
|
||||
|
||||
## [Examples:](https://github.com/go-vgo/robotgo/blob/master/examples)
|
||||
|
||||
#### [Mouse](https://github.com/go-vgo/robotgo/blob/master/examples/mouse/main.go)
|
||||
@ -144,11 +178,22 @@ Note go1.10.x C file compilation cache problem, [golang #24355](https://github.c
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-vgo/robotgo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// robotgo.ScrollMouse(10, "up")
|
||||
robotgo.MouseSleep = 300
|
||||
|
||||
robotgo.Move(100, 100)
|
||||
fmt.Println(robotgo.Location())
|
||||
robotgo.Move(100, -200) // multi screen supported
|
||||
robotgo.MoveSmooth(120, -150)
|
||||
fmt.Println(robotgo.Location())
|
||||
|
||||
robotgo.ScrollDir(10, "up")
|
||||
robotgo.ScrollDir(20, "right")
|
||||
|
||||
robotgo.Scroll(0, -10)
|
||||
robotgo.Scroll(100, 0)
|
||||
|
||||
@ -156,10 +201,9 @@ func main() {
|
||||
robotgo.ScrollSmooth(-10, 6)
|
||||
// robotgo.ScrollRelative(10, -100)
|
||||
|
||||
robotgo.MouseSleep = 100
|
||||
robotgo.Move(10, 20)
|
||||
robotgo.MoveRelative(0, -10)
|
||||
robotgo.Drag(10, 10)
|
||||
robotgo.DragSmooth(10, 10)
|
||||
|
||||
robotgo.Click("wheelRight")
|
||||
robotgo.Click("left", true)
|
||||
@ -183,10 +227,11 @@ import (
|
||||
|
||||
func main() {
|
||||
robotgo.TypeStr("Hello World")
|
||||
robotgo.TypeStr("だんしゃり", 1.0)
|
||||
robotgo.TypeStr("だんしゃり", 0, 1)
|
||||
// robotgo.TypeStr("テストする")
|
||||
|
||||
robotgo.TypeStr("Hi galaxy. こんにちは世界.")
|
||||
robotgo.TypeStr("Hi, Seattle space needle, Golden gate bridge, One world trade center.")
|
||||
robotgo.TypeStr("Hi galaxy, hi stars, hi MT.Rainier, hi sea. こんにちは世界.")
|
||||
robotgo.Sleep(1)
|
||||
|
||||
// ustr := uint32(robotgo.CharCodeAt("Test", 0))
|
||||
@ -195,9 +240,9 @@ func main() {
|
||||
robotgo.KeySleep = 100
|
||||
robotgo.KeyTap("enter")
|
||||
// robotgo.TypeStr("en")
|
||||
robotgo.KeyTap("i", "alt", "command")
|
||||
robotgo.KeyTap("i", "alt", "cmd")
|
||||
|
||||
arr := []string{"alt", "command"}
|
||||
arr := []string{"alt", "cmd"}
|
||||
robotgo.KeyTap("i", arr)
|
||||
|
||||
robotgo.MilliSleep(100)
|
||||
@ -219,13 +264,14 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
"github.com/vcaesar/imgo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
x, y := robotgo.GetMousePos()
|
||||
x, y := robotgo.Location()
|
||||
fmt.Println("pos: ", x, y)
|
||||
|
||||
color := robotgo.GetPixelColor(100, 200)
|
||||
@ -236,14 +282,30 @@ func main() {
|
||||
|
||||
bit := robotgo.CaptureScreen(10, 10, 30, 30)
|
||||
defer robotgo.FreeBitmap(bit)
|
||||
robotgo.SaveBitmap(bit, "test_1.png")
|
||||
|
||||
img := robotgo.ToImage(bit)
|
||||
imgo.Save("test.png", img)
|
||||
|
||||
num := robotgo.DisplaysNum()
|
||||
for i := 0; i < num; i++ {
|
||||
robotgo.DisplayID = i
|
||||
img1, _ := robotgo.CaptureImg()
|
||||
path1 := "save_" + strconv.Itoa(i)
|
||||
robotgo.Save(img1, path1+".png")
|
||||
robotgo.SaveJpeg(img1, path1+".jpeg", 50)
|
||||
|
||||
img2, _ := robotgo.CaptureImg(10, 10, 20, 20)
|
||||
robotgo.Save(img2, "test_"+strconv.Itoa(i)+".png")
|
||||
|
||||
x, y, w, h := robotgo.GetDisplayBounds(i)
|
||||
img3, err := robotgo.CaptureImg(x, y, w, h)
|
||||
fmt.Println("Capture error: ", err)
|
||||
robotgo.Save(img3, path1+"_1.png")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### [Bitmap](https://github.com/go-vgo/robotgo/blob/master/examples/bitmap/main.go)
|
||||
#### [Bitmap](https://github.com/vcaesar/bitmap/blob/main/examples/main.go)
|
||||
|
||||
```Go
|
||||
package main
|
||||
@ -252,30 +314,31 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
"github.com/vcaesar/bitmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
bitmap := robotgo.CaptureScreen(10, 20, 30, 40)
|
||||
bit := robotgo.CaptureScreen(10, 20, 30, 40)
|
||||
// use `defer robotgo.FreeBitmap(bit)` to free the bitmap
|
||||
defer robotgo.FreeBitmap(bitmap)
|
||||
defer robotgo.FreeBitmap(bit)
|
||||
|
||||
fmt.Println("bitmap...", bitmap)
|
||||
img := robotgo.ToImage(bitmap)
|
||||
robotgo.SavePng(img, "test_1.png")
|
||||
fmt.Println("bitmap...", bit)
|
||||
img := robotgo.ToImage(bit)
|
||||
// robotgo.SavePng(img, "test_1.png")
|
||||
robotgo.Save(img, "test_1.png")
|
||||
|
||||
bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(img))
|
||||
fx, fy := robotgo.FindBitmap(bit2)
|
||||
fx, fy := bitmap.Find(bit2)
|
||||
fmt.Println("FindBitmap------ ", fx, fy)
|
||||
robotgo.Move(fx, fy)
|
||||
|
||||
arr := robotgo.FindAllBitmap(bit2)
|
||||
arr := bitmap.FindAll(bit2)
|
||||
fmt.Println("Find all bitmap: ", arr)
|
||||
robotgo.SaveBitmap(bitmap, "test.png")
|
||||
|
||||
fx, fy = robotgo.FindBitmap(bitmap)
|
||||
fx, fy = bitmap.Find(bit)
|
||||
fmt.Println("FindBitmap------ ", fx, fy)
|
||||
|
||||
robotgo.SaveBitmap(bitmap, "test.png")
|
||||
bitmap.Save(bit, "test.png")
|
||||
}
|
||||
```
|
||||
|
||||
@ -290,6 +353,7 @@ import (
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
"github.com/vcaesar/gcv"
|
||||
"github.com/vcaesar/bitmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -306,18 +370,18 @@ func opencv() {
|
||||
fmt.Println(gcv.FindImgFile(name1, name))
|
||||
fmt.Println(gcv.FindAllImgFile(name1, name))
|
||||
|
||||
bit := robotgo.OpenBitmap(name1)
|
||||
defer robotgo.FindBitmap(bit)
|
||||
bit := bitmap.Open(name1)
|
||||
defer robotgo.FreeBitmap(bit)
|
||||
fmt.Print("find bitmap: ")
|
||||
fmt.Println(robotgo.FindBitmap(bit))
|
||||
fmt.Println(bitmap.Find(bit))
|
||||
|
||||
// bit0 := robotgo.CaptureScreen()
|
||||
// img := robotgo.ToImage(bit0)
|
||||
// bit1 := robotgo.CaptureScreen(10, 10, 30, 30)
|
||||
// img1 := robotgo.ToImage(bit1)
|
||||
// defer robotgo.FreeBitmapArr(bit0, bit1)
|
||||
img := robotgo.CaptureImg()
|
||||
img1 := robotgo.CaptureImg(10, 10, 30, 30)
|
||||
img, _ := robotgo.CaptureImg()
|
||||
img1, _ := robotgo.CaptureImg(10, 10, 30, 30)
|
||||
|
||||
fmt.Print("gcv find image: ")
|
||||
fmt.Println(gcv.FindImg(img1, img))
|
||||
@ -341,7 +405,7 @@ func opencv() {
|
||||
}
|
||||
```
|
||||
|
||||
#### [Event](https://github.com/go-vgo/robotgo/blob/master/examples/gohook/main.go)
|
||||
#### [Event](https://github.com/robotn/gohook/blob/master/examples/main.go)
|
||||
|
||||
```Go
|
||||
package main
|
||||
@ -349,7 +413,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
// "github.com/go-vgo/robotgo"
|
||||
hook "github.com/robotn/gohook"
|
||||
)
|
||||
|
||||
@ -361,18 +425,18 @@ func main() {
|
||||
|
||||
func add() {
|
||||
fmt.Println("--- Please press ctrl + shift + q to stop hook ---")
|
||||
robotgo.EventHook(hook.KeyDown, []string{"q", "ctrl", "shift"}, func(e hook.Event) {
|
||||
hook.Register(hook.KeyDown, []string{"q", "ctrl", "shift"}, func(e hook.Event) {
|
||||
fmt.Println("ctrl-shift-q")
|
||||
robotgo.EventEnd()
|
||||
hook.End()
|
||||
})
|
||||
|
||||
fmt.Println("--- Please press w---")
|
||||
robotgo.EventHook(hook.KeyDown, []string{"w"}, func(e hook.Event) {
|
||||
hook.Register(hook.KeyDown, []string{"w"}, func(e hook.Event) {
|
||||
fmt.Println("w")
|
||||
})
|
||||
|
||||
s := robotgo.EventStart()
|
||||
<-robotgo.EventProcess(s)
|
||||
s := hook.Start()
|
||||
<-hook.Process(s)
|
||||
}
|
||||
|
||||
func low() {
|
||||
@ -385,17 +449,17 @@ func low() {
|
||||
}
|
||||
|
||||
func event() {
|
||||
ok := robotgo.AddEvents("q", "ctrl", "shift")
|
||||
ok := hook.AddEvents("q", "ctrl", "shift")
|
||||
if ok {
|
||||
fmt.Println("add events...")
|
||||
}
|
||||
|
||||
keve := robotgo.AddEvent("k")
|
||||
keve := hook.AddEvent("k")
|
||||
if keve {
|
||||
fmt.Println("you press... ", "k")
|
||||
}
|
||||
|
||||
mleft := robotgo.AddEvent("mleft")
|
||||
mleft := hook.AddEvent("mleft")
|
||||
if mleft {
|
||||
fmt.Println("you press... ", "mouse left button")
|
||||
}
|
||||
@ -419,7 +483,13 @@ func main() {
|
||||
fmt.Println("pids... ", fpid)
|
||||
|
||||
if len(fpid) > 0 {
|
||||
robotgo.ActivePID(fpid[0])
|
||||
robotgo.TypeStr("Hi galaxy!", fpid[0])
|
||||
robotgo.KeyTap("a", fpid[0], "cmd")
|
||||
|
||||
robotgo.KeyToggle("a", fpid[0])
|
||||
robotgo.KeyToggle("a", fpid[0], "up")
|
||||
|
||||
robotgo.ActivePid(fpid[0])
|
||||
|
||||
robotgo.Kill(fpid[0])
|
||||
}
|
||||
@ -434,7 +504,7 @@ func main() {
|
||||
robotgo.Kill(100)
|
||||
}
|
||||
|
||||
abool := robotgo.ShowAlert("test", "robotgo")
|
||||
abool := robotgo.Alert("test", "robotgo")
|
||||
if abool {
|
||||
fmt.Println("ok@@@ ", "ok")
|
||||
}
|
||||
@ -444,46 +514,19 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
## CrossCompiling
|
||||
|
||||
##### Windows64 to windows32
|
||||
```Go
|
||||
SET CGO_ENABLED=1
|
||||
SET GOARCH=386
|
||||
go build main.go
|
||||
```
|
||||
|
||||
#### Other to windows
|
||||
|
||||
Install Requirements (Ubuntu):
|
||||
```bash
|
||||
sudo apt install gcc-multilib
|
||||
sudo apt install gcc-mingw-w64
|
||||
# fix err: zlib.h: No such file or directory
|
||||
sudo apt install libz-mingw-w64-dev
|
||||
```
|
||||
|
||||
Build the binary:
|
||||
```Go
|
||||
GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ./
|
||||
```
|
||||
|
||||
```
|
||||
// CC=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\gcc.exe
|
||||
// CXX=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\g++.exe
|
||||
```
|
||||
|
||||
Some discussions and questions, please see [issues/228](https://github.com/go-vgo/robotgo/issues/228), [issues/143](https://github.com/go-vgo/robotgo/issues/143).
|
||||
|
||||
## Authors
|
||||
* [The author is vz](https://github.com/vcaesar)
|
||||
* [Maintainers](https://github.com/orgs/go-vgo/people)
|
||||
* [Contributors](https://github.com/go-vgo/robotgo/graphs/contributors)
|
||||
|
||||
- [The author is vz](https://github.com/vcaesar)
|
||||
- [Maintainers](https://github.com/orgs/go-vgo/people)
|
||||
- [Contributors](https://github.com/go-vgo/robotgo/graphs/contributors)
|
||||
|
||||
## Plans
|
||||
- Update Find an image on screen, read pixels from an image
|
||||
|
||||
- Refactor some C code to Go (such as x11, windows)
|
||||
- Better multiscreen support
|
||||
- Wayland support
|
||||
- Update Window Handle
|
||||
- Try support Android, maybe support IOS
|
||||
- Try to support Android and IOS
|
||||
|
||||
## Contributors
|
||||
|
||||
|
21
README_zh.md
21
README_zh.md
@ -1,5 +1,7 @@
|
||||
# Robotgo
|
||||
|
||||
## !!! Warning: this page not updated !!!
|
||||
|
||||
[](https://github.com/go-vgo/robotgo/commits/master)
|
||||
[](https://circleci.com/gh/go-vgo/robotgo)
|
||||
[](https://travis-ci.org/go-vgo/robotgo)
|
||||
@ -15,7 +17,7 @@ RobotGo 支持 Mac, Windows, and Linux(X11).
|
||||
|
||||
<br>
|
||||
|
||||
提 Issues 请到 [Github](https://github.com/go-vgo/robotgo), 便于统一管理和即时更新
|
||||
提 Issues 请到 [Github](https://github.com/go-vgo/robotgo), 便于统一管理和即时更新; `REDAME_zh.md 已废弃, 不再更新`
|
||||
|
||||
## Contents
|
||||
- [Docs](#docs)
|
||||
@ -34,8 +36,8 @@ RobotGo 支持 Mac, Windows, and Linux(X11).
|
||||
## Docs
|
||||
- [GoDoc](https://godoc.org/github.com/go-vgo/robotgo) <br>
|
||||
|
||||
- [中文文档](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md) (弃用)
|
||||
- [English Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) (弃用)
|
||||
<!-- - [中文文档](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md) (弃用)
|
||||
- [English Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) (弃用) -->
|
||||
|
||||
## Binding:
|
||||
|
||||
@ -67,19 +69,24 @@ xcode-select --install
|
||||
|
||||
```
|
||||
Or the other GCC (But you should compile the "libpng" with yourself.
|
||||
Or you can removed the bitmap.go )
|
||||
Or you can removed the bitmap.go.)
|
||||
```
|
||||
|
||||
#### For everything else (Linux 等其他系统):
|
||||
|
||||
```
|
||||
GCC, libpng
|
||||
GCC,
|
||||
libpng(bitmap)
|
||||
|
||||
X11 with the XTest extension (also known as the Xtst library)
|
||||
|
||||
事件:
|
||||
|
||||
xcb, xkb, libxkbcommon
|
||||
|
||||
Clipboard:
|
||||
|
||||
xsel xclip
|
||||
```
|
||||
|
||||
##### Ubuntu:
|
||||
@ -98,7 +105,7 @@ sudo apt install xsel xclip
|
||||
##### Fedora:
|
||||
|
||||
```yml
|
||||
sudo dnf install libxkbcommon-devel libXtst-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel
|
||||
sudo dnf install libXtst-devel libxkbcommon-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel
|
||||
|
||||
sudo dnf install libpng-devel
|
||||
|
||||
@ -425,7 +432,7 @@ func main() {
|
||||
robotgo.Kill(100)
|
||||
}
|
||||
|
||||
abool := robotgo.ShowAlert("test", "robotgo")
|
||||
abool := robotgo.Alert("test", "robotgo")
|
||||
if abool {
|
||||
fmt.Println("ok@@@ ", "ok")
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ environment:
|
||||
PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH%
|
||||
# - COMPILER: MINGW_W64
|
||||
# ARCHITECTURE: x64
|
||||
GOVERSION: 1.17.5
|
||||
GOVERSION: 1.23.0
|
||||
# GOPATH: c:\gopath
|
||||
|
||||
# scripts that run after cloning repository
|
||||
|
@ -5,89 +5,32 @@
|
||||
#include "types.h"
|
||||
#include "rgb.h"
|
||||
#include <assert.h>
|
||||
// #include <stdint.h>
|
||||
#if defined(_MSC_VER)
|
||||
#include "ms_stdint.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
struct _MMBitmap {
|
||||
uint8_t *imageBuffer; /* Pixels stored in Quad I format; i.e., origin is in
|
||||
* top left. Length should be height * bytewidth. */
|
||||
size_t width; /* Never 0, unless image is NULL. */
|
||||
size_t height; /* Never 0, unless image is NULL. */
|
||||
size_t bytewidth; /* The aligned width (width + padding). */
|
||||
uint8_t *imageBuffer; /* Pixels stored in Quad I format; */
|
||||
int32_t width; /* Never 0, unless image is NULL. */
|
||||
int32_t height; /* Never 0, unless image is NULL. */
|
||||
|
||||
int32_t bytewidth; /* The aligned width (width + padding). */
|
||||
uint8_t bitsPerPixel; /* Should be either 24 or 32. */
|
||||
uint8_t bytesPerPixel; /* For convenience; should be bitsPerPixel / 8. */
|
||||
};
|
||||
|
||||
typedef struct _MMBitmap MMBitmap;
|
||||
typedef MMBitmap *MMBitmapRef;
|
||||
// MMBitmapRef bitmap;
|
||||
|
||||
/* Creates new MMBitmap with the given values.
|
||||
* Follows the Create Rule (caller is responsible for destroy()'ing object). */
|
||||
MMBitmapRef createMMBitmap(uint8_t *buffer, size_t width, size_t height,
|
||||
size_t bytewidth, uint8_t bitsPerPixel,
|
||||
uint8_t bytesPerPixel);
|
||||
#define MMBitmapPointInBounds(image, p) ((p).x < (image)->width && (p).y < (image)->height)
|
||||
|
||||
/* Releases memory occupied by MMBitmap. */
|
||||
void destroyMMBitmap(MMBitmapRef bitmap);
|
||||
|
||||
/* Releases memory occupied by MMBitmap. Acts via CallBack method*/
|
||||
void destroyMMBitmapBuffer(char * bitmapBuffer, void * hint);
|
||||
|
||||
/* Returns copy of MMBitmap, to be destroy()'d by caller. */
|
||||
MMBitmapRef copyMMBitmap(MMBitmapRef bitmap);
|
||||
|
||||
/* Returns copy of one MMBitmap juxtaposed in another (to be destroy()'d
|
||||
* by the caller.), or NULL on error. */
|
||||
MMBitmapRef copyMMBitmapFromPortion(MMBitmapRef source, MMRect rect);
|
||||
|
||||
#define MMBitmapPointInBounds(image, p) ((p).x < (image)->width && \
|
||||
(p).y < (image)->height)
|
||||
#define MMBitmapRectInBounds(image, r) \
|
||||
(((r).origin.x + (r).size.width <= (image)->width) && \
|
||||
((r).origin.y + (r).size.height <= (image)->height))
|
||||
|
||||
#define MMBitmapGetBounds(image) MMRectMake(0, 0, image->width, image->height)
|
||||
|
||||
/* Get pointer to pixel of MMBitmapRef. No bounds checking is performed (check
|
||||
* yourself before calling this with MMBitmapPointInBounds(). */
|
||||
/* Get pointer to pixel of MMBitmapRef. No bounds checking is performed */
|
||||
#define MMRGBColorRefAtPoint(image, x, y) \
|
||||
(MMRGBColor *)(assert(MMBitmapPointInBounds(image, MMPointMake(x, y))), \
|
||||
((image)->imageBuffer) + (((image)->bytewidth * (y)) \
|
||||
+ ((x) * (image)->bytesPerPixel)))
|
||||
(MMRGBColor *)(assert(MMBitmapPointInBounds(image, MMPointInt32Make(x, y))), \
|
||||
((image)->imageBuffer) + (((image)->bytewidth * (y)) + ((x) * (image)->bytesPerPixel)))
|
||||
|
||||
/* Dereference pixel of MMBitmapRef. Again, no bounds checking is performed. */
|
||||
#define MMRGBColorAtPoint(image, x, y) *MMRGBColorRefAtPoint(image, x, y)
|
||||
|
||||
/* Hex/integer value of color at point. */
|
||||
#define MMRGBHexAtPoint(image, x, y) \
|
||||
hexFromMMRGB(MMRGBColorAtPoint(image, x, y))
|
||||
|
||||
/* Increment either point.x or point.y depending on the position of point.x.
|
||||
* That is, if x + 1 is >= width, increment y and start x at the beginning.
|
||||
* Otherwise, increment x.
|
||||
*
|
||||
* This is used as a convenience macro to scan rows when calling functions such
|
||||
* as findColorInRectAt() and findBitmapInBitmapAt(). */
|
||||
#define ITER_NEXT_POINT(pixel, width, start_x) \
|
||||
do { \
|
||||
if (++(pixel).x >= (width)) { \
|
||||
(pixel).x = start_x; \
|
||||
++(point).y; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define MMRGBHexAtPoint(image, x, y) hexFromMMRGB(MMRGBColorAtPoint(image, x, y))
|
||||
|
||||
#endif /* MMBITMAP_H */
|
@ -1,96 +0,0 @@
|
||||
#include "MMBitmap.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
//MMBitmapRef createMMBitmap()
|
||||
MMBitmapRef createMMBitmap(
|
||||
uint8_t *buffer,
|
||||
size_t width,
|
||||
size_t height,
|
||||
size_t bytewidth,
|
||||
uint8_t bitsPerPixel,
|
||||
uint8_t bytesPerPixel
|
||||
){
|
||||
MMBitmapRef bitmap = malloc(sizeof(MMBitmap));
|
||||
if (bitmap == NULL) return NULL;
|
||||
|
||||
bitmap->imageBuffer = buffer;
|
||||
bitmap->width = width;
|
||||
bitmap->height = height;
|
||||
bitmap->bytewidth = bytewidth;
|
||||
bitmap->bitsPerPixel = bitsPerPixel;
|
||||
bitmap->bytesPerPixel = bytesPerPixel;
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void destroyMMBitmap(MMBitmapRef bitmap)
|
||||
{
|
||||
assert(bitmap != NULL);
|
||||
|
||||
if (bitmap->imageBuffer != NULL) {
|
||||
free(bitmap->imageBuffer);
|
||||
bitmap->imageBuffer = NULL;
|
||||
}
|
||||
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
void destroyMMBitmapBuffer(char * bitmapBuffer, void * hint)
|
||||
{
|
||||
if (bitmapBuffer != NULL)
|
||||
{
|
||||
free(bitmapBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
MMBitmapRef copyMMBitmap(MMBitmapRef bitmap)
|
||||
{
|
||||
uint8_t *copiedBuf = NULL;
|
||||
|
||||
assert(bitmap != NULL);
|
||||
if (bitmap->imageBuffer != NULL) {
|
||||
const size_t bufsize = bitmap->height * bitmap->bytewidth;
|
||||
copiedBuf = malloc(bufsize);
|
||||
if (copiedBuf == NULL) return NULL;
|
||||
|
||||
memcpy(copiedBuf, bitmap->imageBuffer, bufsize);
|
||||
}
|
||||
|
||||
return createMMBitmap(copiedBuf,
|
||||
bitmap->width,
|
||||
bitmap->height,
|
||||
bitmap->bytewidth,
|
||||
bitmap->bitsPerPixel,
|
||||
bitmap->bytesPerPixel);
|
||||
}
|
||||
|
||||
MMBitmapRef copyMMBitmapFromPortion(MMBitmapRef source, MMRect rect)
|
||||
{
|
||||
assert(source != NULL);
|
||||
|
||||
if (source->imageBuffer == NULL || !MMBitmapRectInBounds(source, rect)) {
|
||||
return NULL;
|
||||
} else {
|
||||
uint8_t *copiedBuf = NULL;
|
||||
const size_t bufsize = rect.size.height * source->bytewidth;
|
||||
const size_t offset = (source->bytewidth * rect.origin.y) +
|
||||
(rect.origin.x * source->bytesPerPixel);
|
||||
|
||||
/* Don't go over the bounds, programmer! */
|
||||
assert((bufsize + offset) <= (source->bytewidth * source->height));
|
||||
|
||||
copiedBuf = malloc(bufsize);
|
||||
if (copiedBuf == NULL) return NULL;
|
||||
|
||||
memcpy(copiedBuf, source->imageBuffer + offset, bufsize);
|
||||
|
||||
return createMMBitmap(copiedBuf,
|
||||
rect.size.width,
|
||||
rect.size.height,
|
||||
source->bytewidth,
|
||||
source->bitsPerPixel,
|
||||
source->bytesPerPixel);
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef MMARRAY_H
|
||||
#define MMARRAY_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct _MMPointArray {
|
||||
MMPoint *array; /* Pointer to actual data. */
|
||||
size_t count; /* Number of elements in array. */
|
||||
size_t _allocedCount; /* Private; do not use outside of MMPointArray.c. */
|
||||
};
|
||||
|
||||
typedef struct _MMPointArray MMPointArray;
|
||||
typedef MMPointArray *MMPointArrayRef;
|
||||
|
||||
/* Creates array of an initial size (the maximum size is still limitless).
|
||||
* This follows the "Create" Rule; i.e., responsibility for "destroying" the
|
||||
* array is given to the caller. */
|
||||
MMPointArrayRef createMMPointArray(size_t initialCount);
|
||||
|
||||
/* Frees memory occupied by |pointArray|. Does not accept NULL. */
|
||||
void destroyMMPointArray(MMPointArrayRef pointArray);
|
||||
|
||||
/* Appends a point to an array, increasing the internal size if necessary. */
|
||||
void MMPointArrayAppendPoint(MMPointArrayRef pointArray, MMPoint point);
|
||||
|
||||
/* Retrieve point from array. */
|
||||
#define MMPointArrayGetItem(a, i) ((a)->array)[i]
|
||||
|
||||
/* Set point in array. */
|
||||
#define MMPointArraySetItem(a, i, item) ((a)->array[i] = item)
|
||||
|
||||
#endif /* MMARRAY_H */
|
@ -1,41 +0,0 @@
|
||||
#include "MMPointArray.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
MMPointArrayRef createMMPointArray(size_t initialCount)
|
||||
{
|
||||
MMPointArrayRef pointArray = calloc(1, sizeof(MMPointArray));
|
||||
|
||||
if (initialCount == 0) initialCount = 1;
|
||||
|
||||
pointArray->_allocedCount = initialCount;
|
||||
pointArray->array = malloc(pointArray->_allocedCount * sizeof(MMPoint));
|
||||
if (pointArray->array == NULL) return NULL;
|
||||
|
||||
return pointArray;
|
||||
}
|
||||
|
||||
void destroyMMPointArray(MMPointArrayRef pointArray)
|
||||
{
|
||||
if (pointArray->array != NULL) {
|
||||
free(pointArray->array);
|
||||
pointArray->array = NULL;
|
||||
}
|
||||
|
||||
free(pointArray);
|
||||
}
|
||||
|
||||
void MMPointArrayAppendPoint(MMPointArrayRef pointArray, MMPoint point)
|
||||
{
|
||||
const size_t newCount = ++(pointArray->count);
|
||||
if (pointArray->_allocedCount < newCount) {
|
||||
do {
|
||||
/* Double size each time to avoid calls to realloc(). */
|
||||
pointArray->_allocedCount <<= 1;
|
||||
} while (pointArray->_allocedCount < newCount);
|
||||
pointArray->array = realloc(pointArray->array,
|
||||
sizeof(point) *
|
||||
pointArray->_allocedCount);
|
||||
}
|
||||
|
||||
pointArray->array[pointArray->count - 1] = point;
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef UTHASHTABLE_H
|
||||
#define UTHASHTABLE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "uthash.h"
|
||||
|
||||
/* All node structs must begin with this (note that there is NO semicolon). */
|
||||
#define UTHashNode_HEAD UT_hash_handle hh;
|
||||
|
||||
/* This file contains convenience macros and a standard struct for working with
|
||||
* uthash hash tables.
|
||||
*
|
||||
* The main purpose of this is for convenience of creating/freeing nodes. */
|
||||
struct _UTHashTable {
|
||||
void *uttable; /* The uthash table -- must start out as NULL. */
|
||||
void *nodes; /* Contiguous array of nodes. */
|
||||
size_t allocedNodeCount; /* Node count currently allocated for. */
|
||||
size_t nodeCount; /* Current node count. */
|
||||
size_t nodeSize; /* Size of each node. */
|
||||
};
|
||||
|
||||
typedef struct _UTHashTable UTHashTable;
|
||||
|
||||
/* Initiates a hash table to the default values. |table| should point to an
|
||||
* already allocated UTHashTable struct.
|
||||
*
|
||||
* If the |initialCount| argument in initHashTable is given, |nodes| is
|
||||
* allocated immediately to the maximum size and new nodes are simply slices of
|
||||
* that array. This can save calls to malloc if many nodes are to be added, and
|
||||
* the a reasonable maximum number is known ahead of time.
|
||||
*
|
||||
* If the node count goes over this maximum, or if |initialCount| is 0, the
|
||||
* array is dynamically reallocated to fit the size.
|
||||
*/
|
||||
void initHashTable(UTHashTable *table, size_t initialCount, size_t nodeSize);
|
||||
|
||||
/* Frees memory occupied by a UTHashTable's members.
|
||||
*
|
||||
* Note that this does NOT free memory for the UTHashTable pointed to by
|
||||
* |table| itself; if that was allocated on the heap, you must free() it
|
||||
* yourself after calling this. */
|
||||
void destroyHashTable(UTHashTable *table);
|
||||
|
||||
/* Returns memory allocated for a new node. Responsibility for freeing this is
|
||||
* up to the destroyHashTable() macro; this should NOT be freed by the caller.
|
||||
*
|
||||
* This is intended to be used with a HASH_ADD() macro, e.g.:
|
||||
* {%
|
||||
* struct myNode *uttable = utHashTable->uttable;
|
||||
* struct myNode *node = getNewNode(utHashTable);
|
||||
* node->key = 42;
|
||||
* node->value = someValue;
|
||||
* HASH_ADD_INT(uttable, key, node);
|
||||
* utHashTable->uttable = uttable;
|
||||
* %}
|
||||
*
|
||||
* Or, use the UTHASHTABLE_ADD_INT or UTHASHTABLE_ADD_STR macros
|
||||
* for convenience (they are exactly equivalent):
|
||||
* {%
|
||||
* struct myNode *node = getNewNode(utHashTable);
|
||||
* node->key = 42;
|
||||
* node->value = someValue;
|
||||
* UTHASHTABLE_ADD_INT(utHashTable, key, node, struct myNode);
|
||||
* %}
|
||||
*/
|
||||
void *getNewNode(UTHashTable *table);
|
||||
|
||||
#define UTHASHTABLE_ADD_INT(tablePtr, keyName, node, nodeType) \
|
||||
do { \
|
||||
nodeType *uttable = (tablePtr)->uttable; \
|
||||
HASH_ADD_INT(uttable, keyName, node); \
|
||||
(tablePtr)->uttable = uttable; \
|
||||
} while (0)
|
||||
|
||||
#define UTHASHTABLE_ADD_STR(tablePtr, keyName, node, nodeType) \
|
||||
do { \
|
||||
nodeType *uttable = (tablePtr)->uttable; \
|
||||
HASH_ADD_STR(uttable, keyName, node); \
|
||||
(tablePtr)->uttable = uttable; \
|
||||
} while (0)
|
||||
|
||||
#endif /* MMHASHTABLE_H */
|
@ -1,56 +0,0 @@
|
||||
#include "UTHashTable.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* Base struct class (all nodes must contain at least the elements in
|
||||
* this struct). */
|
||||
struct _UTHashNode {
|
||||
UTHashNode_HEAD
|
||||
};
|
||||
|
||||
typedef struct _UTHashNode UTHashNode;
|
||||
|
||||
void initHashTable(UTHashTable *table, size_t initialCount, size_t nodeSize)
|
||||
{
|
||||
assert(table != NULL);
|
||||
assert(nodeSize >= sizeof(UTHashNode));
|
||||
|
||||
table->uttable = NULL; /* Must be set to NULL for uthash. */
|
||||
table->allocedNodeCount = (initialCount == 0) ? 1 : initialCount;
|
||||
table->nodeCount = 0;
|
||||
table->nodeSize = nodeSize;
|
||||
table->nodes = calloc(table->nodeSize, nodeSize * table->allocedNodeCount);
|
||||
}
|
||||
|
||||
void destroyHashTable(UTHashTable *table)
|
||||
{
|
||||
UTHashNode *uttable = table->uttable;
|
||||
UTHashNode *node;
|
||||
|
||||
/* Let uthash do its magic. */
|
||||
while (uttable != NULL) {
|
||||
node = uttable; /* Grab pointer to first item. */
|
||||
HASH_DEL(uttable, node); /* Delete it (table advances to next). */
|
||||
}
|
||||
|
||||
/* Only giant malloc'd block containing each node must be freed. */
|
||||
if (table->nodes != NULL) free(table->nodes);
|
||||
table->uttable = table->nodes = NULL;
|
||||
}
|
||||
|
||||
void *getNewNode(UTHashTable *table)
|
||||
{
|
||||
/* Increment node count, resizing table if necessary. */
|
||||
const size_t newNodeCount = ++(table->nodeCount);
|
||||
if (table->allocedNodeCount < newNodeCount) {
|
||||
do {
|
||||
/* Double size each time to avoid calls to realloc(). */
|
||||
table->allocedNodeCount <<= 1;
|
||||
} while (table->allocedNodeCount < newNodeCount);
|
||||
|
||||
table->nodes = realloc(table->nodes, table->nodeSize *
|
||||
table->allocedNodeCount);
|
||||
}
|
||||
|
||||
return (char *)table->nodes + (table->nodeSize * (table->nodeCount - 1));
|
||||
}
|
2
base/base.go
Normal file
2
base/base.go
Normal file
@ -0,0 +1,2 @@
|
||||
// https://github.com/golang/go/issues/26366
|
||||
package base
|
109
base/base64.c
109
base/base64.c
@ -1,109 +0,0 @@
|
||||
#include "base64.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* Encoding table as described in RFC1113. */
|
||||
const static uint8_t b64_encode_table[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
/* Decoding table. */
|
||||
const static int8_t b64_decode_table[256] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00-0F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10-1F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 20-2F */
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 30-3F */
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 40-4F */
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 50-5F */
|
||||
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 60-6F */
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 70-7F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80-8F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90-9F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0-AF */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0-BF */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0-CF */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0-DF */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0-EF */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* F0-FF */
|
||||
};
|
||||
|
||||
uint8_t *base64decode(const uint8_t *src, const size_t buflen, size_t *retlen){
|
||||
int8_t digit, lastdigit;
|
||||
size_t i, j;
|
||||
uint8_t *decoded;
|
||||
const size_t maxlen = ((buflen + 3) / 4) * 3;
|
||||
|
||||
/* Sanity check */
|
||||
assert(src != NULL);
|
||||
|
||||
digit = lastdigit = j = 0;
|
||||
decoded = malloc(maxlen + 1);
|
||||
if (decoded == NULL) return NULL;
|
||||
for (i = 0; i < buflen; ++i) {
|
||||
if ((digit = b64_decode_table[src[i]]) != -1) {
|
||||
/* Decode block */
|
||||
switch (i % 4) {
|
||||
case 1:
|
||||
decoded[j++] = ((lastdigit << 2) | ((digit & 0x30) >> 4));
|
||||
break;
|
||||
case 2:
|
||||
decoded[j++] = (((lastdigit & 0xF) << 4) | ((digit & 0x3C) >> 2));
|
||||
break;
|
||||
case 3:
|
||||
decoded[j++] = (((lastdigit & 0x03) << 6) | digit);
|
||||
break;
|
||||
}
|
||||
lastdigit = digit;
|
||||
}
|
||||
}
|
||||
|
||||
if (retlen != NULL) *retlen = j;
|
||||
decoded[j] = '\0';
|
||||
return decoded; /* Must be free()'d by caller */
|
||||
}
|
||||
|
||||
uint8_t *base64encode(const uint8_t *src, const size_t buflen, size_t *retlen){
|
||||
size_t i, j;
|
||||
const size_t maxlen = (((buflen + 3) & ~3)) * 4;
|
||||
uint8_t *encoded = malloc(maxlen + 1);
|
||||
if (encoded == NULL) return NULL;
|
||||
|
||||
/* Sanity check */
|
||||
assert(src != NULL);
|
||||
assert(buflen > 0);
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < buflen + 1; ++i) {
|
||||
/* Encode block */
|
||||
switch (i % 3) {
|
||||
case 0:
|
||||
encoded[j++] = b64_encode_table[src[i] >> 2];
|
||||
encoded[j++] = b64_encode_table[((src[i] & 0x03) << 4) |
|
||||
((src[i + 1] & 0xF0) >> 4)];
|
||||
break;
|
||||
case 1:
|
||||
encoded[j++] = b64_encode_table[((src[i] & 0x0F) << 2) |
|
||||
((src[i + 1] & 0xC0) >> 6)];
|
||||
break;
|
||||
case 2:
|
||||
encoded[j++] = b64_encode_table[(src[i] & 0x3F)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add padding if necessary */
|
||||
if ((j % 4) != 0) {
|
||||
const size_t with_padding = ((j + 3) & ~3); /* Align to 4 bytes */
|
||||
do {
|
||||
encoded[j++] = '=';
|
||||
} while (j < with_padding);
|
||||
}
|
||||
|
||||
assert(j <= maxlen);
|
||||
|
||||
if (retlen != NULL) *retlen = j;
|
||||
encoded[j] = '\0';
|
||||
return encoded; /* Must be free()'d by caller */
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef BASE64_H
|
||||
#define BASE64_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include "ms_stdint.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Decode a base64 encoded string discarding line breaks and noise.
|
||||
*
|
||||
* Returns a new string to be free()'d by caller, or NULL on error.
|
||||
* Returned string is guaranteed to be NUL-terminated.
|
||||
*
|
||||
* If |retlen| is not NULL, it is set to the length of the returned string
|
||||
* (minus the NUL-terminator) on successful return. */
|
||||
uint8_t *base64decode(const uint8_t *buf, const size_t buflen, size_t *retlen);
|
||||
|
||||
/* Encode a base64 encoded string without line breaks or noise.
|
||||
*
|
||||
* Returns a new string to be free()'d by caller, or NULL on error.
|
||||
* Returned string is guaranteed to be NUL-terminated with the correct padding.
|
||||
*
|
||||
* If |retlen| is not NULL, it is set to the length of the returned string
|
||||
* (minus the NUL-terminator) on successful return. */
|
||||
uint8_t *base64encode(const uint8_t *buf, const size_t buflen, size_t *retlen);
|
||||
|
||||
#endif /* BASE64_H */
|
111
base/base64_c.h
111
base/base64_c.h
@ -1,111 +0,0 @@
|
||||
#include "base64.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* Encoding table as described in RFC1113. */
|
||||
const static uint8_t b64_encode_table[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
/* Decoding table. */
|
||||
const static int8_t b64_decode_table[256] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00-0F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10-1F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 20-2F */
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 30-3F */
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 40-4F */
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 50-5F */
|
||||
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 60-6F */
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 70-7F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80-8F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90-9F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0-AF */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0-BF */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0-CF */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0-DF */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0-EF */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* F0-FF */
|
||||
};
|
||||
|
||||
uint8_t *base64decode(const uint8_t *src, const size_t buflen, size_t *retlen)
|
||||
{
|
||||
int8_t digit, lastdigit;
|
||||
size_t i, j;
|
||||
uint8_t *decoded;
|
||||
const size_t maxlen = ((buflen + 3) / 4) * 3;
|
||||
|
||||
/* Sanity check */
|
||||
assert(src != NULL);
|
||||
|
||||
digit = lastdigit = j = 0;
|
||||
decoded = malloc(maxlen + 1);
|
||||
if (decoded == NULL) return NULL;
|
||||
for (i = 0; i < buflen; ++i) {
|
||||
if ((digit = b64_decode_table[src[i]]) != -1) {
|
||||
/* Decode block */
|
||||
switch (i % 4) {
|
||||
case 1:
|
||||
decoded[j++] = ((lastdigit << 2) | ((digit & 0x30) >> 4));
|
||||
break;
|
||||
case 2:
|
||||
decoded[j++] = (((lastdigit & 0xF) << 4) | ((digit & 0x3C) >> 2));
|
||||
break;
|
||||
case 3:
|
||||
decoded[j++] = (((lastdigit & 0x03) << 6) | digit);
|
||||
break;
|
||||
}
|
||||
lastdigit = digit;
|
||||
}
|
||||
}
|
||||
|
||||
if (retlen != NULL) *retlen = j;
|
||||
decoded[j] = '\0';
|
||||
return decoded; /* Must be free()'d by caller */
|
||||
}
|
||||
|
||||
uint8_t *base64encode(const uint8_t *src, const size_t buflen, size_t *retlen)
|
||||
{
|
||||
size_t i, j;
|
||||
const size_t maxlen = (((buflen + 3) & ~3)) * 4;
|
||||
uint8_t *encoded = malloc(maxlen + 1);
|
||||
if (encoded == NULL) return NULL;
|
||||
|
||||
/* Sanity check */
|
||||
assert(src != NULL);
|
||||
assert(buflen > 0);
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < buflen + 1; ++i) {
|
||||
/* Encode block */
|
||||
switch (i % 3) {
|
||||
case 0:
|
||||
encoded[j++] = b64_encode_table[src[i] >> 2];
|
||||
encoded[j++] = b64_encode_table[((src[i] & 0x03) << 4) |
|
||||
((src[i + 1] & 0xF0) >> 4)];
|
||||
break;
|
||||
case 1:
|
||||
encoded[j++] = b64_encode_table[((src[i] & 0x0F) << 2) |
|
||||
((src[i + 1] & 0xC0) >> 6)];
|
||||
break;
|
||||
case 2:
|
||||
encoded[j++] = b64_encode_table[(src[i] & 0x3F)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add padding if necessary */
|
||||
if ((j % 4) != 0) {
|
||||
const size_t with_padding = ((j + 3) & ~3); /* Align to 4 bytes */
|
||||
do {
|
||||
encoded[j++] = '=';
|
||||
} while (j < with_padding);
|
||||
}
|
||||
|
||||
assert(j <= maxlen);
|
||||
|
||||
if (retlen != NULL) *retlen = j;
|
||||
encoded[j] = '\0';
|
||||
return encoded; /* Must be free()'d by caller */
|
||||
}
|
36
base/bitmap_free_c.h
Normal file
36
base/bitmap_free_c.h
Normal file
@ -0,0 +1,36 @@
|
||||
#include "MMBitmap.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
MMBitmapRef createMMBitmap_c(uint8_t *buffer, int32_t width, int32_t height,
|
||||
int32_t bytewidth, uint8_t bitsPerPixel, uint8_t bytesPerPixel
|
||||
) {
|
||||
MMBitmapRef bitmap = malloc(sizeof(MMBitmap));
|
||||
if (bitmap == NULL) { return NULL; }
|
||||
|
||||
bitmap->imageBuffer = buffer;
|
||||
bitmap->width = width;
|
||||
bitmap->height = height;
|
||||
bitmap->bytewidth = bytewidth;
|
||||
bitmap->bitsPerPixel = bitsPerPixel;
|
||||
bitmap->bytesPerPixel = bytesPerPixel;
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void destroyMMBitmap(MMBitmapRef bitmap) {
|
||||
assert(bitmap != NULL);
|
||||
|
||||
if (bitmap->imageBuffer != NULL) {
|
||||
free(bitmap->imageBuffer);
|
||||
bitmap->imageBuffer = NULL;
|
||||
}
|
||||
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
void destroyMMBitmapBuffer(char * bitmapBuffer, void * hint) {
|
||||
if (bitmapBuffer != NULL) {
|
||||
free(bitmapBuffer);
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef BMP_IO_H
|
||||
#define BMP_IO_H
|
||||
|
||||
#include "MMBitmap.h"
|
||||
#include "file_io.h"
|
||||
|
||||
enum _BMPReadError {
|
||||
kBMPGenericError = 0,
|
||||
kBMPAccessError,
|
||||
kBMPInvalidKeyError,
|
||||
kBMPUnsupportedHeaderError,
|
||||
kBMPInvalidColorPanesError,
|
||||
kBMPUnsupportedColorDepthError,
|
||||
kBMPUnsupportedCompressionError,
|
||||
kBMPInvalidPixelDataError
|
||||
};
|
||||
|
||||
typedef MMIOError MMBMPReadError;
|
||||
|
||||
/* Returns description of given MMBMPReadError.
|
||||
* Returned string is constant and hence should not be freed. */
|
||||
const char *MMBMPReadErrorString(MMIOError error);
|
||||
|
||||
/* Attempts to read bitmap file at path; returns new MMBitmap on success, or
|
||||
* NULL on error. If |error| is non-NULL, it will be set to the error code
|
||||
* on return.
|
||||
*
|
||||
* Currently supports:
|
||||
* - Uncompressed Windows v3/v4/v5 24-bit or 32-bit BMP.
|
||||
* - OS/2 v1 or v2 24-bit BMP.
|
||||
* - Does NOT yet support: 1-bit, 4-bit, 8-bit, 16-bit, compressed bitmaps,
|
||||
* or PNGs/JPEGs disguised as BMPs (and returns NULL if those are given).
|
||||
*
|
||||
* Responsibility for destroy()'ing returned MMBitmap is left up to caller. */
|
||||
MMBitmapRef newMMBitmapFromBMP(const char *path, MMBMPReadError *error);
|
||||
|
||||
/* Returns a buffer containing the raw BMP file data in Windows v3 BMP format,
|
||||
* ready to be saved to a file. If |len| is not NULL, it will be set to the
|
||||
* number of bytes allocated in the returned buffer.
|
||||
*
|
||||
* Responsibility for free()'ing data is left up to the caller. */
|
||||
uint8_t *createBitmapData(MMBitmapRef bitmap, size_t *len);
|
||||
|
||||
/* Saves bitmap to file in Windows v3 BMP format.
|
||||
* Returns 0 on success, -1 on error. */
|
||||
int saveMMBitmapAsBMP(MMBitmapRef bitmap, const char *path);
|
||||
|
||||
/* Swaps bitmap from Quadrant 1 to Quadran III format, or vice versa
|
||||
* (upside-down Cartesian/PostScript/GL <-> right side up QD/CG raster format).
|
||||
*/
|
||||
void flipBitmapData(void *data, size_t width, size_t height, size_t bytewidth);
|
||||
|
||||
#endif /* BMP_IO_H */
|
441
base/bmp_io_c.h
441
base/bmp_io_c.h
@ -1,441 +0,0 @@
|
||||
#include "bmp_io.h"
|
||||
#include "os.h"
|
||||
#include "endian.h"
|
||||
#include <stdio.h> /* fopen() */
|
||||
#include <string.h> /* memcpy() */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include "ms_stdbool.h"
|
||||
#include "ms_stdint.h"
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#pragma pack(push, 1) /* The following structs should be continguous, so we can
|
||||
* copy them in one read. */
|
||||
/*
|
||||
* Standard, initial BMP Header
|
||||
*/
|
||||
struct BITMAP_FILE_HEADER {
|
||||
uint16_t magic; /* First two byes of the file; should be 0x4D42. */
|
||||
uint32_t fileSize; /* Size of the BMP file in bytes (unreliable). */
|
||||
uint32_t reserved; /* Application-specific. */
|
||||
uint32_t imageOffset; /* Offset to bitmap data. */
|
||||
};
|
||||
|
||||
#define BMP_MAGIC 0x4D42 /* The starting key that marks the file as a BMP. */
|
||||
|
||||
enum _BMP_COMPRESSION {
|
||||
kBMP_RGB = 0, /* No compression. */
|
||||
kBMP_RLE8 = 1, /* Can only be used with 8-bit bitmaps. */
|
||||
kBMP_RLE4 = 2, /* Can only be used with 4-bit bitmaps. */
|
||||
kBMP_BITFIELDS = 3, /* Can only be used with 16/32-bit bitmaps. */
|
||||
kBMP_JPEG = 4, /* Bitmap contains a JPEG image. */
|
||||
kBMP_PNG = 5 /* Bitmap contains a PNG image. */
|
||||
};
|
||||
|
||||
typedef uint32_t BMP_COMPRESSION;
|
||||
|
||||
/*
|
||||
* Windows 3 Header
|
||||
*/
|
||||
struct BITMAP_INFO_HEADER {
|
||||
uint32_t headerSize; /* The size of this header (40 bytes). */
|
||||
int32_t width; /* The bitmap width in pixels. */
|
||||
int32_t height; /* The bitmap height in pixels. */
|
||||
/* (A negative value denotes that the image
|
||||
* is flipped.) */
|
||||
uint16_t colorPlanes; /* The number of color planes; must be 1. */
|
||||
uint16_t bitsPerPixel; /* The color depth of the image (1, 4, 8, 16,
|
||||
* 24, or 32). */
|
||||
BMP_COMPRESSION compression; /* The compression method being used. */
|
||||
uint32_t imageSize; /* Size of the bitmap in bytes (unreliable).*/
|
||||
int32_t xRes; /* The horizontal resolution (unreliable). */
|
||||
int32_t yRes; /* The vertical resolution (unreliable). */
|
||||
uint32_t colorsUsed; /* The number of colors in the color table,
|
||||
* or 0 to default to 2^n. */
|
||||
uint32_t colorsImportant; /* Colors important for displaying bitmap,
|
||||
* or 0 when every color is equally important;
|
||||
* ignored. */
|
||||
};
|
||||
|
||||
/*
|
||||
* OS/2 v1 Header
|
||||
*/
|
||||
struct BITMAP_CORE_HEADER {
|
||||
uint32_t headerSize; /* The size of this header (12 bytes). */
|
||||
uint16_t width; /* The bitmap width in pixels. */
|
||||
uint16_t height; /* The bitmap height in pixels. */
|
||||
uint16_t colorPlanes; /* The number of color planes; must be 1. */
|
||||
uint16_t bitsPerPixel; /* Color depth of the image (1, 4, 8, or 24). */
|
||||
};
|
||||
|
||||
#pragma pack(pop) /* Let the compiler do what it wants now. */
|
||||
|
||||
/* BMP files are always saved in little endian format (x86), so we need to
|
||||
* convert them if we're not on a little endian machine (e.g., ARM & ppc). */
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
|
||||
/* Converts bitmap file header from to and from little endian, if and only if
|
||||
* host is big endian. */
|
||||
static void convertBitmapFileHeader(struct BITMAP_FILE_HEADER *header)
|
||||
{
|
||||
header->magic = swapLittleAndHost16(header->magic);
|
||||
swapLittleAndHost32(header->fileSize);
|
||||
swapLittleAndHost32(header->reserved);
|
||||
swapLittleAndHost32(header->imageOffset);
|
||||
}
|
||||
|
||||
/* Converts bitmap info header from to and from little endian, if and only if
|
||||
* host is big endian. */
|
||||
static void convertBitmapInfoHeader(struct BITMAP_INFO_HEADER *header)
|
||||
{
|
||||
header->headerSize = swapLittleAndHost32(header->headerSize);
|
||||
header->width = swapLittleAndHost32(header->width);
|
||||
header->height = swapLittleAndHost32(header->height);
|
||||
header->colorPlanes = swapLittleAndHost16(header->colorPlanes);
|
||||
header->bitsPerPixel = swapLittleAndHost16(header->bitsPerPixel);
|
||||
header->compression = swapLittleAndHost32(header->compression);
|
||||
header->imageSize = swapLittleAndHost32(header->imageSize);
|
||||
header->xRes = swapLittleAndHost32(header->xRes);
|
||||
header->yRes = swapLittleAndHost32(header->yRes);
|
||||
header->colorsUsed = swapLittleAndHost32(header->colorsUsed);
|
||||
header->colorsImportant = swapLittleAndHost32(header->colorsImportant);
|
||||
}
|
||||
|
||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
/* No conversion necessary if we are already little endian. */
|
||||
#define convertBitmapFileHeader(header)
|
||||
#define convertBitmapInfoHeader(header)
|
||||
#endif
|
||||
|
||||
/* Returns newly alloc'd image data from bitmap file. The current position of
|
||||
* the file must be at the start of the image before calling this. */
|
||||
static uint8_t *readImageData(FILE *fp, size_t width, size_t height,
|
||||
uint8_t bytesPerPixel, size_t bytewidth);
|
||||
|
||||
/* Copys image buffer from |bitmap| to |dest| in BGR format. */
|
||||
static void copyBGRDataFromMMBitmap(MMBitmapRef bitmap, uint8_t *dest);
|
||||
|
||||
const char *MMBMPReadErrorString(MMIOError error)
|
||||
{
|
||||
switch (error) {
|
||||
case kBMPAccessError:
|
||||
return "Could not open file";
|
||||
case kBMPInvalidKeyError:
|
||||
return "Not a BMP file";
|
||||
case kBMPUnsupportedHeaderError:
|
||||
return "Unsupported BMP header";
|
||||
case kBMPInvalidColorPanesError:
|
||||
return "Invalid number of color panes in BMP file";
|
||||
case kBMPUnsupportedColorDepthError:
|
||||
return "Unsupported color depth in BMP file";
|
||||
case kBMPUnsupportedCompressionError:
|
||||
return "Unsupported file compression in BMP file";
|
||||
case kBMPInvalidPixelDataError:
|
||||
return "Could not read BMP pixel data";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
MMBitmapRef newMMBitmapFromBMP(const char *path, MMBMPReadError *err)
|
||||
{
|
||||
FILE *fp;
|
||||
struct BITMAP_FILE_HEADER fileHeader = {0}; /* Initialize elements to 0. */
|
||||
struct BITMAP_INFO_HEADER dibHeader = {0};
|
||||
uint32_t headerSize = 0;
|
||||
uint8_t bytesPerPixel;
|
||||
size_t bytewidth;
|
||||
uint8_t *imageBuf;
|
||||
|
||||
if ((fp = fopen(path, "rb")) == NULL) {
|
||||
if (err != NULL) *err = kBMPAccessError;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize error code to generic value. */
|
||||
if (err != NULL) *err = kBMPGenericError;
|
||||
|
||||
if (fread(&fileHeader, sizeof(fileHeader), 1, fp) == 0) goto bail;
|
||||
|
||||
/* Convert from little-endian if it's not already. */
|
||||
convertBitmapFileHeader(&fileHeader);
|
||||
|
||||
/* First two bytes should always be 0x4D42. */
|
||||
if (fileHeader.magic != BMP_MAGIC) {
|
||||
if (err != NULL) *err = kBMPInvalidKeyError;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Get header size. */
|
||||
if (fread(&headerSize, sizeof(headerSize), 1, fp) == 0) goto bail;
|
||||
headerSize = swapLittleAndHost32(headerSize);
|
||||
|
||||
/* Back up before reading header. */
|
||||
if (fseek(fp, -(long)sizeof(headerSize), SEEK_CUR) < 0) goto bail;
|
||||
|
||||
if (headerSize == 12) { /* OS/2 v1 header */
|
||||
struct BITMAP_CORE_HEADER coreHeader = {0};
|
||||
if (fread(&coreHeader, sizeof(coreHeader), 1, fp) == 0) goto bail;
|
||||
|
||||
dibHeader.width = coreHeader.width;
|
||||
dibHeader.height = coreHeader.height;
|
||||
dibHeader.colorPlanes = coreHeader.colorPlanes;
|
||||
dibHeader.bitsPerPixel = coreHeader.bitsPerPixel;
|
||||
} else if (headerSize == 40 || headerSize == 108 || headerSize == 124) {
|
||||
/* Windows v3/v4/v5 header */
|
||||
/* Read only the common part (v3) and skip over the rest. */
|
||||
if (fread(&dibHeader, sizeof(dibHeader), 1, fp) == 0) goto bail;
|
||||
} else {
|
||||
if (err != NULL) *err = kBMPUnsupportedHeaderError;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
convertBitmapInfoHeader(&dibHeader);
|
||||
|
||||
if (dibHeader.colorPlanes != 1) {
|
||||
if (err != NULL) *err = kBMPInvalidColorPanesError;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Currently only 24-bit and 32-bit are supported. */
|
||||
if (dibHeader.bitsPerPixel != 24 && dibHeader.bitsPerPixel != 32) {
|
||||
if (err != NULL) *err = kBMPUnsupportedColorDepthError;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (dibHeader.compression != kBMP_RGB) {
|
||||
if (err != NULL) *err = kBMPUnsupportedCompressionError;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* This can happen because we don't fully parse Windows v4/v5 headers. */
|
||||
if (ftell(fp) != (long)fileHeader.imageOffset) {
|
||||
fseek(fp, fileHeader.imageOffset, SEEK_SET);
|
||||
}
|
||||
|
||||
/* Get bytes per row, including padding. */
|
||||
bytesPerPixel = dibHeader.bitsPerPixel / 8;
|
||||
bytewidth = ADD_PADDING(dibHeader.width * bytesPerPixel);
|
||||
|
||||
imageBuf = readImageData(fp, dibHeader.width, abs(dibHeader.height),
|
||||
bytesPerPixel, bytewidth);
|
||||
fclose(fp);
|
||||
|
||||
if (imageBuf == NULL) {
|
||||
if (err != NULL) *err = kBMPInvalidPixelDataError;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* A negative height indicates that the image is flipped.
|
||||
*
|
||||
* We store our bitmaps as "flipped" according to the BMP format; i.e., (0, 0)
|
||||
* is the top left, not bottom left. So we only need to flip the bitmap if
|
||||
* the height is NOT negative. */
|
||||
if (dibHeader.height < 0) {
|
||||
dibHeader.height = -dibHeader.height;
|
||||
} else {
|
||||
flipBitmapData(imageBuf, dibHeader.width, dibHeader.height, bytewidth);
|
||||
}
|
||||
|
||||
return createMMBitmap(imageBuf, dibHeader.width, dibHeader.height,
|
||||
bytewidth, (uint8_t)dibHeader.bitsPerPixel,
|
||||
bytesPerPixel);
|
||||
|
||||
bail:
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *createBitmapData(MMBitmapRef bitmap, size_t *len)
|
||||
{
|
||||
/* BMP files are always aligned to 4 bytes. */
|
||||
const size_t bytewidth = ((bitmap->width * bitmap->bytesPerPixel) + 3) & ~3;
|
||||
|
||||
const size_t imageSize = bytewidth * bitmap->height;
|
||||
struct BITMAP_FILE_HEADER *fileHeader;
|
||||
struct BITMAP_INFO_HEADER *dibHeader;
|
||||
|
||||
/* Should always be 54. */
|
||||
const size_t imageOffset = sizeof(*fileHeader) + sizeof(*dibHeader);
|
||||
uint8_t *data;
|
||||
const size_t dataLen = imageOffset + imageSize;
|
||||
|
||||
data = calloc(1, dataLen);
|
||||
if (data == NULL) return NULL;
|
||||
|
||||
/* Save top header. */
|
||||
fileHeader = (struct BITMAP_FILE_HEADER *)data;
|
||||
fileHeader->magic = BMP_MAGIC;
|
||||
fileHeader->fileSize = (uint32_t)(sizeof(*dibHeader) + imageSize);
|
||||
fileHeader->imageOffset = (uint32_t)imageOffset;
|
||||
|
||||
/* BMP files are always stored as little-endian, so we need to convert back
|
||||
* if necessary. */
|
||||
convertBitmapFileHeader(fileHeader);
|
||||
|
||||
/* Copy Windows v3 header. */
|
||||
dibHeader = (struct BITMAP_INFO_HEADER *)(data + sizeof(*fileHeader));
|
||||
dibHeader->headerSize = sizeof(*dibHeader); /* Should always be 40. */
|
||||
dibHeader->width = (int32_t)bitmap->width;
|
||||
dibHeader->height = -(int32_t)bitmap->height; /* Our bitmaps are "flipped". */
|
||||
dibHeader->colorPlanes = 1;
|
||||
dibHeader->bitsPerPixel = bitmap->bitsPerPixel;
|
||||
dibHeader->compression = kBMP_RGB; /* Don't save with compression. */
|
||||
dibHeader->imageSize = (uint32_t)imageSize;
|
||||
|
||||
convertBitmapInfoHeader(dibHeader);
|
||||
|
||||
/* Lastly, copy the pixel data. */
|
||||
copyBGRDataFromMMBitmap(bitmap, data + imageOffset);
|
||||
|
||||
if (len != NULL) *len = dataLen;
|
||||
return data;
|
||||
}
|
||||
|
||||
int saveMMBitmapAsBMP(MMBitmapRef bitmap, const char *path)
|
||||
{
|
||||
FILE *fp;
|
||||
size_t dataLen;
|
||||
uint8_t *data;
|
||||
|
||||
if ((fp = fopen(path, "wb")) == NULL) return -1;
|
||||
|
||||
if ((data = createBitmapData(bitmap, &dataLen)) == NULL) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fwrite(data, dataLen, 1, fp) == 0) {
|
||||
free(data);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(data);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *saveMMBitmapAsBytes(MMBitmapRef bitmap, size_t *dataLen)
|
||||
{
|
||||
uint8_t *data;
|
||||
if ((data = createBitmapData(bitmap, dataLen)) == NULL) {
|
||||
*dataLen = -1;
|
||||
return NULL;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static uint8_t *readImageData(FILE *fp, size_t width, size_t height,
|
||||
uint8_t bytesPerPixel, size_t bytewidth)
|
||||
{
|
||||
size_t imageSize = bytewidth * height;
|
||||
uint8_t *imageBuf = calloc(1, imageSize);
|
||||
|
||||
if (MMRGB_IS_BGR && (bytewidth % 4) == 0) { /* No conversion needed. */
|
||||
if (fread(imageBuf, imageSize, 1, fp) == 0) {
|
||||
free(imageBuf);
|
||||
return NULL;
|
||||
}
|
||||
} else { /* Convert from BGR with 4-byte alignment. */
|
||||
uint8_t *row = malloc(bytewidth);
|
||||
size_t y;
|
||||
const size_t bmp_bytewidth = (width * bytesPerPixel + 3) & ~3;
|
||||
|
||||
if (row == NULL) return NULL;
|
||||
assert(bmp_bytewidth <= bytewidth);
|
||||
|
||||
/* Read image data row by row. */
|
||||
for (y = 0; y < height; ++y) {
|
||||
const size_t rowOffset = y * bytewidth;
|
||||
size_t x;
|
||||
uint8_t *rowptr = row;
|
||||
if (fread(row, bmp_bytewidth, 1, fp) == 0) {
|
||||
free(imageBuf);
|
||||
free(row);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (x = 0; x < width; ++x) {
|
||||
const size_t colOffset = x * bytesPerPixel;
|
||||
MMRGBColor *color = (MMRGBColor *)(imageBuf +
|
||||
rowOffset + colOffset);
|
||||
|
||||
/* BMP files are stored in BGR format. */
|
||||
color->blue = rowptr[0];
|
||||
color->green = rowptr[1];
|
||||
color->red = rowptr[2];
|
||||
rowptr += bytesPerPixel;
|
||||
}
|
||||
}
|
||||
|
||||
free(row);
|
||||
}
|
||||
|
||||
return imageBuf;
|
||||
}
|
||||
|
||||
static void copyBGRDataFromMMBitmap(MMBitmapRef bitmap, uint8_t *dest)
|
||||
{
|
||||
if (MMRGB_IS_BGR && (bitmap->bytewidth % 4) == 0) { /* No conversion needed. */
|
||||
memcpy(dest, bitmap->imageBuffer, bitmap->bytewidth * bitmap->height);
|
||||
} else { /* Convert to RGB with other-than-4-byte alignment. */
|
||||
const size_t bytewidth = (bitmap->width * bitmap->bytesPerPixel + 3) & ~3;
|
||||
size_t y;
|
||||
|
||||
/* Copy image data row by row. */
|
||||
for (y = 0; y < bitmap->height; ++y) {
|
||||
uint8_t *rowptr = dest + (y * bytewidth);
|
||||
size_t x;
|
||||
for (x = 0; x < bitmap->width; ++x) {
|
||||
MMRGBColor *color = MMRGBColorRefAtPoint(bitmap, x, y);
|
||||
|
||||
/* BMP files are stored in BGR format. */
|
||||
rowptr[0] = color->blue;
|
||||
rowptr[1] = color->green;
|
||||
rowptr[2] = color->red;
|
||||
|
||||
rowptr += bitmap->bytesPerPixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform an in-place swap from Quadrant 1 to Quadrant III format (upside-down
|
||||
* PostScript/GL to right side up QD/CG raster format) We do this in-place,
|
||||
* which requires more copying, but will touch only half the pages.
|
||||
*
|
||||
* This is blatantly copied from Apple's glGrab example code. */
|
||||
void flipBitmapData(void *data, size_t width, size_t height, size_t bytewidth)
|
||||
{
|
||||
size_t top, bottom;
|
||||
void *topP;
|
||||
void *bottomP;
|
||||
void *tempbuf;
|
||||
|
||||
if (height <= 1) return; /* No flipping necessary if height is <= 1. */
|
||||
|
||||
top = 0;
|
||||
bottom = height - 1;
|
||||
tempbuf = malloc(bytewidth);
|
||||
if (tempbuf == NULL) return;
|
||||
|
||||
while (top < bottom) {
|
||||
topP = (void *)((top * bytewidth) + (intptr_t)data);
|
||||
bottomP = (void *)((bottom * bytewidth) + (intptr_t)data);
|
||||
|
||||
/* Save and swap scanlines.
|
||||
* Does a simple in-place exchange with a temp buffer. */
|
||||
memcpy(tempbuf, topP, bytewidth);
|
||||
memcpy(topP, bottomP, bytewidth);
|
||||
memcpy(bottomP, tempbuf, bytewidth);
|
||||
|
||||
++top;
|
||||
--bottom;
|
||||
}
|
||||
free(tempbuf);
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef COLOR_FIND_H
|
||||
#define COLOR_FIND_H
|
||||
|
||||
#include "MMBitmap.h"
|
||||
#include "MMPointArray.h"
|
||||
|
||||
/* Convenience wrapper around findColorInRect(), where |rect| is the bounds of
|
||||
* the image. */
|
||||
#define findColorInImage(image, color, pointPtr, tolerance) \
|
||||
findColorInRect(image, color, pointPtr, MMBitmapGetBounds(image), tolerance)
|
||||
|
||||
/* Attempt to find a pixel with the given color in |image| inside |rect|.
|
||||
* Returns 0 on success, non-zero on failure. If the color was found and
|
||||
* |point| is not NULL, it will be initialized to the (x, y) coordinates the
|
||||
* RGB color.
|
||||
*
|
||||
* |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the
|
||||
* colors need to match, with 0 being exact and 1 being any. */
|
||||
int findColorInRect(MMBitmapRef image, MMRGBHex color, MMPoint *point,
|
||||
MMRect rect, float tolerance);
|
||||
|
||||
/* Convenience wrapper around findAllRGBInRect(), where |rect| is the bounds of
|
||||
* the image. */
|
||||
#define findAllColorInImage(image, color, tolerance) \
|
||||
findAllColorInRect(image, color, MMBitmapGetBounds(image), tolerance)
|
||||
|
||||
/* Returns MMPointArray of all pixels of given color in |image| inside of
|
||||
* |rect|. Note that an array is returned regardless of whether the color was
|
||||
* found; check array->count to see if it actually was.
|
||||
*
|
||||
* Responsibility for freeing the MMPointArray with destroyMMPointArray() is
|
||||
* given to the caller.
|
||||
*
|
||||
* |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the
|
||||
* colors need to match, with 0 being exact and 1 being any. */
|
||||
MMPointArrayRef findAllColorInRect(MMBitmapRef image, MMRGBHex color,
|
||||
MMRect rect, float tolerance);
|
||||
|
||||
/* Convenience wrapper around countOfColorsInRect, where |rect| is the bounds
|
||||
* of the image. */
|
||||
#define countOfColorsInImage(image, color, tolerance) \
|
||||
countOfColorsInRect(image, color, MMBitmapGetBounds(image), tolerance)
|
||||
|
||||
/* Returns the count of the given color in |rect| inside of |image|. */
|
||||
size_t countOfColorsInRect(MMBitmapRef image, MMRGBHex color, MMRect rect,
|
||||
float tolerance);
|
||||
|
||||
#endif /* COLOR_FIND_H */
|
@ -1,58 +0,0 @@
|
||||
#include "color_find.h"
|
||||
// #include "../screen/screen_init.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Abstracted, general function to avoid repeated code. */
|
||||
static int findColorInRectAt(MMBitmapRef image, MMRGBHex color, MMPoint *point,
|
||||
MMRect rect, float tolerance, MMPoint startPoint)
|
||||
{
|
||||
MMPoint scan = startPoint;
|
||||
if (!MMBitmapRectInBounds(image, rect)) return -1;
|
||||
|
||||
for (; scan.y < rect.size.height; ++scan.y) {
|
||||
for (; scan.x < rect.size.width; ++scan.x) {
|
||||
MMRGBHex found = MMRGBHexAtPoint(image, scan.x, scan.y);
|
||||
if (MMRGBHexSimilarToColor(color, found, tolerance)) {
|
||||
if (point != NULL) *point = scan;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
scan.x = rect.origin.x;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int findColorInRect(MMBitmapRef image, MMRGBHex color,
|
||||
MMPoint *point, MMRect rect, float tolerance)
|
||||
{
|
||||
return findColorInRectAt(image, color, point, rect, tolerance, rect.origin);
|
||||
}
|
||||
|
||||
MMPointArrayRef findAllColorInRect(MMBitmapRef image, MMRGBHex color,
|
||||
MMRect rect, float tolerance)
|
||||
{
|
||||
MMPointArrayRef pointArray = createMMPointArray(0);
|
||||
MMPoint point = MMPointZero;
|
||||
|
||||
while (findColorInRectAt(image, color, &point, rect, tolerance, point) == 0) {
|
||||
MMPointArrayAppendPoint(pointArray, point);
|
||||
ITER_NEXT_POINT(point, rect.size.width, rect.origin.x);
|
||||
}
|
||||
|
||||
return pointArray;
|
||||
}
|
||||
|
||||
size_t countOfColorsInRect(MMBitmapRef image, MMRGBHex color, MMRect rect,
|
||||
float tolerance)
|
||||
{
|
||||
size_t count = 0;
|
||||
MMPoint point = MMPointZero;
|
||||
|
||||
while (findColorInRectAt(image, color, &point, rect, tolerance, point) == 0) {
|
||||
ITER_NEXT_POINT(point, rect.size.width, rect.origin.x);
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
@ -4,11 +4,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define DEADBEEF_MAX UINT32_MAX
|
||||
|
||||
/* Dead Beef Random Number Generator
|
||||
* From: http://inglorion.net/software/deadbeef_rand
|
||||
* A fast, portable psuedo-random number generator by BJ Amsterdam Zuidoost.
|
||||
* Stated in license terms: "Feel free to use the code in your own software." */
|
||||
/* Dead Beef Random Number Generator From: http://inglorion.net/software/deadbeef_rand */
|
||||
|
||||
/* Generates a random number between 0 and DEADBEEF_MAX. */
|
||||
uint32_t deadbeef_rand(void);
|
||||
@ -22,14 +18,11 @@ uint32_t deadbeef_generate_seed(void);
|
||||
/* Seeds with the above function. */
|
||||
#define deadbeef_srand_time() deadbeef_srand(deadbeef_generate_seed())
|
||||
|
||||
/* Returns random double in the range [a, b).
|
||||
* Taken directly from the rand() man page. */
|
||||
/* Returns random double in the range [a, b).*/
|
||||
#define DEADBEEF_UNIFORM(a, b) \
|
||||
((a) + (deadbeef_rand() / (((double)DEADBEEF_MAX / (b - a) + 1))))
|
||||
|
||||
/* Returns random integer in the range [a, b).
|
||||
* Also taken from the rand() man page. */
|
||||
#define DEADBEEF_RANDRANGE(a, b) \
|
||||
(uint32_t)DEADBEEF_UNIFORM(a, b)
|
||||
/* Returns random integer in the range [a, b).*/
|
||||
#define DEADBEEF_RANDRANGE(a, b) (uint32_t)DEADBEEF_UNIFORM(a, b)
|
||||
|
||||
#endif /* DEADBEEF_RAND_H */
|
||||
|
@ -4,23 +4,19 @@
|
||||
static uint32_t deadbeef_seed;
|
||||
static uint32_t deadbeef_beef = 0xdeadbeef;
|
||||
|
||||
uint32_t deadbeef_rand(void)
|
||||
{
|
||||
uint32_t deadbeef_rand(void) {
|
||||
deadbeef_seed = (deadbeef_seed << 7) ^ ((deadbeef_seed >> 25) + deadbeef_beef);
|
||||
deadbeef_beef = (deadbeef_beef << 7) ^ ((deadbeef_beef >> 25) + 0xdeadbeef);
|
||||
return deadbeef_seed;
|
||||
}
|
||||
|
||||
void deadbeef_srand(uint32_t x)
|
||||
{
|
||||
void deadbeef_srand(uint32_t x) {
|
||||
deadbeef_seed = x;
|
||||
deadbeef_beef = 0xdeadbeef;
|
||||
}
|
||||
|
||||
/* Taken directly from the documentation:
|
||||
* http://inglorion.net/software/cstuff/deadbeef_rand/ */
|
||||
uint32_t deadbeef_generate_seed(void)
|
||||
{
|
||||
/* Taken directly from the documentation: http://inglorion.net/software/cstuff/deadbeef_rand/ */
|
||||
uint32_t deadbeef_generate_seed(void) {
|
||||
uint32_t t = (uint32_t)time(NULL);
|
||||
uint32_t c = (uint32_t)clock();
|
||||
return (t << 24) ^ (c << 11) ^ t ^ (size_t) &c;
|
||||
|
123
base/endian.h
123
base/endian.h
@ -1,123 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef ENDIAN_H
|
||||
#define ENDIAN_H
|
||||
|
||||
#include "os.h"
|
||||
|
||||
/*
|
||||
* (Mostly) cross-platform endian definitions and bit swapping macros.
|
||||
* Unfortunately, there is no standard C header for this, so we just
|
||||
* include the most common ones and fallback to our own custom macros.
|
||||
*/
|
||||
|
||||
#if defined(__linux__) /* Linux */
|
||||
#include <endian.h>
|
||||
#include <byteswap.h>
|
||||
#elif (defined(__FreeBSD__) && __FreeBSD_version >= 470000) || \
|
||||
defined(__OpenBSD__) || defined(__NetBSD__) /* (Free|Open|Net)BSD */
|
||||
#include <sys/endian.h>
|
||||
#define __BIG_ENDIAN BIG_ENDIAN
|
||||
#define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
#define __BYTE_ORDER BYTE_ORDER
|
||||
#elif defined(IS_MACOSX) || (defined(BSD) && (BSD >= 199103)) /* Other BSD */
|
||||
#include <machine/endian.h>
|
||||
#define __BIG_ENDIAN BIG_ENDIAN
|
||||
#define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
#define __BYTE_ORDER BYTE_ORDER
|
||||
#elif defined(IS_WINDOWS) /* Windows is assumed to be little endian only. */
|
||||
#define __BIG_ENDIAN 4321
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
/* Fallback to custom constants. */
|
||||
#if !defined(__BIG_ENDIAN)
|
||||
#define __BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
#if !defined(__LITTLE_ENDIAN)
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
|
||||
/* Prefer compiler flag settings if given. */
|
||||
#if defined(MM_BIG_ENDIAN)
|
||||
#undef __BYTE_ORDER /* Avoid redefined macro compiler warning. */
|
||||
#define __BYTE_ORDER __BIG_ENDIAN
|
||||
#elif defined(MM_LITTLE_ENDIAN)
|
||||
#undef __BYTE_ORDER /* Avoid redefined macro compiler warning. */
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
/* Define default endian-ness. */
|
||||
#ifndef __LITTLE_ENDIAN
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#endif /* __LITTLE_ENDIAN */
|
||||
|
||||
#ifndef __BIG_ENDIAN
|
||||
#define __BIG_ENDIAN 4321
|
||||
#endif /* __BIG_ENDIAN */
|
||||
|
||||
#ifndef __BYTE_ORDER
|
||||
#warning "Byte order not defined on your system; assuming little endian"
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#endif /* __BYTE_ORDER */
|
||||
|
||||
#if __BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN
|
||||
#error "__BYTE_ORDER set to unknown byte order"
|
||||
#endif
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
#include <libkern/OSByteOrder.h>
|
||||
|
||||
/* OS X system functions. */
|
||||
#define bitswap16(i) OSSwapInt16(i)
|
||||
#define bitswap32(i) OSSwapInt32(i)
|
||||
#define swapLittleAndHost32(i) OSSwapLittleToHostInt32(i)
|
||||
#define swapLittleAndHost16(i) OSSwapLittleToHostInt16(i)
|
||||
#else
|
||||
#ifndef bitswap16
|
||||
#if defined(bswap16)
|
||||
#define bitswap16(i) bswap16(i) /* FreeBSD system function */
|
||||
#elif defined(bswap_16)
|
||||
#define bitswap16(i) bswap_16(i) /* Linux system function */
|
||||
#else /* Default macro */
|
||||
#define bitswap16(i) (((uint16_t)(i) & 0xFF00) >> 8) | \
|
||||
(((uint16_t)(i) & 0x00FF) << 8)
|
||||
#endif
|
||||
#endif /* bitswap16 */
|
||||
|
||||
#ifndef bitswap32
|
||||
#if defined(bswap32)
|
||||
#define bitswap32(i) bswap32(i) /* FreeBSD system function. */
|
||||
#elif defined(bswap_32)
|
||||
#define bitswap32(i) bswap_32(i) /* Linux system function. */
|
||||
#else /* Default macro */
|
||||
#define bitswap32(i) (((uint32_t)(i) & 0xFF000000) >> 24) | \
|
||||
((uint32_t)((i) & 0x00FF0000) >> 8) | \
|
||||
((uint32_t)((i) & 0x0000FF00) << 8) | \
|
||||
((uint32_t)((i) & 0x000000FF) << 24)
|
||||
#endif
|
||||
#endif /* bitswap32 */
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
/* Little endian to/from host byte order (big endian). */
|
||||
#ifndef swapLittleAndHost16
|
||||
#define swapLittleAndHost16(i) bitswap16(i)
|
||||
#endif /* swapLittleAndHost16 */
|
||||
|
||||
#ifndef swapLittleAndHost32
|
||||
#define swapLittleAndHost32(i) bitswap32(i)
|
||||
#endif /* swapLittleAndHost32 */
|
||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
/* We are already little endian, so no conversion is needed. */
|
||||
#ifndef swapLittleAndHost16
|
||||
#define swapLittleAndHost16(i) i
|
||||
#endif /* swapLittleAndHost16 */
|
||||
|
||||
#ifndef swapLittleAndHost32
|
||||
#define swapLittleAndHost32(i) i
|
||||
#endif /* swapLittleAndHost32 */
|
||||
#endif
|
||||
|
||||
#endif /* ENDIAN_H */
|
@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef FILE_IO_H
|
||||
#define FILE_IO_H
|
||||
|
||||
#include "MMBitmap.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
enum _MMImageType {
|
||||
kInvalidImageType = 0,
|
||||
kPNGImageType,
|
||||
kBMPImageType /* Currently only PNG and BMP are supported. */
|
||||
};
|
||||
|
||||
typedef uint16_t MMImageType;
|
||||
|
||||
enum _MMIOError {
|
||||
kMMIOUnsupportedTypeError = 0
|
||||
};
|
||||
|
||||
typedef uint16_t MMIOError;
|
||||
|
||||
const char *getExtension(const char *fname, size_t len);
|
||||
|
||||
/* Returns best guess at the MMImageType based on a file extension, or
|
||||
* |kInvalidImageType| if no matching type was found. */
|
||||
MMImageType imageTypeFromExtension(const char *ext);
|
||||
|
||||
/* Attempts to parse the file of the given type at the given path.
|
||||
* |filepath| is an ASCII string describing the absolute POSIX path.
|
||||
* Returns new bitmap (to be destroy()'d by caller) on success, NULL on error.
|
||||
* If |error| is non-NULL, it will be set to the error code on return.
|
||||
*/
|
||||
MMBitmapRef newMMBitmapFromFile(const char *path, MMImageType type, MMIOError *err);
|
||||
|
||||
/* Saves |bitmap| to a file of the given type at the given path.
|
||||
* |filepath| is an ASCII string describing the absolute POSIX path.
|
||||
* Returns 0 on success, -1 on error. */
|
||||
int saveMMBitmapToFile(MMBitmapRef bitmap, const char *path, MMImageType type);
|
||||
|
||||
/* Returns description of given error code.
|
||||
* Returned string is constant and hence should not be freed. */
|
||||
const char *MMIOErrorString(MMImageType type, MMIOError error);
|
||||
|
||||
#endif /* IO_H */
|
@ -1,70 +0,0 @@
|
||||
#include "file_io.h"
|
||||
// #include "os.h"
|
||||
#include "bmp_io_c.h"
|
||||
#include "png_io_c.h"
|
||||
#include <stdio.h> /* For fputs() */
|
||||
#include <string.h> /* For strcmp() */
|
||||
#include <ctype.h> /* For tolower() */
|
||||
|
||||
const char *getExtension(const char *fname, size_t len){
|
||||
if (fname == NULL || len <= 0) return NULL;
|
||||
|
||||
while (--len > 0 && fname[len] != '.' && fname[len] != '\0')
|
||||
;
|
||||
|
||||
return fname + len + 1;
|
||||
}
|
||||
|
||||
MMImageType imageTypeFromExtension(const char *extension){
|
||||
char ext[4];
|
||||
const size_t maxlen = sizeof(ext) / sizeof(ext[0]);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; extension[i] != '\0'; ++i) {
|
||||
if (i >= maxlen) return kInvalidImageType;
|
||||
ext[i] = tolower(extension[i]);
|
||||
}
|
||||
ext[i] = '\0';
|
||||
|
||||
if (strcmp(ext, "png") == 0) {
|
||||
return kPNGImageType;
|
||||
} else if (strcmp(ext, "bmp") == 0) {
|
||||
return kBMPImageType;
|
||||
} else {
|
||||
return kInvalidImageType;
|
||||
}
|
||||
}
|
||||
|
||||
MMBitmapRef newMMBitmapFromFile(const char *path, MMImageType type, MMIOError *err){
|
||||
switch (type) {
|
||||
case kBMPImageType:
|
||||
return newMMBitmapFromBMP(path, err);
|
||||
case kPNGImageType:
|
||||
return newMMBitmapFromPNG(path, err);
|
||||
default:
|
||||
if (err != NULL) *err = kMMIOUnsupportedTypeError;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int saveMMBitmapToFile(MMBitmapRef bitmap, const char *path, MMImageType type){
|
||||
switch (type) {
|
||||
case kBMPImageType:
|
||||
return saveMMBitmapAsBMP(bitmap, path);
|
||||
case kPNGImageType:
|
||||
return saveMMBitmapAsPNG(bitmap, path);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *MMIOErrorString(MMImageType type, MMIOError error){
|
||||
switch (type) {
|
||||
case kBMPImageType:
|
||||
return MMBMPReadErrorString(error);
|
||||
case kPNGImageType:
|
||||
return MMPNGReadErrorString(error);
|
||||
default:
|
||||
return "Unsupported image type";
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
/* A complicated, portable model for declaring inline functions in
|
||||
* header files. */
|
||||
/* A complicated, portable model for declaring inline functions in header files. */
|
||||
#if !defined(H_INLINE)
|
||||
#if defined(__GNUC__)
|
||||
#define H_INLINE static __inline__ __attribute__((always_inline))
|
||||
|
70
base/io.c
70
base/io.c
@ -1,70 +0,0 @@
|
||||
#include "file_io.h"
|
||||
#include "os.h"
|
||||
#include "bmp_io.h"
|
||||
#include "png_io.h"
|
||||
#include <stdio.h> /* For fputs() */
|
||||
#include <string.h> /* For strcmp() */
|
||||
#include <ctype.h> /* For tolower() */
|
||||
|
||||
const char *getExtension(const char *fname, size_t len){
|
||||
if (fname == NULL || len <= 0) return NULL;
|
||||
|
||||
while (--len > 0 && fname[len] != '.' && fname[len] != '\0')
|
||||
;
|
||||
|
||||
return fname + len + 1;
|
||||
}
|
||||
|
||||
MMImageType imageTypeFromExtension(const char *extension){
|
||||
char ext[4];
|
||||
const size_t maxlen = sizeof(ext) / sizeof(ext[0]);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; extension[i] != '\0'; ++i) {
|
||||
if (i >= maxlen) return kInvalidImageType;
|
||||
ext[i] = tolower(extension[i]);
|
||||
}
|
||||
ext[i] = '\0';
|
||||
|
||||
if (strcmp(ext, "png") == 0) {
|
||||
return kPNGImageType;
|
||||
} else if (strcmp(ext, "bmp") == 0) {
|
||||
return kBMPImageType;
|
||||
} else {
|
||||
return kInvalidImageType;
|
||||
}
|
||||
}
|
||||
|
||||
MMBitmapRef newMMBitmapFromFile(const char *path, MMImageType type, MMIOError *err){
|
||||
switch (type) {
|
||||
case kBMPImageType:
|
||||
return newMMBitmapFromBMP(path, err);
|
||||
case kPNGImageType:
|
||||
return newMMBitmapFromPNG(path, err);
|
||||
default:
|
||||
if (err != NULL) *err = kMMIOUnsupportedTypeError;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int saveMMBitmapToFile(MMBitmapRef bitmap, const char *path, MMImageType type){
|
||||
switch (type) {
|
||||
case kBMPImageType:
|
||||
return saveMMBitmapAsBMP(bitmap, path);
|
||||
case kPNGImageType:
|
||||
return saveMMBitmapAsPNG(bitmap, path);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *MMIOErrorString(MMImageType type, MMIOError error){
|
||||
switch (type) {
|
||||
case kBMPImageType:
|
||||
return MMBMPReadErrorString(error);
|
||||
case kPNGImageType:
|
||||
return MMPNGReadErrorString(error);
|
||||
default:
|
||||
return "Unsupported image type";
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
#include "os.h"
|
||||
#include "inline_keywords.h"
|
||||
|
||||
// todo: removed
|
||||
#if !defined(IS_WINDOWS)
|
||||
/* Make sure nanosleep gets defined even when using C89. */
|
||||
#if !defined(__USE_POSIX199309) || !__USE_POSIX199309
|
||||
@ -14,21 +15,12 @@
|
||||
#include <time.h> /* For nanosleep() */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A more widely supported alternative to usleep(), based on Sleep() in Windows
|
||||
* and nanosleep() everywhere else.
|
||||
*
|
||||
* Pauses execution for the given amount of milliseconds.
|
||||
*/
|
||||
/* A more widely supported alternative to usleep(), based on Sleep() in Windows and nanosleep() */
|
||||
H_INLINE void microsleep(double milliseconds) {
|
||||
#if defined(IS_WINDOWS)
|
||||
Sleep((DWORD)milliseconds); /* (Unfortunately truncated to a 32-bit integer.) */
|
||||
#else
|
||||
/* Technically, nanosleep() is not an ANSI function, but it is the most
|
||||
* supported precise sleeping function I can find.
|
||||
*
|
||||
* If it is really necessary, it may be possible to emulate this with some
|
||||
* hack using select() in the future if we really have to. */
|
||||
/* Technically, nanosleep() is not an ANSI function */
|
||||
struct timespec sleepytime;
|
||||
sleepytime.tv_sec = milliseconds / 1000;
|
||||
sleepytime.tv_nsec = (milliseconds - (sleepytime.tv_sec * 1000)) * 1000000;
|
||||
|
@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
#if !defined(MS_STDBOOL_H) && \
|
||||
(!defined(__bool_true_false_are_defined) || __bool_true_false_are_defined)
|
||||
#define MS_STDBOOL_H
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#if defined(true) || defined(false) || defined(bool)
|
||||
#error "Boolean type already defined"
|
||||
#endif
|
||||
|
||||
enum {
|
||||
false = 0,
|
||||
true = 1
|
||||
};
|
||||
|
||||
typedef unsigned char bool;
|
||||
|
||||
#endif /* !__cplusplus */
|
||||
|
||||
#endif /* MS_STDBOOL_H */
|
224
base/ms_stdint.h
224
base/ms_stdint.h
@ -1,224 +0,0 @@
|
||||
/* ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
* Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
*
|
||||
* Copyright (c) 2006-2008 Alexander Chemeris
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of the author may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#ifndef MSC_STDINT_H
|
||||
#define MSC_STDINT_H
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/* For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
* compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
* or compiler give many errors like this: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#include <wchar.h>
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Define _W64 macros to mark types changing their size, like intptr_t. */
|
||||
#ifndef _W64
|
||||
#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
#define _W64 __w64
|
||||
#else
|
||||
#define _W64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* 7.18.1 Integer types */
|
||||
|
||||
/* 7.18.1.1 Exact-width integer types */
|
||||
|
||||
/* Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
* realize that, e.g. char has the same size as __int8
|
||||
* so we give up on __intX for them. */
|
||||
#if _MSC_VER < 1300
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
/* 7.18.1.2 Minimum-width integer types */
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
/* 7.18.1.3 Fastest minimum-width integer types */
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
/* 7.18.1.4 Integer types capable of holding object pointers */
|
||||
#if defined(_WIN64)
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif /* _WIN64 ] */
|
||||
|
||||
/* 7.18.1.5 Greatest-width integer types */
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
/* 7.18.2 Limits of specified-width integer types */
|
||||
|
||||
/* See footnote 220 at page 257 and footnote 221 at page 259 */
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
|
||||
|
||||
/* 7.18.2.1 Limits of exact-width integer types */
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
/* 7.18.2.2 Limits of minimum-width integer types */
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
/* 7.18.2.4 Limits of integer types capable of holding object pointers */
|
||||
#if defined(_WIN64)
|
||||
#define INTPTR_MIN INT64_MIN
|
||||
#define INTPTR_MAX INT64_MAX
|
||||
#define UINTPTR_MAX UINT64_MAX
|
||||
#else
|
||||
#define INTPTR_MIN INT32_MIN
|
||||
#define INTPTR_MAX INT32_MAX
|
||||
#define UINTPTR_MAX UINT32_MAX
|
||||
#endif
|
||||
|
||||
/* 7.18.3 Limits of other integer types */
|
||||
|
||||
#if defined(_WIN64)
|
||||
#define PTRDIFF_MIN _I64_MIN
|
||||
#define PTRDIFF_MAX _I64_MAX
|
||||
#else
|
||||
#define PTRDIFF_MIN _I32_MIN
|
||||
#define PTRDIFF_MAX _I32_MAX
|
||||
#endif /* _WIN64 */
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#if defined(_WIN64)
|
||||
#define SIZE_MAX _UI64_MAX
|
||||
#else
|
||||
#define SIZE_MAX _UI32_MAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> */
|
||||
#ifndef WCHAR_MIN
|
||||
#define WCHAR_MIN 0
|
||||
#endif /* WCHAR_MIN */
|
||||
|
||||
#ifndef WCHAR_MAX
|
||||
#define WCHAR_MAX _UI16_MAX
|
||||
#endif /* WCHAR_MAX */
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
#endif /* __STDC_LIMIT_MACROS */
|
||||
|
||||
|
||||
/* 7.18.4 Limits of other integer types */
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) /* See footnote 224 at page 260 */
|
||||
|
||||
/* 7.18.4.1 Macros for minimum-width integer constants */
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
/* 7.18.4.2 Macros for greatest-width integer constants */
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif /* __STDC_CONSTANT_MACROS */
|
||||
|
||||
#endif /* MSC_STDINT_H */
|
26
base/os.h
26
base/os.h
@ -2,19 +2,12 @@
|
||||
#ifndef OS_H
|
||||
#define OS_H
|
||||
|
||||
/* Python versions under 2.5 don't support this macro, but it's not
|
||||
* terribly difficult to replicate: */
|
||||
#ifndef PyModule_AddIntMacro
|
||||
#define PyModule_AddIntMacro(module, macro) \
|
||||
PyModule_AddIntConstant(module, #macro, macro)
|
||||
#endif /* PyModule_AddIntMacro */
|
||||
|
||||
#if !defined(IS_MACOSX) && defined(__APPLE__) && defined(__MACH__)
|
||||
#define IS_MACOSX
|
||||
#endif /* IS_MACOSX */
|
||||
|
||||
#if !defined(IS_WINDOWS) && (defined(WIN32) || defined(_WIN32) || \
|
||||
defined(__WIN32__) || defined(__WINDOWS__) || defined(__CYGWIN__))
|
||||
defined(__WIN32__) || defined(__WINDOWS__) || defined(__CYGWIN__))
|
||||
#define IS_WINDOWS
|
||||
#endif /* IS_WINDOWS */
|
||||
|
||||
@ -30,8 +23,7 @@
|
||||
#error "Sorry, this platform isn't supported yet!"
|
||||
#endif
|
||||
|
||||
/* Interval to align by for large buffers (e.g. bitmaps). */
|
||||
/* Must be a power of 2. */
|
||||
/* Interval to align by for large buffers (e.g. bitmaps). Must be a power of 2. */
|
||||
#ifndef BYTE_ALIGN
|
||||
#define BYTE_ALIGN 4 /* Bytes to align pixel buffers to. */
|
||||
/* #include <stddef.h> */
|
||||
@ -46,4 +38,18 @@
|
||||
#define ADD_PADDING(width) (BYTE_ALIGN + (((width) - 1) & ~(BYTE_ALIGN - 1)))
|
||||
#endif
|
||||
|
||||
#if defined(IS_WINDOWS)
|
||||
#if defined (_WIN64)
|
||||
#define RobotGo_64
|
||||
#else
|
||||
#define RobotGo_32
|
||||
#endif
|
||||
#else
|
||||
#if defined (__x86_64__)
|
||||
#define RobotGo_64
|
||||
#else
|
||||
#define RobotGo_32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* OS_H */
|
||||
|
@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef PASTEBOARD_H
|
||||
#define PASTEBOARD_H
|
||||
|
||||
#include "MMBitmap.h"
|
||||
#include "file_io.h"
|
||||
|
||||
enum _MMBitmapPasteError {
|
||||
kMMPasteNoError = 0,
|
||||
kMMPasteGenericError,
|
||||
kMMPasteOpenError,
|
||||
kMMPasteClearError,
|
||||
kMMPasteDataError,
|
||||
kMMPastePasteError,
|
||||
kMMPasteUnsupportedError
|
||||
};
|
||||
|
||||
typedef MMIOError MMPasteError;
|
||||
|
||||
/* Copies |bitmap| to the pasteboard as a PNG.
|
||||
* Returns 0 on success, non-zero on error. */
|
||||
MMPasteError copyMMBitmapToPasteboard(MMBitmapRef bitmap);
|
||||
|
||||
/* Returns description of given MMPasteError.
|
||||
* Returned string is constant and hence should not be freed. */
|
||||
const char *MMPasteErrorString(MMPasteError error);
|
||||
|
||||
#endif /* PASTEBOARD_H */
|
@ -1,106 +0,0 @@
|
||||
#include "pasteboard.h"
|
||||
#include "os.h"
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
#include "png_io.h"
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#elif defined(IS_WINDOWS)
|
||||
#include "bmp_io.h"
|
||||
#endif
|
||||
|
||||
MMPasteError copyMMBitmapToPasteboard(MMBitmapRef bitmap)
|
||||
{
|
||||
#if defined(IS_MACOSX)
|
||||
PasteboardRef clipboard;
|
||||
|
||||
size_t len;
|
||||
uint8_t *pngbuf;
|
||||
CFDataRef data;
|
||||
OSStatus err;
|
||||
|
||||
if (PasteboardCreate(kPasteboardClipboard, &clipboard) != noErr) {
|
||||
return kMMPasteOpenError;
|
||||
}
|
||||
|
||||
if (PasteboardClear(clipboard) != noErr) {
|
||||
CFRelease(clipboard);
|
||||
return kMMPasteClearError;
|
||||
}
|
||||
|
||||
pngbuf = createPNGData(bitmap, &len);
|
||||
if (pngbuf == NULL) {
|
||||
CFRelease(clipboard);
|
||||
return kMMPasteDataError;
|
||||
}
|
||||
|
||||
data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, pngbuf, len,
|
||||
kCFAllocatorNull);
|
||||
if (data == NULL) {
|
||||
CFRelease(clipboard);
|
||||
free(pngbuf);
|
||||
return kMMPasteDataError;
|
||||
}
|
||||
|
||||
err = PasteboardPutItemFlavor(clipboard, bitmap, kUTTypePNG, data, 0);
|
||||
CFRelease(data);
|
||||
CFRelease(clipboard);
|
||||
free(pngbuf);
|
||||
return (err == noErr) ? kMMPasteNoError : kMMPastePasteError;
|
||||
#elif defined(IS_WINDOWS)
|
||||
MMPasteError ret = kMMPasteNoError;
|
||||
uint8_t *bmpData;
|
||||
size_t len;
|
||||
HGLOBAL handle;
|
||||
|
||||
if (!OpenClipboard(NULL)) return kMMPasteOpenError;
|
||||
if (!EmptyClipboard()) return kMMPasteClearError;
|
||||
|
||||
bmpData = createBitmapData(bitmap, &len);
|
||||
if (bmpData == NULL) return kMMPasteDataError;
|
||||
|
||||
/* CF_DIB does not include the BITMAPFILEHEADER struct (and displays a
|
||||
* cryptic error if it is included). */
|
||||
len -= sizeof(BITMAPFILEHEADER);
|
||||
|
||||
/* SetClipboardData() needs a "handle", not just a buffer, so we have to
|
||||
* allocate one with GlobalAlloc(). */
|
||||
if ((handle = GlobalAlloc(GMEM_MOVEABLE, len)) == NULL) {
|
||||
CloseClipboard();
|
||||
free(bmpData);
|
||||
return kMMPasteDataError;
|
||||
}
|
||||
|
||||
memcpy(GlobalLock(handle), bmpData + sizeof(BITMAPFILEHEADER), len);
|
||||
GlobalUnlock(handle);
|
||||
free(bmpData);
|
||||
|
||||
if (SetClipboardData(CF_DIB, handle) == NULL) {
|
||||
ret = kMMPastePasteError;
|
||||
}
|
||||
|
||||
CloseClipboard();
|
||||
GlobalFree(handle);
|
||||
return ret;
|
||||
#elif defined(USE_X11)
|
||||
/* TODO (X11's clipboard is _weird_.) */
|
||||
return kMMPasteUnsupportedError;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *MMPasteErrorString(MMPasteError err)
|
||||
{
|
||||
switch (err) {
|
||||
case kMMPasteOpenError:
|
||||
return "Could not open pasteboard";
|
||||
case kMMPasteClearError:
|
||||
return "Could not clear pasteboard";
|
||||
case kMMPasteDataError:
|
||||
return "Could not create image data from bitmap";
|
||||
case kMMPastePasteError:
|
||||
return "Could not paste data";
|
||||
case kMMPasteUnsupportedError:
|
||||
return "Unsupported platform";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef PNG_IO_H
|
||||
#define PNG_IO_H
|
||||
|
||||
// #include "MMBitmap_c.h"
|
||||
// #include "file_io_c.h"
|
||||
|
||||
enum _PNGReadError {
|
||||
kPNGGenericError = 0,
|
||||
kPNGReadError,
|
||||
kPNGAccessError,
|
||||
kPNGInvalidHeaderError
|
||||
};
|
||||
|
||||
typedef MMIOError MMPNGReadError;
|
||||
|
||||
/* Returns description of given MMPNGReadError.
|
||||
* Returned string is constant and hence should not be freed. */
|
||||
const char *MMPNGReadErrorString(MMIOError error);
|
||||
|
||||
/* Attempts to read PNG file at path; returns new MMBitmap on success, or
|
||||
* NULL on error. If |error| is non-NULL, it will be set to the error code
|
||||
* on return.
|
||||
* Responsibility for destroy()'ing returned MMBitmap is left up to caller. */
|
||||
MMBitmapRef newMMBitmapFromPNG(const char *path, MMPNGReadError *error);
|
||||
|
||||
/* Attempts to write PNG at path; returns 0 on success, -1 on error. */
|
||||
int saveMMBitmapAsPNG(MMBitmapRef bitmap, const char *path);
|
||||
|
||||
/* Returns a buffer containing the raw PNG file data, ready to be saved to a
|
||||
* file. |len| will be set to the number of bytes allocated in the returned
|
||||
* buffer (it cannot be NULL).
|
||||
*
|
||||
* Responsibility for free()'ing data is left up to the caller. */
|
||||
uint8_t *createPNGData(MMBitmapRef bitmap, size_t *len);
|
||||
|
||||
#endif /* PNG_IO_H */
|
346
base/png_io_c.h
346
base/png_io_c.h
@ -1,346 +0,0 @@
|
||||
#include "png_io.h"
|
||||
#include "os.h"
|
||||
// #include "libpng/png.c"
|
||||
#if defined(IS_MACOSX)
|
||||
#include "../cdeps/mac/png.h"
|
||||
#elif defined(USE_X11)
|
||||
#include <png.h>
|
||||
#elif defined(IS_WINDOWS)
|
||||
#include "../cdeps/win/png.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* fopen() */
|
||||
#include <stdlib.h> /* malloc/realloc */
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include "ms_stdint.h"
|
||||
#include "ms_stdbool.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
const char *MMPNGReadErrorString(MMIOError error)
|
||||
{
|
||||
switch (error) {
|
||||
case kPNGAccessError:
|
||||
return "Could not open file";
|
||||
case kPNGReadError:
|
||||
return "Could not read file";
|
||||
case kPNGInvalidHeaderError:
|
||||
return "Not a PNG file";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
MMBitmapRef newMMBitmapFromPNG(const char *path, MMPNGReadError *err)
|
||||
{
|
||||
FILE *fp;
|
||||
uint8_t header[8];
|
||||
png_struct *png_ptr = NULL;
|
||||
png_info *info_ptr = NULL;
|
||||
png_byte bit_depth, color_type;
|
||||
uint8_t *row, *bitmapData;
|
||||
uint8_t bytesPerPixel;
|
||||
png_uint_32 width, height, y;
|
||||
uint32_t bytewidth;
|
||||
|
||||
if ((fp = fopen(path, "rb")) == NULL) {
|
||||
if (err != NULL) *err = kPNGAccessError;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize error code to generic value. */
|
||||
if (err != NULL) *err = kPNGGenericError;
|
||||
|
||||
/* Validate the PNG. */
|
||||
if (fread(header, 1, sizeof header, fp) == 0) {
|
||||
if (err != NULL) *err = kPNGReadError;
|
||||
goto bail;
|
||||
} else if (png_sig_cmp(header, 0, sizeof(header)) != 0) {
|
||||
if (err != NULL) *err = kPNGInvalidHeaderError;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (png_ptr == NULL) goto bail;
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) goto bail;
|
||||
|
||||
/* Set up error handling. */
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
/* Skip past the header. */
|
||||
png_set_sig_bytes(png_ptr, sizeof header);
|
||||
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
/* Convert different image types to common type to be read. */
|
||||
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||
color_type = png_get_color_type(png_ptr, info_ptr);
|
||||
|
||||
/* Convert color palettes to RGB. */
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
}
|
||||
|
||||
/* Convert PNG to bit depth of 8. */
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
} else if (bit_depth == 16) {
|
||||
png_set_strip_16(png_ptr);
|
||||
}
|
||||
|
||||
/* Convert transparency chunk to alpha channel. */
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
}
|
||||
|
||||
/* Convert gray images to RGB. */
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
}
|
||||
|
||||
/* Ignore alpha for now. */
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA) {
|
||||
png_set_strip_alpha(png_ptr);
|
||||
}
|
||||
|
||||
/* Get image attributes. */
|
||||
width = png_get_image_width(png_ptr, info_ptr);
|
||||
height = png_get_image_height(png_ptr, info_ptr);
|
||||
bytesPerPixel = 3; /* All images decompress to this size. */
|
||||
bytewidth = ADD_PADDING(width * bytesPerPixel); /* Align width. */
|
||||
|
||||
/* Decompress the PNG row by row. */
|
||||
bitmapData = calloc(1, bytewidth * height);
|
||||
row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
|
||||
if (bitmapData == NULL || row == NULL) goto bail;
|
||||
for (y = 0; y < height; ++y) {
|
||||
png_uint_32 x;
|
||||
const uint32_t rowOffset = y * bytewidth;
|
||||
uint8_t *rowptr = row;
|
||||
png_read_row(png_ptr, (png_byte *)row, NULL);
|
||||
|
||||
for (x = 0; x < width; ++x) {
|
||||
const uint32_t colOffset = x * bytesPerPixel;
|
||||
MMRGBColor *color = (MMRGBColor *)(bitmapData + rowOffset + colOffset);
|
||||
color->red = *rowptr++;
|
||||
color->green = *rowptr++;
|
||||
color->blue = *rowptr++;
|
||||
}
|
||||
}
|
||||
free(row);
|
||||
|
||||
/* Finish reading. */
|
||||
png_read_end(png_ptr, NULL);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
fclose(fp);
|
||||
|
||||
return createMMBitmap(bitmapData, width, height,
|
||||
bytewidth, bytesPerPixel * 8, bytesPerPixel);
|
||||
|
||||
bail:
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct _PNGWriteInfo {
|
||||
png_struct *png_ptr;
|
||||
png_info *info_ptr;
|
||||
png_byte **row_pointers;
|
||||
size_t row_count;
|
||||
bool free_row_pointers;
|
||||
};
|
||||
|
||||
typedef struct _PNGWriteInfo PNGWriteInfo;
|
||||
typedef PNGWriteInfo *PNGWriteInfoRef;
|
||||
|
||||
/* Returns pointer to PNGWriteInfo struct containing data ready to be used with
|
||||
* functions such as png_write_png().
|
||||
*
|
||||
* It is the caller's responsibility to destroy() the returned structure with
|
||||
* destroyPNGWriteInfo(). */
|
||||
static PNGWriteInfoRef createPNGWriteInfo(MMBitmapRef bitmap)
|
||||
{
|
||||
PNGWriteInfoRef info = malloc(sizeof(PNGWriteInfo));
|
||||
png_uint_32 y;
|
||||
|
||||
if (info == NULL) return NULL;
|
||||
info->png_ptr = NULL;
|
||||
info->info_ptr = NULL;
|
||||
info->row_pointers = NULL;
|
||||
|
||||
assert(bitmap != NULL);
|
||||
|
||||
/* Initialize the write struct. */
|
||||
info->png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL, NULL, NULL);
|
||||
if (info->png_ptr == NULL) goto bail;
|
||||
|
||||
/* Set up error handling. */
|
||||
if (setjmp(png_jmpbuf(info->png_ptr))) {
|
||||
png_destroy_write_struct(&(info->png_ptr), &(info->info_ptr));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Initialize the info struct. */
|
||||
info->info_ptr = png_create_info_struct(info->png_ptr);
|
||||
if (info->info_ptr == NULL) {
|
||||
png_destroy_write_struct(&(info->png_ptr), NULL);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Set image attributes. */
|
||||
png_set_IHDR(info->png_ptr,
|
||||
info->info_ptr,
|
||||
(png_uint_32)bitmap->width,
|
||||
(png_uint_32)bitmap->height,
|
||||
8,
|
||||
PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
info->row_count = bitmap->height;
|
||||
info->row_pointers = png_malloc(info->png_ptr,
|
||||
sizeof(png_byte *) * info->row_count);
|
||||
|
||||
if (bitmap->bytesPerPixel == 3) {
|
||||
/* No alpha channel; image data can be copied directly. */
|
||||
for (y = 0; y < info->row_count; ++y) {
|
||||
info->row_pointers[y] = bitmap->imageBuffer + (bitmap->bytewidth * y);
|
||||
}
|
||||
info->free_row_pointers = false;
|
||||
|
||||
/* Convert BGR to RGB if necessary. */
|
||||
if (MMRGB_IS_BGR) {
|
||||
png_set_bgr(info->png_ptr);
|
||||
}
|
||||
} else {
|
||||
/* Ignore alpha channel; copy image data row by row. */
|
||||
const size_t bytesPerPixel = 3;
|
||||
const size_t bytewidth = ADD_PADDING(bitmap->width * bytesPerPixel);
|
||||
|
||||
for (y = 0; y < info->row_count; ++y) {
|
||||
png_uint_32 x;
|
||||
png_byte *row_ptr = png_malloc(info->png_ptr, bytewidth);
|
||||
info->row_pointers[y] = row_ptr;
|
||||
for (x = 0; x < bitmap->width; ++x) {
|
||||
MMRGBColor *color = MMRGBColorRefAtPoint(bitmap, x, y);
|
||||
row_ptr[0] = color->red;
|
||||
row_ptr[1] = color->green;
|
||||
row_ptr[2] = color->blue;
|
||||
|
||||
row_ptr += bytesPerPixel;
|
||||
}
|
||||
}
|
||||
info->free_row_pointers = true;
|
||||
}
|
||||
|
||||
png_set_rows(info->png_ptr, info->info_ptr, info->row_pointers);
|
||||
return info;
|
||||
|
||||
bail:
|
||||
if (info != NULL) free(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Free memory in use by |info|. */
|
||||
static void destroyPNGWriteInfo(PNGWriteInfoRef info)
|
||||
{
|
||||
assert(info != NULL);
|
||||
if (info->row_pointers != NULL) {
|
||||
if (info->free_row_pointers) {
|
||||
size_t y;
|
||||
for (y = 0; y < info->row_count; ++y) {
|
||||
free(info->row_pointers[y]);
|
||||
}
|
||||
}
|
||||
png_free(info->png_ptr, info->row_pointers);
|
||||
}
|
||||
|
||||
png_destroy_write_struct(&(info->png_ptr), &(info->info_ptr));
|
||||
free(info);
|
||||
}
|
||||
|
||||
int saveMMBitmapAsPNG(MMBitmapRef bitmap, const char *path)
|
||||
{
|
||||
FILE *fp = fopen(path, "wb");
|
||||
PNGWriteInfoRef info;
|
||||
if (fp == NULL) return -1;
|
||||
|
||||
if ((info = createPNGWriteInfo(bitmap)) == NULL) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
png_init_io(info->png_ptr, fp);
|
||||
png_write_png(info->png_ptr, info->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
||||
fclose(fp);
|
||||
|
||||
destroyPNGWriteInfo(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Structure to store PNG image bytes. */
|
||||
struct io_data
|
||||
{
|
||||
uint8_t *buffer; /* Pointer to raw file data. */
|
||||
size_t size; /* Number of bytes actually written to buffer. */
|
||||
size_t allocedSize; /* Number of bytes allocated for buffer. */
|
||||
};
|
||||
|
||||
/* Called each time libpng attempts to write data in createPNGData(). */
|
||||
void png_append_data(png_struct *png_ptr,
|
||||
png_byte *new_data,
|
||||
png_size_t length)
|
||||
{
|
||||
struct io_data *data = png_get_io_ptr(png_ptr);
|
||||
data->size += length;
|
||||
|
||||
/* Allocate or grow buffer. */
|
||||
if (data->buffer == NULL) {
|
||||
data->allocedSize = data->size;
|
||||
data->buffer = png_malloc(png_ptr, data->allocedSize);
|
||||
assert(data->buffer != NULL);
|
||||
} else if (data->allocedSize < data->size) {
|
||||
do {
|
||||
/* Double size each time to avoid calls to realloc. */
|
||||
data->allocedSize <<= 1;
|
||||
} while (data->allocedSize < data->size);
|
||||
|
||||
data->buffer = realloc(data->buffer, data->allocedSize);
|
||||
}
|
||||
|
||||
/* Copy new bytes to end of buffer. */
|
||||
memcpy(data->buffer + data->size - length, new_data, length);
|
||||
}
|
||||
|
||||
uint8_t *createPNGData(MMBitmapRef bitmap, size_t *len)
|
||||
{
|
||||
PNGWriteInfoRef info = NULL;
|
||||
struct io_data data = {NULL, 0, 0};
|
||||
|
||||
assert(bitmap != NULL);
|
||||
assert(len != NULL);
|
||||
|
||||
if ((info = createPNGWriteInfo(bitmap)) == NULL) return NULL;
|
||||
|
||||
png_set_write_fn(info->png_ptr, &data, &png_append_data, NULL);
|
||||
png_write_png(info->png_ptr, info->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
||||
|
||||
destroyPNGWriteInfo(info);
|
||||
|
||||
*len = data.size;
|
||||
return data.buffer;
|
||||
}
|
33
base/pubs.h
Normal file
33
base/pubs.h
Normal file
@ -0,0 +1,33 @@
|
||||
#if defined(IS_WINDOWS)
|
||||
BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
|
||||
uint32_t *count = (uint32_t*)dwData;
|
||||
(*count)++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
HWND hWnd;
|
||||
DWORD dwPid;
|
||||
}WNDINFO;
|
||||
|
||||
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam){
|
||||
WNDINFO* pInfo = (WNDINFO*)lParam;
|
||||
DWORD dwProcessId = 0;
|
||||
GetWindowThreadProcessId(hWnd, &dwProcessId);
|
||||
|
||||
if (dwProcessId == pInfo->dwPid) {
|
||||
pInfo->hWnd = hWnd;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HWND GetHwndByPid(DWORD dwProcessId) {
|
||||
WNDINFO info = {0};
|
||||
info.hWnd = NULL;
|
||||
info.dwPid = dwProcessId;
|
||||
EnumWindows(EnumWindowsProc, (LPARAM)&info);
|
||||
|
||||
return info.hWnd;
|
||||
}
|
||||
#endif
|
52
base/rgb.h
52
base/rgb.h
@ -5,21 +5,7 @@
|
||||
#include <stdlib.h> /* For abs() */
|
||||
#include <math.h>
|
||||
#include "inline_keywords.h" /* For H_INLINE */
|
||||
// #include <stdint.h>
|
||||
#if defined(_MSC_VER)
|
||||
#include "ms_stdint.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* RGB colors in MMBitmaps are stored as BGR for convenience in converting
|
||||
* to/from certain formats (mainly OpenGL).
|
||||
*
|
||||
* It is best not to rely on the order (simply use rgb.{blue,green,red} to
|
||||
* access values), but some situations (e.g., glReadPixels) require one to
|
||||
* do so. In that case, check to make sure to use MMRGB_IS_BGR for future
|
||||
* compatibility. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* #define MMRGB_IS_BGR (offsetof(MMRGBColor, red) > offsetof(MMRGBColor, blue)) */
|
||||
#define MMRGB_IS_BGR 1
|
||||
@ -29,25 +15,19 @@ struct _MMRGBColor {
|
||||
uint8_t green;
|
||||
uint8_t red;
|
||||
};
|
||||
|
||||
typedef struct _MMRGBColor MMRGBColor;
|
||||
|
||||
/* MMRGBHex is a hexadecimal color value, akin to HTML's, in the form 0xRRGGBB
|
||||
* where RR is the red value expressed as hexadecimal, GG is the green value,
|
||||
* and BB is the blue value. */
|
||||
/* MMRGBHex is a hexadecimal color value*/
|
||||
typedef uint32_t MMRGBHex;
|
||||
|
||||
#define MMRGBHEX_MIN 0x000000
|
||||
#define MMRGBHEX_MAX 0xFFFFFF
|
||||
|
||||
/* Converts rgb color to hexadecimal value.
|
||||
* |red|, |green|, and |blue| should each be of the type |uint8_t|, where the
|
||||
* range is 0 - 255. */
|
||||
/* Converts rgb color to hexadecimal value. */
|
||||
#define RGB_TO_HEX(red, green, blue) (((red) << 16) | ((green) << 8) | (blue))
|
||||
|
||||
/* Convenience wrapper for MMRGBColors. */
|
||||
H_INLINE MMRGBHex hexFromMMRGB(MMRGBColor rgb)
|
||||
{
|
||||
H_INLINE MMRGBHex hexFromMMRGB(MMRGBColor rgb) {
|
||||
return RGB_TO_HEX(rgb.red, rgb.green, rgb.blue);
|
||||
}
|
||||
|
||||
@ -56,8 +36,7 @@ H_INLINE MMRGBHex hexFromMMRGB(MMRGBColor rgb)
|
||||
#define BLUE_FROM_HEX(hex) (hex & 0xFF)
|
||||
|
||||
/* Converts hexadecimal color to MMRGBColor. */
|
||||
H_INLINE MMRGBColor MMRGBFromHex(MMRGBHex hex)
|
||||
{
|
||||
H_INLINE MMRGBColor MMRGBFromHex(MMRGBHex hex) {
|
||||
MMRGBColor color;
|
||||
color.red = RED_FROM_HEX(hex);
|
||||
color.green = GREEN_FROM_HEX(hex);
|
||||
@ -70,12 +49,8 @@ H_INLINE MMRGBColor MMRGBFromHex(MMRGBHex hex)
|
||||
(c1).blue == (c2).blue && \
|
||||
(c1).green == (c2).green)
|
||||
|
||||
/* Returns whether two colors are similar within the given range, |tolerance|.
|
||||
* Tolerance can be in the range 0.0f - 1.0f, where 0 denotes the exact
|
||||
* color and 1 denotes any color. */
|
||||
H_INLINE int MMRGBColorSimilarToColor(MMRGBColor c1, MMRGBColor c2,
|
||||
float tolerance)
|
||||
{
|
||||
/* Returns whether two colors are similar within the given range, |tolerance|.*/
|
||||
H_INLINE int MMRGBColorSimilarToColor(MMRGBColor c1, MMRGBColor c2, float tolerance) {
|
||||
/* Speedy case */
|
||||
if (tolerance <= 0.0f) {
|
||||
return MMRGBColorEqualToColor(c1, c2);
|
||||
@ -83,27 +58,20 @@ H_INLINE int MMRGBColorSimilarToColor(MMRGBColor c1, MMRGBColor c2,
|
||||
uint8_t d1 = c1.red - c2.red;
|
||||
uint8_t d2 = c1.green - c2.green;
|
||||
uint8_t d3 = c1.blue - c2.blue;
|
||||
return sqrt((double)(d1 * d1) +
|
||||
(d2 * d2) +
|
||||
return sqrt((double)(d1 * d1) + (d2 * d2) +
|
||||
(d3 * d3)) <= (tolerance * 442.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Identical to MMRGBColorSimilarToColor, only for hex values. */
|
||||
H_INLINE int MMRGBHexSimilarToColor(MMRGBHex h1, MMRGBHex h2, float tolerance)
|
||||
{
|
||||
H_INLINE int MMRGBHexSimilarToColor(MMRGBHex h1, MMRGBHex h2, float tolerance) {
|
||||
if (tolerance <= 0.0f) {
|
||||
return h1 == h2;
|
||||
} else {
|
||||
// uint8_t d1 = RED_FROM_HEX(h1) - RED_FROM_HEX(h2);
|
||||
// uint8_t d2 = GREEN_FROM_HEX(h1) - GREEN_FROM_HEX(h2);
|
||||
// uint8_t d3 = BLUE_FROM_HEX(h1) - BLUE_FROM_HEX(h2);
|
||||
int d1 = RED_FROM_HEX(h1) - RED_FROM_HEX(h2);
|
||||
int d2 = GREEN_FROM_HEX(h1) - GREEN_FROM_HEX(h2);
|
||||
int d3 = BLUE_FROM_HEX(h1) - BLUE_FROM_HEX(h2);
|
||||
return sqrt((double)(d1 * d1) +
|
||||
(d2 * d2) +
|
||||
return sqrt((double)(d1 * d1) + (d2 * d2) +
|
||||
(d3 * d3)) <= (tolerance * 442.0f);
|
||||
}
|
||||
}
|
||||
|
@ -1,46 +0,0 @@
|
||||
#ifndef _PORTABLE_SNPRINTF_H_
|
||||
#define _PORTABLE_SNPRINTF_H_
|
||||
|
||||
#define PORTABLE_SNPRINTF_VERSION_MAJOR 2
|
||||
#define PORTABLE_SNPRINTF_VERSION_MINOR 2
|
||||
|
||||
#include "os.h"
|
||||
#if defined(IS_MACOSX)
|
||||
#define HAVE_SNPRINTF
|
||||
#else
|
||||
#define HAVE_SNPRINTF
|
||||
#define PREFER_PORTABLE_SNPRINTF
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SNPRINTF
|
||||
#include <stdio.h>
|
||||
#else
|
||||
extern int snprintf(char *, size_t, const char *, /*args*/ ...);
|
||||
extern int vsnprintf(char *, size_t, const char *, va_list);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SNPRINTF) && defined(PREFER_PORTABLE_SNPRINTF)
|
||||
extern int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...);
|
||||
extern int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap);
|
||||
#define snprintf portable_snprintf
|
||||
#define vsnprintf portable_vsnprintf
|
||||
#endif
|
||||
|
||||
extern int asprintf (char **ptr, const char *fmt, /*args*/ ...);
|
||||
extern int vasprintf (char **ptr, const char *fmt, va_list ap);
|
||||
extern int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...);
|
||||
extern int vasnprintf(char **ptr, size_t str_m, const char *fmt, va_list ap);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
1019
base/snprintf_c.h
1019
base/snprintf_c.h
File diff suppressed because it is too large
Load Diff
@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef STR_IO_H
|
||||
#define STR_IO_H
|
||||
|
||||
#include "MMBitmap.h"
|
||||
#include "file_io.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
enum _MMBMPStringError {
|
||||
kMMBMPStringGenericError = 0,
|
||||
kMMBMPStringInvalidHeaderError,
|
||||
kMMBMPStringDecodeError,
|
||||
kMMBMPStringDecompressError,
|
||||
kMMBMPStringSizeError, /* Size does not match header. */
|
||||
MMMBMPStringEncodeError,
|
||||
kMMBMPStringCompressError
|
||||
};
|
||||
|
||||
typedef MMIOError MMBMPStringError;
|
||||
|
||||
/* Creates a 24-bit bitmap from a compressed, printable string.
|
||||
*
|
||||
* String should be in the format: "b[width],[height],[data]",
|
||||
* where [width] and [height] are the image width & height, and [data]
|
||||
* is the raw image data run through zlib_compress() and base64_encode().
|
||||
*
|
||||
* Returns NULL on error; follows the Create Rule (that is, the caller is
|
||||
* responsible for destroy'()ing object).
|
||||
* If |error| is non-NULL, it will be set to the error code on return.
|
||||
*/
|
||||
MMBitmapRef createMMBitmapFromString(const uint8_t *buffer, size_t buflen,
|
||||
MMBMPStringError *error);
|
||||
|
||||
/* Inverse of createMMBitmapFromString().
|
||||
*
|
||||
* Creates string in the format: "b[width],[height],[data]", where [width] and
|
||||
* [height] are the image width & height, and [data] is the raw image data run
|
||||
* through zlib_compress() and base64_encode().
|
||||
*
|
||||
* Returns NULL on error, or new string on success (to be free'()d by caller).
|
||||
* If |error| is non-NULL, it will be set to the error code on return.
|
||||
*/
|
||||
uint8_t *createStringFromMMBitmap(MMBitmapRef bitmap, MMBMPStringError *error);
|
||||
|
||||
/* Returns description of given error code.
|
||||
* Returned string is constant and hence should not be freed. */
|
||||
const char *MMBitmapStringErrorString(MMBMPStringError err);
|
||||
|
||||
#endif /* STR_IO_H */
|
208
base/str_io_c.h
208
base/str_io_c.h
@ -1,208 +0,0 @@
|
||||
#include "str_io.h"
|
||||
#include "zlib_util_c.h"
|
||||
#include "base64_c.h"
|
||||
#include "snprintf_c.h" /* snprintf() */
|
||||
#include <stdio.h> /* fputs() */
|
||||
#include <ctype.h> /* isdigit() */
|
||||
#include <stdlib.h> /* atoi() */
|
||||
#include <string.h> /* strlen() */
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include "ms_stdbool.h"
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#define STR_BITS_PER_PIXEL 24
|
||||
#define STR_BYTES_PER_PIXEL ((STR_BITS_PER_PIXEL) / 8)
|
||||
|
||||
#define MAX_DIMENSION_LEN 5 /* Maximum length for [width] or [height]
|
||||
* in string. */
|
||||
|
||||
const char *MMBitmapStringErrorString(MMBMPStringError err)
|
||||
{
|
||||
switch (err) {
|
||||
case kMMBMPStringInvalidHeaderError:
|
||||
return "Invalid header for string";
|
||||
case kMMBMPStringDecodeError:
|
||||
return "Error decoding string";
|
||||
case kMMBMPStringDecompressError:
|
||||
return "Error decompressing string";
|
||||
case kMMBMPStringSizeError:
|
||||
return "String not of expected size";
|
||||
case MMMBMPStringEncodeError:
|
||||
return "Error encoding string";
|
||||
case kMMBMPStringCompressError:
|
||||
return "Error compressing string";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parses beginning of string in the form of "[width],[height],*".
|
||||
*
|
||||
* If successful, |width| and |height| are set to the appropropriate values,
|
||||
* |len| is set to the length of [width] + the length of [height] + 2,
|
||||
* and true is returned; otherwise, false is returned.
|
||||
*/
|
||||
static bool getSizeFromString(const uint8_t *buf, size_t buflen,
|
||||
size_t *width, size_t *height,
|
||||
size_t *len);
|
||||
|
||||
MMBitmapRef createMMBitmapFromString(const uint8_t *buffer, size_t buflen,
|
||||
MMBMPStringError *err)
|
||||
{
|
||||
uint8_t *decoded, *decompressed;
|
||||
size_t width, height;
|
||||
size_t len, bytewidth;
|
||||
|
||||
if (*buffer++ != 'b' || !getSizeFromString(buffer, --buflen,
|
||||
&width, &height, &len)) {
|
||||
if (err != NULL) *err = kMMBMPStringInvalidHeaderError;
|
||||
return NULL;
|
||||
}
|
||||
buffer += len;
|
||||
buflen -= len;
|
||||
|
||||
decoded = base64decode(buffer, buflen, NULL);
|
||||
if (decoded == NULL) {
|
||||
if (err != NULL) *err = kMMBMPStringDecodeError;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
decompressed = zlib_decompress(decoded, &len);
|
||||
free(decoded);
|
||||
|
||||
if (decompressed == NULL) {
|
||||
if (err != NULL) *err = kMMBMPStringDecompressError;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bytewidth = width * STR_BYTES_PER_PIXEL; /* Note that bytewidth is NOT
|
||||
* aligned to a padding. */
|
||||
if (height * bytewidth != len) {
|
||||
if (err != NULL) *err = kMMBMPStringSizeError;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return createMMBitmap(decompressed, width, height,
|
||||
bytewidth, STR_BITS_PER_PIXEL, STR_BYTES_PER_PIXEL);
|
||||
}
|
||||
|
||||
/* Returns bitmap data suitable for encoding to a string; that is, 24-bit BGR
|
||||
* bitmap with no padding and 3 bytes per pixel.
|
||||
*
|
||||
* Caller is responsible for free()'ing returned buffer. */
|
||||
static uint8_t *createRawBitmapData(MMBitmapRef bitmap);
|
||||
|
||||
uint8_t *createStringFromMMBitmap(MMBitmapRef bitmap, MMBMPStringError *err)
|
||||
{
|
||||
uint8_t *raw, *compressed;
|
||||
uint8_t *ret, *encoded;
|
||||
size_t len, retlen;
|
||||
|
||||
assert(bitmap != NULL);
|
||||
|
||||
raw = createRawBitmapData(bitmap);
|
||||
if (raw == NULL) {
|
||||
if (err != NULL) *err = kMMBMPStringGenericError;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
compressed = zlib_compress(raw,
|
||||
bitmap->width * bitmap->height *
|
||||
STR_BYTES_PER_PIXEL,
|
||||
9, &len);
|
||||
free(raw);
|
||||
if (compressed == NULL) {
|
||||
if (err != NULL) *err = kMMBMPStringCompressError;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
encoded = base64encode(compressed, len - 1, &retlen);
|
||||
free(compressed);
|
||||
if (encoded == NULL) {
|
||||
if (err != NULL) *err = MMMBMPStringEncodeError;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retlen += 3 + (MAX_DIMENSION_LEN * 2);
|
||||
ret = calloc(sizeof(char), (retlen + 1));
|
||||
snprintf((char *)ret, retlen, "b%lu,%lu,%s", (unsigned long)bitmap->width,
|
||||
(unsigned long)bitmap->height,
|
||||
encoded);
|
||||
ret[retlen] = '\0';
|
||||
free(encoded);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t parseDimension(const uint8_t *buf, size_t buflen,
|
||||
size_t *numlen);
|
||||
|
||||
static bool getSizeFromString(const uint8_t *buf, size_t buflen,
|
||||
size_t *width, size_t *height,
|
||||
size_t *len)
|
||||
{
|
||||
size_t numlen;
|
||||
assert(buf != NULL);
|
||||
assert(width != NULL);
|
||||
assert(height != NULL);
|
||||
|
||||
if ((*width = parseDimension(buf, buflen, &numlen)) == 0) {
|
||||
return false;
|
||||
}
|
||||
*len = numlen + 1;
|
||||
|
||||
if ((*height = parseDimension(buf + *len, buflen, &numlen)) == 0) {
|
||||
return false;
|
||||
}
|
||||
*len += numlen + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parses one dimension from string as described in getSizeFromString().
|
||||
* Returns dimension on success, or 0 on error. */
|
||||
static uint32_t parseDimension(const uint8_t *buf,
|
||||
size_t buflen, size_t *numlen){
|
||||
char num[MAX_DIMENSION_LEN + 1];
|
||||
size_t i;
|
||||
// ssize_t len;
|
||||
// size_t len;
|
||||
// uint8_t *len;
|
||||
|
||||
assert(buf != NULL);
|
||||
// assert(len != NULL);
|
||||
for (i = 0; i < buflen && buf[i] != ',' && buf[i] != '\0'; ++i) {
|
||||
if (!isdigit(buf[i]) || i > MAX_DIMENSION_LEN) return 0;
|
||||
num[i] = buf[i];
|
||||
}
|
||||
num[i] = '\0';
|
||||
*numlen = i;
|
||||
|
||||
return (uint32_t)atoi(num);
|
||||
}
|
||||
|
||||
static uint8_t *createRawBitmapData(MMBitmapRef bitmap)
|
||||
{
|
||||
uint8_t *raw = calloc(STR_BYTES_PER_PIXEL, bitmap->width * bitmap->height);
|
||||
size_t y;
|
||||
|
||||
for (y = 0; y < bitmap->height; ++y) {
|
||||
/* No padding is added to string bitmaps. */
|
||||
const size_t rowOffset = y * bitmap->width * STR_BYTES_PER_PIXEL;
|
||||
size_t x;
|
||||
for (x = 0; x < bitmap->width; ++x) {
|
||||
/* Copy in BGR format. */
|
||||
const size_t colOffset = x * STR_BYTES_PER_PIXEL;
|
||||
uint8_t *dest = raw + rowOffset + colOffset;
|
||||
MMRGBColor *srcColor = MMRGBColorRefAtPoint(bitmap, x, y);
|
||||
dest[0] = srcColor->blue;
|
||||
dest[1] = srcColor->green;
|
||||
dest[2] = srcColor->red;
|
||||
}
|
||||
}
|
||||
|
||||
return raw;
|
||||
}
|
83
base/types.h
83
base/types.h
@ -6,116 +6,63 @@
|
||||
#include "inline_keywords.h" /* For H_INLINE */
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Some generic, cross-platform types. */
|
||||
|
||||
struct _MMPoint {
|
||||
size_t x;
|
||||
size_t y;
|
||||
};
|
||||
|
||||
typedef struct _MMPoint MMPoint;
|
||||
#ifdef RobotGo_64
|
||||
typedef int64_t intptr;
|
||||
typedef uint64_t uintptr;
|
||||
#else
|
||||
typedef int32_t intptr;
|
||||
typedef uint32_t uintptr; // Unsigned pointer integer
|
||||
#endif
|
||||
|
||||
struct _MMPointInt32 {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
};
|
||||
|
||||
typedef struct _MMPointInt32 MMPointInt32;
|
||||
|
||||
struct _MMSize {
|
||||
size_t width;
|
||||
size_t height;
|
||||
};
|
||||
|
||||
typedef struct _MMSize MMSize;
|
||||
|
||||
struct _MMSizeInt32 {
|
||||
int32_t w;
|
||||
int32_t h;
|
||||
};
|
||||
|
||||
typedef struct _MMSizeInt32 MMSizeInt32;
|
||||
|
||||
|
||||
struct _MMRect {
|
||||
MMPoint origin;
|
||||
MMSize size;
|
||||
};
|
||||
|
||||
typedef struct _MMRect MMRect;
|
||||
|
||||
struct _MMRectInt32 {
|
||||
MMPointInt32 origin;
|
||||
MMSizeInt32 size;
|
||||
};
|
||||
|
||||
typedef struct _MMRectInt32 MMRectInt32;
|
||||
|
||||
H_INLINE MMPoint MMPointMake(size_t x, size_t y)
|
||||
{
|
||||
MMPoint point;
|
||||
point.x = x;
|
||||
point.y = y;
|
||||
return point;
|
||||
}
|
||||
|
||||
H_INLINE MMPointInt32 MMPointInt32Make(int32_t x, int32_t y)
|
||||
{
|
||||
H_INLINE MMPointInt32 MMPointInt32Make(int32_t x, int32_t y) {
|
||||
MMPointInt32 point;
|
||||
point.x = x;
|
||||
point.y = y;
|
||||
return point;
|
||||
}
|
||||
|
||||
H_INLINE MMSize MMSizeMake(size_t width, size_t height)
|
||||
{
|
||||
MMSize size;
|
||||
size.width = width;
|
||||
size.height = height;
|
||||
return size;
|
||||
}
|
||||
|
||||
H_INLINE MMSizeInt32 MMSizeInt32Make(int32_t w, int32_t h)
|
||||
{
|
||||
H_INLINE MMSizeInt32 MMSizeInt32Make(int32_t w, int32_t h) {
|
||||
MMSizeInt32 size;
|
||||
size.w = w;
|
||||
size.h = h;
|
||||
return size;
|
||||
}
|
||||
|
||||
H_INLINE MMRect MMRectMake(size_t x, size_t y, size_t width, size_t height)
|
||||
{
|
||||
MMRect rect;
|
||||
rect.origin = MMPointMake(x, y);
|
||||
rect.size = MMSizeMake(width, height);
|
||||
return rect;
|
||||
}
|
||||
|
||||
H_INLINE MMRectInt32 MMRectInt32Make(int32_t x, int32_t y, int32_t w, int32_t h)
|
||||
{
|
||||
H_INLINE MMRectInt32 MMRectInt32Make(int32_t x, int32_t y, int32_t w, int32_t h) {
|
||||
MMRectInt32 rect;
|
||||
rect.origin = MMPointInt32Make(x, y);
|
||||
rect.size = MMSizeInt32Make(w, h);
|
||||
return rect;
|
||||
}
|
||||
|
||||
//
|
||||
#define MMPointZero MMPointMake(0, 0)
|
||||
#define MMPointZero MMPointInt32Make(0, 0)
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
#define CGPointFromMMPoint(p) CGPointMake((CGFloat)(p).x, (CGFloat)(p).y)
|
||||
#define MMPointFromCGPoint(p) MMPointMake((size_t)(p).x, (size_t)(p).y)
|
||||
|
||||
#define CGPointFromMMPointInt32(p) CGPointMake((CGFloat)(p).x, (CGFloat)(p).y)
|
||||
#define MMPointInt32FromCGPoint(p) MMPointInt32Make((int32_t)(p).x, (int32_t)(p).y)
|
||||
|
||||
#define CGPointFromMMPointInt32(p) CGPointMake((CGFloat)(p).x, (CGFloat)(p).y)
|
||||
#define MMPointInt32FromCGPoint(p) MMPointInt32Make((int32_t)(p).x, (int32_t)(p).y)
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
#define MMPointFromPOINT(p) MMPointMake((size_t)p.x, (size_t)p.y)
|
||||
#define MMPointInt32FromPOINT(p) MMPointInt32Make((int32_t)p.x, (int32_t)p.y)
|
||||
|
||||
#define MMPointInt32FromPOINT(p) MMPointInt32Make((int32_t)p.x, (int32_t)p.y)
|
||||
#endif
|
||||
|
||||
#endif /* TYPES_H */
|
||||
|
929
base/uthash.h
929
base/uthash.h
@ -1,929 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2009, Troy D. Hanson http://uthash.sourceforge.net
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef UTHASH_H
|
||||
#define UTHASH_H
|
||||
|
||||
#include <string.h> /* memcmp, strlen */
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define UTHASH_VERSION 1.8
|
||||
|
||||
/* C++ requires extra stringent casting */
|
||||
#if defined __cplusplus
|
||||
#define TYPEOF(x) (typeof(x))
|
||||
#else
|
||||
#define TYPEOF(x)
|
||||
#endif
|
||||
|
||||
|
||||
#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
|
||||
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
|
||||
#define uthash_free(ptr) free(ptr) /* free fcn */
|
||||
|
||||
#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
|
||||
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
|
||||
|
||||
/* initial number of buckets */
|
||||
#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
|
||||
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
|
||||
#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
|
||||
|
||||
/* calculate the element whose hash handle address is hhe */
|
||||
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)hhp) - (tbl)->hho))
|
||||
|
||||
#define HASH_FIND(hh,head,keyptr,keylen,out) \
|
||||
do { \
|
||||
unsigned _hf_bkt,_hf_hashv; \
|
||||
out=TYPEOF(out)NULL; \
|
||||
if (head) { \
|
||||
HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
|
||||
if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
|
||||
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
|
||||
keyptr,keylen,out); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#if defined(HASH_BLOOM)
|
||||
#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
|
||||
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
|
||||
#define HASH_BLOOM_MAKE(tbl) \
|
||||
do { \
|
||||
(tbl)->bloom_nbits = HASH_BLOOM; \
|
||||
(tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
|
||||
if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
|
||||
memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
|
||||
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
|
||||
} while (0);
|
||||
|
||||
#define HASH_BLOOM_FREE(tbl) \
|
||||
do { \
|
||||
uthash_free((tbl)->bloom_bv); \
|
||||
} while (0);
|
||||
|
||||
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
|
||||
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
|
||||
|
||||
#define HASH_BLOOM_ADD(tbl,hashv) \
|
||||
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
|
||||
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) \
|
||||
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
|
||||
|
||||
#else
|
||||
#define HASH_BLOOM_MAKE(tbl)
|
||||
#define HASH_BLOOM_FREE(tbl)
|
||||
#define HASH_BLOOM_ADD(tbl,hashv)
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) (1)
|
||||
#endif
|
||||
|
||||
#define HASH_MAKE_TABLE(hh,head) \
|
||||
do { \
|
||||
(head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
|
||||
sizeof(UT_hash_table)); \
|
||||
if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
|
||||
memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
|
||||
(head)->hh.tbl->tail = &((head)->hh); \
|
||||
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
|
||||
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
|
||||
(head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
|
||||
(head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
|
||||
if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
|
||||
memset((head)->hh.tbl->buckets, 0, \
|
||||
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
|
||||
HASH_BLOOM_MAKE((head)->hh.tbl); \
|
||||
(head)->hh.tbl->signature = HASH_SIGNATURE; \
|
||||
} while(0)
|
||||
|
||||
#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
|
||||
HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add)
|
||||
|
||||
#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
|
||||
do { \
|
||||
unsigned _ha_bkt; \
|
||||
(add)->hh.next = NULL; \
|
||||
(add)->hh.key = (char*)keyptr; \
|
||||
(add)->hh.keylen = keylen_in; \
|
||||
if (!(head)) { \
|
||||
head = (add); \
|
||||
(head)->hh.prev = NULL; \
|
||||
HASH_MAKE_TABLE(hh,head); \
|
||||
} else { \
|
||||
(head)->hh.tbl->tail->next = (add); \
|
||||
(add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
|
||||
(head)->hh.tbl->tail = &((add)->hh); \
|
||||
} \
|
||||
(head)->hh.tbl->num_items++; \
|
||||
(add)->hh.tbl = (head)->hh.tbl; \
|
||||
HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
|
||||
(add)->hh.hashv, _ha_bkt); \
|
||||
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
|
||||
HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
|
||||
HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
|
||||
HASH_FSCK(hh,head); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
|
||||
do { \
|
||||
bkt = ((hashv) & ((num_bkts) - 1)); \
|
||||
} while(0)
|
||||
|
||||
/* delete "delptr" from the hash table.
|
||||
* "the usual" patch-up process for the app-order doubly-linked-list.
|
||||
* The use of _hd_hh_del below deserves special explanation.
|
||||
* These used to be expressed using (delptr) but that led to a bug
|
||||
* if someone used the same symbol for the head and deletee, like
|
||||
* HASH_DELETE(hh,users,users);
|
||||
* We want that to work, but by changing the head (users) below
|
||||
* we were forfeiting our ability to further refer to the deletee (users)
|
||||
* in the patch-up process. Solution: use scratch space in the table to
|
||||
* copy the deletee pointer, then the latter references are via that
|
||||
* scratch pointer rather than through the repointed (users) symbol.
|
||||
*/
|
||||
#define HASH_DELETE(hh,head,delptr) \
|
||||
do { \
|
||||
unsigned _hd_bkt; \
|
||||
struct UT_hash_handle *_hd_hh_del; \
|
||||
if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
|
||||
uthash_free((head)->hh.tbl->buckets ); \
|
||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||
uthash_free((head)->hh.tbl); \
|
||||
head = NULL; \
|
||||
} else { \
|
||||
_hd_hh_del = &((delptr)->hh); \
|
||||
if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
|
||||
(head)->hh.tbl->tail = \
|
||||
(UT_hash_handle*)((char*)((delptr)->hh.prev) + \
|
||||
(head)->hh.tbl->hho); \
|
||||
} \
|
||||
if ((delptr)->hh.prev) { \
|
||||
((UT_hash_handle*)((char*)((delptr)->hh.prev) + \
|
||||
(head)->hh.tbl->hho))->next = (delptr)->hh.next; \
|
||||
} else { \
|
||||
head = TYPEOF(head)((delptr)->hh.next); \
|
||||
} \
|
||||
if (_hd_hh_del->next) { \
|
||||
((UT_hash_handle*)((char*)_hd_hh_del->next + \
|
||||
(head)->hh.tbl->hho))->prev = \
|
||||
_hd_hh_del->prev; \
|
||||
} \
|
||||
HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
|
||||
HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
|
||||
(head)->hh.tbl->num_items--; \
|
||||
} \
|
||||
HASH_FSCK(hh,head); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
|
||||
#define HASH_FIND_STR(head,findstr,out) \
|
||||
HASH_FIND(hh,head,findstr,strlen(findstr),out)
|
||||
#define HASH_ADD_STR(head,strfield,add) \
|
||||
HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
|
||||
#define HASH_FIND_INT(head,findint,out) \
|
||||
HASH_FIND(hh,head,findint,sizeof(int),out)
|
||||
#define HASH_ADD_INT(head,intfield,add) \
|
||||
HASH_ADD(hh,head,intfield,sizeof(int),add)
|
||||
#define HASH_DEL(head,delptr) \
|
||||
HASH_DELETE(hh,head,delptr)
|
||||
|
||||
/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
|
||||
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
|
||||
*/
|
||||
#if defined(HASH_DEBUG)
|
||||
#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
|
||||
#define HASH_FSCK(hh,head) \
|
||||
do { \
|
||||
unsigned _bkt_i; \
|
||||
unsigned _count, _bkt_count; \
|
||||
char *_prev; \
|
||||
struct UT_hash_handle *_thh; \
|
||||
if (head) { \
|
||||
_count = 0; \
|
||||
for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
|
||||
_bkt_count = 0; \
|
||||
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
|
||||
_prev = NULL; \
|
||||
while (_thh) { \
|
||||
if (_prev != (char*)(_thh->hh_prev)) { \
|
||||
HASH_OOPS("invalid hh_prev %p, actual %p\n", \
|
||||
_thh->hh_prev, _prev ); \
|
||||
} \
|
||||
_bkt_count++; \
|
||||
_prev = (char*)(_thh); \
|
||||
_thh = _thh->hh_next; \
|
||||
} \
|
||||
_count += _bkt_count; \
|
||||
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
|
||||
HASH_OOPS("invalid bucket count %d, actual %d\n", \
|
||||
(head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
|
||||
} \
|
||||
} \
|
||||
if (_count != (head)->hh.tbl->num_items) { \
|
||||
HASH_OOPS("invalid hh item count %d, actual %d\n", \
|
||||
(head)->hh.tbl->num_items, _count ); \
|
||||
} \
|
||||
/* traverse hh in app order; check next/prev integrity, count */ \
|
||||
_count = 0; \
|
||||
_prev = NULL; \
|
||||
_thh = &(head)->hh; \
|
||||
while (_thh) { \
|
||||
_count++; \
|
||||
if (_prev !=(char*)(_thh->prev)) { \
|
||||
HASH_OOPS("invalid prev %p, actual %p\n", \
|
||||
_thh->prev, _prev ); \
|
||||
} \
|
||||
_prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
|
||||
_thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
|
||||
(head)->hh.tbl->hho) : NULL ); \
|
||||
} \
|
||||
if (_count != (head)->hh.tbl->num_items) { \
|
||||
HASH_OOPS("invalid app item count %d, actual %d\n", \
|
||||
(head)->hh.tbl->num_items, _count ); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define HASH_FSCK(hh,head)
|
||||
#endif
|
||||
|
||||
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
|
||||
* the descriptor to which this macro is defined for tuning the hash function.
|
||||
* The app can #include <unistd.h> to get the prototype for write(2). */
|
||||
#if defined(HASH_EMIT_KEYS)
|
||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
|
||||
do { \
|
||||
unsigned _klen = fieldlen; \
|
||||
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
|
||||
write(HASH_EMIT_KEYS, keyptr, fieldlen); \
|
||||
} while (0)
|
||||
#else
|
||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
|
||||
#endif
|
||||
|
||||
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
|
||||
#if defined(HASH_FUNCTION)
|
||||
#define HASH_FCN HASH_FUNCTION
|
||||
#else
|
||||
#define HASH_FCN HASH_JEN
|
||||
#endif
|
||||
|
||||
/* The Bernstein hash function, used in Perl prior to v5.6 */
|
||||
#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _hb_keylen=keylen; \
|
||||
char *_hb_key=(char*)key; \
|
||||
(hashv) = 0; \
|
||||
while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
|
||||
bkt = (hashv) & (num_bkts-1); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
|
||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
|
||||
#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _sx_i; \
|
||||
char *_hs_key=(char*)key; \
|
||||
hashv = 0; \
|
||||
for(_sx_i=0; _sx_i < keylen; _sx_i++) \
|
||||
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _fn_i; \
|
||||
char *_hf_key=(char*)key; \
|
||||
hashv = 2166136261UL; \
|
||||
for(_fn_i=0; _fn_i < keylen; _fn_i++) \
|
||||
hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0);
|
||||
|
||||
#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _ho_i; \
|
||||
char *_ho_key=(char*)key; \
|
||||
hashv = 0; \
|
||||
for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
|
||||
hashv += _ho_key[_ho_i]; \
|
||||
hashv += (hashv << 10); \
|
||||
hashv ^= (hashv >> 6); \
|
||||
} \
|
||||
hashv += (hashv << 3); \
|
||||
hashv ^= (hashv >> 11); \
|
||||
hashv += (hashv << 15); \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_JEN_MIX(a,b,c) \
|
||||
do { \
|
||||
a -= b; a -= c; a ^= ( c >> 13 ); \
|
||||
b -= c; b -= a; b ^= ( a << 8 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 13 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 12 ); \
|
||||
b -= c; b -= a; b ^= ( a << 16 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 5 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 3 ); \
|
||||
b -= c; b -= a; b ^= ( a << 10 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 15 ); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _hj_i,_hj_j,_hj_k; \
|
||||
char *_hj_key=(char*)key; \
|
||||
hashv = 0xfeedbeef; \
|
||||
_hj_i = _hj_j = 0x9e3779b9; \
|
||||
_hj_k = keylen; \
|
||||
while (_hj_k >= 12) { \
|
||||
_hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[2] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[3] << 24 ) ); \
|
||||
_hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[6] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[7] << 24 ) ); \
|
||||
hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[10] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[11] << 24 ) ); \
|
||||
\
|
||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||
\
|
||||
_hj_key += 12; \
|
||||
_hj_k -= 12; \
|
||||
} \
|
||||
hashv += keylen; \
|
||||
switch ( _hj_k ) { \
|
||||
case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
|
||||
case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
|
||||
case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
|
||||
case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
|
||||
case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
|
||||
case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
|
||||
case 5: _hj_j += _hj_key[4]; \
|
||||
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
|
||||
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
|
||||
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
|
||||
case 1: _hj_i += _hj_key[0]; \
|
||||
} \
|
||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
/* The Paul Hsieh hash function */
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
||||
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
char *_sfh_key=(char*)key; \
|
||||
uint32_t _sfh_tmp, _sfh_len = keylen; \
|
||||
\
|
||||
int _sfh_rem = _sfh_len & 3; \
|
||||
_sfh_len >>= 2; \
|
||||
hashv = 0xcafebabe; \
|
||||
\
|
||||
/* Main loop */ \
|
||||
for (;_sfh_len > 0; _sfh_len--) { \
|
||||
hashv += get16bits (_sfh_key); \
|
||||
_sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \
|
||||
hashv = (hashv << 16) ^ _sfh_tmp; \
|
||||
_sfh_key += 2*sizeof (uint16_t); \
|
||||
hashv += hashv >> 11; \
|
||||
} \
|
||||
\
|
||||
/* Handle end cases */ \
|
||||
switch (_sfh_rem) { \
|
||||
case 3: hashv += get16bits (_sfh_key); \
|
||||
hashv ^= hashv << 16; \
|
||||
hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \
|
||||
hashv += hashv >> 11; \
|
||||
break; \
|
||||
case 2: hashv += get16bits (_sfh_key); \
|
||||
hashv ^= hashv << 11; \
|
||||
hashv += hashv >> 17; \
|
||||
break; \
|
||||
case 1: hashv += *_sfh_key; \
|
||||
hashv ^= hashv << 10; \
|
||||
hashv += hashv >> 1; \
|
||||
} \
|
||||
\
|
||||
/* Force "avalanching" of final 127 bits */ \
|
||||
hashv ^= hashv << 3; \
|
||||
hashv += hashv >> 5; \
|
||||
hashv ^= hashv << 4; \
|
||||
hashv += hashv >> 17; \
|
||||
hashv ^= hashv << 25; \
|
||||
hashv += hashv >> 6; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0);
|
||||
|
||||
#if defined(HASH_USING_NO_STRICT_ALIASING)
|
||||
/* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads.
|
||||
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
|
||||
* So MurmurHash comes in two versions, the faster unaligned one and the slower
|
||||
* aligned one. We only use the faster one on CPU's where we know it's safe.
|
||||
*
|
||||
* Note the preprocessor built-in defines can be emitted using:
|
||||
*
|
||||
* gcc -m64 -dM -E - < /dev/null (on gcc)
|
||||
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
|
||||
*/
|
||||
#if (defined(__i386__) || defined(__x86_64__))
|
||||
#define HASH_MUR HASH_MUR_UNALIGNED
|
||||
#else
|
||||
#define HASH_MUR HASH_MUR_ALIGNED
|
||||
#endif
|
||||
|
||||
/* Appleby's MurmurHash fast version for unaligned-tolerant archs like i386 */
|
||||
#define HASH_MUR_UNALIGNED(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
const unsigned int _mur_m = 0x5bd1e995; \
|
||||
const int _mur_r = 24; \
|
||||
hashv = 0xcafebabe ^ keylen; \
|
||||
char *_mur_key = (char *)key; \
|
||||
uint32_t _mur_tmp, _mur_len = keylen; \
|
||||
\
|
||||
for (;_mur_len >= 4; _mur_len-=4) { \
|
||||
_mur_tmp = *(uint32_t *)_mur_key; \
|
||||
_mur_tmp *= _mur_m; \
|
||||
_mur_tmp ^= _mur_tmp >> _mur_r; \
|
||||
_mur_tmp *= _mur_m; \
|
||||
hashv *= _mur_m; \
|
||||
hashv ^= _mur_tmp; \
|
||||
_mur_key += 4; \
|
||||
} \
|
||||
\
|
||||
switch(_mur_len) \
|
||||
{ \
|
||||
case 3: hashv ^= _mur_key[2] << 16; \
|
||||
case 2: hashv ^= _mur_key[1] << 8; \
|
||||
case 1: hashv ^= _mur_key[0]; \
|
||||
hashv *= _mur_m; \
|
||||
}; \
|
||||
\
|
||||
hashv ^= hashv >> 13; \
|
||||
hashv *= _mur_m; \
|
||||
hashv ^= hashv >> 15; \
|
||||
\
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
/* Appleby's MurmurHash version for alignment-sensitive archs like Sparc */
|
||||
#define HASH_MUR_ALIGNED(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
const unsigned int _mur_m = 0x5bd1e995; \
|
||||
const int _mur_r = 24; \
|
||||
hashv = 0xcafebabe ^ keylen; \
|
||||
char *_mur_key = (char *)key; \
|
||||
uint32_t _mur_len = keylen; \
|
||||
int _mur_align = (int)_mur_key & 3; \
|
||||
\
|
||||
if (_mur_align && (_mur_len >= 4)) { \
|
||||
unsigned _mur_t = 0, _mur_d = 0; \
|
||||
switch(_mur_align) { \
|
||||
case 1: _mur_t |= _mur_key[2] << 16; \
|
||||
case 2: _mur_t |= _mur_key[1] << 8; \
|
||||
case 3: _mur_t |= _mur_key[0]; \
|
||||
} \
|
||||
_mur_t <<= (8 * _mur_align); \
|
||||
_mur_key += 4-_mur_align; \
|
||||
_mur_len -= 4-_mur_align; \
|
||||
int _mur_sl = 8 * (4-_mur_align); \
|
||||
int _mur_sr = 8 * _mur_align; \
|
||||
\
|
||||
for (;_mur_len >= 4; _mur_len-=4) { \
|
||||
_mur_d = *(unsigned *)_mur_key; \
|
||||
_mur_t = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
|
||||
unsigned _mur_k = _mur_t; \
|
||||
_mur_k *= _mur_m; \
|
||||
_mur_k ^= _mur_k >> _mur_r; \
|
||||
_mur_k *= _mur_m; \
|
||||
hashv *= _mur_m; \
|
||||
hashv ^= _mur_k; \
|
||||
_mur_t = _mur_d; \
|
||||
_mur_key += 4; \
|
||||
} \
|
||||
_mur_d = 0; \
|
||||
if(_mur_len >= _mur_align) { \
|
||||
switch(_mur_align) { \
|
||||
case 3: _mur_d |= _mur_key[2] << 16; \
|
||||
case 2: _mur_d |= _mur_key[1] << 8; \
|
||||
case 1: _mur_d |= _mur_key[0]; \
|
||||
} \
|
||||
unsigned _mur_k = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
|
||||
_mur_k *= _mur_m; \
|
||||
_mur_k ^= _mur_k >> _mur_r; \
|
||||
_mur_k *= _mur_m; \
|
||||
hashv *= _mur_m; \
|
||||
hashv ^= _mur_k; \
|
||||
_mur_k += _mur_align; \
|
||||
_mur_len -= _mur_align; \
|
||||
\
|
||||
switch(_mur_len) \
|
||||
{ \
|
||||
case 3: hashv ^= _mur_key[2] << 16; \
|
||||
case 2: hashv ^= _mur_key[1] << 8; \
|
||||
case 1: hashv ^= _mur_key[0]; \
|
||||
hashv *= _mur_m; \
|
||||
} \
|
||||
} else { \
|
||||
switch(_mur_len) \
|
||||
{ \
|
||||
case 3: _mur_d ^= _mur_key[2] << 16; \
|
||||
case 2: _mur_d ^= _mur_key[1] << 8; \
|
||||
case 1: _mur_d ^= _mur_key[0]; \
|
||||
case 0: hashv ^= (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
|
||||
hashv *= _mur_m; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
hashv ^= hashv >> 13; \
|
||||
hashv *= _mur_m; \
|
||||
hashv ^= hashv >> 15; \
|
||||
} else { \
|
||||
for (;_mur_len >= 4; _mur_len-=4) { \
|
||||
unsigned _mur_k = *(unsigned*)_mur_key; \
|
||||
_mur_k *= _mur_m; \
|
||||
_mur_k ^= _mur_k >> _mur_r; \
|
||||
_mur_k *= _mur_m; \
|
||||
hashv *= _mur_m; \
|
||||
hashv ^= _mur_k; \
|
||||
_mur_key += 4; \
|
||||
} \
|
||||
switch(_mur_len) \
|
||||
{ \
|
||||
case 3: hashv ^= _mur_key[2] << 16; \
|
||||
case 2: hashv ^= _mur_key[1] << 8; \
|
||||
case 1: hashv ^= _mur_key[0]; \
|
||||
hashv *= _mur_m; \
|
||||
} \
|
||||
\
|
||||
hashv ^= hashv >> 13; \
|
||||
hashv *= _mur_m; \
|
||||
hashv ^= hashv >> 15; \
|
||||
} \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
#endif /* HASH_USING_NO_STRICT_ALIASING */
|
||||
|
||||
/* key comparison function; return 0 if keys equal */
|
||||
#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
|
||||
|
||||
/* iterate over items in a known bucket to find desired item */
|
||||
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
|
||||
out = TYPEOF(out)((head.hh_head) ? ELMT_FROM_HH(tbl,head.hh_head) : NULL); \
|
||||
while (out) { \
|
||||
if (out->hh.keylen == keylen_in) { \
|
||||
if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \
|
||||
} \
|
||||
out= TYPEOF(out)((out->hh.hh_next) ? \
|
||||
ELMT_FROM_HH(tbl,out->hh.hh_next) : NULL); \
|
||||
}
|
||||
|
||||
/* add an item to a bucket */
|
||||
#define HASH_ADD_TO_BKT(head,addhh) \
|
||||
do { \
|
||||
head.count++; \
|
||||
(addhh)->hh_next = head.hh_head; \
|
||||
(addhh)->hh_prev = NULL; \
|
||||
if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
|
||||
(head).hh_head=addhh; \
|
||||
if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
|
||||
&& (addhh)->tbl->noexpand != 1) { \
|
||||
HASH_EXPAND_BUCKETS((addhh)->tbl); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* remove an item from a given bucket */
|
||||
#define HASH_DEL_IN_BKT(hh,head,hh_del) \
|
||||
(head).count--; \
|
||||
if ((head).hh_head == hh_del) { \
|
||||
(head).hh_head = hh_del->hh_next; \
|
||||
} \
|
||||
if (hh_del->hh_prev) { \
|
||||
hh_del->hh_prev->hh_next = hh_del->hh_next; \
|
||||
} \
|
||||
if (hh_del->hh_next) { \
|
||||
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
|
||||
}
|
||||
|
||||
/* Bucket expansion has the effect of doubling the number of buckets
|
||||
* and redistributing the items into the new buckets. Ideally the
|
||||
* items will distribute more or less evenly into the new buckets
|
||||
* (the extent to which this is true is a measure of the quality of
|
||||
* the hash function as it applies to the key domain).
|
||||
*
|
||||
* With the items distributed into more buckets, the chain length
|
||||
* (item count) in each bucket is reduced. Thus by expanding buckets
|
||||
* the hash keeps a bound on the chain length. This bounded chain
|
||||
* length is the essence of how a hash provides constant time lookup.
|
||||
*
|
||||
* The calculation of tbl->ideal_chain_maxlen below deserves some
|
||||
* explanation. First, keep in mind that we're calculating the ideal
|
||||
* maximum chain length based on the *new* (doubled) bucket count.
|
||||
* In fractions this is just n/b (n=number of items,b=new num buckets).
|
||||
* Since the ideal chain length is an integer, we want to calculate
|
||||
* ceil(n/b). We don't depend on floating point arithmetic in this
|
||||
* hash, so to calculate ceil(n/b) with integers we could write
|
||||
*
|
||||
* ceil(n/b) = (n/b) + ((n%b)?1:0)
|
||||
*
|
||||
* and in fact a previous version of this hash did just that.
|
||||
* But now we have improved things a bit by recognizing that b is
|
||||
* always a power of two. We keep its base 2 log handy (call it lb),
|
||||
* so now we can write this with a bit shift and logical AND:
|
||||
*
|
||||
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
|
||||
*
|
||||
*/
|
||||
#define HASH_EXPAND_BUCKETS(tbl) \
|
||||
do { \
|
||||
unsigned _he_bkt; \
|
||||
unsigned _he_bkt_i; \
|
||||
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
|
||||
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
|
||||
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
|
||||
memset(_he_new_buckets, 0, \
|
||||
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
tbl->ideal_chain_maxlen = \
|
||||
(tbl->num_items >> (tbl->log2_num_buckets+1)) + \
|
||||
((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
|
||||
tbl->nonideal_items = 0; \
|
||||
for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
|
||||
{ \
|
||||
_he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
|
||||
while (_he_thh) { \
|
||||
_he_hh_nxt = _he_thh->hh_next; \
|
||||
HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
|
||||
_he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
|
||||
if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
|
||||
tbl->nonideal_items++; \
|
||||
_he_newbkt->expand_mult = _he_newbkt->count / \
|
||||
tbl->ideal_chain_maxlen; \
|
||||
} \
|
||||
_he_thh->hh_prev = NULL; \
|
||||
_he_thh->hh_next = _he_newbkt->hh_head; \
|
||||
if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
|
||||
_he_thh; \
|
||||
_he_newbkt->hh_head = _he_thh; \
|
||||
_he_thh = _he_hh_nxt; \
|
||||
} \
|
||||
} \
|
||||
tbl->num_buckets *= 2; \
|
||||
tbl->log2_num_buckets++; \
|
||||
uthash_free( tbl->buckets ); \
|
||||
tbl->buckets = _he_new_buckets; \
|
||||
tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
|
||||
(tbl->ineff_expands+1) : 0; \
|
||||
if (tbl->ineff_expands > 1) { \
|
||||
tbl->noexpand=1; \
|
||||
uthash_noexpand_fyi(tbl); \
|
||||
} \
|
||||
uthash_expand_fyi(tbl); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
|
||||
/* Note that HASH_SORT assumes the hash handle name to be hh.
|
||||
* HASH_SRT was added to allow the hash handle name to be passed in. */
|
||||
#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
|
||||
#define HASH_SRT(hh,head,cmpfcn) \
|
||||
do { \
|
||||
unsigned _hs_i; \
|
||||
unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
|
||||
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
|
||||
if (head) { \
|
||||
_hs_insize = 1; \
|
||||
_hs_looping = 1; \
|
||||
_hs_list = &((head)->hh); \
|
||||
while (_hs_looping) { \
|
||||
_hs_p = _hs_list; \
|
||||
_hs_list = NULL; \
|
||||
_hs_tail = NULL; \
|
||||
_hs_nmerges = 0; \
|
||||
while (_hs_p) { \
|
||||
_hs_nmerges++; \
|
||||
_hs_q = _hs_p; \
|
||||
_hs_psize = 0; \
|
||||
for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
|
||||
_hs_psize++; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
if (! (_hs_q) ) break; \
|
||||
} \
|
||||
_hs_qsize = _hs_insize; \
|
||||
while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
|
||||
if (_hs_psize == 0) { \
|
||||
_hs_e = _hs_q; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_qsize--; \
|
||||
} else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
|
||||
_hs_e = _hs_p; \
|
||||
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
|
||||
((void*)((char*)(_hs_p->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_psize--; \
|
||||
} else if (( \
|
||||
cmpfcn(TYPEOF(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
|
||||
TYPEOF(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
|
||||
) <= 0) { \
|
||||
_hs_e = _hs_p; \
|
||||
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
|
||||
((void*)((char*)(_hs_p->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_psize--; \
|
||||
} else { \
|
||||
_hs_e = _hs_q; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_qsize--; \
|
||||
} \
|
||||
if ( _hs_tail ) { \
|
||||
_hs_tail->next = ((_hs_e) ? \
|
||||
ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
|
||||
} else { \
|
||||
_hs_list = _hs_e; \
|
||||
} \
|
||||
_hs_e->prev = ((_hs_tail) ? \
|
||||
ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
|
||||
_hs_tail = _hs_e; \
|
||||
} \
|
||||
_hs_p = _hs_q; \
|
||||
} \
|
||||
_hs_tail->next = NULL; \
|
||||
if ( _hs_nmerges <= 1 ) { \
|
||||
_hs_looping=0; \
|
||||
(head)->hh.tbl->tail = _hs_tail; \
|
||||
(head) = TYPEOF(head)ELMT_FROM_HH((head)->hh.tbl, _hs_list); \
|
||||
} \
|
||||
_hs_insize *= 2; \
|
||||
} \
|
||||
HASH_FSCK(hh,head); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* This function selects items from one hash into another hash.
|
||||
* The end result is that the selected items have dual presence
|
||||
* in both hashes. There is no copy of the items made; rather
|
||||
* they are added into the new hash through a secondary hash
|
||||
* hash handle that must be present in the structure. */
|
||||
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
|
||||
do { \
|
||||
unsigned _src_bkt, _dst_bkt; \
|
||||
void *_last_elt=NULL, *_elt; \
|
||||
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
|
||||
ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
|
||||
if (src) { \
|
||||
for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
|
||||
for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
|
||||
_src_hh; \
|
||||
_src_hh = _src_hh->hh_next) { \
|
||||
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
|
||||
if (cond(_elt)) { \
|
||||
_dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
|
||||
_dst_hh->key = _src_hh->key; \
|
||||
_dst_hh->keylen = _src_hh->keylen; \
|
||||
_dst_hh->hashv = _src_hh->hashv; \
|
||||
_dst_hh->prev = _last_elt; \
|
||||
_dst_hh->next = NULL; \
|
||||
if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
|
||||
if (!dst) { \
|
||||
dst = TYPEOF(dst)_elt; \
|
||||
HASH_MAKE_TABLE(hh_dst,dst); \
|
||||
} else { \
|
||||
_dst_hh->tbl = (dst)->hh_dst.tbl; \
|
||||
} \
|
||||
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
|
||||
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
|
||||
(dst)->hh_dst.tbl->num_items++; \
|
||||
_last_elt = _elt; \
|
||||
_last_elt_hh = _dst_hh; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
HASH_FSCK(hh_dst,dst); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_CLEAR(hh,head) \
|
||||
do { \
|
||||
if (head) { \
|
||||
uthash_free((head)->hh.tbl->buckets ); \
|
||||
uthash_free((head)->hh.tbl); \
|
||||
(head)=NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* obtain a count of items in the hash */
|
||||
#define HASH_COUNT(head) HASH_CNT(hh,head)
|
||||
#define HASH_CNT(hh,head) (head?(head->hh.tbl->num_items):0)
|
||||
|
||||
typedef struct UT_hash_bucket {
|
||||
struct UT_hash_handle *hh_head;
|
||||
unsigned count;
|
||||
|
||||
/* expand_mult is normally set to 0. In this situation, the max chain length
|
||||
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
|
||||
* the bucket's chain exceeds this length, bucket expansion is triggered).
|
||||
* However, setting expand_mult to a non-zero value delays bucket expansion
|
||||
* (that would be triggered by additions to this particular bucket)
|
||||
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
|
||||
* (The multiplier is simply expand_mult+1). The whole idea of this
|
||||
* multiplier is to reduce bucket expansions, since they are expensive, in
|
||||
* situations where we know that a particular bucket tends to be overused.
|
||||
* It is better to let its chain length grow to a longer yet-still-bounded
|
||||
* value, than to do an O(n) bucket expansion too often.
|
||||
*/
|
||||
unsigned expand_mult;
|
||||
|
||||
} UT_hash_bucket;
|
||||
|
||||
/* random signature used only to find hash tables in external analysis */
|
||||
#define HASH_SIGNATURE 0xa0111fe1
|
||||
#define HASH_BLOOM_SIGNATURE 0xb12220f2
|
||||
|
||||
typedef struct UT_hash_table {
|
||||
UT_hash_bucket *buckets;
|
||||
unsigned num_buckets, log2_num_buckets;
|
||||
unsigned num_items;
|
||||
struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
|
||||
ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
|
||||
|
||||
/* in an ideal situation (all buckets used equally), no bucket would have
|
||||
* more than ceil(#items/#buckets) items. that's the ideal chain length. */
|
||||
unsigned ideal_chain_maxlen;
|
||||
|
||||
/* nonideal_items is the number of items in the hash whose chain position
|
||||
* exceeds the ideal chain maxlen. these items pay the penalty for an uneven
|
||||
* hash distribution; reaching them in a chain traversal takes >ideal steps */
|
||||
unsigned nonideal_items;
|
||||
|
||||
/* ineffective expands occur when a bucket doubling was performed, but
|
||||
* afterward, more than half the items in the hash had nonideal chain
|
||||
* positions. If this happens on two consecutive expansions we inhibit any
|
||||
* further expansion, as it's not helping; this happens when the hash
|
||||
* function isn't a good fit for the key domain. When expansion is inhibited
|
||||
* the hash will still work, albeit no longer in constant time. */
|
||||
unsigned ineff_expands, noexpand;
|
||||
|
||||
uint32_t signature; /* used only to find hash tables in external analysis */
|
||||
#if defined(HASH_BLOOM)
|
||||
uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
|
||||
uint8_t *bloom_bv;
|
||||
char bloom_nbits;
|
||||
#endif
|
||||
|
||||
} UT_hash_table;
|
||||
|
||||
typedef struct UT_hash_handle {
|
||||
struct UT_hash_table *tbl;
|
||||
void *prev; /* prev element in app order */
|
||||
void *next; /* next element in app order */
|
||||
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
|
||||
struct UT_hash_handle *hh_next; /* next hh in bucket order */
|
||||
void *key; /* ptr to enclosing struct's key */
|
||||
unsigned keylen; /* enclosing struct's key len */
|
||||
unsigned hashv; /* result of hash-fcn(key) */
|
||||
} UT_hash_handle;
|
||||
|
||||
#endif /* UTHASH_H */
|
@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef XDISPLAY_H
|
||||
#define XDISPLAY_H
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
/* Returns the main display, closed either on exit or when closeMainDisplay()
|
||||
* is invoked. This removes a bit of the overhead of calling XOpenDisplay() &
|
||||
* XCloseDisplay() everytime the main display needs to be used.
|
||||
*
|
||||
* Note that this is almost certainly not thread safe. */
|
||||
Display *XGetMainDisplay(void);
|
||||
|
||||
/* Closes the main display if it is open, or does nothing if not. */
|
||||
void XCloseMainDisplay(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
char *getXDisplay(void);
|
||||
void setXDisplay(char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* XDISPLAY_H */
|
@ -1,14 +1,21 @@
|
||||
#include "xdisplay.h"
|
||||
#include <stdio.h> /* For fputs() */
|
||||
#include <stdlib.h> /* For atexit() */
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
static Display *mainDisplay = NULL;
|
||||
static int registered = 0;
|
||||
static char *displayName = ":0.0";
|
||||
|
||||
static char *displayName = NULL;
|
||||
static int hasDisplayNameChanged = 0;
|
||||
|
||||
Display *XGetMainDisplay(void)
|
||||
{
|
||||
void XCloseMainDisplay(void) {
|
||||
if (mainDisplay != NULL) {
|
||||
XCloseDisplay(mainDisplay);
|
||||
mainDisplay = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Display *XGetMainDisplay(void) {
|
||||
/* Close the display if displayName has changed */
|
||||
if (hasDisplayNameChanged) {
|
||||
XCloseMainDisplay();
|
||||
@ -20,10 +27,15 @@ Display *XGetMainDisplay(void)
|
||||
mainDisplay = XOpenDisplay(displayName);
|
||||
|
||||
/* Then try using environment variable DISPLAY */
|
||||
if (mainDisplay == NULL) {
|
||||
if (mainDisplay == NULL && displayName != NULL) {
|
||||
mainDisplay = XOpenDisplay(NULL);
|
||||
}
|
||||
|
||||
/* Fall back to the most likely :0.0*/
|
||||
if (mainDisplay == NULL) {
|
||||
mainDisplay = XOpenDisplay(":0.0");
|
||||
}
|
||||
|
||||
if (mainDisplay == NULL) {
|
||||
fputs("Could not open main display\n", stderr);
|
||||
} else if (!registered) {
|
||||
@ -35,22 +47,11 @@ Display *XGetMainDisplay(void)
|
||||
return mainDisplay;
|
||||
}
|
||||
|
||||
void XCloseMainDisplay(void)
|
||||
{
|
||||
if (mainDisplay != NULL) {
|
||||
XCloseDisplay(mainDisplay);
|
||||
mainDisplay = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void setXDisplay(char *name)
|
||||
{
|
||||
void setXDisplay(char *name) {
|
||||
displayName = strdup(name);
|
||||
hasDisplayNameChanged = 1;
|
||||
}
|
||||
|
||||
char *getXDisplay(void)
|
||||
{
|
||||
char *getXDisplay(void) {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
|
@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef ZLIB_UTIL_H
|
||||
#define ZLIB_UTIL_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include "ms_stdint.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Attempts to decompress given deflated NUL-terminated buffer.
|
||||
*
|
||||
* If successful and |len| is not NULL, |len| will be set to the number of
|
||||
* bytes in the returned buffer.
|
||||
* Returns new string to be free()'d by caller, or NULL on error. */
|
||||
uint8_t *zlib_decompress(const uint8_t *buf, size_t *len);
|
||||
|
||||
/* Attempt to compress given buffer.
|
||||
*
|
||||
* The compression level is passed directly to zlib: it must between 0 and 9,
|
||||
* where 1 gives best speed, 9 gives best compression, and 0 gives no
|
||||
* compression at all.
|
||||
*
|
||||
* If successful and |len| is not NULL, |len| will be set to the number of
|
||||
* bytes in the returned buffer.
|
||||
* Returns new string to be free()'d by caller, or NULL on error. */
|
||||
uint8_t *zlib_compress(const uint8_t *buf, const size_t buflen, int level,
|
||||
size_t *len);
|
||||
|
||||
#endif /* ZLIB_UTIL_H */
|
@ -1,98 +0,0 @@
|
||||
#include "zlib_util.h"
|
||||
#include <zlib.h>
|
||||
#include <stdio.h> /* fprintf() */
|
||||
#include <stdlib.h> /* malloc() */
|
||||
#include <assert.h>
|
||||
|
||||
#define ZLIB_CHUNK (16 * 1024)
|
||||
|
||||
uint8_t *zlib_decompress(const uint8_t *buf, size_t *len){
|
||||
size_t output_size = ZLIB_CHUNK;
|
||||
uint8_t *output = malloc(output_size);
|
||||
int err;
|
||||
z_stream zst;
|
||||
|
||||
/* Sanity check */
|
||||
if (output == NULL) return NULL;
|
||||
assert(buf != NULL);
|
||||
|
||||
/* Set inflate state */
|
||||
zst.zalloc = Z_NULL;
|
||||
zst.zfree = Z_NULL;
|
||||
zst.opaque = Z_NULL;
|
||||
zst.next_out = (Byte *)output;
|
||||
zst.next_in = (Byte *)buf;
|
||||
zst.avail_out = ZLIB_CHUNK;
|
||||
|
||||
if (inflateInit(&zst) != Z_OK) goto error;
|
||||
|
||||
/* Decompress input buffer */
|
||||
do {
|
||||
if ((err = inflate(&zst, Z_NO_FLUSH)) == Z_OK) { /* Need more memory */
|
||||
zst.avail_out = (uInt)output_size;
|
||||
|
||||
/* Double size each time to avoid calls to realloc() */
|
||||
output_size <<= 1;
|
||||
output = realloc(output, output_size + 1);
|
||||
if (output == NULL) return NULL;
|
||||
|
||||
zst.next_out = (Byte *)(output + zst.avail_out);
|
||||
} else if (err != Z_STREAM_END) { /* Error decompressing */
|
||||
if (zst.msg != NULL) {
|
||||
fprintf(stderr, "Could not decompress data: %s\n", zst.msg);
|
||||
}
|
||||
inflateEnd(&zst);
|
||||
goto error;
|
||||
}
|
||||
} while (err != Z_STREAM_END);
|
||||
|
||||
if (len != NULL) *len = zst.total_out;
|
||||
if (inflateEnd(&zst) != Z_OK) goto error;
|
||||
return output; /* To be free()'d by caller */
|
||||
|
||||
error:
|
||||
if (output != NULL) free(output);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *zlib_compress(const uint8_t *buf, const size_t buflen, int level,
|
||||
size_t *len)
|
||||
{
|
||||
z_stream zst;
|
||||
uint8_t *output = NULL;
|
||||
|
||||
/* Sanity check */
|
||||
assert(buf != NULL);
|
||||
assert(len != NULL);
|
||||
assert(level <= 9 && level >= 0);
|
||||
|
||||
zst.avail_out = (uInt)((buflen + (buflen / 10)) + 12);
|
||||
output = malloc(zst.avail_out);
|
||||
if (output == NULL) return NULL;
|
||||
|
||||
/* Set deflate state */
|
||||
zst.zalloc = Z_NULL;
|
||||
zst.zfree = Z_NULL;
|
||||
zst.next_out = (Byte *)output;
|
||||
zst.next_in = (Byte *)buf;
|
||||
zst.avail_in = (uInt)buflen;
|
||||
|
||||
if (deflateInit(&zst, level) != Z_OK) goto error;
|
||||
|
||||
/* Compress input buffer */
|
||||
if (deflate(&zst, Z_FINISH) != Z_STREAM_END) {
|
||||
if (zst.msg != NULL) {
|
||||
fprintf(stderr, "Could not compress data: %s\n", zst.msg);
|
||||
}
|
||||
deflateEnd(&zst);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (len != NULL) *len = zst.total_out;
|
||||
if (deflateEnd(&zst) != Z_OK) goto error;
|
||||
return output; /* To be free()'d by caller */
|
||||
|
||||
error:
|
||||
if (output != NULL) free(output);
|
||||
return NULL;
|
||||
}
|
550
bitmap.go
550
bitmap.go
@ -1,550 +0,0 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
package robotgo
|
||||
|
||||
/*
|
||||
#cgo darwin,amd64 LDFLAGS:-L${SRCDIR}/cdeps/mac/amd -lpng -lz
|
||||
#cgo darwin,arm64 LDFLAGS:-L${SRCDIR}/cdeps/mac/m1 -lpng -lz
|
||||
//
|
||||
#cgo linux LDFLAGS: -L/usr/src -lpng -lz
|
||||
//
|
||||
#cgo windows,amd64 LDFLAGS: -L${SRCDIR}/cdeps/win/amd/win64 -lpng -lz
|
||||
#cgo windows,386 LDFLAGS: -L${SRCDIR}/cdeps/win/amd/win32 -lpng -lz
|
||||
#cgo windows,arm64 LDFLAGS:-L${SRCDIR}/cdeps/win/arm -lpng -lz
|
||||
//
|
||||
//#include "screen/goScreen.h"
|
||||
#include "bitmap/goBitmap.h"
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/vcaesar/tt"
|
||||
)
|
||||
|
||||
/*
|
||||
.______ __ .___________..___ ___. ___ .______
|
||||
| _ \ | | | || \/ | / \ | _ \
|
||||
| |_) | | | `---| |----`| \ / | / ^ \ | |_) |
|
||||
| _ < | | | | | |\/| | / /_\ \ | ___/
|
||||
| |_) | | | | | | | | | / _____ \ | |
|
||||
|______/ |__| |__| |__| |__| /__/ \__\ | _|
|
||||
*/
|
||||
|
||||
// SaveCapture capture screen and save
|
||||
func SaveCapture(spath string, args ...int) string {
|
||||
bit := CaptureScreen(args...)
|
||||
|
||||
err := SaveBitmap(bit, spath)
|
||||
FreeBitmap(bit)
|
||||
return err
|
||||
}
|
||||
|
||||
// FreeBitmapArr free and dealloc the C bitmap array
|
||||
func FreeBitmapArr(bit ...C.MMBitmapRef) {
|
||||
for i := 0; i < len(bit); i++ {
|
||||
FreeBitmap(bit[i])
|
||||
}
|
||||
}
|
||||
|
||||
// ToCBitmap trans Bitmap to C.MMBitmapRef
|
||||
func ToCBitmap(bit Bitmap) C.MMBitmapRef {
|
||||
cbitmap := C.createMMBitmap(
|
||||
(*C.uint8_t)(bit.ImgBuf),
|
||||
C.size_t(bit.Width),
|
||||
C.size_t(bit.Height),
|
||||
C.size_t(bit.Bytewidth),
|
||||
C.uint8_t(bit.BitsPixel),
|
||||
C.uint8_t(bit.BytesPerPixel),
|
||||
)
|
||||
|
||||
return cbitmap
|
||||
}
|
||||
|
||||
// ToMMBitmapRef trans CBitmap to C.MMBitmapRef
|
||||
func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef {
|
||||
return C.MMBitmapRef(bit)
|
||||
}
|
||||
|
||||
// ToBitmapBytes saves Bitmap to bitmap format in bytes
|
||||
func ToBitmapBytes(bit C.MMBitmapRef) []byte {
|
||||
var len C.size_t
|
||||
ptr := C.saveMMBitmapAsBytes(bit, &len)
|
||||
if int(len) < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
bs := C.GoBytes(unsafe.Pointer(ptr), C.int(len))
|
||||
C.free(unsafe.Pointer(ptr))
|
||||
return bs
|
||||
}
|
||||
|
||||
// TostringBitmap tostring bitmap to string
|
||||
func TostringBitmap(bit C.MMBitmapRef) string {
|
||||
strBit := C.tostring_bitmap(bit)
|
||||
return C.GoString(strBit)
|
||||
}
|
||||
|
||||
// TocharBitmap tostring bitmap to C.char
|
||||
func TocharBitmap(bit C.MMBitmapRef) *C.char {
|
||||
strBit := C.tostring_bitmap(bit)
|
||||
return strBit
|
||||
}
|
||||
|
||||
func internalFindBitmap(bit, sbit C.MMBitmapRef, tolerance float64) (int, int) {
|
||||
pos := C.find_bitmap(bit, sbit, C.float(tolerance))
|
||||
// fmt.Println("pos----", pos)
|
||||
return int(pos.x), int(pos.y)
|
||||
}
|
||||
|
||||
// FindCBitmap find bitmap's pos by CBitmap
|
||||
func FindCBitmap(bmp CBitmap, args ...interface{}) (int, int) {
|
||||
return FindBitmap(ToMMBitmapRef(bmp), args...)
|
||||
}
|
||||
|
||||
// FindBitmap find the bitmap's pos
|
||||
//
|
||||
// robotgo.FindBitmap(bitmap, source_bitamp C.MMBitmapRef, tolerance float64)
|
||||
//
|
||||
// |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the
|
||||
// colors in the bitmaps need to match, with 0 being exact and 1 being any.
|
||||
//
|
||||
// This method only automatically free the internal bitmap,
|
||||
// use `defer robotgo.FreeBitmap(bit)` to free the bitmap
|
||||
func FindBitmap(bit C.MMBitmapRef, args ...interface{}) (int, int) {
|
||||
var (
|
||||
sbit C.MMBitmapRef
|
||||
tolerance = 0.01
|
||||
)
|
||||
|
||||
if len(args) > 0 && args[0] != nil {
|
||||
sbit = args[0].(C.MMBitmapRef)
|
||||
} else {
|
||||
sbit = CaptureScreen()
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
tolerance = args[1].(float64)
|
||||
}
|
||||
|
||||
fx, fy := internalFindBitmap(bit, sbit, tolerance)
|
||||
// FreeBitmap(bit)
|
||||
if len(args) <= 0 || (len(args) > 0 && args[0] == nil) {
|
||||
FreeBitmap(sbit)
|
||||
}
|
||||
|
||||
return fx, fy
|
||||
}
|
||||
|
||||
// FindPic finding the image by path
|
||||
//
|
||||
// robotgo.FindPic(path string, source_bitamp C.MMBitmapRef, tolerance float64)
|
||||
//
|
||||
// This method only automatically free the internal bitmap,
|
||||
// use `defer robotgo.FreeBitmap(bit)` to free the bitmap
|
||||
func FindPic(path string, args ...interface{}) (int, int) {
|
||||
var (
|
||||
sbit C.MMBitmapRef
|
||||
tolerance = 0.01
|
||||
)
|
||||
|
||||
openbit := OpenBitmap(path)
|
||||
|
||||
if len(args) > 0 && args[0] != nil {
|
||||
sbit = args[0].(C.MMBitmapRef)
|
||||
} else {
|
||||
sbit = CaptureScreen()
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
tolerance = args[1].(float64)
|
||||
}
|
||||
|
||||
fx, fy := internalFindBitmap(openbit, sbit, tolerance)
|
||||
FreeBitmap(openbit)
|
||||
if len(args) <= 0 || (len(args) > 0 && args[0] == nil) {
|
||||
FreeBitmap(sbit)
|
||||
}
|
||||
|
||||
return fx, fy
|
||||
}
|
||||
|
||||
// FreeMMPointArr free MMPoint array
|
||||
func FreeMMPointArr(pointArray C.MMPointArrayRef) {
|
||||
C.destroyMMPointArray(pointArray)
|
||||
}
|
||||
|
||||
// Deprecated: use the FindAllBitmap(),
|
||||
//
|
||||
// FindEveryBitmap find the every bitmap, same with the FindAllBitmap()
|
||||
func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) []Point {
|
||||
return FindAllBitmap(bit, args...)
|
||||
}
|
||||
|
||||
// FindAllBitmap find the all bitmap
|
||||
func FindAllBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []Point) {
|
||||
var (
|
||||
sbit C.MMBitmapRef
|
||||
tolerance C.float = 0.01
|
||||
lpos C.MMPoint
|
||||
)
|
||||
|
||||
if len(args) > 0 && args[0] != nil {
|
||||
sbit = args[0].(C.MMBitmapRef)
|
||||
} else {
|
||||
sbit = CaptureScreen()
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
tolerance = C.float(args[1].(float64))
|
||||
}
|
||||
|
||||
if len(args) > 2 {
|
||||
lpos.x = C.size_t(args[2].(int))
|
||||
lpos.y = 0
|
||||
} else {
|
||||
lpos.x = 0
|
||||
lpos.y = 0
|
||||
}
|
||||
|
||||
if len(args) > 3 {
|
||||
lpos.x = C.size_t(args[2].(int))
|
||||
lpos.y = C.size_t(args[3].(int))
|
||||
}
|
||||
|
||||
pos := C.find_every_bitmap(bit, sbit, tolerance, &lpos)
|
||||
// FreeBitmap(bit)
|
||||
if len(args) <= 0 || (len(args) > 0 && args[0] == nil) {
|
||||
FreeBitmap(sbit)
|
||||
}
|
||||
if pos == nil {
|
||||
return
|
||||
}
|
||||
defer FreeMMPointArr(pos)
|
||||
|
||||
cSize := pos.count
|
||||
cArray := pos.array
|
||||
gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize]
|
||||
for i := 0; i < len(gSlice); i++ {
|
||||
posArr = append(posArr, Point{
|
||||
X: int(gSlice[i].x),
|
||||
Y: int(gSlice[i].y),
|
||||
})
|
||||
}
|
||||
|
||||
// fmt.Println("pos----", pos)
|
||||
return
|
||||
}
|
||||
|
||||
// CountBitmap count of the bitmap
|
||||
func CountBitmap(bitmap, sbit C.MMBitmapRef, args ...float32) int {
|
||||
var tolerance C.float = 0.01
|
||||
if len(args) > 0 {
|
||||
tolerance = C.float(args[0])
|
||||
}
|
||||
|
||||
count := C.count_of_bitmap(bitmap, sbit, tolerance)
|
||||
return int(count)
|
||||
}
|
||||
|
||||
// BitmapClick find the bitmap and click
|
||||
func BitmapClick(bitmap C.MMBitmapRef, args ...interface{}) {
|
||||
x, y := FindBitmap(bitmap)
|
||||
MovesClick(x, y, args...)
|
||||
}
|
||||
|
||||
// PointInBounds bitmap point in bounds
|
||||
func PointInBounds(bitmap C.MMBitmapRef, x, y int) bool {
|
||||
var point C.MMPoint
|
||||
point.x = C.size_t(x)
|
||||
point.y = C.size_t(y)
|
||||
cbool := C.point_in_bounds(bitmap, point)
|
||||
|
||||
return bool(cbool)
|
||||
}
|
||||
|
||||
// OpenBitmap open the bitmap return C.MMBitmapRef
|
||||
//
|
||||
// robotgo.OpenBitmap(path string, type int)
|
||||
func OpenBitmap(gpath string, args ...int) C.MMBitmapRef {
|
||||
path := C.CString(gpath)
|
||||
var mtype C.uint16_t = 1
|
||||
|
||||
if len(args) > 0 {
|
||||
mtype = C.uint16_t(args[0])
|
||||
}
|
||||
|
||||
bit := C.bitmap_open(path, mtype)
|
||||
C.free(unsafe.Pointer(path))
|
||||
|
||||
return bit
|
||||
}
|
||||
|
||||
// Deprecated: use the BitmapFromStr(),
|
||||
//
|
||||
// BitmapStr bitmap from string
|
||||
func BitmapStr(str string) C.MMBitmapRef {
|
||||
return BitmapFromStr(str)
|
||||
}
|
||||
|
||||
// BitmapFromStr read bitmap from the string
|
||||
func BitmapFromStr(str string) C.MMBitmapRef {
|
||||
cs := C.CString(str)
|
||||
bit := C.bitmap_from_string(cs)
|
||||
C.free(unsafe.Pointer(cs))
|
||||
|
||||
return bit
|
||||
}
|
||||
|
||||
// SaveBitmap save the bitmap to image
|
||||
//
|
||||
// robotgo.SaveBimap(bitmap C.MMBitmapRef, path string, type int)
|
||||
func SaveBitmap(bitmap C.MMBitmapRef, gpath string, args ...int) string {
|
||||
var mtype C.uint16_t = 1
|
||||
if len(args) > 0 {
|
||||
mtype = C.uint16_t(args[0])
|
||||
}
|
||||
|
||||
path := C.CString(gpath)
|
||||
saveBit := C.bitmap_save(bitmap, path, mtype)
|
||||
C.free(unsafe.Pointer(path))
|
||||
|
||||
return C.GoString(saveBit)
|
||||
}
|
||||
|
||||
// GetPortion get bitmap portion
|
||||
func GetPortion(bit C.MMBitmapRef, x, y, w, h int) C.MMBitmapRef {
|
||||
var rect C.MMRect
|
||||
rect.origin.x = C.size_t(x)
|
||||
rect.origin.y = C.size_t(y)
|
||||
rect.size.width = C.size_t(w)
|
||||
rect.size.height = C.size_t(h)
|
||||
|
||||
pos := C.get_portion(bit, rect)
|
||||
return pos
|
||||
}
|
||||
|
||||
// Convert convert the bitmap
|
||||
//
|
||||
// robotgo.Convert(opath, spath string, type int)
|
||||
func Convert(opath, spath string, args ...int) string {
|
||||
var mtype = 1
|
||||
if len(args) > 0 {
|
||||
mtype = args[0]
|
||||
}
|
||||
|
||||
// C.CString()
|
||||
bitmap := OpenBitmap(opath)
|
||||
// fmt.Println("a----", bit_map)
|
||||
return SaveBitmap(bitmap, spath, mtype)
|
||||
}
|
||||
|
||||
// ReadBitmap returns false and sets error if |bitmap| is NULL
|
||||
func ReadBitmap(bitmap C.MMBitmapRef) bool {
|
||||
abool := C.bitmap_ready(bitmap)
|
||||
gbool := bool(abool)
|
||||
return gbool
|
||||
}
|
||||
|
||||
// CopyBitPB copy bitmap to pasteboard
|
||||
func CopyBitPB(bitmap C.MMBitmapRef) bool {
|
||||
abool := C.bitmap_copy_to_pboard(bitmap)
|
||||
gbool := bool(abool)
|
||||
|
||||
return gbool
|
||||
}
|
||||
|
||||
// Deprecated: CopyBitpb copy bitmap to pasteboard, Wno-deprecated
|
||||
//
|
||||
// This function will be removed in version v1.0.0
|
||||
func CopyBitpb(bitmap C.MMBitmapRef) bool {
|
||||
tt.Drop("CopyBitpb", "CopyBitPB")
|
||||
return CopyBitPB(bitmap)
|
||||
}
|
||||
|
||||
// DeepCopyBit deep copy bitmap
|
||||
func DeepCopyBit(bitmap C.MMBitmapRef) C.MMBitmapRef {
|
||||
bit := C.bitmap_deepcopy(bitmap)
|
||||
return bit
|
||||
}
|
||||
|
||||
// GetColor get the bitmap color
|
||||
func GetColor(bitmap C.MMBitmapRef, x, y int) C.MMRGBHex {
|
||||
color := C.bitmap_get_color(bitmap, C.size_t(x), C.size_t(y))
|
||||
|
||||
return color
|
||||
}
|
||||
|
||||
// GetColors get bitmap color retrun string
|
||||
func GetColors(bitmap C.MMBitmapRef, x, y int) string {
|
||||
clo := GetColor(bitmap, x, y)
|
||||
|
||||
return PadHex(clo)
|
||||
}
|
||||
|
||||
// FindColor find bitmap color
|
||||
//
|
||||
// robotgo.FindColor(color CHex, bitmap C.MMBitmapRef, tolerance float)
|
||||
func FindColor(color CHex, args ...interface{}) (int, int) {
|
||||
var (
|
||||
tolerance C.float = 0.01
|
||||
bitmap C.MMBitmapRef
|
||||
)
|
||||
|
||||
if len(args) > 0 && args[0] != nil {
|
||||
bitmap = args[0].(C.MMBitmapRef)
|
||||
} else {
|
||||
bitmap = CaptureScreen()
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
tolerance = C.float(args[1].(float64))
|
||||
}
|
||||
|
||||
pos := C.bitmap_find_color(bitmap, C.MMRGBHex(color), tolerance)
|
||||
if len(args) <= 0 || (len(args) > 0 && args[0] == nil) {
|
||||
FreeBitmap(bitmap)
|
||||
}
|
||||
|
||||
x := int(pos.x)
|
||||
y := int(pos.y)
|
||||
|
||||
return x, y
|
||||
}
|
||||
|
||||
// FindColorCS findcolor by CaptureScreen
|
||||
func FindColorCS(color CHex, x, y, w, h int, args ...float64) (int, int) {
|
||||
var tolerance = 0.01
|
||||
|
||||
if len(args) > 0 {
|
||||
tolerance = args[0]
|
||||
}
|
||||
|
||||
bitmap := CaptureScreen(x, y, w, h)
|
||||
rx, ry := FindColor(color, bitmap, tolerance)
|
||||
FreeBitmap(bitmap)
|
||||
|
||||
return rx, ry
|
||||
}
|
||||
|
||||
// Deprecated: use the FindAllColor(),
|
||||
//
|
||||
// FindEveryColor find the every color, same with the FindAllColor()
|
||||
func FindEveryColor(color CHex, args ...interface{}) []Point {
|
||||
return FindAllColor(color, args...)
|
||||
}
|
||||
|
||||
// FindAllColor find the all color
|
||||
func FindAllColor(color CHex, args ...interface{}) (posArr []Point) {
|
||||
var (
|
||||
bitmap C.MMBitmapRef
|
||||
tolerance C.float = 0.01
|
||||
lpos C.MMPoint
|
||||
)
|
||||
|
||||
if len(args) > 0 && args[0] != nil {
|
||||
bitmap = args[0].(C.MMBitmapRef)
|
||||
} else {
|
||||
bitmap = CaptureScreen()
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
tolerance = C.float(args[1].(float64))
|
||||
}
|
||||
|
||||
if len(args) > 2 {
|
||||
lpos.x = C.size_t(args[2].(int))
|
||||
lpos.y = 0
|
||||
} else {
|
||||
lpos.x = 0
|
||||
lpos.y = 0
|
||||
}
|
||||
|
||||
if len(args) > 3 {
|
||||
lpos.x = C.size_t(args[2].(int))
|
||||
lpos.y = C.size_t(args[3].(int))
|
||||
}
|
||||
|
||||
pos := C.bitmap_find_every_color(bitmap, C.MMRGBHex(color), tolerance, &lpos)
|
||||
if len(args) <= 0 || (len(args) > 0 && args[0] == nil) {
|
||||
FreeBitmap(bitmap)
|
||||
}
|
||||
|
||||
if pos == nil {
|
||||
return
|
||||
}
|
||||
defer FreeMMPointArr(pos)
|
||||
|
||||
cSize := pos.count
|
||||
cArray := pos.array
|
||||
gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize]
|
||||
for i := 0; i < len(gSlice); i++ {
|
||||
posArr = append(posArr, Point{
|
||||
X: int(gSlice[i].x),
|
||||
Y: int(gSlice[i].y),
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CountColor count bitmap color
|
||||
func CountColor(color CHex, args ...interface{}) int {
|
||||
var (
|
||||
tolerance C.float = 0.01
|
||||
bitmap C.MMBitmapRef
|
||||
)
|
||||
|
||||
if len(args) > 0 && args[0] != nil {
|
||||
bitmap = args[0].(C.MMBitmapRef)
|
||||
} else {
|
||||
bitmap = CaptureScreen()
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
tolerance = C.float(args[1].(float64))
|
||||
}
|
||||
|
||||
count := C.bitmap_count_of_color(bitmap, C.MMRGBHex(color), tolerance)
|
||||
if len(args) <= 0 || (len(args) > 0 && args[0] == nil) {
|
||||
FreeBitmap(bitmap)
|
||||
}
|
||||
|
||||
return int(count)
|
||||
}
|
||||
|
||||
// CountColorCS count bitmap color by CaptureScreen
|
||||
func CountColorCS(color CHex, x, y, w, h int, args ...float64) int {
|
||||
var tolerance = 0.01
|
||||
|
||||
if len(args) > 0 {
|
||||
tolerance = args[0]
|
||||
}
|
||||
|
||||
bitmap := CaptureScreen(x, y, w, h)
|
||||
rx := CountColor(color, bitmap, tolerance)
|
||||
FreeBitmap(bitmap)
|
||||
|
||||
return rx
|
||||
}
|
||||
|
||||
// GetImgSize get the image size
|
||||
func GetImgSize(imgPath string) (int, int) {
|
||||
bitmap := OpenBitmap(imgPath)
|
||||
gbit := ToBitmap(bitmap)
|
||||
|
||||
w := gbit.Width / 2
|
||||
h := gbit.Height / 2
|
||||
FreeBitmap(bitmap)
|
||||
|
||||
return w, h
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
// #ifndef BITMAP_CLASS_H
|
||||
// #define BITMAP_CLASS_H
|
||||
|
||||
#include "../base/MMBitmap.h"
|
||||
|
||||
/* This file defines the class "Bitmap" for dealing with raw bitmaps. */
|
||||
struct _BitmapObject {
|
||||
MMBitmapRef bitmap;
|
||||
MMPoint point; /* For iterator */
|
||||
};
|
||||
|
||||
typedef struct _BitmapObject BitmapObject;
|
||||
|
||||
// extern PyTypeObject Bitmap_Type;
|
||||
|
||||
/* Returns a newly-initialized BitmapObject from the given MMBitmap.
|
||||
* The reference to |bitmap| is "stolen"; i.e., only the pointer is copied, and
|
||||
* the reponsibility for free()'ing the buffer is given to the |BitmapObject|.
|
||||
*
|
||||
* Remember to call PyType_Ready() before using this for the first time! */
|
||||
BitmapObject BitmapObject_FromMMBitmap(MMBitmapRef bitmap);
|
||||
|
||||
// #endif /* PY_BITMAP_CLASS_H */
|
@ -1,55 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef BITMAP_H
|
||||
#define BITMAP_H
|
||||
|
||||
// #include "../base/types.h"
|
||||
#include "../base/MMBitmap.h"
|
||||
#include "../base/MMPointArray_c.h"
|
||||
|
||||
/* Convenience wrapper around findBitmapInRect(), where |rect| is the bounds
|
||||
* of |haystack|. */
|
||||
#define findBitmapInBitmap(needle, haystack, pointPtr, tol) \
|
||||
findBitmapInRect(needle, haystack, pointPtr, MMBitmapGetBounds(haystack), tol)
|
||||
|
||||
/* Returns 0 and sets |point| to the origin of |needle| in |haystack| if
|
||||
* |needle| was found in |haystack| inside of |rect|, or returns -1 if not.
|
||||
*
|
||||
* |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the
|
||||
* colors in the bitmaps need to match, with 0 being exact and 1 being any.
|
||||
*/
|
||||
int findBitmapInRect(MMBitmapRef needle, MMBitmapRef haystack,
|
||||
MMPoint *point, MMRect rect, float tolerance);
|
||||
|
||||
/* Convenience wrapper around findAllBitmapInRect(), where |rect| is the bounds
|
||||
* of |haystack|. */
|
||||
#define findAllBitmapInBitmap(needle, haystack, tolerance) \
|
||||
findAllBitmapInRect(needle, haystack, \
|
||||
MMBitmapGetBounds(haystack), tolerance)
|
||||
|
||||
/* Returns MMPointArray of all occurrences of |needle| in |haystack| inside of
|
||||
* |rect|. Note that an is returned regardless of whether |needle| was found;
|
||||
* check array->count to see if it actually was.
|
||||
*
|
||||
* |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the
|
||||
* colors in the bitmaps need to match, with 0 being exact and 1 being any.
|
||||
*
|
||||
* Responsibility for freeing the MMPointArray with destroyMMPointArray() is
|
||||
* given to the caller.
|
||||
*/
|
||||
MMPointArrayRef findAllBitmapInRect(MMBitmapRef needle, MMBitmapRef haystack,
|
||||
MMRect rect, float tolerance);
|
||||
|
||||
// #define MMRGBHexAtPoint(image, x, y) \
|
||||
// hexFromMMRGB(MMRGBColorAtPoint(image, x, y))
|
||||
|
||||
/* Convenience wrapper around countOfBitmapInRect(), where |rect| is the bounds
|
||||
* of |haystack|. */
|
||||
#define countOfBitmapInBitmap(needle, haystack, tolerance) \
|
||||
countOfBitmapInRect(needle, haystack, MMBitmapGetBounds(haystack), tolerance)
|
||||
|
||||
/* Returns the number of occurences of |needle| in |haystack| inside
|
||||
* of |rect|. */
|
||||
size_t countOfBitmapInRect(MMBitmapRef needle, MMBitmapRef haystack,
|
||||
MMRect rect, float tolerance);
|
||||
|
||||
#endif /* BITMAP_H */
|
@ -1,270 +0,0 @@
|
||||
#include "bitmap_find.h"
|
||||
#include "../base/UTHashTable_c.h"
|
||||
#include <assert.h>
|
||||
|
||||
/* Node to be used in hash table. */
|
||||
struct shiftNode {
|
||||
UTHashNode_HEAD /* Make structure hashable */
|
||||
MMRGBHex color; /* Key */
|
||||
MMPoint offset; /* Value */
|
||||
};
|
||||
|
||||
/* --- Hash table helper functions --- */
|
||||
|
||||
/* Adds hex-color/offset pair to jump table. */
|
||||
static void addNodeToTable(UTHashTable *table, MMRGBHex color, MMPoint offset);
|
||||
|
||||
/* Returns node associated with color in jump table, or NULL if it
|
||||
* doesn't exist. */
|
||||
static struct shiftNode *nodeForColor(UTHashTable *table, MMRGBHex color);
|
||||
|
||||
/* Returns nonzero (true) if table has key, or zero (false) if not. */
|
||||
#define tableHasKey(table, color) (nodeForColor(table, color) != NULL)
|
||||
|
||||
/* --- Boyer-Moore helper functions --- */
|
||||
|
||||
/* Calculates the first table for use in a Boyer-Moore search algorithm.
|
||||
* Table is in the form [colors: shift_values], where colors are those in
|
||||
* |needle|, and the shift values are each color's distance from the rightmost
|
||||
* offset. All other colors are assumed to have a shift value equal to the
|
||||
* length of needle.
|
||||
*/
|
||||
static void initBadShiftTable(UTHashTable *jumpTable, MMBitmapRef needle);
|
||||
|
||||
/* Frees memory occupied by calling initBadShiftTable().
|
||||
* Currently this is just an alias for destroyHashTable(). */
|
||||
#define destroyBadShiftTable(jumpTable) destroyHashTable(jumpTable)
|
||||
|
||||
/* Returns true if |needle| is found in |haystack| at |offset|. */
|
||||
static int needleAtOffset(MMBitmapRef needle, MMBitmapRef haystack,
|
||||
MMPoint offset, float tolerance);
|
||||
/* --- --- */
|
||||
|
||||
/* An modification of the Boyer-Moore-Horspool Algorithm, only applied to
|
||||
* bitmaps and colors instead of strings and characters.
|
||||
*
|
||||
* TODO: The Boyer-Moore algorithm (with the second jump table) would probably
|
||||
* be more efficient, but this was simpler (for now).
|
||||
*
|
||||
* The jump table (|badShiftTable|) is passed as a parameter to avoid being
|
||||
* recalculated each time. It should be a pointer to a UTHashTable init'd with
|
||||
* initBadShiftTable().
|
||||
*
|
||||
* Returns 0 and sets |point| to the starting point of |needle| in |haystack|
|
||||
* if |needle| was found in |haystack|, or returns -1 if not. */
|
||||
static int findBitmapInRectAt(MMBitmapRef needle,
|
||||
MMBitmapRef haystack,
|
||||
MMPoint *point,
|
||||
MMRect rect,
|
||||
float tolerance,
|
||||
MMPoint startPoint,
|
||||
UTHashTable *badShiftTable)
|
||||
{
|
||||
const size_t scanHeight = rect.size.height - needle->height;
|
||||
const size_t scanWidth = rect.size.width - needle->width;
|
||||
MMPoint pointOffset = startPoint;
|
||||
/* const MMPoint lastPoint = MMPointMake(needle->width - 1, needle->height - 1); */
|
||||
|
||||
/* Sanity check */
|
||||
if (needle->height > haystack->height || needle->width > haystack->width ||
|
||||
!MMBitmapRectInBounds(haystack, rect)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(point != NULL);
|
||||
assert(needle != NULL);
|
||||
assert(needle->height > 0 && needle->width > 0);
|
||||
assert(haystack != NULL);
|
||||
assert(haystack->height > 0 && haystack->width > 0);
|
||||
assert(badShiftTable != NULL);
|
||||
|
||||
/* Search |haystack|, while |needle| can still be within it. */
|
||||
while (pointOffset.y <= scanHeight) {
|
||||
/* struct shiftNode *node = NULL;
|
||||
MMRGBHex lastColor; */
|
||||
|
||||
while (pointOffset.x <= scanWidth) {
|
||||
/* Check offset in |haystack| for |needle|. */
|
||||
if (needleAtOffset(needle, haystack, pointOffset, tolerance)) {
|
||||
// ++pointOffset.x;
|
||||
// ++pointOffset.y;
|
||||
*point = pointOffset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Otherwise, calculate next x offset to check. */
|
||||
/*
|
||||
* Note that here we are getting the skip value based on the last
|
||||
* color of |needle|, no matter where we didn't match. The
|
||||
* alternative of pretending that the mismatched color was the previous
|
||||
* color is slower in the normal case.
|
||||
*/
|
||||
/* lastColor = MMRGBHexAtPoint(haystack, pointOffset.x + lastPoint.x,
|
||||
pointOffset.y + lastPoint.y); */
|
||||
|
||||
/* TODO: This fails on certain edge cases (issue#7). */
|
||||
/* When a color is encountered that does not occur in |needle|, we can
|
||||
* safely skip ahead for the whole length of |needle|.
|
||||
* Otherwise, use the value stored in the jump table. */
|
||||
/* node = nodeForColor(badShiftTable, lastColor);
|
||||
pointOffset.x += (node == NULL) ? needle->width : (node->offset).x; */
|
||||
|
||||
/* For now, be naive. */
|
||||
++pointOffset.x;
|
||||
}
|
||||
|
||||
pointOffset.x = rect.origin.x;
|
||||
|
||||
/* lastColor = MMRGBHexAtPoint(haystack, pointOffset.x + lastPoint.x,
|
||||
pointOffset.y + lastPoint.y);
|
||||
node = nodeForColor(badShiftTable, lastColor);
|
||||
pointOffset.y += node == NULL ? lastPoint.y : (node->offset).y; */
|
||||
|
||||
/* TODO: The above commented out code fails at certain edge cases, e.g.:
|
||||
* Needle: [B, b
|
||||
* b, b,
|
||||
* B, b]
|
||||
* Haystack: [w, w, w, w, w
|
||||
* w, w, w, w, b
|
||||
* w, w, w, b, b
|
||||
* w, w, w, w, b]
|
||||
* The previous algorithm noticed that the first 3 x 3 block had nothing
|
||||
* in common with the image, and thus, after scanning the first row,
|
||||
* skipped three blocks downward to scan the next (which didn't exist,
|
||||
* so the loop ended). However, the needle was hidden IN-BETWEEN this
|
||||
* jump -- skipping was appropriate for scanning the column but not
|
||||
* the row.
|
||||
*
|
||||
* I need to figure out a more optimal solution; temporarily I am just
|
||||
* scanning every single y coordinate, only skipping on x's. This
|
||||
* always works, but is probably not optimal.
|
||||
*/
|
||||
++pointOffset.y;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int findBitmapInRect(MMBitmapRef needle,
|
||||
MMBitmapRef haystack,
|
||||
MMPoint *point,
|
||||
MMRect rect,
|
||||
float tolerance)
|
||||
{
|
||||
UTHashTable badShiftTable;
|
||||
int ret;
|
||||
|
||||
initBadShiftTable(&badShiftTable, needle);
|
||||
ret = findBitmapInRectAt(needle, haystack, point, rect,
|
||||
tolerance, MMPointZero, &badShiftTable);
|
||||
destroyBadShiftTable(&badShiftTable);
|
||||
return ret;
|
||||
}
|
||||
|
||||
MMPointArrayRef findAllBitmapInRect(MMBitmapRef needle, MMBitmapRef haystack,
|
||||
MMRect rect, float tolerance)
|
||||
{
|
||||
MMPointArrayRef pointArray = createMMPointArray(0);
|
||||
MMPoint point = MMPointZero;
|
||||
UTHashTable badShiftTable;
|
||||
|
||||
initBadShiftTable(&badShiftTable, needle);
|
||||
while (findBitmapInRectAt(needle, haystack, &point, rect,
|
||||
tolerance, point, &badShiftTable) == 0) {
|
||||
const size_t scanWidth = (haystack->width - needle->width) + 1;
|
||||
MMPointArrayAppendPoint(pointArray, point);
|
||||
ITER_NEXT_POINT(point, scanWidth, 0);
|
||||
}
|
||||
destroyBadShiftTable(&badShiftTable);
|
||||
|
||||
return pointArray;
|
||||
}
|
||||
|
||||
size_t countOfBitmapInRect(MMBitmapRef needle, MMBitmapRef haystack,
|
||||
MMRect rect, float tolerance)
|
||||
{
|
||||
size_t count = 0;
|
||||
MMPoint point = MMPointZero;
|
||||
UTHashTable badShiftTable;
|
||||
|
||||
initBadShiftTable(&badShiftTable, needle);
|
||||
while (findBitmapInRectAt(needle, haystack, &point, rect,
|
||||
tolerance, point, &badShiftTable) == 0) {
|
||||
const size_t scanWidth = (haystack->width - needle->width) + 1;
|
||||
++count;
|
||||
ITER_NEXT_POINT(point, scanWidth, 0);
|
||||
}
|
||||
destroyBadShiftTable(&badShiftTable);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* --- Boyer-Moore helper functions --- */
|
||||
|
||||
static void initBadShiftTable(UTHashTable *jumpTable, MMBitmapRef needle)
|
||||
{
|
||||
const MMPoint lastPoint = MMPointMake(needle->width - 1, needle->height - 1);
|
||||
const size_t maxColors = needle->width * needle->height;
|
||||
MMPoint scan;
|
||||
|
||||
/* Allocate max size initially to avoid a million calls to malloc(). */
|
||||
initHashTable(jumpTable, maxColors, sizeof(struct shiftNode));
|
||||
|
||||
/* Populate jumpTable with analysis of |needle|. */
|
||||
for (scan.y = lastPoint.y; ; --scan.y) {
|
||||
for (scan.x = lastPoint.x; ; --scan.x) {
|
||||
MMRGBHex color = MMRGBHexAtPoint(needle, scan.x, scan.y);
|
||||
if (!tableHasKey(jumpTable, color)) {
|
||||
addNodeToTable(jumpTable, color,
|
||||
MMPointMake(needle->width - scan.x,
|
||||
needle->height - scan.y));
|
||||
}
|
||||
|
||||
if (scan.x == 0) break; /* Avoid infinite loop from unsigned type. */
|
||||
}
|
||||
if (scan.y == 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
static int needleAtOffset(MMBitmapRef needle, MMBitmapRef haystack,
|
||||
MMPoint offset, float tolerance)
|
||||
{
|
||||
const MMPoint lastPoint = MMPointMake(needle->width - 1, needle->height - 1);
|
||||
MMPoint scan;
|
||||
|
||||
/* Note that |needle| is searched backwards, in accordance with the
|
||||
* Boyer-Moore search algorithm. */
|
||||
for (scan.y = lastPoint.y; ; --scan.y) {
|
||||
for (scan.x = lastPoint.x; ; --scan.x) {
|
||||
MMRGBHex ncolor = MMRGBHexAtPoint(needle, scan.x, scan.y);
|
||||
MMRGBHex hcolor = MMRGBHexAtPoint(haystack, offset.x + scan.x,
|
||||
offset.y + scan.y);
|
||||
if (!MMRGBHexSimilarToColor(ncolor, hcolor, tolerance)) return 0;
|
||||
if (scan.x == 0) break; /* Avoid infinite loop from unsigned type. */
|
||||
}
|
||||
if (scan.y == 0) break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* --- Hash table helper functions --- */
|
||||
|
||||
static void addNodeToTable(UTHashTable *table,
|
||||
MMRGBHex hexColor,
|
||||
MMPoint offset)
|
||||
{
|
||||
struct shiftNode *node = getNewNode(table);
|
||||
node->color = hexColor;
|
||||
node->offset = offset;
|
||||
UTHASHTABLE_ADD_INT(table, color, node, struct shiftNode);
|
||||
}
|
||||
|
||||
static struct shiftNode *nodeForColor(UTHashTable *table,
|
||||
MMRGBHex color)
|
||||
{
|
||||
struct shiftNode *uttable = table->uttable;
|
||||
struct shiftNode *node;
|
||||
HASH_FIND_INT(uttable, &color, node);
|
||||
return node;
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#include "bitmap_class.h"
|
||||
#include "bitmap_find_c.h"
|
||||
#include "../base/color_find_c.h"
|
||||
// #include "../screen/screen_c.h"
|
||||
#include "../base/file_io_c.h"
|
||||
#include "../base/pasteboard_c.h"
|
||||
#include "../base/str_io_c.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Returns false and sets error if |bitmap| is NULL. */
|
||||
bool bitmap_ready(MMBitmapRef bitmap){
|
||||
if (bitmap == NULL || bitmap->imageBuffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// void bitmap_dealloc(MMBitmapRef bitmap){
|
||||
// if (bitmap != NULL) {
|
||||
// destroyMMBitmap(bitmap);
|
||||
// bitmap = NULL;
|
||||
// }
|
||||
// }
|
||||
|
||||
bool bitmap_copy_to_pboard(MMBitmapRef bitmap){
|
||||
MMPasteError err;
|
||||
|
||||
if (!bitmap_ready(bitmap)) return false;
|
||||
if ((err = copyMMBitmapToPasteboard(bitmap)) != kMMPasteNoError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MMBitmapRef bitmap_deepcopy(MMBitmapRef bitmap){
|
||||
return bitmap == NULL ? NULL : copyMMBitmap(bitmap);
|
||||
}
|
||||
|
||||
MMPoint find_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance){
|
||||
MMPoint point = {-1, -1};
|
||||
// printf("tolenrance=%f\n", tolerance);
|
||||
if (!bitmap_ready(sbit) || !bitmap_ready(bitmap)) {
|
||||
printf("bitmap is not ready yet!\n");
|
||||
return point;
|
||||
}
|
||||
|
||||
MMRect rect = MMBitmapGetBounds(sbit);
|
||||
// printf("x=%d, y=%d, width=%d, height=%d\n", rect.origin.x,
|
||||
// rect.origin.y, rect.size.width, rect.size.height);
|
||||
|
||||
if (findBitmapInRect(bitmap, sbit, &point, rect, tolerance) == 0) {
|
||||
return point;
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
MMPointArrayRef find_every_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance, MMPoint *list){
|
||||
if (!bitmap_ready(bitmap) || !bitmap_ready(sbit)) { return NULL; }
|
||||
|
||||
MMPoint point;
|
||||
MMPointArrayRef pointArray;
|
||||
MMRect rect = MMBitmapGetBounds(sbit);
|
||||
|
||||
if (findBitmapInRect(bitmap, sbit, &point, rect, tolerance) == 0) {
|
||||
// return NULL;
|
||||
}
|
||||
|
||||
pointArray = findAllBitmapInRect(bitmap, sbit, rect, tolerance);
|
||||
return pointArray;
|
||||
}
|
||||
|
||||
int count_of_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance){
|
||||
if (!bitmap_ready(bitmap) || !bitmap_ready(sbit)) { return 0; }
|
||||
|
||||
MMRect rect = MMBitmapGetBounds(bitmap);
|
||||
return countOfBitmapInRect(bitmap, sbit, rect, tolerance);
|
||||
}
|
||||
|
||||
bool point_in_bounds(MMBitmapRef bitmap, MMPoint point){
|
||||
if (!bitmap_ready(bitmap)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (MMBitmapPointInBounds(bitmap, point)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MMBitmapRef bitmap_open(char *path, uint16_t ttype){
|
||||
// MMImageType type;
|
||||
MMBitmapRef bitmap;
|
||||
MMIOError err;
|
||||
|
||||
bitmap = newMMBitmapFromFile(path, ttype, &err);
|
||||
// printf("....%zd\n", bitmap->width);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
MMBitmapRef bitmap_from_string(const char *str){
|
||||
size_t len = strlen(str);
|
||||
|
||||
MMBitmapRef bitmap;
|
||||
MMBMPStringError err;
|
||||
|
||||
if ((bitmap = createMMBitmapFromString((unsigned char*)str, len, &err))
|
||||
== NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
char *bitmap_save(MMBitmapRef bitmap, char *path, uint16_t type){
|
||||
if (saveMMBitmapToFile(bitmap, path, (MMImageType) type) != 0) {
|
||||
return "Could not save image to file.";
|
||||
}
|
||||
// destroyMMBitmap(bitmap);
|
||||
return "";
|
||||
}
|
||||
|
||||
char *tostring_bitmap(MMBitmapRef bitmap){
|
||||
char *buf = NULL;
|
||||
MMBMPStringError err;
|
||||
|
||||
buf = (char *)createStringFromMMBitmap(bitmap, &err);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// char out size 200 is enough
|
||||
bool bitmap_str(MMBitmapRef bitmap, char *out){
|
||||
if (!bitmap_ready(bitmap)) { return false; }
|
||||
sprintf(out, "<Bitmap with resolution %lu%lu, \
|
||||
%u bits per pixel, and %u bytes per pixel>",
|
||||
(unsigned long)bitmap->width,
|
||||
(unsigned long)bitmap->height,
|
||||
bitmap->bitsPerPixel,
|
||||
bitmap->bytesPerPixel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MMBitmapRef get_portion(MMBitmapRef bit_map, MMRect rect){
|
||||
// MMRect rect;
|
||||
MMBitmapRef portion = NULL;
|
||||
|
||||
portion = copyMMBitmapFromPortion(bit_map, rect);
|
||||
return portion;
|
||||
}
|
||||
|
||||
MMRGBHex bitmap_get_color(MMBitmapRef bitmap, size_t x, size_t y){
|
||||
if (!bitmap_ready(bitmap)) { return 0; }
|
||||
|
||||
MMPoint point;
|
||||
point = MMPointMake(x, y);
|
||||
|
||||
if (!MMBitmapPointInBounds(bitmap, point)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return MMRGBHexAtPoint(bitmap, point.x, point.y);
|
||||
}
|
||||
|
||||
MMPoint bitmap_find_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance){
|
||||
MMRect rect = MMBitmapGetBounds(bitmap);
|
||||
MMPoint point = {-1, -1};
|
||||
|
||||
if (findColorInRect(bitmap, color, &point, rect, tolerance) == 0) {
|
||||
return point;
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
MMPointArrayRef bitmap_find_every_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance, MMPoint *list){
|
||||
if (!bitmap_ready(bitmap)) { return NULL; }
|
||||
MMRect rect = MMBitmapGetBounds(bitmap);
|
||||
MMPointArrayRef pointArray;
|
||||
|
||||
pointArray = findAllColorInRect(bitmap, color, rect, tolerance);
|
||||
return pointArray;
|
||||
}
|
||||
|
||||
int bitmap_count_of_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance){
|
||||
if (!bitmap_ready(bitmap)) return 0;
|
||||
MMRect rect = MMBitmapGetBounds(bitmap);
|
||||
|
||||
return countOfColorsInRect(bitmap, color, rect, tolerance);
|
||||
}
|
@ -1 +0,0 @@
|
||||
C language dependent package, better to compilation. ( zlib and libpng )
|
Binary file not shown.
Binary file not shown.
3278
cdeps/mac/png.h
3278
cdeps/mac/png.h
File diff suppressed because it is too large
Load Diff
@ -1,622 +0,0 @@
|
||||
|
||||
/* pngconf.h - machine configurable file for libpng
|
||||
*
|
||||
* libpng version 1.6.34, September 29, 2017
|
||||
*
|
||||
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*
|
||||
* Any machine specific code is near the front of this file, so if you
|
||||
* are configuring libpng for a machine, you may want to read the section
|
||||
* starting here down to where it starts to typedef png_color, png_text,
|
||||
* and png_info.
|
||||
*/
|
||||
|
||||
#ifndef PNGCONF_H
|
||||
#define PNGCONF_H
|
||||
|
||||
#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */
|
||||
|
||||
/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C
|
||||
* compiler for correct compilation. The following header files are required by
|
||||
* the standard. If your compiler doesn't provide these header files, or they
|
||||
* do not match the standard, you will need to provide/improve them.
|
||||
*/
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Library header files. These header files are all defined by ISOC90; libpng
|
||||
* expects conformant implementations, however, an ISOC90 conformant system need
|
||||
* not provide these header files if the functionality cannot be implemented.
|
||||
* In this case it will be necessary to disable the relevant parts of libpng in
|
||||
* the build of pnglibconf.h.
|
||||
*
|
||||
* Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not
|
||||
* include this unnecessary header file.
|
||||
*/
|
||||
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
/* Required for the definition of FILE: */
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef PNG_SETJMP_SUPPORTED
|
||||
/* Required for the definition of jmp_buf and the declaration of longjmp: */
|
||||
# include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef PNG_CONVERT_tIME_SUPPORTED
|
||||
/* Required for struct tm: */
|
||||
# include <time.h>
|
||||
#endif
|
||||
|
||||
#endif /* PNG_BUILDING_SYMBOL_TABLE */
|
||||
|
||||
/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using
|
||||
* PNG_NO_CONST; this is no longer supported except for data declarations which
|
||||
* apparently still cause problems in 2011 on some compilers.
|
||||
*/
|
||||
#define PNG_CONST const /* backward compatibility only */
|
||||
|
||||
/* This controls optimization of the reading of 16-bit and 32-bit values
|
||||
* from PNG files. It can be set on a per-app-file basis - it
|
||||
* just changes whether a macro is used when the function is called.
|
||||
* The library builder sets the default; if read functions are not
|
||||
* built into the library the macro implementation is forced on.
|
||||
*/
|
||||
#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED
|
||||
# define PNG_USE_READ_MACROS
|
||||
#endif
|
||||
#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS)
|
||||
# if PNG_DEFAULT_READ_MACROS
|
||||
# define PNG_USE_READ_MACROS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* COMPILER SPECIFIC OPTIONS.
|
||||
*
|
||||
* These options are provided so that a variety of difficult compilers
|
||||
* can be used. Some are fixed at build time (e.g. PNG_API_RULE
|
||||
* below) but still have compiler specific implementations, others
|
||||
* may be changed on a per-file basis when compiling against libpng.
|
||||
*/
|
||||
|
||||
/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect
|
||||
* against legacy (pre ISOC90) compilers that did not understand function
|
||||
* prototypes. It is not required for modern C compilers.
|
||||
*/
|
||||
#ifndef PNGARG
|
||||
# define PNGARG(arglist) arglist
|
||||
#endif
|
||||
|
||||
/* Function calling conventions.
|
||||
* =============================
|
||||
* Normally it is not necessary to specify to the compiler how to call
|
||||
* a function - it just does it - however on x86 systems derived from
|
||||
* Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems
|
||||
* and some others) there are multiple ways to call a function and the
|
||||
* default can be changed on the compiler command line. For this reason
|
||||
* libpng specifies the calling convention of every exported function and
|
||||
* every function called via a user supplied function pointer. This is
|
||||
* done in this file by defining the following macros:
|
||||
*
|
||||
* PNGAPI Calling convention for exported functions.
|
||||
* PNGCBAPI Calling convention for user provided (callback) functions.
|
||||
* PNGCAPI Calling convention used by the ANSI-C library (required
|
||||
* for longjmp callbacks and sometimes used internally to
|
||||
* specify the calling convention for zlib).
|
||||
*
|
||||
* These macros should never be overridden. If it is necessary to
|
||||
* change calling convention in a private build this can be done
|
||||
* by setting PNG_API_RULE (which defaults to 0) to one of the values
|
||||
* below to select the correct 'API' variants.
|
||||
*
|
||||
* PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout.
|
||||
* This is correct in every known environment.
|
||||
* PNG_API_RULE=1 Use the operating system convention for PNGAPI and
|
||||
* the 'C' calling convention (from PNGCAPI) for
|
||||
* callbacks (PNGCBAPI). This is no longer required
|
||||
* in any known environment - if it has to be used
|
||||
* please post an explanation of the problem to the
|
||||
* libpng mailing list.
|
||||
*
|
||||
* These cases only differ if the operating system does not use the C
|
||||
* calling convention, at present this just means the above cases
|
||||
* (x86 DOS/Windows sytems) and, even then, this does not apply to
|
||||
* Cygwin running on those systems.
|
||||
*
|
||||
* Note that the value must be defined in pnglibconf.h so that what
|
||||
* the application uses to call the library matches the conventions
|
||||
* set when building the library.
|
||||
*/
|
||||
|
||||
/* Symbol export
|
||||
* =============
|
||||
* When building a shared library it is almost always necessary to tell
|
||||
* the compiler which symbols to export. The png.h macro 'PNG_EXPORT'
|
||||
* is used to mark the symbols. On some systems these symbols can be
|
||||
* extracted at link time and need no special processing by the compiler,
|
||||
* on other systems the symbols are flagged by the compiler and just
|
||||
* the declaration requires a special tag applied (unfortunately) in a
|
||||
* compiler dependent way. Some systems can do either.
|
||||
*
|
||||
* A small number of older systems also require a symbol from a DLL to
|
||||
* be flagged to the program that calls it. This is a problem because
|
||||
* we do not know in the header file included by application code that
|
||||
* the symbol will come from a shared library, as opposed to a statically
|
||||
* linked one. For this reason the application must tell us by setting
|
||||
* the magic flag PNG_USE_DLL to turn on the special processing before
|
||||
* it includes png.h.
|
||||
*
|
||||
* Four additional macros are used to make this happen:
|
||||
*
|
||||
* PNG_IMPEXP The magic (if any) to cause a symbol to be exported from
|
||||
* the build or imported if PNG_USE_DLL is set - compiler
|
||||
* and system specific.
|
||||
*
|
||||
* PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to
|
||||
* 'type', compiler specific.
|
||||
*
|
||||
* PNG_DLL_EXPORT Set to the magic to use during a libpng build to
|
||||
* make a symbol exported from the DLL. Not used in the
|
||||
* public header files; see pngpriv.h for how it is used
|
||||
* in the libpng build.
|
||||
*
|
||||
* PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come
|
||||
* from a DLL - used to define PNG_IMPEXP when
|
||||
* PNG_USE_DLL is set.
|
||||
*/
|
||||
|
||||
/* System specific discovery.
|
||||
* ==========================
|
||||
* This code is used at build time to find PNG_IMPEXP, the API settings
|
||||
* and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL
|
||||
* import processing is possible. On Windows systems it also sets
|
||||
* compiler-specific macros to the values required to change the calling
|
||||
* conventions of the various functions.
|
||||
*/
|
||||
#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
|
||||
defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
|
||||
/* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or
|
||||
* MinGW on any architecture currently supported by Windows. Also includes
|
||||
* Watcom builds but these need special treatment because they are not
|
||||
* compatible with GCC or Visual C because of different calling conventions.
|
||||
*/
|
||||
# if PNG_API_RULE == 2
|
||||
/* If this line results in an error, either because __watcall is not
|
||||
* understood or because of a redefine just below you cannot use *this*
|
||||
* build of the library with the compiler you are using. *This* build was
|
||||
* build using Watcom and applications must also be built using Watcom!
|
||||
*/
|
||||
# define PNGCAPI __watcall
|
||||
# endif
|
||||
|
||||
# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800))
|
||||
# define PNGCAPI __cdecl
|
||||
# if PNG_API_RULE == 1
|
||||
/* If this line results in an error __stdcall is not understood and
|
||||
* PNG_API_RULE should not have been set to '1'.
|
||||
*/
|
||||
# define PNGAPI __stdcall
|
||||
# endif
|
||||
# else
|
||||
/* An older compiler, or one not detected (erroneously) above,
|
||||
* if necessary override on the command line to get the correct
|
||||
* variants for the compiler.
|
||||
*/
|
||||
# ifndef PNGCAPI
|
||||
# define PNGCAPI _cdecl
|
||||
# endif
|
||||
# if PNG_API_RULE == 1 && !defined(PNGAPI)
|
||||
# define PNGAPI _stdcall
|
||||
# endif
|
||||
# endif /* compiler/api */
|
||||
|
||||
/* NOTE: PNGCBAPI always defaults to PNGCAPI. */
|
||||
|
||||
# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD)
|
||||
# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed"
|
||||
# endif
|
||||
|
||||
# if (defined(_MSC_VER) && _MSC_VER < 800) ||\
|
||||
(defined(__BORLANDC__) && __BORLANDC__ < 0x500)
|
||||
/* older Borland and MSC
|
||||
* compilers used '__export' and required this to be after
|
||||
* the type.
|
||||
*/
|
||||
# ifndef PNG_EXPORT_TYPE
|
||||
# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP
|
||||
# endif
|
||||
# define PNG_DLL_EXPORT __export
|
||||
# else /* newer compiler */
|
||||
# define PNG_DLL_EXPORT __declspec(dllexport)
|
||||
# ifndef PNG_DLL_IMPORT
|
||||
# define PNG_DLL_IMPORT __declspec(dllimport)
|
||||
# endif
|
||||
# endif /* compiler */
|
||||
|
||||
#else /* !Windows */
|
||||
# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
|
||||
# define PNGAPI _System
|
||||
# else /* !Windows/x86 && !OS/2 */
|
||||
/* Use the defaults, or define PNG*API on the command line (but
|
||||
* this will have to be done for every compile!)
|
||||
*/
|
||||
# endif /* other system, !OS/2 */
|
||||
#endif /* !Windows/x86 */
|
||||
|
||||
/* Now do all the defaulting . */
|
||||
#ifndef PNGCAPI
|
||||
# define PNGCAPI
|
||||
#endif
|
||||
#ifndef PNGCBAPI
|
||||
# define PNGCBAPI PNGCAPI
|
||||
#endif
|
||||
#ifndef PNGAPI
|
||||
# define PNGAPI PNGCAPI
|
||||
#endif
|
||||
|
||||
/* PNG_IMPEXP may be set on the compilation system command line or (if not set)
|
||||
* then in an internal header file when building the library, otherwise (when
|
||||
* using the library) it is set here.
|
||||
*/
|
||||
#ifndef PNG_IMPEXP
|
||||
# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT)
|
||||
/* This forces use of a DLL, disallowing static linking */
|
||||
# define PNG_IMPEXP PNG_DLL_IMPORT
|
||||
# endif
|
||||
|
||||
# ifndef PNG_IMPEXP
|
||||
# define PNG_IMPEXP
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat
|
||||
* 'attributes' as a storage class - the attributes go at the start of the
|
||||
* function definition, and attributes are always appended regardless of the
|
||||
* compiler. This considerably simplifies these macros but may cause problems
|
||||
* if any compilers both need function attributes and fail to handle them as
|
||||
* a storage class (this is unlikely.)
|
||||
*/
|
||||
#ifndef PNG_FUNCTION
|
||||
# define PNG_FUNCTION(type, name, args, attributes) attributes type name args
|
||||
#endif
|
||||
|
||||
#ifndef PNG_EXPORT_TYPE
|
||||
# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type
|
||||
#endif
|
||||
|
||||
/* The ordinal value is only relevant when preprocessing png.h for symbol
|
||||
* table entries, so we discard it here. See the .dfn files in the
|
||||
* scripts directory.
|
||||
*/
|
||||
|
||||
#ifndef PNG_EXPORTA
|
||||
# define PNG_EXPORTA(ordinal, type, name, args, attributes) \
|
||||
PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \
|
||||
PNG_LINKAGE_API attributes)
|
||||
#endif
|
||||
|
||||
/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument,
|
||||
* so make something non-empty to satisfy the requirement:
|
||||
*/
|
||||
#define PNG_EMPTY /*empty list*/
|
||||
|
||||
#define PNG_EXPORT(ordinal, type, name, args) \
|
||||
PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY)
|
||||
|
||||
/* Use PNG_REMOVED to comment out a removed interface. */
|
||||
#ifndef PNG_REMOVED
|
||||
# define PNG_REMOVED(ordinal, type, name, args, attributes)
|
||||
#endif
|
||||
|
||||
#ifndef PNG_CALLBACK
|
||||
# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args)
|
||||
#endif
|
||||
|
||||
/* Support for compiler specific function attributes. These are used
|
||||
* so that where compiler support is available incorrect use of API
|
||||
* functions in png.h will generate compiler warnings.
|
||||
*
|
||||
* Added at libpng-1.2.41.
|
||||
*/
|
||||
|
||||
#ifndef PNG_NO_PEDANTIC_WARNINGS
|
||||
# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED
|
||||
# define PNG_PEDANTIC_WARNINGS_SUPPORTED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED
|
||||
/* Support for compiler specific function attributes. These are used
|
||||
* so that where compiler support is available, incorrect use of API
|
||||
* functions in png.h will generate compiler warnings. Added at libpng
|
||||
* version 1.2.41. Disabling these removes the warnings but may also produce
|
||||
* less efficient code.
|
||||
*/
|
||||
# if defined(__clang__) && defined(__has_attribute)
|
||||
/* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */
|
||||
# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__)
|
||||
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
|
||||
# endif
|
||||
# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__)
|
||||
# define PNG_NORETURN __attribute__((__noreturn__))
|
||||
# endif
|
||||
# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__)
|
||||
# define PNG_ALLOCATED __attribute__((__malloc__))
|
||||
# endif
|
||||
# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__)
|
||||
# define PNG_DEPRECATED __attribute__((__deprecated__))
|
||||
# endif
|
||||
# if !defined(PNG_PRIVATE)
|
||||
# ifdef __has_extension
|
||||
# if __has_extension(attribute_unavailable_with_message)
|
||||
# define PNG_PRIVATE __attribute__((__unavailable__(\
|
||||
"This function is not exported by libpng.")))
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
|
||||
# elif defined(__GNUC__)
|
||||
# ifndef PNG_USE_RESULT
|
||||
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
|
||||
# endif
|
||||
# ifndef PNG_NORETURN
|
||||
# define PNG_NORETURN __attribute__((__noreturn__))
|
||||
# endif
|
||||
# if __GNUC__ >= 3
|
||||
# ifndef PNG_ALLOCATED
|
||||
# define PNG_ALLOCATED __attribute__((__malloc__))
|
||||
# endif
|
||||
# ifndef PNG_DEPRECATED
|
||||
# define PNG_DEPRECATED __attribute__((__deprecated__))
|
||||
# endif
|
||||
# ifndef PNG_PRIVATE
|
||||
# if 0 /* Doesn't work so we use deprecated instead*/
|
||||
# define PNG_PRIVATE \
|
||||
__attribute__((warning("This function is not exported by libpng.")))
|
||||
# else
|
||||
# define PNG_PRIVATE \
|
||||
__attribute__((__deprecated__))
|
||||
# endif
|
||||
# endif
|
||||
# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1))
|
||||
# ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */
|
||||
# endif /* __GNUC__ >= 3 */
|
||||
|
||||
# elif defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||
# ifndef PNG_USE_RESULT
|
||||
# define PNG_USE_RESULT /* not supported */
|
||||
# endif
|
||||
# ifndef PNG_NORETURN
|
||||
# define PNG_NORETURN __declspec(noreturn)
|
||||
# endif
|
||||
# ifndef PNG_ALLOCATED
|
||||
# if (_MSC_VER >= 1400)
|
||||
# define PNG_ALLOCATED __declspec(restrict)
|
||||
# endif
|
||||
# endif
|
||||
# ifndef PNG_DEPRECATED
|
||||
# define PNG_DEPRECATED __declspec(deprecated)
|
||||
# endif
|
||||
# ifndef PNG_PRIVATE
|
||||
# define PNG_PRIVATE __declspec(deprecated)
|
||||
# endif
|
||||
# ifndef PNG_RESTRICT
|
||||
# if (_MSC_VER >= 1400)
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# elif defined(__WATCOMC__)
|
||||
# ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
# endif
|
||||
#endif /* PNG_PEDANTIC_WARNINGS */
|
||||
|
||||
#ifndef PNG_DEPRECATED
|
||||
# define PNG_DEPRECATED /* Use of this function is deprecated */
|
||||
#endif
|
||||
#ifndef PNG_USE_RESULT
|
||||
# define PNG_USE_RESULT /* The result of this function must be checked */
|
||||
#endif
|
||||
#ifndef PNG_NORETURN
|
||||
# define PNG_NORETURN /* This function does not return */
|
||||
#endif
|
||||
#ifndef PNG_ALLOCATED
|
||||
# define PNG_ALLOCATED /* The result of the function is new memory */
|
||||
#endif
|
||||
#ifndef PNG_PRIVATE
|
||||
# define PNG_PRIVATE /* This is a private libpng function */
|
||||
#endif
|
||||
#ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT /* The C99 "restrict" feature */
|
||||
#endif
|
||||
|
||||
#ifndef PNG_FP_EXPORT /* A floating point API. */
|
||||
# ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
# define PNG_FP_EXPORT(ordinal, type, name, args)\
|
||||
PNG_EXPORT(ordinal, type, name, args);
|
||||
# else /* No floating point APIs */
|
||||
# define PNG_FP_EXPORT(ordinal, type, name, args)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef PNG_FIXED_EXPORT /* A fixed point API. */
|
||||
# ifdef PNG_FIXED_POINT_SUPPORTED
|
||||
# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
|
||||
PNG_EXPORT(ordinal, type, name, args);
|
||||
# else /* No fixed point APIs */
|
||||
# define PNG_FIXED_EXPORT(ordinal, type, name, args)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef PNG_BUILDING_SYMBOL_TABLE
|
||||
/* Some typedefs to get us started. These should be safe on most of the common
|
||||
* platforms.
|
||||
*
|
||||
* png_uint_32 and png_int_32 may, currently, be larger than required to hold a
|
||||
* 32-bit value however this is not normally advisable.
|
||||
*
|
||||
* png_uint_16 and png_int_16 should always be two bytes in size - this is
|
||||
* verified at library build time.
|
||||
*
|
||||
* png_byte must always be one byte in size.
|
||||
*
|
||||
* The checks below use constants from limits.h, as defined by the ISOC90
|
||||
* standard.
|
||||
*/
|
||||
#if CHAR_BIT == 8 && UCHAR_MAX == 255
|
||||
typedef unsigned char png_byte;
|
||||
#else
|
||||
# error "libpng requires 8-bit bytes"
|
||||
#endif
|
||||
|
||||
#if INT_MIN == -32768 && INT_MAX == 32767
|
||||
typedef int png_int_16;
|
||||
#elif SHRT_MIN == -32768 && SHRT_MAX == 32767
|
||||
typedef short png_int_16;
|
||||
#else
|
||||
# error "libpng requires a signed 16-bit type"
|
||||
#endif
|
||||
|
||||
#if UINT_MAX == 65535
|
||||
typedef unsigned int png_uint_16;
|
||||
#elif USHRT_MAX == 65535
|
||||
typedef unsigned short png_uint_16;
|
||||
#else
|
||||
# error "libpng requires an unsigned 16-bit type"
|
||||
#endif
|
||||
|
||||
#if INT_MIN < -2147483646 && INT_MAX > 2147483646
|
||||
typedef int png_int_32;
|
||||
#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646
|
||||
typedef long int png_int_32;
|
||||
#else
|
||||
# error "libpng requires a signed 32-bit (or more) type"
|
||||
#endif
|
||||
|
||||
#if UINT_MAX > 4294967294U
|
||||
typedef unsigned int png_uint_32;
|
||||
#elif ULONG_MAX > 4294967294U
|
||||
typedef unsigned long int png_uint_32;
|
||||
#else
|
||||
# error "libpng requires an unsigned 32-bit (or more) type"
|
||||
#endif
|
||||
|
||||
/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however,
|
||||
* requires an ISOC90 compiler and relies on consistent behavior of sizeof.
|
||||
*/
|
||||
typedef size_t png_size_t;
|
||||
typedef ptrdiff_t png_ptrdiff_t;
|
||||
|
||||
/* libpng needs to know the maximum value of 'size_t' and this controls the
|
||||
* definition of png_alloc_size_t, below. This maximum value of size_t limits
|
||||
* but does not control the maximum allocations the library makes - there is
|
||||
* direct application control of this through png_set_user_limits().
|
||||
*/
|
||||
#ifndef PNG_SMALL_SIZE_T
|
||||
/* Compiler specific tests for systems where size_t is known to be less than
|
||||
* 32 bits (some of these systems may no longer work because of the lack of
|
||||
* 'far' support; see above.)
|
||||
*/
|
||||
# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\
|
||||
(defined(_MSC_VER) && defined(MAXSEG_64K))
|
||||
# define PNG_SMALL_SIZE_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no
|
||||
* smaller than png_uint_32. Casts from png_size_t or png_uint_32 to
|
||||
* png_alloc_size_t are not necessary; in fact, it is recommended not to use
|
||||
* them at all so that the compiler can complain when something turns out to be
|
||||
* problematic.
|
||||
*
|
||||
* Casts in the other direction (from png_alloc_size_t to png_size_t or
|
||||
* png_uint_32) should be explicitly applied; however, we do not expect to
|
||||
* encounter practical situations that require such conversions.
|
||||
*
|
||||
* PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than
|
||||
* 4294967295 - i.e. less than the maximum value of png_uint_32.
|
||||
*/
|
||||
#ifdef PNG_SMALL_SIZE_T
|
||||
typedef png_uint_32 png_alloc_size_t;
|
||||
#else
|
||||
typedef png_size_t png_alloc_size_t;
|
||||
#endif
|
||||
|
||||
/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler
|
||||
* implementations of Intel CPU specific support of user-mode segmented address
|
||||
* spaces, where 16-bit pointers address more than 65536 bytes of memory using
|
||||
* separate 'segment' registers. The implementation requires two different
|
||||
* types of pointer (only one of which includes the segment value.)
|
||||
*
|
||||
* If required this support is available in version 1.2 of libpng and may be
|
||||
* available in versions through 1.5, although the correctness of the code has
|
||||
* not been verified recently.
|
||||
*/
|
||||
|
||||
/* Typedef for floating-point numbers that are converted to fixed-point with a
|
||||
* multiple of 100,000, e.g., gamma
|
||||
*/
|
||||
typedef png_int_32 png_fixed_point;
|
||||
|
||||
/* Add typedefs for pointers */
|
||||
typedef void * png_voidp;
|
||||
typedef const void * png_const_voidp;
|
||||
typedef png_byte * png_bytep;
|
||||
typedef const png_byte * png_const_bytep;
|
||||
typedef png_uint_32 * png_uint_32p;
|
||||
typedef const png_uint_32 * png_const_uint_32p;
|
||||
typedef png_int_32 * png_int_32p;
|
||||
typedef const png_int_32 * png_const_int_32p;
|
||||
typedef png_uint_16 * png_uint_16p;
|
||||
typedef const png_uint_16 * png_const_uint_16p;
|
||||
typedef png_int_16 * png_int_16p;
|
||||
typedef const png_int_16 * png_const_int_16p;
|
||||
typedef char * png_charp;
|
||||
typedef const char * png_const_charp;
|
||||
typedef png_fixed_point * png_fixed_point_p;
|
||||
typedef const png_fixed_point * png_const_fixed_point_p;
|
||||
typedef png_size_t * png_size_tp;
|
||||
typedef const png_size_t * png_const_size_tp;
|
||||
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
typedef FILE * png_FILE_p;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
typedef double * png_doublep;
|
||||
typedef const double * png_const_doublep;
|
||||
#endif
|
||||
|
||||
/* Pointers to pointers; i.e. arrays */
|
||||
typedef png_byte * * png_bytepp;
|
||||
typedef png_uint_32 * * png_uint_32pp;
|
||||
typedef png_int_32 * * png_int_32pp;
|
||||
typedef png_uint_16 * * png_uint_16pp;
|
||||
typedef png_int_16 * * png_int_16pp;
|
||||
typedef const char * * png_const_charpp;
|
||||
typedef char * * png_charpp;
|
||||
typedef png_fixed_point * * png_fixed_point_pp;
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
typedef double * * png_doublepp;
|
||||
#endif
|
||||
|
||||
/* Pointers to pointers to pointers; i.e., pointer to array */
|
||||
typedef char * * * png_charppp;
|
||||
|
||||
#endif /* PNG_BUILDING_SYMBOL_TABLE */
|
||||
|
||||
#endif /* PNGCONF_H */
|
@ -1,218 +0,0 @@
|
||||
/* pnglibconf.h - library build configuration */
|
||||
|
||||
/* libpng version 1.6.34, September 29, 2017 */
|
||||
|
||||
/* Copyright (c) 1998-2017 Glenn Randers-Pehrson */
|
||||
|
||||
/* This code is released under the libpng license. */
|
||||
/* For conditions of distribution and use, see the disclaimer */
|
||||
/* and license in png.h */
|
||||
|
||||
/* pnglibconf.h */
|
||||
/* Machine generated file: DO NOT EDIT */
|
||||
/* Derived from: scripts/pnglibconf.dfa */
|
||||
#ifndef PNGLCONF_H
|
||||
#define PNGLCONF_H
|
||||
/* options */
|
||||
#define PNG_16BIT_SUPPORTED
|
||||
#define PNG_ALIGNED_MEMORY_SUPPORTED
|
||||
/*#undef PNG_ARM_NEON_API_SUPPORTED*/
|
||||
/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
|
||||
#define PNG_BENIGN_ERRORS_SUPPORTED
|
||||
#define PNG_BENIGN_READ_ERRORS_SUPPORTED
|
||||
/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
|
||||
#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
|
||||
#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
|
||||
#define PNG_COLORSPACE_SUPPORTED
|
||||
#define PNG_CONSOLE_IO_SUPPORTED
|
||||
#define PNG_CONVERT_tIME_SUPPORTED
|
||||
#define PNG_EASY_ACCESS_SUPPORTED
|
||||
/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/
|
||||
#define PNG_ERROR_TEXT_SUPPORTED
|
||||
#define PNG_FIXED_POINT_SUPPORTED
|
||||
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
|
||||
#define PNG_FLOATING_POINT_SUPPORTED
|
||||
#define PNG_FORMAT_AFIRST_SUPPORTED
|
||||
#define PNG_FORMAT_BGR_SUPPORTED
|
||||
#define PNG_GAMMA_SUPPORTED
|
||||
#define PNG_GET_PALETTE_MAX_SUPPORTED
|
||||
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
||||
#define PNG_INCH_CONVERSIONS_SUPPORTED
|
||||
#define PNG_INFO_IMAGE_SUPPORTED
|
||||
#define PNG_IO_STATE_SUPPORTED
|
||||
#define PNG_MNG_FEATURES_SUPPORTED
|
||||
#define PNG_POINTER_INDEXING_SUPPORTED
|
||||
/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/
|
||||
/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/
|
||||
#define PNG_PROGRESSIVE_READ_SUPPORTED
|
||||
#define PNG_READ_16BIT_SUPPORTED
|
||||
#define PNG_READ_ALPHA_MODE_SUPPORTED
|
||||
#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_BACKGROUND_SUPPORTED
|
||||
#define PNG_READ_BGR_SUPPORTED
|
||||
#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
|
||||
#define PNG_READ_COMPOSITE_NODIV_SUPPORTED
|
||||
#define PNG_READ_COMPRESSED_TEXT_SUPPORTED
|
||||
#define PNG_READ_EXPAND_16_SUPPORTED
|
||||
#define PNG_READ_EXPAND_SUPPORTED
|
||||
#define PNG_READ_FILLER_SUPPORTED
|
||||
#define PNG_READ_GAMMA_SUPPORTED
|
||||
#define PNG_READ_GET_PALETTE_MAX_SUPPORTED
|
||||
#define PNG_READ_GRAY_TO_RGB_SUPPORTED
|
||||
#define PNG_READ_INTERLACING_SUPPORTED
|
||||
#define PNG_READ_INT_FUNCTIONS_SUPPORTED
|
||||
#define PNG_READ_INVERT_ALPHA_SUPPORTED
|
||||
#define PNG_READ_INVERT_SUPPORTED
|
||||
#define PNG_READ_OPT_PLTE_SUPPORTED
|
||||
#define PNG_READ_PACKSWAP_SUPPORTED
|
||||
#define PNG_READ_PACK_SUPPORTED
|
||||
#define PNG_READ_QUANTIZE_SUPPORTED
|
||||
#define PNG_READ_RGB_TO_GRAY_SUPPORTED
|
||||
#define PNG_READ_SCALE_16_TO_8_SUPPORTED
|
||||
#define PNG_READ_SHIFT_SUPPORTED
|
||||
#define PNG_READ_STRIP_16_TO_8_SUPPORTED
|
||||
#define PNG_READ_STRIP_ALPHA_SUPPORTED
|
||||
#define PNG_READ_SUPPORTED
|
||||
#define PNG_READ_SWAP_ALPHA_SUPPORTED
|
||||
#define PNG_READ_SWAP_SUPPORTED
|
||||
#define PNG_READ_TEXT_SUPPORTED
|
||||
#define PNG_READ_TRANSFORMS_SUPPORTED
|
||||
#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_USER_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_USER_TRANSFORM_SUPPORTED
|
||||
#define PNG_READ_bKGD_SUPPORTED
|
||||
#define PNG_READ_cHRM_SUPPORTED
|
||||
#define PNG_READ_eXIf_SUPPORTED
|
||||
#define PNG_READ_gAMA_SUPPORTED
|
||||
#define PNG_READ_hIST_SUPPORTED
|
||||
#define PNG_READ_iCCP_SUPPORTED
|
||||
#define PNG_READ_iTXt_SUPPORTED
|
||||
#define PNG_READ_oFFs_SUPPORTED
|
||||
#define PNG_READ_pCAL_SUPPORTED
|
||||
#define PNG_READ_pHYs_SUPPORTED
|
||||
#define PNG_READ_sBIT_SUPPORTED
|
||||
#define PNG_READ_sCAL_SUPPORTED
|
||||
#define PNG_READ_sPLT_SUPPORTED
|
||||
#define PNG_READ_sRGB_SUPPORTED
|
||||
#define PNG_READ_tEXt_SUPPORTED
|
||||
#define PNG_READ_tIME_SUPPORTED
|
||||
#define PNG_READ_tRNS_SUPPORTED
|
||||
#define PNG_READ_zTXt_SUPPORTED
|
||||
#define PNG_SAVE_INT_32_SUPPORTED
|
||||
#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_SEQUENTIAL_READ_SUPPORTED
|
||||
#define PNG_SETJMP_SUPPORTED
|
||||
#define PNG_SET_OPTION_SUPPORTED
|
||||
#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_SET_USER_LIMITS_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_READ_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||
#define PNG_STDIO_SUPPORTED
|
||||
#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_TEXT_SUPPORTED
|
||||
#define PNG_TIME_RFC1123_SUPPORTED
|
||||
#define PNG_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_USER_CHUNKS_SUPPORTED
|
||||
#define PNG_USER_LIMITS_SUPPORTED
|
||||
#define PNG_USER_MEM_SUPPORTED
|
||||
#define PNG_USER_TRANSFORM_INFO_SUPPORTED
|
||||
#define PNG_USER_TRANSFORM_PTR_SUPPORTED
|
||||
#define PNG_WARNINGS_SUPPORTED
|
||||
#define PNG_WRITE_16BIT_SUPPORTED
|
||||
#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
|
||||
#define PNG_WRITE_BGR_SUPPORTED
|
||||
#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
|
||||
#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
|
||||
#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
|
||||
#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
|
||||
#define PNG_WRITE_FILLER_SUPPORTED
|
||||
#define PNG_WRITE_FILTER_SUPPORTED
|
||||
#define PNG_WRITE_FLUSH_SUPPORTED
|
||||
#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED
|
||||
#define PNG_WRITE_INTERLACING_SUPPORTED
|
||||
#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
|
||||
#define PNG_WRITE_INVERT_ALPHA_SUPPORTED
|
||||
#define PNG_WRITE_INVERT_SUPPORTED
|
||||
#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
|
||||
#define PNG_WRITE_PACKSWAP_SUPPORTED
|
||||
#define PNG_WRITE_PACK_SUPPORTED
|
||||
#define PNG_WRITE_SHIFT_SUPPORTED
|
||||
#define PNG_WRITE_SUPPORTED
|
||||
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
|
||||
#define PNG_WRITE_SWAP_SUPPORTED
|
||||
#define PNG_WRITE_TEXT_SUPPORTED
|
||||
#define PNG_WRITE_TRANSFORMS_SUPPORTED
|
||||
#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
|
||||
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||
#define PNG_WRITE_bKGD_SUPPORTED
|
||||
#define PNG_WRITE_cHRM_SUPPORTED
|
||||
#define PNG_WRITE_eXIf_SUPPORTED
|
||||
#define PNG_WRITE_gAMA_SUPPORTED
|
||||
#define PNG_WRITE_hIST_SUPPORTED
|
||||
#define PNG_WRITE_iCCP_SUPPORTED
|
||||
#define PNG_WRITE_iTXt_SUPPORTED
|
||||
#define PNG_WRITE_oFFs_SUPPORTED
|
||||
#define PNG_WRITE_pCAL_SUPPORTED
|
||||
#define PNG_WRITE_pHYs_SUPPORTED
|
||||
#define PNG_WRITE_sBIT_SUPPORTED
|
||||
#define PNG_WRITE_sCAL_SUPPORTED
|
||||
#define PNG_WRITE_sPLT_SUPPORTED
|
||||
#define PNG_WRITE_sRGB_SUPPORTED
|
||||
#define PNG_WRITE_tEXt_SUPPORTED
|
||||
#define PNG_WRITE_tIME_SUPPORTED
|
||||
#define PNG_WRITE_tRNS_SUPPORTED
|
||||
#define PNG_WRITE_zTXt_SUPPORTED
|
||||
#define PNG_bKGD_SUPPORTED
|
||||
#define PNG_cHRM_SUPPORTED
|
||||
#define PNG_eXIf_SUPPORTED
|
||||
#define PNG_gAMA_SUPPORTED
|
||||
#define PNG_hIST_SUPPORTED
|
||||
#define PNG_iCCP_SUPPORTED
|
||||
#define PNG_iTXt_SUPPORTED
|
||||
#define PNG_oFFs_SUPPORTED
|
||||
#define PNG_pCAL_SUPPORTED
|
||||
#define PNG_pHYs_SUPPORTED
|
||||
#define PNG_sBIT_SUPPORTED
|
||||
#define PNG_sCAL_SUPPORTED
|
||||
#define PNG_sPLT_SUPPORTED
|
||||
#define PNG_sRGB_SUPPORTED
|
||||
#define PNG_tEXt_SUPPORTED
|
||||
#define PNG_tIME_SUPPORTED
|
||||
#define PNG_tRNS_SUPPORTED
|
||||
#define PNG_zTXt_SUPPORTED
|
||||
/* end of options */
|
||||
/* settings */
|
||||
#define PNG_API_RULE 0
|
||||
#define PNG_DEFAULT_READ_MACROS 1
|
||||
#define PNG_GAMMA_THRESHOLD_FIXED 5000
|
||||
#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
|
||||
#define PNG_INFLATE_BUF_SIZE 1024
|
||||
#define PNG_LINKAGE_API extern
|
||||
#define PNG_LINKAGE_CALLBACK extern
|
||||
#define PNG_LINKAGE_DATA extern
|
||||
#define PNG_LINKAGE_FUNCTION extern
|
||||
#define PNG_MAX_GAMMA_8 11
|
||||
#define PNG_QUANTIZE_BLUE_BITS 5
|
||||
#define PNG_QUANTIZE_GREEN_BITS 5
|
||||
#define PNG_QUANTIZE_RED_BITS 5
|
||||
#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1)
|
||||
#define PNG_TEXT_Z_DEFAULT_STRATEGY 0
|
||||
#define PNG_USER_CHUNK_CACHE_MAX 1000
|
||||
#define PNG_USER_CHUNK_MALLOC_MAX 8000000
|
||||
#define PNG_USER_HEIGHT_MAX 1000000
|
||||
#define PNG_USER_WIDTH_MAX 1000000
|
||||
#define PNG_ZBUF_SIZE 8192
|
||||
#define PNG_ZLIB_VERNUM 0x12b0
|
||||
#define PNG_Z_DEFAULT_COMPRESSION (-1)
|
||||
#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
|
||||
#define PNG_Z_DEFAULT_STRATEGY 1
|
||||
#define PNG_sCAL_PRECISION 5
|
||||
#define PNG_sRGB_PROFILE_CHECKS 2
|
||||
/* end of settings */
|
||||
#endif /* PNGLCONF_H */
|
Binary file not shown.
Binary file not shown.
2309
cdeps/win/png.h
2309
cdeps/win/png.h
File diff suppressed because it is too large
Load Diff
@ -1,649 +0,0 @@
|
||||
|
||||
/* pngconf.h - machine configurable file for libpng
|
||||
*
|
||||
* libpng version 1.5.2 - March 31, 2011
|
||||
*
|
||||
* Copyright (c) 1998-2011 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*
|
||||
*/
|
||||
|
||||
/* Any machine specific code is near the front of this file, so if you
|
||||
* are configuring libpng for a machine, you may want to read the section
|
||||
* starting here down to where it starts to typedef png_color, png_text,
|
||||
* and png_info.
|
||||
*/
|
||||
|
||||
#ifndef PNGCONF_H
|
||||
#define PNGCONF_H
|
||||
|
||||
#ifndef PNG_BUILDING_SYMBOL_TABLE
|
||||
/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C
|
||||
* definition file for machine specific limits, this may impact the
|
||||
* correctness of the definitons below (see uses of INT_MAX).
|
||||
*/
|
||||
# ifndef PNG_NO_LIMITS_H
|
||||
# include <limits.h>
|
||||
# endif
|
||||
|
||||
/* For the memory copy APIs (i.e. the standard definitions of these),
|
||||
* because this file defines png_memcpy and so on the base APIs must
|
||||
* be defined here.
|
||||
*/
|
||||
# ifdef BSD
|
||||
# include <strings.h>
|
||||
# else
|
||||
# include <string.h>
|
||||
# endif
|
||||
|
||||
/* For png_FILE_p - this provides the standard definition of a
|
||||
* FILE
|
||||
*/
|
||||
# ifdef PNG_STDIO_SUPPORTED
|
||||
# include <stdio.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This controls optimization of the reading of 16 and 32 bit values
|
||||
* from PNG files. It can be set on a per-app-file basis - it
|
||||
* just changes whether a macro is used to the function is called.
|
||||
* The library builder sets the default, if read functions are not
|
||||
* built into the library the macro implementation is forced on.
|
||||
*/
|
||||
#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED
|
||||
# define PNG_USE_READ_MACROS
|
||||
#endif
|
||||
#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS)
|
||||
# if PNG_DEFAULT_READ_MACROS
|
||||
# define PNG_USE_READ_MACROS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* COMPILER SPECIFIC OPTIONS.
|
||||
*
|
||||
* These options are provided so that a variety of difficult compilers
|
||||
* can be used. Some are fixed at build time (e.g. PNG_API_RULE
|
||||
* below) but still have compiler specific implementations, others
|
||||
* may be changed on a per-file basis when compiling against libpng.
|
||||
*/
|
||||
|
||||
/* The PNGARG macro protects us against machines that don't have function
|
||||
* prototypes (ie K&R style headers). If your compiler does not handle
|
||||
* function prototypes, define this macro and use the included ansi2knr.
|
||||
* I've always been able to use _NO_PROTO as the indicator, but you may
|
||||
* need to drag the empty declaration out in front of here, or change the
|
||||
* ifdef to suit your own needs.
|
||||
*/
|
||||
#ifndef PNGARG
|
||||
|
||||
# ifdef OF /* zlib prototype munger */
|
||||
# define PNGARG(arglist) OF(arglist)
|
||||
# else
|
||||
|
||||
# ifdef _NO_PROTO
|
||||
# define PNGARG(arglist) ()
|
||||
# else
|
||||
# define PNGARG(arglist) arglist
|
||||
# endif /* _NO_PROTO */
|
||||
|
||||
# endif /* OF */
|
||||
|
||||
#endif /* PNGARG */
|
||||
|
||||
/* Function calling conventions.
|
||||
* =============================
|
||||
* Normally it is not necessary to specify to the compiler how to call
|
||||
* a function - it just does it - however on x86 systems derived from
|
||||
* Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems
|
||||
* and some others) there are multiple ways to call a function and the
|
||||
* default can be changed on the compiler command line. For this reason
|
||||
* libpng specifies the calling convention of every exported function and
|
||||
* every function called via a user supplied function pointer. This is
|
||||
* done in this file by defining the following macros:
|
||||
*
|
||||
* PNGAPI Calling convention for exported functions.
|
||||
* PNGCBAPI Calling convention for user provided (callback) functions.
|
||||
* PNGCAPI Calling convention used by the ANSI-C library (required
|
||||
* for longjmp callbacks and sometimes used internally to
|
||||
* specify the calling convention for zlib).
|
||||
*
|
||||
* These macros should never be overridden. If it is necessary to
|
||||
* change calling convention in a private build this can be done
|
||||
* by setting PNG_API_RULE (which defaults to 0) to one of the values
|
||||
* below to select the correct 'API' variants.
|
||||
*
|
||||
* PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout.
|
||||
* This is correct in every known environment.
|
||||
* PNG_API_RULE=1 Use the operating system convention for PNGAPI and
|
||||
* the 'C' calling convention (from PNGCAPI) for
|
||||
* callbacks (PNGCBAPI). This is no longer required
|
||||
* in any known environment - if it has to be used
|
||||
* please post an explanation of the problem to the
|
||||
* libpng mailing list.
|
||||
*
|
||||
* These cases only differ if the operating system does not use the C
|
||||
* calling convention, at present this just means the above cases
|
||||
* (x86 DOS/Windows sytems) and, even then, this does not apply to
|
||||
* Cygwin running on those systems.
|
||||
*
|
||||
* Note that the value must be defined in pnglibconf.h so that what
|
||||
* the application uses to call the library matches the conventions
|
||||
* set when building the library.
|
||||
*/
|
||||
|
||||
/* Symbol export
|
||||
* =============
|
||||
* When building a shared library it is almost always necessary to tell
|
||||
* the compiler which symbols to export. The png.h macro 'PNG_EXPORT'
|
||||
* is used to mark the symbols. On some systems these symbols can be
|
||||
* extracted at link time and need no special processing by the compiler,
|
||||
* on other systems the symbols are flagged by the compiler and just
|
||||
* the declaration requires a special tag applied (unfortunately) in a
|
||||
* compiler dependent way. Some systems can do either.
|
||||
*
|
||||
* A small number of older systems also require a symbol from a DLL to
|
||||
* be flagged to the program that calls it. This is a problem because
|
||||
* we do not know in the header file included by application code that
|
||||
* the symbol will come from a shared library, as opposed to a statically
|
||||
* linked one. For this reason the application must tell us by setting
|
||||
* the magic flag PNG_USE_DLL to turn on the special processing before
|
||||
* it includes png.h.
|
||||
*
|
||||
* Four additional macros are used to make this happen:
|
||||
*
|
||||
* PNG_IMPEXP The magic (if any) to cause a symbol to be exported from
|
||||
* the build or imported if PNG_USE_DLL is set - compiler
|
||||
* and system specific.
|
||||
*
|
||||
* PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to
|
||||
* 'type', compiler specific.
|
||||
*
|
||||
* PNG_DLL_EXPORT Set to the magic to use during a libpng build to
|
||||
* make a symbol exported from the DLL.
|
||||
*
|
||||
* PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come
|
||||
* from a DLL - used to define PNG_IMPEXP when
|
||||
* PNG_USE_DLL is set.
|
||||
*/
|
||||
|
||||
/* System specific discovery.
|
||||
* ==========================
|
||||
* This code is used at build time to find PNG_IMPEXP, the API settings
|
||||
* and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL
|
||||
* import processing is possible. On Windows/x86 systems it also sets
|
||||
* compiler-specific macros to the values required to change the calling
|
||||
* conventions of the various functions.
|
||||
*/
|
||||
#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
|
||||
defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\
|
||||
( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\
|
||||
defined(_M_X64) || defined(_M_IA64) )
|
||||
/* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes
|
||||
* builds under Cygwin or MinGW. Also includes Watcom builds but these need
|
||||
* special treatment because they are not compatible with GCC or Visual C
|
||||
* because of different calling conventions.
|
||||
*/
|
||||
# if PNG_API_RULE == 2
|
||||
/* If this line results in an error, either because __watcall is not
|
||||
* understood or because of a redefine just below you cannot use *this*
|
||||
* build of the library with the compiler you are using. *This* build was
|
||||
* build using Watcom and applications must also be built using Watcom!
|
||||
*/
|
||||
# define PNGCAPI __watcall
|
||||
# endif
|
||||
|
||||
# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800))
|
||||
# define PNGCAPI __cdecl
|
||||
# if PNG_API_RULE == 1
|
||||
# define PNGAPI __stdcall
|
||||
# endif
|
||||
# else
|
||||
/* An older compiler, or one not detected (erroneously) above,
|
||||
* if necessary override on the command line to get the correct
|
||||
* variants for the compiler.
|
||||
*/
|
||||
# ifndef PNGCAPI
|
||||
# define PNGCAPI _cdecl
|
||||
# endif
|
||||
# if PNG_API_RULE == 1 && !defined(PNGAPI)
|
||||
# define PNGAPI _stdcall
|
||||
# endif
|
||||
# endif /* compiler/api */
|
||||
/* NOTE: PNGCBAPI always defaults to PNGCAPI. */
|
||||
|
||||
# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD)
|
||||
ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed
|
||||
# endif
|
||||
|
||||
# if (defined(_MSC_VER) && _MSC_VER < 800) ||\
|
||||
(defined(__BORLANDC__) && __BORLANDC__ < 0x500)
|
||||
/* older Borland and MSC
|
||||
* compilers used '__export' and required this to be after
|
||||
* the type.
|
||||
*/
|
||||
# ifndef PNG_EXPORT_TYPE
|
||||
# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP
|
||||
# endif
|
||||
# define PNG_DLL_EXPORT __export
|
||||
# else /* newer compiler */
|
||||
# define PNG_DLL_EXPORT __declspec(dllexport)
|
||||
# ifndef PNG_DLL_IMPORT
|
||||
# define PNG_DLL_IMPORT __declspec(dllimport)
|
||||
# endif
|
||||
# endif /* compiler */
|
||||
|
||||
#else /* !Windows/x86 */
|
||||
# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
|
||||
# define PNGAPI _System
|
||||
# else /* !Windows/x86 && !OS/2 */
|
||||
/* Use the defaults, or define PNG*API on the command line (but
|
||||
* this will have to be done for every compile!)
|
||||
*/
|
||||
# endif /* other system, !OS/2 */
|
||||
#endif /* !Windows/x86 */
|
||||
|
||||
/* Now do all the defaulting . */
|
||||
#ifndef PNGCAPI
|
||||
# define PNGCAPI
|
||||
#endif
|
||||
#ifndef PNGCBAPI
|
||||
# define PNGCBAPI PNGCAPI
|
||||
#endif
|
||||
#ifndef PNGAPI
|
||||
# define PNGAPI PNGCAPI
|
||||
#endif
|
||||
|
||||
/* The default for PNG_IMPEXP depends on whether the library is
|
||||
* being built or used.
|
||||
*/
|
||||
#ifndef PNG_IMPEXP
|
||||
# ifdef PNGLIB_BUILD
|
||||
/* Building the library */
|
||||
# if (defined(DLL_EXPORT)/*from libtool*/ ||\
|
||||
defined(_WINDLL) || defined(_DLL) || defined(__DLL__) ||\
|
||||
defined(_USRDLL) ||\
|
||||
defined(PNG_BUILD_DLL)) && defined(PNG_DLL_EXPORT)
|
||||
/* Building a DLL. */
|
||||
# define PNG_IMPEXP PNG_DLL_EXPORT
|
||||
# endif /* DLL */
|
||||
# else
|
||||
/* Using the library */
|
||||
# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT)
|
||||
/* This forces use of a DLL, disallowing static linking */
|
||||
# define PNG_IMPEXP PNG_DLL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef PNG_IMPEXP
|
||||
# define PNG_IMPEXP
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat
|
||||
* 'attributes' as a storage class - the attributes go at the start of the
|
||||
* function definition, and attributes are always appended regardless of the
|
||||
* compiler. This considerably simplifies these macros but may cause problems
|
||||
* if any compilers both need function attributes and fail to handle them as
|
||||
* a storage class (this is unlikely.)
|
||||
*/
|
||||
#ifndef PNG_FUNCTION
|
||||
# define PNG_FUNCTION(type, name, args, attributes) attributes type name args
|
||||
#endif
|
||||
|
||||
#ifndef PNG_EXPORT_TYPE
|
||||
# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type
|
||||
#endif
|
||||
|
||||
/* The ordinal value is only relevant when preprocessing png.h for symbol
|
||||
* table entries, so we discard it here. See the .dfn files in the
|
||||
* scripts directory.
|
||||
*/
|
||||
#ifndef PNG_EXPORTA
|
||||
|
||||
# define PNG_EXPORTA(ordinal, type, name, args, attributes)\
|
||||
PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \
|
||||
extern attributes)
|
||||
#endif
|
||||
|
||||
/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument,
|
||||
* so make something non-empty to satisfy the requirement:
|
||||
*/
|
||||
#define PNG_EMPTY /*empty list*/
|
||||
|
||||
#define PNG_EXPORT(ordinal, type, name, args)\
|
||||
PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY)
|
||||
|
||||
/* Use PNG_REMOVED to comment out a removed interface. */
|
||||
#ifndef PNG_REMOVED
|
||||
# define PNG_REMOVED(ordinal, type, name, args, attributes)
|
||||
#endif
|
||||
|
||||
#ifndef PNG_CALLBACK
|
||||
# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args)
|
||||
#endif
|
||||
|
||||
/* Support for compiler specific function attributes. These are used
|
||||
* so that where compiler support is available incorrect use of API
|
||||
* functions in png.h will generate compiler warnings.
|
||||
*
|
||||
* Added at libpng-1.2.41.
|
||||
*/
|
||||
|
||||
#ifndef PNG_NO_PEDANTIC_WARNINGS
|
||||
# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED
|
||||
# define PNG_PEDANTIC_WARNINGS_SUPPORTED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED
|
||||
/* Support for compiler specific function attributes. These are used
|
||||
* so that where compiler support is available incorrect use of API
|
||||
* functions in png.h will generate compiler warnings. Added at libpng
|
||||
* version 1.2.41.
|
||||
*/
|
||||
# if defined(__GNUC__)
|
||||
# ifndef PNG_USE_RESULT
|
||||
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
|
||||
# endif
|
||||
# ifndef PNG_NORETURN
|
||||
# define PNG_NORETURN __attribute__((__noreturn__))
|
||||
# endif
|
||||
# ifndef PNG_PTR_NORETURN
|
||||
/* It's not enough to have the compiler be the correct compiler at
|
||||
* this point - it's necessary for the library (which defines
|
||||
* the type of the library longjmp) to also be the GNU library.
|
||||
* This is because many systems use the GNU compiler with a
|
||||
* non-GNU libc implementation. Min/GW headers are also compatible
|
||||
* with GCC as well as uclibc, so it seems best to exclude known
|
||||
* problem libcs here rather than just including known libcs.
|
||||
*
|
||||
* NOTE: this relies on the only use of PNG_PTR_NORETURN being with
|
||||
* the system longjmp. If the same type is used elsewhere then this
|
||||
* will need to be changed.
|
||||
*/
|
||||
# if !defined(__CYGWIN__)
|
||||
# define PNG_PTR_NORETURN __attribute__((__noreturn__))
|
||||
# endif
|
||||
# endif
|
||||
# ifndef PNG_ALLOCATED
|
||||
# define PNG_ALLOCATED __attribute__((__malloc__))
|
||||
# endif
|
||||
|
||||
/* This specifically protects structure members that should only be
|
||||
* accessed from within the library, therefore should be empty during
|
||||
* a library build.
|
||||
*/
|
||||
# ifndef PNGLIB_BUILD
|
||||
# ifndef PNG_DEPRECATED
|
||||
# define PNG_DEPRECATED __attribute__((__deprecated__))
|
||||
# endif
|
||||
# ifndef PNG_DEPSTRUCT
|
||||
# define PNG_DEPSTRUCT __attribute__((__deprecated__))
|
||||
# endif
|
||||
# ifndef PNG_PRIVATE
|
||||
# if 0 /* Doesn't work so we use deprecated instead*/
|
||||
# define PNG_PRIVATE \
|
||||
__attribute__((warning("This function is not exported by libpng.")))
|
||||
# else
|
||||
# define PNG_PRIVATE \
|
||||
__attribute__((__deprecated__))
|
||||
# endif
|
||||
# endif
|
||||
# endif /* PNGLIB_BUILD */
|
||||
# endif /* __GNUC__ */
|
||||
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||
# ifndef PNG_USE_RESULT
|
||||
# define PNG_USE_RESULT /* not supported */
|
||||
# endif
|
||||
# ifndef PNG_NORETURN
|
||||
# define PNG_NORETURN __declspec(noreturn)
|
||||
# endif
|
||||
# ifndef PNG_PTR_NORETURN
|
||||
# define PNG_PTR_NORETURN /* not supported */
|
||||
# endif
|
||||
# ifndef PNG_ALLOCATED
|
||||
# define PNG_ALLOCATED __declspec(restrict)
|
||||
# endif
|
||||
|
||||
/* This specifically protects structure members that should only be
|
||||
* accessed from within the library, therefore should be empty during
|
||||
* a library build.
|
||||
*/
|
||||
# ifndef PNGLIB_BUILD
|
||||
# ifndef PNG_DEPRECATED
|
||||
# define PNG_DEPRECATED __declspec(deprecated)
|
||||
# endif
|
||||
# ifndef PNG_DEPSTRUCT
|
||||
# define PNG_DEPSTRUCT __declspec(deprecated)
|
||||
# endif
|
||||
# ifndef PNG_PRIVATE
|
||||
# define PNG_PRIVATE __declspec(deprecated)
|
||||
# endif
|
||||
# endif /* PNGLIB_BUILD */
|
||||
# endif /* _MSC_VER */
|
||||
#endif /* PNG_PEDANTIC_WARNINGS */
|
||||
|
||||
#ifndef PNG_DEPRECATED
|
||||
# define PNG_DEPRECATED /* Use of this function is deprecated */
|
||||
#endif
|
||||
#ifndef PNG_USE_RESULT
|
||||
# define PNG_USE_RESULT /* The result of this function must be checked */
|
||||
#endif
|
||||
#ifndef PNG_NORETURN
|
||||
# define PNG_NORETURN /* This function does not return */
|
||||
#endif
|
||||
#ifndef PNG_PTR_NORETURN
|
||||
# define PNG_PTR_NORETURN /* This function does not return */
|
||||
#endif
|
||||
#ifndef PNG_ALLOCATED
|
||||
# define PNG_ALLOCATED /* The result of the function is new memory */
|
||||
#endif
|
||||
#ifndef PNG_DEPSTRUCT
|
||||
# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */
|
||||
#endif
|
||||
#ifndef PNG_PRIVATE
|
||||
# define PNG_PRIVATE /* This is a private libpng function */
|
||||
#endif
|
||||
#ifndef PNG_FP_EXPORT /* A floating point API. */
|
||||
# ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
# define PNG_FP_EXPORT(ordinal, type, name, args)\
|
||||
PNG_EXPORT(ordinal, type, name, args)
|
||||
# else /* No floating point APIs */
|
||||
# define PNG_FP_EXPORT(ordinal, type, name, args)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef PNG_FIXED_EXPORT /* A fixed point API. */
|
||||
# ifdef PNG_FIXED_POINT_SUPPORTED
|
||||
# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
|
||||
PNG_EXPORT(ordinal, type, name, args)
|
||||
# else /* No fixed point APIs */
|
||||
# define PNG_FIXED_EXPORT(ordinal, type, name, args)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The following uses const char * instead of char * for error
|
||||
* and warning message functions, so some compilers won't complain.
|
||||
* If you do not want to use const, define PNG_NO_CONST here.
|
||||
*
|
||||
* This should not change how the APIs are called, so it can be done
|
||||
* on a per-file basis in the application.
|
||||
*/
|
||||
#ifndef PNG_CONST
|
||||
# ifndef PNG_NO_CONST
|
||||
# define PNG_CONST const
|
||||
# else
|
||||
# define PNG_CONST
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Some typedefs to get us started. These should be safe on most of the
|
||||
* common platforms. The typedefs should be at least as large as the
|
||||
* numbers suggest (a png_uint_32 must be at least 32 bits long), but they
|
||||
* don't have to be exactly that size. Some compilers dislike passing
|
||||
* unsigned shorts as function parameters, so you may be better off using
|
||||
* unsigned int for png_uint_16.
|
||||
*/
|
||||
|
||||
#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL)
|
||||
typedef unsigned int png_uint_32;
|
||||
typedef int png_int_32;
|
||||
#else
|
||||
typedef unsigned long png_uint_32;
|
||||
typedef long png_int_32;
|
||||
#endif
|
||||
typedef unsigned short png_uint_16;
|
||||
typedef short png_int_16;
|
||||
typedef unsigned char png_byte;
|
||||
|
||||
#ifdef PNG_NO_SIZE_T
|
||||
typedef unsigned int png_size_t;
|
||||
#else
|
||||
typedef size_t png_size_t;
|
||||
#endif
|
||||
#define png_sizeof(x) (sizeof (x))
|
||||
|
||||
/* The following is needed for medium model support. It cannot be in the
|
||||
* pngpriv.h header. Needs modification for other compilers besides
|
||||
* MSC. Model independent support declares all arrays and pointers to be
|
||||
* large using the far keyword. The zlib version used must also support
|
||||
* model independent data. As of version zlib 1.0.4, the necessary changes
|
||||
* have been made in zlib. The USE_FAR_KEYWORD define triggers other
|
||||
* changes that are needed. (Tim Wegner)
|
||||
*/
|
||||
|
||||
/* Separate compiler dependencies (problem here is that zlib.h always
|
||||
* defines FAR. (SJT)
|
||||
*/
|
||||
#ifdef __BORLANDC__
|
||||
# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
|
||||
# define LDATA 1
|
||||
# else
|
||||
# define LDATA 0
|
||||
# endif
|
||||
/* GRR: why is Cygwin in here? Cygwin is not Borland C... */
|
||||
# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__)
|
||||
# define PNG_MAX_MALLOC_64K /* only used in build */
|
||||
# if (LDATA != 1)
|
||||
# ifndef FAR
|
||||
# define FAR __far
|
||||
# endif
|
||||
# define USE_FAR_KEYWORD
|
||||
# endif /* LDATA != 1 */
|
||||
/* Possibly useful for moving data out of default segment.
|
||||
* Uncomment it if you want. Could also define FARDATA as
|
||||
* const if your compiler supports it. (SJT)
|
||||
# define FARDATA FAR
|
||||
*/
|
||||
# endif /* __WIN32__, __FLAT__, __CYGWIN__ */
|
||||
#endif /* __BORLANDC__ */
|
||||
|
||||
|
||||
/* Suggest testing for specific compiler first before testing for
|
||||
* FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM,
|
||||
* making reliance oncertain keywords suspect. (SJT)
|
||||
*/
|
||||
|
||||
/* MSC Medium model */
|
||||
#ifdef FAR
|
||||
# ifdef M_I86MM
|
||||
# define USE_FAR_KEYWORD
|
||||
# define FARDATA FAR
|
||||
# include <dos.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* SJT: default case */
|
||||
#ifndef FAR
|
||||
# define FAR
|
||||
#endif
|
||||
|
||||
/* At this point FAR is always defined */
|
||||
#ifndef FARDATA
|
||||
# define FARDATA
|
||||
#endif
|
||||
|
||||
/* Typedef for floating-point numbers that are converted
|
||||
* to fixed-point with a multiple of 100,000, e.g., gamma
|
||||
*/
|
||||
typedef png_int_32 png_fixed_point;
|
||||
|
||||
/* Add typedefs for pointers */
|
||||
typedef void FAR * png_voidp;
|
||||
typedef PNG_CONST void FAR * png_const_voidp;
|
||||
typedef png_byte FAR * png_bytep;
|
||||
typedef PNG_CONST png_byte FAR * png_const_bytep;
|
||||
typedef png_uint_32 FAR * png_uint_32p;
|
||||
typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p;
|
||||
typedef png_int_32 FAR * png_int_32p;
|
||||
typedef PNG_CONST png_int_32 FAR * png_const_int_32p;
|
||||
typedef png_uint_16 FAR * png_uint_16p;
|
||||
typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p;
|
||||
typedef png_int_16 FAR * png_int_16p;
|
||||
typedef PNG_CONST png_int_16 FAR * png_const_int_16p;
|
||||
typedef char FAR * png_charp;
|
||||
typedef PNG_CONST char FAR * png_const_charp;
|
||||
typedef png_fixed_point FAR * png_fixed_point_p;
|
||||
typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p;
|
||||
typedef png_size_t FAR * png_size_tp;
|
||||
typedef PNG_CONST png_size_t FAR * png_const_size_tp;
|
||||
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
typedef FILE * png_FILE_p;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
typedef double FAR * png_doublep;
|
||||
typedef PNG_CONST double FAR * png_const_doublep;
|
||||
#endif
|
||||
|
||||
/* Pointers to pointers; i.e. arrays */
|
||||
typedef png_byte FAR * FAR * png_bytepp;
|
||||
typedef png_uint_32 FAR * FAR * png_uint_32pp;
|
||||
typedef png_int_32 FAR * FAR * png_int_32pp;
|
||||
typedef png_uint_16 FAR * FAR * png_uint_16pp;
|
||||
typedef png_int_16 FAR * FAR * png_int_16pp;
|
||||
typedef PNG_CONST char FAR * FAR * png_const_charpp;
|
||||
typedef char FAR * FAR * png_charpp;
|
||||
typedef png_fixed_point FAR * FAR * png_fixed_point_pp;
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
typedef double FAR * FAR * png_doublepp;
|
||||
#endif
|
||||
|
||||
/* Pointers to pointers to pointers; i.e., pointer to array */
|
||||
typedef char FAR * FAR * FAR * png_charppp;
|
||||
|
||||
/* png_alloc_size_t is guaranteed to be no smaller than png_size_t,
|
||||
* and no smaller than png_uint_32. Casts from png_size_t or png_uint_32
|
||||
* to png_alloc_size_t are not necessary; in fact, it is recommended
|
||||
* not to use them at all so that the compiler can complain when something
|
||||
* turns out to be problematic.
|
||||
* Casts in the other direction (from png_alloc_size_t to png_size_t or
|
||||
* png_uint_32) should be explicitly applied; however, we do not expect
|
||||
* to encounter practical situations that require such conversions.
|
||||
*/
|
||||
#if defined(__TURBOC__) && !defined(__FLAT__)
|
||||
typedef unsigned long png_alloc_size_t;
|
||||
#else
|
||||
# if defined(_MSC_VER) && defined(MAXSEG_64K)
|
||||
typedef unsigned long png_alloc_size_t;
|
||||
# else
|
||||
/* This is an attempt to detect an old Windows system where (int) is
|
||||
* actually 16 bits, in that case png_malloc must have an argument with a
|
||||
* bigger size to accomodate the requirements of the library.
|
||||
*/
|
||||
# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \
|
||||
(!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL)
|
||||
typedef DWORD png_alloc_size_t;
|
||||
# else
|
||||
typedef png_size_t png_alloc_size_t;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* PNGCONF_H */
|
@ -1,181 +0,0 @@
|
||||
|
||||
/* libpng STANDARD API DEFINITION */
|
||||
|
||||
/* pnglibconf.h - library build configuration */
|
||||
|
||||
/* libpng version 1.5.0 - last changed on February 11, 2011 */
|
||||
|
||||
/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */
|
||||
|
||||
/* This code is released under the libpng license. */
|
||||
/* For conditions of distribution and use, see the disclaimer */
|
||||
/* and license in png.h */
|
||||
|
||||
/* pnglibconf.h */
|
||||
/* Derived from: scripts/pnglibconf.dfa */
|
||||
/* If you edit this file by hand you must obey the rules expressed in */
|
||||
/* pnglibconf.dfa with respect to the dependencies between the following */
|
||||
/* symbols. It is much better to generate a new file using */
|
||||
/* scripts/libpngconf.mak */
|
||||
|
||||
#ifndef PNGLCONF_H
|
||||
#define PNGLCONF_H
|
||||
/* settings */
|
||||
#define PNG_API_RULE 0
|
||||
#define PNG_CALLOC_SUPPORTED
|
||||
#define PNG_COST_SHIFT 3
|
||||
#define PNG_DEFAULT_READ_MACROS 1
|
||||
#define PNG_GAMMA_THRESHOLD_FIXED 5000
|
||||
#define PNG_MAX_GAMMA_8 11
|
||||
#define PNG_QUANTIZE_BLUE_BITS 5
|
||||
#define PNG_QUANTIZE_GREEN_BITS 5
|
||||
#define PNG_QUANTIZE_RED_BITS 5
|
||||
#define PNG_sCAL_PRECISION 5
|
||||
#define PNG_USER_CHUNK_CACHE_MAX 0
|
||||
#define PNG_USER_CHUNK_MALLOC_MAX 0
|
||||
#define PNG_USER_HEIGHT_MAX 1000000L
|
||||
#define PNG_USER_WIDTH_MAX 1000000L
|
||||
#define PNG_WEIGHT_SHIFT 8
|
||||
#define PNG_ZBUF_SIZE 8192
|
||||
/* end of settings */
|
||||
/* options */
|
||||
#define PNG_16BIT_SUPPORTED
|
||||
#define PNG_ALIGN_MEMORY_SUPPORTED
|
||||
#define PNG_BENIGN_ERRORS_SUPPORTED
|
||||
#define PNG_bKGD_SUPPORTED
|
||||
#define PNG_CHECK_cHRM_SUPPORTED
|
||||
#define PNG_cHRM_SUPPORTED
|
||||
#define PNG_CONSOLE_IO_SUPPORTED
|
||||
#define PNG_CONVERT_tIME_SUPPORTED
|
||||
#define PNG_EASY_ACCESS_SUPPORTED
|
||||
#define PNG_ERROR_TEXT_SUPPORTED
|
||||
#define PNG_FIXED_POINT_SUPPORTED
|
||||
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
|
||||
#define PNG_FLOATING_POINT_SUPPORTED
|
||||
#define PNG_gAMA_SUPPORTED
|
||||
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
||||
#define PNG_hIST_SUPPORTED
|
||||
#define PNG_iCCP_SUPPORTED
|
||||
#define PNG_INCH_CONVERSIONS_SUPPORTED
|
||||
#define PNG_INFO_IMAGE_SUPPORTED
|
||||
#define PNG_IO_STATE_SUPPORTED
|
||||
#define PNG_iTXt_SUPPORTED
|
||||
#define PNG_MNG_FEATURES_SUPPORTED
|
||||
#define PNG_oFFs_SUPPORTED
|
||||
#define PNG_pCAL_SUPPORTED
|
||||
#define PNG_pHYs_SUPPORTED
|
||||
#define PNG_POINTER_INDEXING_SUPPORTED
|
||||
#define PNG_PROGRESSIVE_READ_SUPPORTED
|
||||
#define PNG_READ_16BIT_SUPPORTED
|
||||
#define PNG_READ_16_TO_8_SUPPORTED
|
||||
#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_BACKGROUND_SUPPORTED
|
||||
#define PNG_READ_BGR_SUPPORTED
|
||||
#define PNG_READ_bKGD_SUPPORTED
|
||||
#define PNG_READ_cHRM_SUPPORTED
|
||||
#define PNG_READ_COMPOSITE_NODIV_SUPPORTED
|
||||
#define PNG_READ_EXPAND_16_SUPPORTED
|
||||
#define PNG_READ_EXPAND_SUPPORTED
|
||||
#define PNG_READ_FILLER_SUPPORTED
|
||||
#define PNG_READ_gAMA_SUPPORTED
|
||||
#define PNG_READ_GAMMA_SUPPORTED
|
||||
#define PNG_READ_GRAY_TO_RGB_SUPPORTED
|
||||
#define PNG_READ_hIST_SUPPORTED
|
||||
#define PNG_READ_iCCP_SUPPORTED
|
||||
#define PNG_READ_INTERLACING_SUPPORTED
|
||||
#define PNG_READ_INT_FUNCTIONS_SUPPORTED
|
||||
#define PNG_READ_INVERT_ALPHA_SUPPORTED
|
||||
#define PNG_READ_INVERT_SUPPORTED
|
||||
#define PNG_READ_iTXt_SUPPORTED
|
||||
#define PNG_READ_oFFs_SUPPORTED
|
||||
#define PNG_READ_OPT_PLTE_SUPPORTED
|
||||
#define PNG_READ_PACK_SUPPORTED
|
||||
#define PNG_READ_PACKSWAP_SUPPORTED
|
||||
#define PNG_READ_pCAL_SUPPORTED
|
||||
#define PNG_READ_pHYs_SUPPORTED
|
||||
#define PNG_READ_QUANTIZE_SUPPORTED
|
||||
#define PNG_READ_RGB_TO_GRAY_SUPPORTED
|
||||
#define PNG_READ_sBIT_SUPPORTED
|
||||
#define PNG_READ_sCAL_SUPPORTED
|
||||
#define PNG_READ_SHIFT_SUPPORTED
|
||||
#define PNG_READ_sPLT_SUPPORTED
|
||||
#define PNG_READ_sRGB_SUPPORTED
|
||||
#define PNG_READ_STRIP_ALPHA_SUPPORTED
|
||||
#define PNG_READ_SUPPORTED
|
||||
#define PNG_READ_SWAP_ALPHA_SUPPORTED
|
||||
#define PNG_READ_SWAP_SUPPORTED
|
||||
#define PNG_READ_tEXt_SUPPORTED
|
||||
#define PNG_READ_TEXT_SUPPORTED
|
||||
#define PNG_READ_tIME_SUPPORTED
|
||||
#define PNG_READ_TRANSFORMS_SUPPORTED
|
||||
#define PNG_READ_tRNS_SUPPORTED
|
||||
#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_USER_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_USER_TRANSFORM_SUPPORTED
|
||||
#define PNG_READ_zTXt_SUPPORTED
|
||||
#define PNG_SAVE_INT_32_SUPPORTED
|
||||
#define PNG_sBIT_SUPPORTED
|
||||
#define PNG_sCAL_SUPPORTED
|
||||
#define PNG_SEQUENTIAL_READ_SUPPORTED
|
||||
#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED
|
||||
#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
|
||||
#define PNG_SETJMP_SUPPORTED
|
||||
#define PNG_SET_USER_LIMITS_SUPPORTED
|
||||
#define PNG_sPLT_SUPPORTED
|
||||
#define PNG_sRGB_SUPPORTED
|
||||
#define PNG_STDIO_SUPPORTED
|
||||
#define PNG_tEXt_SUPPORTED
|
||||
#define PNG_TEXT_SUPPORTED
|
||||
#define PNG_TIME_RFC1123_SUPPORTED
|
||||
#define PNG_tIME_SUPPORTED
|
||||
#define PNG_tRNS_SUPPORTED
|
||||
#define PNG_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_USER_CHUNKS_SUPPORTED
|
||||
#define PNG_USER_LIMITS_SUPPORTED
|
||||
#define PNG_USER_MEM_SUPPORTED
|
||||
#define PNG_USER_TRANSFORM_INFO_SUPPORTED
|
||||
#define PNG_USER_TRANSFORM_PTR_SUPPORTED
|
||||
#define PNG_WARNINGS_SUPPORTED
|
||||
#define PNG_WRITE_16BIT_SUPPORTED
|
||||
#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
|
||||
#define PNG_WRITE_BGR_SUPPORTED
|
||||
#define PNG_WRITE_bKGD_SUPPORTED
|
||||
#define PNG_WRITE_cHRM_SUPPORTED
|
||||
#define PNG_WRITE_FILLER_SUPPORTED
|
||||
#define PNG_WRITE_FILTER_SUPPORTED
|
||||
#define PNG_WRITE_FLUSH_SUPPORTED
|
||||
#define PNG_WRITE_gAMA_SUPPORTED
|
||||
#define PNG_WRITE_hIST_SUPPORTED
|
||||
#define PNG_WRITE_iCCP_SUPPORTED
|
||||
#define PNG_WRITE_INTERLACING_SUPPORTED
|
||||
#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
|
||||
#define PNG_WRITE_INVERT_ALPHA_SUPPORTED
|
||||
#define PNG_WRITE_INVERT_SUPPORTED
|
||||
#define PNG_WRITE_iTXt_SUPPORTED
|
||||
#define PNG_WRITE_oFFs_SUPPORTED
|
||||
#define PNG_WRITE_PACK_SUPPORTED
|
||||
#define PNG_WRITE_PACKSWAP_SUPPORTED
|
||||
#define PNG_WRITE_pCAL_SUPPORTED
|
||||
#define PNG_WRITE_pHYs_SUPPORTED
|
||||
#define PNG_WRITE_sBIT_SUPPORTED
|
||||
#define PNG_WRITE_sCAL_SUPPORTED
|
||||
#define PNG_WRITE_SHIFT_SUPPORTED
|
||||
#define PNG_WRITE_sPLT_SUPPORTED
|
||||
#define PNG_WRITE_sRGB_SUPPORTED
|
||||
#define PNG_WRITE_SUPPORTED
|
||||
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
|
||||
#define PNG_WRITE_SWAP_SUPPORTED
|
||||
#define PNG_WRITE_tEXt_SUPPORTED
|
||||
#define PNG_WRITE_TEXT_SUPPORTED
|
||||
#define PNG_WRITE_tIME_SUPPORTED
|
||||
#define PNG_WRITE_TRANSFORMS_SUPPORTED
|
||||
#define PNG_WRITE_tRNS_SUPPORTED
|
||||
#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
|
||||
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||
#define PNG_WRITE_zTXt_SUPPORTED
|
||||
#define PNG_zTXt_SUPPORTED
|
||||
/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/
|
||||
/*#undef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED*/
|
||||
/* end of options */
|
||||
#endif /* PNGLCONF_H */
|
@ -1,428 +0,0 @@
|
||||
/* zconf.h -- configuration of the zlib compression library
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef ZCONF_H
|
||||
#define ZCONF_H
|
||||
|
||||
/*
|
||||
* If you *really* need a unique prefix for all types and library functions,
|
||||
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
|
||||
* Even better than compiling with -DZ_PREFIX would be to use configure to set
|
||||
* this permanently in zconf.h using "./configure --zprefix".
|
||||
*/
|
||||
#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
|
||||
|
||||
/* all linked symbols */
|
||||
# define _dist_code z__dist_code
|
||||
# define _length_code z__length_code
|
||||
# define _tr_align z__tr_align
|
||||
# define _tr_flush_block z__tr_flush_block
|
||||
# define _tr_init z__tr_init
|
||||
# define _tr_stored_block z__tr_stored_block
|
||||
# define _tr_tally z__tr_tally
|
||||
# define adler32 z_adler32
|
||||
# define adler32_combine z_adler32_combine
|
||||
# define adler32_combine64 z_adler32_combine64
|
||||
# define compress z_compress
|
||||
# define compress2 z_compress2
|
||||
# define compressBound z_compressBound
|
||||
# define crc32 z_crc32
|
||||
# define crc32_combine z_crc32_combine
|
||||
# define crc32_combine64 z_crc32_combine64
|
||||
# define deflate z_deflate
|
||||
# define deflateBound z_deflateBound
|
||||
# define deflateCopy z_deflateCopy
|
||||
# define deflateEnd z_deflateEnd
|
||||
# define deflateInit2_ z_deflateInit2_
|
||||
# define deflateInit_ z_deflateInit_
|
||||
# define deflateParams z_deflateParams
|
||||
# define deflatePrime z_deflatePrime
|
||||
# define deflateReset z_deflateReset
|
||||
# define deflateSetDictionary z_deflateSetDictionary
|
||||
# define deflateSetHeader z_deflateSetHeader
|
||||
# define deflateTune z_deflateTune
|
||||
# define deflate_copyright z_deflate_copyright
|
||||
# define get_crc_table z_get_crc_table
|
||||
# define gz_error z_gz_error
|
||||
# define gz_intmax z_gz_intmax
|
||||
# define gz_strwinerror z_gz_strwinerror
|
||||
# define gzbuffer z_gzbuffer
|
||||
# define gzclearerr z_gzclearerr
|
||||
# define gzclose z_gzclose
|
||||
# define gzclose_r z_gzclose_r
|
||||
# define gzclose_w z_gzclose_w
|
||||
# define gzdirect z_gzdirect
|
||||
# define gzdopen z_gzdopen
|
||||
# define gzeof z_gzeof
|
||||
# define gzerror z_gzerror
|
||||
# define gzflush z_gzflush
|
||||
# define gzgetc z_gzgetc
|
||||
# define gzgets z_gzgets
|
||||
# define gzoffset z_gzoffset
|
||||
# define gzoffset64 z_gzoffset64
|
||||
# define gzopen z_gzopen
|
||||
# define gzopen64 z_gzopen64
|
||||
# define gzprintf z_gzprintf
|
||||
# define gzputc z_gzputc
|
||||
# define gzputs z_gzputs
|
||||
# define gzread z_gzread
|
||||
# define gzrewind z_gzrewind
|
||||
# define gzseek z_gzseek
|
||||
# define gzseek64 z_gzseek64
|
||||
# define gzsetparams z_gzsetparams
|
||||
# define gztell z_gztell
|
||||
# define gztell64 z_gztell64
|
||||
# define gzungetc z_gzungetc
|
||||
# define gzwrite z_gzwrite
|
||||
# define inflate z_inflate
|
||||
# define inflateBack z_inflateBack
|
||||
# define inflateBackEnd z_inflateBackEnd
|
||||
# define inflateBackInit_ z_inflateBackInit_
|
||||
# define inflateCopy z_inflateCopy
|
||||
# define inflateEnd z_inflateEnd
|
||||
# define inflateGetHeader z_inflateGetHeader
|
||||
# define inflateInit2_ z_inflateInit2_
|
||||
# define inflateInit_ z_inflateInit_
|
||||
# define inflateMark z_inflateMark
|
||||
# define inflatePrime z_inflatePrime
|
||||
# define inflateReset z_inflateReset
|
||||
# define inflateReset2 z_inflateReset2
|
||||
# define inflateSetDictionary z_inflateSetDictionary
|
||||
# define inflateSync z_inflateSync
|
||||
# define inflateSyncPoint z_inflateSyncPoint
|
||||
# define inflateUndermine z_inflateUndermine
|
||||
# define inflate_copyright z_inflate_copyright
|
||||
# define inflate_fast z_inflate_fast
|
||||
# define inflate_table z_inflate_table
|
||||
# define uncompress z_uncompress
|
||||
# define zError z_zError
|
||||
# define zcalloc z_zcalloc
|
||||
# define zcfree z_zcfree
|
||||
# define zlibCompileFlags z_zlibCompileFlags
|
||||
# define zlibVersion z_zlibVersion
|
||||
|
||||
/* all zlib typedefs in zlib.h and zconf.h */
|
||||
# define Byte z_Byte
|
||||
# define Bytef z_Bytef
|
||||
# define alloc_func z_alloc_func
|
||||
# define charf z_charf
|
||||
# define free_func z_free_func
|
||||
# define gzFile z_gzFile
|
||||
# define gz_header z_gz_header
|
||||
# define gz_headerp z_gz_headerp
|
||||
# define in_func z_in_func
|
||||
# define intf z_intf
|
||||
# define out_func z_out_func
|
||||
# define uInt z_uInt
|
||||
# define uIntf z_uIntf
|
||||
# define uLong z_uLong
|
||||
# define uLongf z_uLongf
|
||||
# define voidp z_voidp
|
||||
# define voidpc z_voidpc
|
||||
# define voidpf z_voidpf
|
||||
|
||||
/* all zlib structs in zlib.h and zconf.h */
|
||||
# define gz_header_s z_gz_header_s
|
||||
# define internal_state z_internal_state
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__MSDOS__) && !defined(MSDOS)
|
||||
# define MSDOS
|
||||
#endif
|
||||
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
|
||||
# define OS2
|
||||
#endif
|
||||
#if defined(_WINDOWS) && !defined(WINDOWS)
|
||||
# define WINDOWS
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
|
||||
# ifndef WIN32
|
||||
# define WIN32
|
||||
# endif
|
||||
#endif
|
||||
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
|
||||
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
|
||||
# ifndef SYS16BIT
|
||||
# define SYS16BIT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
|
||||
* than 64k bytes at a time (needed on systems with 16-bit int).
|
||||
*/
|
||||
#ifdef SYS16BIT
|
||||
# define MAXSEG_64K
|
||||
#endif
|
||||
#ifdef MSDOS
|
||||
# define UNALIGNED_OK
|
||||
#endif
|
||||
|
||||
#ifdef __STDC_VERSION__
|
||||
# ifndef STDC
|
||||
# define STDC
|
||||
# endif
|
||||
# if __STDC_VERSION__ >= 199901L
|
||||
# ifndef STDC99
|
||||
# define STDC99
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
|
||||
# define STDC
|
||||
#endif
|
||||
|
||||
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
|
||||
# define STDC
|
||||
#endif
|
||||
|
||||
#ifndef STDC
|
||||
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
|
||||
# define const /* note: need a more gentle solution here */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Some Mac compilers merge all .h files incorrectly: */
|
||||
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
|
||||
# define NO_DUMMY_DECL
|
||||
#endif
|
||||
|
||||
/* Maximum value for memLevel in deflateInit2 */
|
||||
#ifndef MAX_MEM_LEVEL
|
||||
# ifdef MAXSEG_64K
|
||||
# define MAX_MEM_LEVEL 8
|
||||
# else
|
||||
# define MAX_MEM_LEVEL 9
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
|
||||
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
|
||||
* created by gzip. (Files created by minigzip can still be extracted by
|
||||
* gzip.)
|
||||
*/
|
||||
#ifndef MAX_WBITS
|
||||
# define MAX_WBITS 15 /* 32K LZ77 window */
|
||||
#endif
|
||||
|
||||
/* The memory requirements for deflate are (in bytes):
|
||||
(1 << (windowBits+2)) + (1 << (memLevel+9))
|
||||
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
|
||||
plus a few kilobytes for small objects. For example, if you want to reduce
|
||||
the default memory requirements from 256K to 128K, compile with
|
||||
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
|
||||
Of course this will generally degrade compression (there's no free lunch).
|
||||
|
||||
The memory requirements for inflate are (in bytes) 1 << windowBits
|
||||
that is, 32K for windowBits=15 (default value) plus a few kilobytes
|
||||
for small objects.
|
||||
*/
|
||||
|
||||
/* Type declarations */
|
||||
|
||||
#ifndef OF /* function prototypes */
|
||||
# ifdef STDC
|
||||
# define OF(args) args
|
||||
# else
|
||||
# define OF(args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The following definitions for FAR are needed only for MSDOS mixed
|
||||
* model programming (small or medium model with some far allocations).
|
||||
* This was tested only with MSC; for other MSDOS compilers you may have
|
||||
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
|
||||
* just define FAR to be empty.
|
||||
*/
|
||||
#ifdef SYS16BIT
|
||||
# if defined(M_I86SM) || defined(M_I86MM)
|
||||
/* MSC small or medium model */
|
||||
# define SMALL_MEDIUM
|
||||
# ifdef _MSC_VER
|
||||
# define FAR _far
|
||||
# else
|
||||
# define FAR far
|
||||
# endif
|
||||
# endif
|
||||
# if (defined(__SMALL__) || defined(__MEDIUM__))
|
||||
/* Turbo C small or medium model */
|
||||
# define SMALL_MEDIUM
|
||||
# ifdef __BORLANDC__
|
||||
# define FAR _far
|
||||
# else
|
||||
# define FAR far
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(WINDOWS) || defined(WIN32)
|
||||
/* If building or using zlib as a DLL, define ZLIB_DLL.
|
||||
* This is not mandatory, but it offers a little performance increase.
|
||||
*/
|
||||
# ifdef ZLIB_DLL
|
||||
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
|
||||
# ifdef ZLIB_INTERNAL
|
||||
# define ZEXTERN extern __declspec(dllexport)
|
||||
# else
|
||||
# define ZEXTERN extern __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
# endif /* ZLIB_DLL */
|
||||
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
|
||||
* define ZLIB_WINAPI.
|
||||
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
|
||||
*/
|
||||
# ifdef ZLIB_WINAPI
|
||||
# ifdef FAR
|
||||
# undef FAR
|
||||
# endif
|
||||
# include <windows.h>
|
||||
/* No need for _export, use ZLIB.DEF instead. */
|
||||
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
|
||||
# define ZEXPORT WINAPI
|
||||
# ifdef WIN32
|
||||
# define ZEXPORTVA WINAPIV
|
||||
# else
|
||||
# define ZEXPORTVA FAR CDECL
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (__BEOS__)
|
||||
# ifdef ZLIB_DLL
|
||||
# ifdef ZLIB_INTERNAL
|
||||
# define ZEXPORT __declspec(dllexport)
|
||||
# define ZEXPORTVA __declspec(dllexport)
|
||||
# else
|
||||
# define ZEXPORT __declspec(dllimport)
|
||||
# define ZEXPORTVA __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZEXTERN
|
||||
# define ZEXTERN extern
|
||||
#endif
|
||||
#ifndef ZEXPORT
|
||||
# define ZEXPORT
|
||||
#endif
|
||||
#ifndef ZEXPORTVA
|
||||
# define ZEXPORTVA
|
||||
#endif
|
||||
|
||||
#ifndef FAR
|
||||
# define FAR
|
||||
#endif
|
||||
|
||||
#if !defined(__MACTYPES__)
|
||||
typedef unsigned char Byte; /* 8 bits */
|
||||
#endif
|
||||
typedef unsigned int uInt; /* 16 bits or more */
|
||||
typedef unsigned long uLong; /* 32 bits or more */
|
||||
|
||||
#ifdef SMALL_MEDIUM
|
||||
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
|
||||
# define Bytef Byte FAR
|
||||
#else
|
||||
typedef Byte FAR Bytef;
|
||||
#endif
|
||||
typedef char FAR charf;
|
||||
typedef int FAR intf;
|
||||
typedef uInt FAR uIntf;
|
||||
typedef uLong FAR uLongf;
|
||||
|
||||
#ifdef STDC
|
||||
typedef void const *voidpc;
|
||||
typedef void FAR *voidpf;
|
||||
typedef void *voidp;
|
||||
#else
|
||||
typedef Byte const *voidpc;
|
||||
typedef Byte FAR *voidpf;
|
||||
typedef Byte *voidp;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
|
||||
# define Z_HAVE_UNISTD_H
|
||||
#endif
|
||||
|
||||
#ifdef STDC
|
||||
# include <sys/types.h> /* for off_t */
|
||||
#endif
|
||||
|
||||
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
|
||||
* "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
|
||||
* though the former does not conform to the LFS document), but considering
|
||||
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
|
||||
* equivalently requesting no 64-bit operations
|
||||
*/
|
||||
#if -_LARGEFILE64_SOURCE - -1 == 1
|
||||
# undef _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
|
||||
# include <unistd.h> /* for SEEK_* and off_t */
|
||||
# ifdef VMS
|
||||
# include <unixio.h> /* for off_t */
|
||||
# endif
|
||||
# ifndef z_off_t
|
||||
# define z_off_t off_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0 /* Seek from beginning of file. */
|
||||
# define SEEK_CUR 1 /* Seek from current position. */
|
||||
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
|
||||
#endif
|
||||
|
||||
#ifndef z_off_t
|
||||
# define z_off_t long
|
||||
#endif
|
||||
|
||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||
# define z_off64_t off64_t
|
||||
#else
|
||||
# define z_off64_t z_off_t
|
||||
#endif
|
||||
|
||||
#if defined(__OS400__)
|
||||
# define NO_vsnprintf
|
||||
#endif
|
||||
|
||||
#if defined(__MVS__)
|
||||
# define NO_vsnprintf
|
||||
#endif
|
||||
|
||||
/* MVS linker does not support external names larger than 8 bytes */
|
||||
#if defined(__MVS__)
|
||||
#pragma map(deflateInit_,"DEIN")
|
||||
#pragma map(deflateInit2_,"DEIN2")
|
||||
#pragma map(deflateEnd,"DEEND")
|
||||
#pragma map(deflateBound,"DEBND")
|
||||
#pragma map(inflateInit_,"ININ")
|
||||
#pragma map(inflateInit2_,"ININ2")
|
||||
#pragma map(inflateEnd,"INEND")
|
||||
#pragma map(inflateSync,"INSY")
|
||||
#pragma map(inflateSetDictionary,"INSEDI")
|
||||
#pragma map(compressBound,"CMBND")
|
||||
#pragma map(inflate_table,"INTABL")
|
||||
#pragma map(inflate_fast,"INFA")
|
||||
#pragma map(inflate_copyright,"INCOPY")
|
||||
#endif
|
||||
|
||||
#endif /* ZCONF_H */
|
1613
cdeps/win/zlib.h
1613
cdeps/win/zlib.h
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
|
||||
Package clipboard read/write on clipboard
|
||||
*/
|
||||
package clipboard
|
||||
|
@ -1,14 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/go-vgo/robotgo/clipboard"
|
||||
)
|
||||
|
||||
func main() {
|
||||
out, err := ioutil.ReadAll(os.Stdin)
|
||||
out, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -1,34 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
)
|
||||
|
||||
func colorPicker() {
|
||||
// click the left mouse button to get the value
|
||||
m := robotgo.AddEvent("mleft")
|
||||
if m {
|
||||
x, y := robotgo.GetMousePos()
|
||||
fmt.Println("mouse pos: ", x, y)
|
||||
|
||||
clo := robotgo.GetPixelColor(x, y)
|
||||
fmt.Println("color: #", clo)
|
||||
|
||||
// clipboard
|
||||
s1 := fmt.Sprint(x, ", ", y) + ": " + "#" + clo
|
||||
err := robotgo.WriteAll(s1)
|
||||
if err != nil {
|
||||
fmt.Println("clipboard err: ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("color picker: ")
|
||||
fmt.Println("click the left mouse button to get the value.")
|
||||
for {
|
||||
colorPicker()
|
||||
}
|
||||
}
|
119
doc.go
Normal file
119
doc.go
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
package robotgo
|
||||
|
||||
/*
|
||||
Keys are supported:
|
||||
"A-Z a-z 0-9"
|
||||
|
||||
"backspace"
|
||||
"delete"
|
||||
"enter"
|
||||
"tab"
|
||||
"esc"
|
||||
"escape"
|
||||
"up" Up arrow key
|
||||
"down" Down arrow key
|
||||
"right" Right arrow key
|
||||
"left" Left arrow key
|
||||
"home"
|
||||
"end"
|
||||
"pageup"
|
||||
"pagedown"
|
||||
|
||||
"f1"
|
||||
"f2"
|
||||
"f3"
|
||||
"f4"
|
||||
"f5"
|
||||
"f6"
|
||||
"f7"
|
||||
"f8"
|
||||
"f9"
|
||||
"f10"
|
||||
"f11"
|
||||
"f12"
|
||||
"f13"
|
||||
"f14"
|
||||
"f15"
|
||||
"f16"
|
||||
"f17"
|
||||
"f18"
|
||||
"f19"
|
||||
"f20"
|
||||
"f21"
|
||||
"f22"
|
||||
"f23"
|
||||
"f24"
|
||||
|
||||
"cmd" this is the "win" key for windows
|
||||
"lcmd" left command
|
||||
"rcmd" right command
|
||||
// "command"
|
||||
"alt"
|
||||
"lalt" left alt
|
||||
"ralt" right alt
|
||||
"ctrl"
|
||||
"lctrl" left ctrl
|
||||
"rctrl" right ctrl
|
||||
"control"
|
||||
"shift"
|
||||
"lshift" left shift
|
||||
"rshift" right shift
|
||||
// "right_shift"
|
||||
"capslock"
|
||||
"space"
|
||||
"print"
|
||||
"printscreen" // No Mac support
|
||||
"insert"
|
||||
"menu" Windows only
|
||||
|
||||
"audio_mute" Mute the volume
|
||||
"audio_vol_down" Lower the volume
|
||||
"audio_vol_up" Increase the volume
|
||||
"audio_play"
|
||||
"audio_stop"
|
||||
"audio_pause"
|
||||
"audio_prev" Previous Track
|
||||
"audio_next" Next Track
|
||||
"audio_rewind" Linux only
|
||||
"audio_forward" Linux only
|
||||
"audio_repeat" Linux only
|
||||
"audio_random" Linux only
|
||||
|
||||
|
||||
"num0"
|
||||
"num1"
|
||||
"num2"
|
||||
"num3"
|
||||
"num4"
|
||||
"num5"
|
||||
"num6"
|
||||
"num7"
|
||||
"num8"
|
||||
"num9"
|
||||
"num_lock"
|
||||
|
||||
"num."
|
||||
"num+"
|
||||
"num-"
|
||||
"num*"
|
||||
"num/"
|
||||
"num_clear"
|
||||
"num_enter"
|
||||
"num_equal"
|
||||
|
||||
"lights_mon_up" Turn up monitor brightness No Windows support
|
||||
"lights_mon_down" Turn down monitor brightness No Windows support
|
||||
"lights_kbd_toggle" Toggle keyboard backlight on/off No Windows support
|
||||
"lights_kbd_up" Turn up keyboard backlight brightness No Windows support
|
||||
"lights_kbd_down" Turn down keyboard backlight brightness No Windows support
|
||||
*/
|
33
docs/install.md
Normal file
33
docs/install.md
Normal file
@ -0,0 +1,33 @@
|
||||
## CrossCompiling
|
||||
|
||||
##### Windows64 to windows32
|
||||
|
||||
```Go
|
||||
SET CGO_ENABLED=1
|
||||
SET GOARCH=386
|
||||
go build main.go
|
||||
```
|
||||
|
||||
#### Other to windows
|
||||
|
||||
Install Requirements (Ubuntu):
|
||||
|
||||
```bash
|
||||
sudo apt install gcc-multilib
|
||||
sudo apt install gcc-mingw-w64
|
||||
# fix err: zlib.h: No such file or directory, Just used by bitmap.
|
||||
sudo apt install libz-mingw-w64-dev
|
||||
```
|
||||
|
||||
Build the binary:
|
||||
|
||||
```Go
|
||||
GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ./
|
||||
```
|
||||
|
||||
```
|
||||
// CC=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\gcc.exe
|
||||
// CXX=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\g++.exe
|
||||
```
|
||||
|
||||
Some discussions and questions, please see [issues/228](https://github.com/go-vgo/robotgo/issues/228), [issues/143](https://github.com/go-vgo/robotgo/issues/143).
|
28
docs/keys.md
28
docs/keys.md
@ -1,3 +1,25 @@
|
||||
## Type Conversion
|
||||
|
||||
| | type conversion | func |
|
||||
| --- | --------------------------------- | ----------------------- |
|
||||
| \* | robotgo.Bitmap -> robotgo.CBitmap | robotgo.ToCBitmap() |
|
||||
| | robotgo.Bitmap -> \*image.RGBA | robotgo.ToRGBAGo() |
|
||||
| \* | robotgo.CBitmap -> C.MMBitmapRef | robotgo.ToMMBitmapRef() |
|
||||
| | robotgo.CBitmap -> robotgo.Bitmap | robotgo.ToBitmap() |
|
||||
| | robotgo.CBitmap -> image.Image | robotgo.ToImage() |
|
||||
| | robotgo.CBitmap -> \*image.RGBA | robotgo.ToRGBA() |
|
||||
| \* | C.MMBitmapRef -> robotgo.CBitmap | robotgo.CBitmap() |
|
||||
| \* | image.Image -> robotgo.Bitmap | robotgo.ImgToBitmap() |
|
||||
| | image.Image -> robotgo.CBitmap | robotgo.ImgToCBitmap() |
|
||||
| | image.Image -> []byte | robotgo.ToByteImg() |
|
||||
| | image.Image -> string | robotgo.ToStringImg() |
|
||||
| \* | \*image.RGBA -> robotgo.Bitmap | robotgo.RGBAToBitmap() |
|
||||
| \* | []byte -> image.Image | robotgo.ByteToImg() |
|
||||
| | []byte-> robotgo.CBitmap | robotgo.ByteToCBitmap() |
|
||||
| | []byte -> string | string() |
|
||||
| \* | string -> image.Image | robotgo.StrToImg() |
|
||||
| | string -> byte | []byte() |
|
||||
|
||||
# Keys
|
||||
|
||||
```Go
|
||||
@ -46,7 +68,7 @@
|
||||
"cmd" is the "win" key for windows
|
||||
"lcmd" left command
|
||||
"rcmd" right command
|
||||
"command"
|
||||
// "command"
|
||||
"alt"
|
||||
"lalt" left alt
|
||||
"ralt" right alt
|
||||
@ -57,7 +79,7 @@
|
||||
"shift"
|
||||
"lshift" left shift
|
||||
"rshift" right shift
|
||||
"right_shift"
|
||||
// "right_shift"
|
||||
"capslock"
|
||||
"space"
|
||||
"print"
|
||||
@ -118,4 +140,4 @@
|
||||
"lights_kbd_toggle" Toggle keyboard backlight on/off No Windows support
|
||||
"lights_kbd_up" Turn up keyboard backlight brightness No Windows support
|
||||
"lights_kbd_down" Turn down keyboard backlight brightness No Windows support
|
||||
```
|
||||
```
|
||||
|
252
event/goEvent.h
252
event/goEvent.h
@ -1,252 +0,0 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "pub.h"
|
||||
|
||||
|
||||
void dispatch_proc(iohook_event * const event) {
|
||||
char buffer[256] = { 0 };
|
||||
size_t length = snprintf(buffer, sizeof(buffer),
|
||||
"id=%i,when=%" PRIu64 ",mask=0x%X",
|
||||
event->type, event->time, event->mask);
|
||||
|
||||
switch (event->type) {
|
||||
case EVENT_KEY_PRESSED:
|
||||
// If the escape key is pressed, naturally terminate the program.
|
||||
if (event->data.keyboard.keycode == VC_ESCAPE) {
|
||||
// int status = hook_stop();
|
||||
// switch (status) {
|
||||
// // System level errors.
|
||||
// case IOHOOK_ERROR_OUT_OF_MEMORY:
|
||||
// loggerProc(LOG_LEVEL_ERROR, "Failed to allocate memory. (%#X)", status);
|
||||
// break;
|
||||
|
||||
// case IOHOOK_ERROR_X_RECORD_GET_CONTEXT:
|
||||
// // NOTE This is the only platform specific error that occurs on hook_stop().
|
||||
// loggerProc(LOG_LEVEL_ERROR, "Failed to get XRecord context. (%#X)", status);
|
||||
// break;
|
||||
|
||||
// // Default error.
|
||||
// case IOHOOK_FAILURE:
|
||||
// default:
|
||||
// loggerProc(LOG_LEVEL_ERROR, "An unknown hook error occurred. (%#X)", status);
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
case EVENT_KEY_RELEASED:
|
||||
snprintf(buffer + length, sizeof(buffer) - length,
|
||||
",keycode=%u,rawcode=0x%X",
|
||||
event->data.keyboard.keycode, event->data.keyboard.rawcode);
|
||||
int akeyCode = (uint16_t) event->data.keyboard.keycode;
|
||||
|
||||
if (event->data.keyboard.keycode == VC_ESCAPE
|
||||
&& atoi(cevent) == 11) {
|
||||
int stopEvent = stop_event();
|
||||
// printf("stop_event%d\n", stopEvent);
|
||||
cstatus = 0;
|
||||
}
|
||||
|
||||
// printf("atoi(str)---%d\n", atoi(cevent));
|
||||
if (akeyCode == atoi(cevent)) {
|
||||
int stopEvent = stop_event();
|
||||
// printf("%d\n", stopEvent);
|
||||
cstatus = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_KEY_TYPED:
|
||||
snprintf(buffer + length, sizeof(buffer) - length,
|
||||
",keychar=%lc,rawcode=%u",
|
||||
(uint16_t) event->data.keyboard.keychar,
|
||||
event->data.keyboard.rawcode);
|
||||
|
||||
#ifdef WE_REALLY_WANT_A_POINTER
|
||||
char *buf = malloc (6);
|
||||
#else
|
||||
char buf[6];
|
||||
#endif
|
||||
|
||||
sprintf(buf, "%lc", (uint16_t) event->data.keyboard.keychar);
|
||||
|
||||
#ifdef WE_REALLY_WANT_A_POINTER
|
||||
free (buf);
|
||||
#endif
|
||||
|
||||
if (strcmp(buf, cevent) == 0) {
|
||||
int stopEvent = stop_event();
|
||||
// printf("%d\n", stopEvent);
|
||||
cstatus = 0;
|
||||
}
|
||||
// return (char*) event->data.keyboard.keychar;
|
||||
break;
|
||||
|
||||
case EVENT_MOUSE_PRESSED:
|
||||
case EVENT_MOUSE_RELEASED:
|
||||
case EVENT_MOUSE_CLICKED:
|
||||
case EVENT_MOUSE_MOVED:
|
||||
case EVENT_MOUSE_DRAGGED:
|
||||
snprintf(buffer + length, sizeof(buffer) - length,
|
||||
",x=%i,y=%i,button=%i,clicks=%i",
|
||||
event->data.mouse.x, event->data.mouse.y,
|
||||
event->data.mouse.button, event->data.mouse.clicks);
|
||||
|
||||
int abutton = event->data.mouse.button;
|
||||
int aclicks = event->data.mouse.clicks;
|
||||
int amouse = -1;
|
||||
|
||||
if (strcmp(cevent, "mleft") == 0) {
|
||||
amouse = 1;
|
||||
}
|
||||
if (strcmp(cevent, "mright") == 0) {
|
||||
amouse = 2;
|
||||
}
|
||||
if (strcmp(cevent, "wheelDown") == 0) {
|
||||
amouse = 4;
|
||||
}
|
||||
if (strcmp(cevent, "wheelUp") == 0) {
|
||||
amouse = 5;
|
||||
}
|
||||
if (strcmp(cevent, "wheelLeft") == 0) {
|
||||
amouse = 6;
|
||||
}
|
||||
if (strcmp(cevent, "wheelRight") == 0) {
|
||||
amouse = 7;
|
||||
}
|
||||
if (abutton == amouse && aclicks == 1) {
|
||||
int stopEvent = stop_event();
|
||||
cstatus = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EVENT_MOUSE_WHEEL:
|
||||
snprintf(buffer + length, sizeof(buffer) - length,
|
||||
",type=%i,amount=%i,rotation=%i",
|
||||
event->data.wheel.type, event->data.wheel.amount,
|
||||
event->data.wheel.rotation);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// fprintf(stdout, "----%s\n", buffer);
|
||||
}
|
||||
|
||||
int add_event(char *key_event) {
|
||||
// (uint16_t *)
|
||||
cevent = key_event;
|
||||
// Set the logger callback for library output.
|
||||
hookSetlogger(&loggerProc);
|
||||
|
||||
// Set the event callback for IOhook events.
|
||||
hook_set_dispatch_proc(&dispatch_proc);
|
||||
// Start the hook and block.
|
||||
// NOTE If EVENT_HOOK_ENABLED was delivered, the status will always succeed.
|
||||
int status = hook_run();
|
||||
|
||||
switch (status) {
|
||||
case IOHOOK_SUCCESS:
|
||||
// Everything is ok.
|
||||
break;
|
||||
|
||||
// System level errors.
|
||||
case IOHOOK_ERROR_OUT_OF_MEMORY:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to allocate memory. (%#X)", status);
|
||||
break;
|
||||
|
||||
|
||||
// X11 specific errors.
|
||||
case IOHOOK_ERROR_X_OPEN_DISPLAY:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to open X11 display. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_X_RECORD_NOT_FOUND:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Unable to locate XRecord extension. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_X_RECORD_ALLOC_RANGE:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Unable to allocate XRecord range. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_X_RECORD_CREATE_CONTEXT:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Unable to allocate XRecord context. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_X_RECORD_ENABLE_CONTEXT:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to enable XRecord context. (%#X)", status);
|
||||
break;
|
||||
|
||||
|
||||
// Windows specific errors.
|
||||
case IOHOOK_ERROR_SET_WINDOWS_HOOK_EX:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to register low level windows hook. (%#X)", status);
|
||||
break;
|
||||
|
||||
|
||||
// Darwin specific errors.
|
||||
case IOHOOK_ERROR_AXAPI_DISABLED:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to enable access for assistive devices. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_CREATE_EVENT_PORT:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to create apple event port. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_CREATE_RUN_LOOP_SOURCE:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to create apple run loop source. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_GET_RUNLOOP:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to acquire apple run loop. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_CREATE_OBSERVER:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to create apple run loop observer. (%#X)", status);
|
||||
break;
|
||||
|
||||
// Default error.
|
||||
case IOHOOK_FAILURE:
|
||||
default:
|
||||
loggerProc(LOG_LEVEL_ERROR, "An unknown hook error occurred. (%#X)", status);
|
||||
break;
|
||||
}
|
||||
|
||||
// return status;
|
||||
// printf("%d\n", status);
|
||||
return cstatus;
|
||||
}
|
||||
|
||||
int stop_event(){
|
||||
int status = hook_stop();
|
||||
switch (status) {
|
||||
// System level errors.
|
||||
case IOHOOK_ERROR_OUT_OF_MEMORY:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to allocate memory. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_X_RECORD_GET_CONTEXT:
|
||||
// NOTE This is the only platform specific error that occurs on hook_stop().
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to get XRecord context. (%#X)", status);
|
||||
break;
|
||||
|
||||
// Default error.
|
||||
case IOHOOK_FAILURE:
|
||||
default:
|
||||
// loggerProc(LOG_LEVEL_ERROR, "An unknown hook error occurred. (%#X)", status);
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
95
event/pub.h
95
event/pub.h
@ -1,95 +0,0 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#include "../base/os.h"
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
#include "../cdeps/hook/darwin/input_c.h"
|
||||
#include "../cdeps/hook/darwin/hook_c.h"
|
||||
#include "../cdeps/hook/darwin/event_c.h"
|
||||
#include "../cdeps/hook/darwin/properties_c.h"
|
||||
#elif defined(USE_X11)
|
||||
//#define USE_XKBCOMMON 0
|
||||
#include "../cdeps/hook/x11/input_c.h"
|
||||
#include "../cdeps/hook/x11/hook_c.h"
|
||||
#include "../cdeps/hook/x11/event_c.h"
|
||||
#include "../cdeps/hook/x11/properties_c.h"
|
||||
#elif defined(IS_WINDOWS)
|
||||
#include "../cdeps/hook/windows/input_c.h"
|
||||
#include "../cdeps/hook/windows/hook_c.h"
|
||||
#include "../cdeps/hook/windows/event_c.h"
|
||||
#include "../cdeps/hook/windows/properties_c.h"
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "../cdeps/hook/iohook.h"
|
||||
|
||||
|
||||
int vccode[100];
|
||||
int codesz;
|
||||
|
||||
char *cevent;
|
||||
int rrevent;
|
||||
// uint16_t *cevent;
|
||||
int cstatus = 1;
|
||||
|
||||
|
||||
int stop_event();
|
||||
int add_event(char *key_event);
|
||||
// int allEvent(char *key_event);
|
||||
int allEvent(char *key_event, int vcode[], int size);
|
||||
|
||||
// NOTE: The following callback executes on the same thread that hook_run() is called
|
||||
// from.
|
||||
|
||||
struct _MEvent {
|
||||
uint8_t id;
|
||||
size_t mask;
|
||||
uint16_t keychar;
|
||||
// char *keychar;
|
||||
size_t x;
|
||||
uint8_t y;
|
||||
uint8_t bytesPerPixel;
|
||||
};
|
||||
|
||||
typedef struct _MEvent MEvent;
|
||||
// typedef MMBitmap *MMBitmapRef;
|
||||
|
||||
MEvent mEvent;
|
||||
|
||||
|
||||
bool loggerProc(unsigned int level, const char *format, ...) {
|
||||
bool status = false;
|
||||
|
||||
va_list args;
|
||||
switch (level) {
|
||||
#ifdef USE_DEBUG
|
||||
case LOG_LEVEL_DEBUG:
|
||||
case LOG_LEVEL_INFO:
|
||||
va_start(args, format);
|
||||
status = vfprintf(stdout, format, args) >= 0;
|
||||
va_end(args);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case LOG_LEVEL_WARN:
|
||||
case LOG_LEVEL_ERROR:
|
||||
va_start(args, format);
|
||||
status = vfprintf(stderr, format, args) >= 0;
|
||||
va_end(args);
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
@ -68,7 +68,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
x, y := robotgo.GetMousePos()
|
||||
x, y := robotgo.Location()
|
||||
fmt.Println("pos:", x, y)
|
||||
color := robotgo.GetPixelColor(100, 200)
|
||||
fmt.Println("color----", color)
|
||||
|
@ -1,34 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
|
||||
"image/jpeg"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
"golang.org/x/image/bmp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
bitMap := robotgo.CaptureScreen()
|
||||
defer robotgo.FreeBitmap(bitMap)
|
||||
|
||||
bs := robotgo.ToBitmapBytes(bitMap)
|
||||
img, err := bmp.Decode(bytes.NewReader(bs))
|
||||
if err != nil {
|
||||
log.Println("bmp.Decode err is: ", err)
|
||||
return
|
||||
}
|
||||
|
||||
b := new(bytes.Buffer)
|
||||
err = jpeg.Encode(b, img, &jpeg.Options{Quality: 20})
|
||||
if err != nil {
|
||||
log.Println("jpeg.Encode err is: ", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("bytes: ", b.Bytes())
|
||||
ioutil.WriteFile("out.jpg", b.Bytes(), 0666)
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-vgo/robotgo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
bmp, free := loadBitmaps("start.png", "chest.png", "eat.png")
|
||||
defer free()
|
||||
|
||||
for {
|
||||
clickBitmap(bmp["start.png"], false)
|
||||
clickBitmap(bmp["chest.png"], true)
|
||||
clickBitmap(bmp["eat.png"], false)
|
||||
}
|
||||
}
|
||||
|
||||
func loadBitmaps(files ...string) (bitmaps map[string]robotgo.Bitmap, free func()) {
|
||||
freeFuncs := make([]func(), 0)
|
||||
bitmaps = make(map[string]robotgo.Bitmap)
|
||||
for _, f := range files {
|
||||
bitmap, freeFunc := readBitmap(f)
|
||||
bitmaps[f] = bitmap
|
||||
freeFuncs = append(freeFuncs, freeFunc)
|
||||
}
|
||||
|
||||
free = func() {
|
||||
for key := range freeFuncs {
|
||||
freeFuncs[key]()
|
||||
}
|
||||
}
|
||||
return bitmaps, free
|
||||
}
|
||||
|
||||
func readBitmap(file string) (bitmap robotgo.Bitmap, free func()) {
|
||||
cBitmap := robotgo.OpenBitmap(file)
|
||||
bitmap = robotgo.ToBitmap(cBitmap)
|
||||
free = func() {
|
||||
robotgo.FreeBitmap(cBitmap)
|
||||
}
|
||||
return bitmap, free
|
||||
}
|
||||
|
||||
func clickBitmap(bmp robotgo.Bitmap, doubleClick bool) bool {
|
||||
fx, fy := robotgo.FindBitmap(robotgo.ToCBitmap(bmp))
|
||||
if fx != -1 && fy != -1 {
|
||||
robotgo.MoveMouse(fx, fy)
|
||||
robotgo.MouseClick("left", doubleClick)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
"github.com/vcaesar/imgo"
|
||||
)
|
||||
|
||||
//go:embed test_007.jpeg
|
||||
var testPng []byte
|
||||
|
||||
func main() {
|
||||
bit1 := robotgo.CaptureScreen(300, 300, 100, 100)
|
||||
defer robotgo.FreeBitmap(bit1)
|
||||
robotgo.SaveBitmap(bit1, "test_003.jpeg")
|
||||
|
||||
m1 := robotgo.ToImage(bit1)
|
||||
fmt.Println("m1: ", m1.Bounds())
|
||||
imgo.SaveToPNG("test_01.png", m1)
|
||||
|
||||
r1 := robotgo.ToRGBA(bit1)
|
||||
fmt.Println("r1: ", r1.Pix)
|
||||
|
||||
bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(m1))
|
||||
robotgo.SaveBitmap(bit2, "test_002.jpeg")
|
||||
|
||||
test()
|
||||
}
|
||||
|
||||
func test() {
|
||||
bitmap := robotgo.CaptureScreen(10, 10, 10, 10)
|
||||
defer robotgo.FreeBitmap(bitmap)
|
||||
|
||||
img := robotgo.ToImage(bitmap)
|
||||
robotgo.SavePng(img, "test_1.png")
|
||||
|
||||
img1, _ := robotgo.ByteToImg(testPng)
|
||||
robotgo.SaveJpeg(img1, "test_7.jpeg")
|
||||
|
||||
bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(img))
|
||||
fx, fy := robotgo.FindBitmap(bit2)
|
||||
fmt.Println("FindBitmap------ ", fx, fy)
|
||||
|
||||
arr := robotgo.FindAllBitmap(bit2)
|
||||
fmt.Println("Find every bitmap: ", arr)
|
||||
robotgo.SaveBitmap(bitmap, "test.png")
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 3.2 KiB |
@ -1,207 +0,0 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
"github.com/vcaesar/imgo"
|
||||
// "go-vgo/robotgo"
|
||||
)
|
||||
|
||||
func toBitmap(bmp robotgo.CBitmap) {
|
||||
bitmap := robotgo.ToMMBitmapRef(bmp)
|
||||
img := robotgo.ToImage(bitmap)
|
||||
fmt.Println("img: ", img)
|
||||
imgo.SaveToPNG("test_IMG.png", img)
|
||||
|
||||
gbit := robotgo.ToBitmap(bitmap)
|
||||
fmt.Println("go bitmap", gbit, gbit.Width)
|
||||
|
||||
cbit := robotgo.ToCBitmap(gbit)
|
||||
// defer robotgo.FreeBitmap(cbit)
|
||||
log.Println("cbit == bitmap: ", cbit == bitmap)
|
||||
robotgo.SaveBitmap(cbit, "tocbitmap.png")
|
||||
}
|
||||
|
||||
// find color
|
||||
func findColor(bmp robotgo.CBitmap) {
|
||||
bitmap := robotgo.ToMMBitmapRef(bmp)
|
||||
|
||||
// find the color in bitmap
|
||||
color := robotgo.GetColor(bitmap, 1, 2)
|
||||
fmt.Println("color...", color)
|
||||
cx, cy := robotgo.FindColor(robotgo.CHex(color), bitmap, 1.0)
|
||||
fmt.Println("pos...", cx, cy)
|
||||
cx, cy = robotgo.FindColor(robotgo.CHex(color))
|
||||
fmt.Println("pos...", cx, cy)
|
||||
|
||||
cx, cy = robotgo.FindColor(0xAADCDC, bitmap)
|
||||
fmt.Println("pos...", cx, cy)
|
||||
cx, cy = robotgo.FindColor(0xAADCDC, nil, 0.1)
|
||||
fmt.Println("pos...", cx, cy)
|
||||
|
||||
cx, cy = robotgo.FindColorCS(0xAADCDC, 388, 179, 300, 300)
|
||||
fmt.Println("pos...", cx, cy)
|
||||
|
||||
cnt := robotgo.CountColor(0xAADCDC, bitmap)
|
||||
fmt.Println("count...", cnt)
|
||||
cnt1 := robotgo.CountColorCS(0xAADCDC, 10, 20, 30, 40)
|
||||
fmt.Println("count...", cnt1)
|
||||
|
||||
arr := robotgo.FindAllColor(0xAADCDC)
|
||||
fmt.Println("find all color: ", arr)
|
||||
for i := 0; i < len(arr); i++ {
|
||||
fmt.Println("pos is: ", arr[i].X, arr[i].Y)
|
||||
}
|
||||
}
|
||||
|
||||
func bitmapString(bmp robotgo.CBitmap) {
|
||||
bitmap := robotgo.ToMMBitmapRef(bmp)
|
||||
|
||||
// creates bitmap from string by bitmap
|
||||
bitstr := robotgo.TostringBitmap(bitmap)
|
||||
fmt.Println("bitstr...", bitstr)
|
||||
|
||||
// sbitmap := robotgo.BitmapFromstring(bitstr, 2)
|
||||
// fmt.Println("...", sbitmap)
|
||||
|
||||
// sbitmap := robotgo.BitmapStr(bitstr)
|
||||
sbitmap := robotgo.BitmapFromStr(bitstr)
|
||||
fmt.Println("bitmap str...", sbitmap)
|
||||
robotgo.SaveBitmap(sbitmap, "teststr.png")
|
||||
}
|
||||
|
||||
func bitmapTool(bmp robotgo.CBitmap) {
|
||||
bitmap := robotgo.ToMMBitmapRef(bmp)
|
||||
|
||||
// bitmap := robotgo.CaptureScreen(10, 20, 30, 40)
|
||||
abool := robotgo.PointInBounds(bitmap, 1, 2)
|
||||
fmt.Println("point in bounds...", abool)
|
||||
|
||||
// returns new bitmap object created from a portion of another
|
||||
bitpos := robotgo.GetPortion(bitmap, 10, 10, 11, 10)
|
||||
fmt.Println(bitpos)
|
||||
|
||||
// saves image to absolute filepath in the given format
|
||||
robotgo.SaveBitmap(bitmap, "test.png")
|
||||
robotgo.SaveBitmap(bitmap, "test31.tif", 1)
|
||||
}
|
||||
|
||||
func decode() {
|
||||
img, name, err := robotgo.DecodeImg("test.png")
|
||||
if err != nil {
|
||||
log.Println("decode image ", err)
|
||||
}
|
||||
fmt.Println("decode test.png", img, name)
|
||||
|
||||
byt, _ := robotgo.OpenImg("test.png")
|
||||
imgo.SaveByte("test2.png", byt)
|
||||
|
||||
w, h := robotgo.GetImgSize("test.png")
|
||||
fmt.Println("image width and hight ", w, h)
|
||||
w, h, _ = imgo.GetSize("test.png")
|
||||
fmt.Println("image width and hight ", w, h)
|
||||
|
||||
// convert image
|
||||
robotgo.Convert("test.png", "test.tif")
|
||||
}
|
||||
|
||||
func bitmapTest(bmp robotgo.CBitmap) {
|
||||
bitmap := robotgo.ToMMBitmapRef(bmp)
|
||||
|
||||
bit := robotgo.CaptureScreen(1, 2, 40, 40)
|
||||
defer robotgo.FreeBitmap(bit)
|
||||
fmt.Println("CaptureScreen...", bit)
|
||||
|
||||
// searches for needle in bitmap
|
||||
fx, fy := robotgo.FindBitmap(bit, bitmap)
|
||||
fmt.Println("FindBitmap------", fx, fy)
|
||||
|
||||
// fx, fy := robotgo.FindBit(bitmap)
|
||||
// fmt.Println("FindBitmap------", fx, fy)
|
||||
|
||||
fx, fy = robotgo.FindBitmap(bit)
|
||||
fmt.Println("FindBitmap------", fx, fy)
|
||||
|
||||
fx, fy = robotgo.FindBitmap(bit, nil, 0.2)
|
||||
fmt.Println("find bitmap: ", fx, fy)
|
||||
|
||||
fx, fy = robotgo.FindBitmap(bit, bitmap, 0.3)
|
||||
fmt.Println("find bitmap: ", fx, fy)
|
||||
}
|
||||
|
||||
func findBitmap(bmp robotgo.CBitmap) {
|
||||
fx, fy := robotgo.FindBitmap(robotgo.ToMMBitmapRef(bmp))
|
||||
fmt.Println("findBitmap: ", fx, fy)
|
||||
|
||||
fx, fy = robotgo.FindCBitmap(bmp)
|
||||
fmt.Println("findCBitmap: ", fx, fy)
|
||||
fx, fy = robotgo.FindCBitmap(bmp, nil, 0.1)
|
||||
fmt.Println("findCBitmap: ", fx, fy)
|
||||
|
||||
// open image bitmap
|
||||
openbit := robotgo.OpenBitmap("test.tif")
|
||||
fmt.Println("openBitmap...", openbit)
|
||||
|
||||
fx, fy = robotgo.FindBitmap(openbit)
|
||||
fmt.Println("FindBitmap------", fx, fy)
|
||||
|
||||
fx, fy = robotgo.FindPic("test.tif")
|
||||
fmt.Println("FindPic------", fx, fy)
|
||||
|
||||
arr := robotgo.FindAllBitmap(openbit)
|
||||
fmt.Println("find all bitmap: ", arr)
|
||||
for i := 0; i < len(arr); i++ {
|
||||
fmt.Println("pos is: ", arr[i].X, arr[i].Y)
|
||||
}
|
||||
}
|
||||
|
||||
func bitmap() {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Bitmap
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// gets all of the screen
|
||||
abitMap := robotgo.CaptureScreen()
|
||||
fmt.Println("abitMap...", abitMap)
|
||||
|
||||
// gets part of the screen
|
||||
bitmap := robotgo.CaptureScreen(100, 200, 30, 30)
|
||||
defer robotgo.FreeBitmap(bitmap)
|
||||
fmt.Println("CaptureScreen...", bitmap)
|
||||
|
||||
cbit := robotgo.CBitmap(bitmap)
|
||||
toBitmap(cbit)
|
||||
|
||||
findColor(cbit)
|
||||
|
||||
count := robotgo.CountBitmap(abitMap, bitmap)
|
||||
fmt.Println("count...", count)
|
||||
|
||||
bitmapTest(cbit)
|
||||
findBitmap(cbit)
|
||||
|
||||
bitmapString(cbit)
|
||||
bitmapTool(cbit)
|
||||
|
||||
decode()
|
||||
|
||||
// free the bitmap
|
||||
robotgo.FreeBitmap(abitMap)
|
||||
// robotgo.FreeBitmap(bitmap)
|
||||
}
|
||||
|
||||
func main() {
|
||||
bitmap()
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
// "go-vgo/robotgo"
|
||||
)
|
||||
|
||||
func addEvent() {
|
||||
fmt.Println("--- Please press ctrl + shift + q ---")
|
||||
ok := robotgo.AddEvents("q", "ctrl", "shift")
|
||||
if ok {
|
||||
fmt.Println("add events...")
|
||||
}
|
||||
|
||||
fmt.Println("--- Please press w---")
|
||||
ok = robotgo.AddEvents("w")
|
||||
if ok {
|
||||
fmt.Println("add events")
|
||||
}
|
||||
|
||||
// start hook
|
||||
s := robotgo.Start()
|
||||
// end hook
|
||||
defer robotgo.End()
|
||||
|
||||
for ev := range s {
|
||||
fmt.Println("hook: ", ev)
|
||||
}
|
||||
}
|
||||
|
||||
func addMouse() {
|
||||
fmt.Println("--- Please press left mouse button ---")
|
||||
ok := robotgo.AddMouse("left")
|
||||
if ok {
|
||||
fmt.Println("add mouse...")
|
||||
}
|
||||
|
||||
fmt.Println("--- Please press left mouse button and move mosue to 100,100 ---")
|
||||
ok = robotgo.AddMouse("left", 100, 100)
|
||||
if ok {
|
||||
fmt.Println("add mouse and move to 100,100 ...")
|
||||
}
|
||||
|
||||
fmt.Println("--- Please move mosue to 100,100 ---")
|
||||
ok = robotgo.AddMousePos(100, 100)
|
||||
if ok {
|
||||
fmt.Println(" move mouse to 100,100 ...")
|
||||
}
|
||||
}
|
||||
|
||||
func add() {
|
||||
fmt.Println("--- Please press v---")
|
||||
eve := robotgo.AddEvent("v")
|
||||
|
||||
if eve {
|
||||
fmt.Println("--- You press v---", "v")
|
||||
}
|
||||
|
||||
fmt.Println("--- Please press k---")
|
||||
keve := robotgo.AddEvent("k")
|
||||
if keve {
|
||||
fmt.Println("--- You press k---", "k")
|
||||
}
|
||||
|
||||
fmt.Println("--- Please press f1---")
|
||||
feve := robotgo.AddEvent("f1")
|
||||
if feve {
|
||||
fmt.Println("You press...", "f1")
|
||||
}
|
||||
}
|
||||
|
||||
func event() {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Global event listener
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
add()
|
||||
|
||||
fmt.Println("--- Please press left mouse button---")
|
||||
mleft := robotgo.AddEvent("mleft")
|
||||
if mleft {
|
||||
fmt.Println("--- You press left mouse button---", "mleft")
|
||||
}
|
||||
|
||||
mright := robotgo.AddEvent("mright")
|
||||
if mright {
|
||||
fmt.Println("--- You press right mouse button---", "mright")
|
||||
}
|
||||
|
||||
// stop AddEvent
|
||||
// robotgo.StopEvent()
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("test begin...")
|
||||
|
||||
addEvent()
|
||||
|
||||
addMouse()
|
||||
|
||||
event()
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
hook "github.com/robotn/gohook"
|
||||
)
|
||||
|
||||
// hook listen and return values using detailed examples
|
||||
func add() {
|
||||
s := hook.Start()
|
||||
defer hook.End()
|
||||
|
||||
ct := false
|
||||
for {
|
||||
i := <-s
|
||||
|
||||
if i.Kind == hook.KeyHold && i.Rawcode == 59 {
|
||||
ct = true
|
||||
}
|
||||
|
||||
if ct && i.Rawcode == 12 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// base hook example
|
||||
func base() {
|
||||
evChan := hook.Start()
|
||||
defer hook.End()
|
||||
|
||||
for ev := range evChan {
|
||||
fmt.Println("hook: ", ev)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
base()
|
||||
|
||||
add()
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
// Copyright 2016 The cauefcr Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/cauefcr/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
hook "github.com/robotn/gohook"
|
||||
)
|
||||
|
||||
func addEvent() {
|
||||
fmt.Println("--- Please press ctrl + shift + q to stop hook ---")
|
||||
robotgo.EventHook(hook.KeyDown, []string{"q", "ctrl", "shift"}, func(e hook.Event) {
|
||||
fmt.Println("ctrl-shift-q")
|
||||
robotgo.EventEnd()
|
||||
})
|
||||
|
||||
fmt.Println("--- Please press w---")
|
||||
robotgo.EventHook(hook.KeyDown, []string{"w"}, func(e hook.Event) {
|
||||
fmt.Println("w")
|
||||
})
|
||||
|
||||
s := robotgo.EventStart()
|
||||
<-robotgo.EventProcess(s)
|
||||
}
|
||||
|
||||
func addMouse() {
|
||||
fmt.Println("--- Please press left mouse button to see it's position and the right mouse button to exit ---")
|
||||
robotgo.EventHook(hook.MouseDown, []string{}, func(e hook.Event) {
|
||||
if e.Button == hook.MouseMap["left"] {
|
||||
fmt.Printf("mouse left @ %v - %v\n", e.X, e.Y)
|
||||
} else if e.Button == hook.MouseMap["right"] {
|
||||
robotgo.EventEnd()
|
||||
}
|
||||
})
|
||||
|
||||
s := robotgo.EventStart()
|
||||
<-robotgo.EventProcess(s)
|
||||
}
|
||||
|
||||
func lowLevel() {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Global event listener
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
fmt.Println("Press q to stop event gathering")
|
||||
evChan := robotgo.EventStart()
|
||||
for e := range evChan {
|
||||
fmt.Println(e)
|
||||
if e.Keychar == 'q' {
|
||||
robotgo.EventEnd()
|
||||
// break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("test begin...")
|
||||
addEvent()
|
||||
|
||||
addMouse()
|
||||
|
||||
lowLevel()
|
||||
}
|
@ -18,26 +18,29 @@ import (
|
||||
)
|
||||
|
||||
func typeStr() {
|
||||
// importing "Hello World"
|
||||
robotgo.TypeStr("Hello World!", 1.0)
|
||||
// typing "Hello World"
|
||||
robotgo.TypeStr("Hello World!", 0, 1)
|
||||
robotgo.KeySleep = 100
|
||||
robotgo.TypeStr("だんしゃり")
|
||||
|
||||
robotgo.TypeStr("Hi galaxy. こんにちは世界. 你好, 再见!")
|
||||
|
||||
robotgo.TypeStr("Hi galaxy, hi stars, hi MT.Rainier, hi sea. こんにちは世界.")
|
||||
robotgo.TypeStr("So, hi, bye! 你好, 再见!")
|
||||
robotgo.Sleep(1)
|
||||
robotgo.TypeStr("So, hi, bye!")
|
||||
|
||||
robotgo.TypeStr("Hi, Seattle space needle, Golden gate bridge, One world trade center.")
|
||||
robotgo.MilliSleep(100)
|
||||
|
||||
ustr := uint32(robotgo.CharCodeAt("So, hi, bye!", 0))
|
||||
robotgo.UnicodeType(ustr)
|
||||
|
||||
robotgo.PasteStr("paste string")
|
||||
err := robotgo.PasteStr("paste string")
|
||||
fmt.Println("PasteStr: ", err)
|
||||
}
|
||||
|
||||
func keyTap() {
|
||||
// press "enter"
|
||||
robotgo.KeyTap("enter")
|
||||
robotgo.KeyTap(robotgo.Enter)
|
||||
robotgo.KeySleep = 200
|
||||
robotgo.KeyTap("a")
|
||||
robotgo.MilliSleep(100)
|
||||
@ -45,19 +48,19 @@ func keyTap() {
|
||||
|
||||
// hide window
|
||||
err := robotgo.KeyTap("h", "cmd")
|
||||
if err != "" {
|
||||
if err != nil {
|
||||
fmt.Println("robotgo.KeyTap run error is: ", err)
|
||||
}
|
||||
|
||||
robotgo.KeyTap("h", "cmd", 12)
|
||||
robotgo.KeyTap("h", "cmd")
|
||||
|
||||
// press "i", "alt", "command" Key combination
|
||||
robotgo.KeyTap("i", "alt", "command")
|
||||
robotgo.KeyTap("i", "alt", "cmd", 11)
|
||||
robotgo.KeyTap(robotgo.KeyI, robotgo.Alt, robotgo.Cmd)
|
||||
robotgo.KeyTap("i", "alt", "cmd")
|
||||
|
||||
arr := []string{"alt", "cmd"}
|
||||
robotgo.KeyTap("i", arr)
|
||||
robotgo.KeyTap("i", arr, 12)
|
||||
robotgo.KeyTap("i", arr)
|
||||
|
||||
robotgo.KeyTap("i", "cmd", " alt", "shift")
|
||||
|
||||
@ -71,9 +74,17 @@ func keyTap() {
|
||||
robotgo.KeyTap("a", "control")
|
||||
}
|
||||
|
||||
func special() {
|
||||
robotgo.TypeStr("{}")
|
||||
robotgo.KeyTap("[", "]")
|
||||
|
||||
robotgo.KeyToggle("(")
|
||||
robotgo.KeyToggle("(", "up")
|
||||
}
|
||||
|
||||
func keyToggle() {
|
||||
// robotgo.KeySleep = 150
|
||||
robotgo.KeyToggle("a", "down")
|
||||
robotgo.KeyToggle(robotgo.KeyA)
|
||||
robotgo.KeyToggle("a", "down", "alt")
|
||||
robotgo.Sleep(1)
|
||||
|
||||
@ -81,8 +92,8 @@ func keyToggle() {
|
||||
robotgo.MilliSleep(100)
|
||||
robotgo.KeyToggle("q", "up", "alt", "cmd", "shift")
|
||||
|
||||
err := robotgo.KeyToggle("enter", "down")
|
||||
if err != "" {
|
||||
err := robotgo.KeyToggle(robotgo.Enter)
|
||||
if err != nil {
|
||||
fmt.Println("robotgo.KeyToggle run error is: ", err)
|
||||
}
|
||||
}
|
||||
@ -110,6 +121,7 @@ func key() {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typeStr()
|
||||
special()
|
||||
|
||||
keyTap()
|
||||
keyToggle()
|
||||
|
@ -25,9 +25,7 @@ func move() {
|
||||
// move the mouse to 100, 200
|
||||
robotgo.Move(100, 200)
|
||||
|
||||
robotgo.Drag(10, 10)
|
||||
robotgo.Drag(20, 20, "right")
|
||||
//
|
||||
// drag mouse with smooth
|
||||
robotgo.DragSmooth(10, 10)
|
||||
robotgo.DragSmooth(100, 200, 1.0, 100.0)
|
||||
|
||||
@ -37,7 +35,7 @@ func move() {
|
||||
robotgo.MoveSmoothRelative(10, -100, 1.0, 30.0)
|
||||
|
||||
for i := 0; i < 1080; i += 1000 {
|
||||
fmt.Println(i)
|
||||
fmt.Println("i: ", i)
|
||||
// MoveMouse(800, i)
|
||||
robotgo.Move(800, i)
|
||||
}
|
||||
@ -57,7 +55,7 @@ func click() {
|
||||
|
||||
func get() {
|
||||
// gets the mouse coordinates
|
||||
x, y := robotgo.GetMousePos()
|
||||
x, y := robotgo.Location()
|
||||
fmt.Println("pos:", x, y)
|
||||
if x == 456 && y == 586 {
|
||||
fmt.Println("mouse...", "586")
|
||||
@ -68,10 +66,15 @@ func get() {
|
||||
|
||||
func toggleAndScroll() {
|
||||
// scrolls the mouse either up
|
||||
// robotgo.ScrollMouse(10, "up")
|
||||
robotgo.ScrollDir(10, "up")
|
||||
robotgo.ScrollDir(10, "right")
|
||||
|
||||
robotgo.Scroll(100, 10)
|
||||
robotgo.Scroll(0, -10)
|
||||
|
||||
robotgo.Toggle("left")
|
||||
robotgo.Toggle("left", "up")
|
||||
|
||||
// toggles the right mouse button
|
||||
robotgo.Toggle("right")
|
||||
robotgo.Toggle("right", "up")
|
||||
|
@ -7,27 +7,44 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
//
|
||||
// syscall.NewLazyDLL("user32.dll").NewProc("SetProcessDPIAware").Call()
|
||||
|
||||
width, height := robotgo.GetScaleSize()
|
||||
fmt.Println("get scale screen size: ", width, height)
|
||||
|
||||
bitmap := robotgo.CaptureScreen(0, 0, width, height)
|
||||
robotgo.SaveBitmap(bitmap, "test.png")
|
||||
defer robotgo.FreeBitmap(bitmap)
|
||||
// bitmap.Save(bitmap, "test.png")
|
||||
robotgo.Save(robotgo.ToImage(bitmap), "test.png")
|
||||
|
||||
sx := robotgo.ScaleX()
|
||||
s := robotgo.Scale()
|
||||
robotgo.Scale = true
|
||||
robotgo.Move(10, 10)
|
||||
robotgo.MoveSmooth(100, 100)
|
||||
|
||||
fmt.Println(robotgo.Location())
|
||||
|
||||
num := robotgo.DisplaysNum()
|
||||
for i := 0; i < num; i++ {
|
||||
rect := robotgo.GetScreenRect(i)
|
||||
fmt.Println("rect: ", rect)
|
||||
}
|
||||
}
|
||||
|
||||
func old() {
|
||||
sx := robotgo.ScaleX() // Deprecated
|
||||
s := robotgo.Scale1() // Deprecated, use the ScaleF() function
|
||||
robotx, roboty := 35*s/100, 25*s/100
|
||||
fmt.Println("scale: ", sx, s, " pos: ", robotx, roboty)
|
||||
|
||||
mx, my := robotgo.GetMousePos()
|
||||
mx, my := robotgo.Location()
|
||||
sx, sy := mx*s/100, my*s/100
|
||||
|
||||
rx, ry, rw, rh := sx, sy, robotx, roboty
|
||||
// bit1 := robotgo.CaptureScreen(10, 20, robotw, roboth)
|
||||
bit1 := robotgo.CaptureScreen(rx, ry, rw, rh)
|
||||
robotgo.SaveBitmap(bit1, "test2.png")
|
||||
defer robotgo.FreeBitmap(bit1)
|
||||
// bitmap.Save(bit1, "test2.png")
|
||||
robotgo.Save(robotgo.ToImage(bit1), "test2.png")
|
||||
|
||||
clo := robotgo.GetPixelColor(robotx, roboty)
|
||||
fmt.Println("GetPixelColor...", clo)
|
||||
|
@ -12,22 +12,47 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
// "go-vgo/robotgo"
|
||||
)
|
||||
|
||||
func bitmap() {
|
||||
abitMap := robotgo.CaptureScreen()
|
||||
fmt.Println("abitMap...", abitMap)
|
||||
gbit := robotgo.ToBitmap(abitMap)
|
||||
bit := robotgo.CaptureScreen()
|
||||
defer robotgo.FreeBitmap(bit)
|
||||
fmt.Println("abitMap...", bit)
|
||||
|
||||
gbit := robotgo.ToBitmap(bit)
|
||||
fmt.Println("bitmap...", gbit.Width)
|
||||
|
||||
gbitMap := robotgo.GoCaptureScreen()
|
||||
fmt.Println("GoCaptureScreen...", gbitMap.Width)
|
||||
gbitMap := robotgo.CaptureGo()
|
||||
fmt.Println("Go CaptureScreen...", gbitMap.Width)
|
||||
// fmt.Println("...", gbitmap.Width, gbitmap.BytesPerPixel)
|
||||
|
||||
robotgo.SaveCapture("saveCapture.png", 10, 20, 100, 100)
|
||||
|
||||
img, err := robotgo.CaptureImg()
|
||||
fmt.Println("error: ", err)
|
||||
robotgo.Save(img, "save.png")
|
||||
|
||||
num := robotgo.DisplaysNum()
|
||||
for i := 0; i < num; i++ {
|
||||
robotgo.DisplayID = i
|
||||
img1, _ := robotgo.CaptureImg()
|
||||
path1 := "save_" + strconv.Itoa(i)
|
||||
robotgo.Save(img1, path1+".png")
|
||||
robotgo.SaveJpeg(img1, path1+".jpeg", 50)
|
||||
|
||||
img2, _ := robotgo.CaptureImg(10, 10, 20, 20)
|
||||
path2 := "test_" + strconv.Itoa(i)
|
||||
robotgo.Save(img2, path2+".png")
|
||||
robotgo.SaveJpeg(img2, path2+".jpeg", 50)
|
||||
|
||||
x, y, w, h := robotgo.GetDisplayBounds(i)
|
||||
img3, err := robotgo.CaptureImg(x, y, w, h)
|
||||
fmt.Println("Capture error: ", err)
|
||||
robotgo.Save(img3, path2+"_1.png")
|
||||
}
|
||||
}
|
||||
|
||||
func color() {
|
||||
@ -64,6 +89,12 @@ func screen() {
|
||||
// gets the screen width and height
|
||||
sx, sy := robotgo.GetScreenSize()
|
||||
fmt.Println("get screen size: ", sx, sy)
|
||||
for i := 0; i < robotgo.DisplaysNum(); i++ {
|
||||
s1 := robotgo.ScaleF(i)
|
||||
fmt.Println("ScaleF: ", s1)
|
||||
}
|
||||
sx, sy = robotgo.GetScaleSize()
|
||||
fmt.Println("get screen scale size: ", sx, sy)
|
||||
|
||||
color()
|
||||
}
|
||||
|
@ -19,17 +19,16 @@ import (
|
||||
|
||||
func alert() {
|
||||
// show Alert Window
|
||||
abool := robotgo.ShowAlert("hello", "robotgo")
|
||||
abool := robotgo.Alert("hello", "robotgo")
|
||||
if abool {
|
||||
fmt.Println("ok@@@", "ok")
|
||||
}
|
||||
robotgo.ShowAlert("hello", "robotgo", "Ok", "Cancel")
|
||||
|
||||
robotgo.Alert("hello", "robotgo", "Ok", "Cancel")
|
||||
}
|
||||
|
||||
func get() {
|
||||
// get the current process id
|
||||
pid := robotgo.GetPID()
|
||||
pid := robotgo.GetPid()
|
||||
fmt.Println("pid----", pid)
|
||||
|
||||
// get current Window Active
|
||||
@ -50,31 +49,45 @@ func get() {
|
||||
func findIds() {
|
||||
// find the process id by the process name
|
||||
fpid, err := robotgo.FindIds("Google")
|
||||
if err == nil {
|
||||
fmt.Println("pids...", fpid)
|
||||
if len(fpid) > 0 {
|
||||
robotgo.ActivePID(fpid[0])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
tl := robotgo.GetTitle(fpid[0])
|
||||
fmt.Println("pid[0] title is: ", tl)
|
||||
if len(fpid) > 0 {
|
||||
robotgo.KeyTap("a", fpid[0])
|
||||
robotgo.TypeStr("Hi galaxy!", fpid[0])
|
||||
|
||||
x, y, w, h := robotgo.GetBounds(fpid[0])
|
||||
fmt.Println("GetBounds is: ", x, y, w, h)
|
||||
robotgo.KeyToggle("a", fpid[0], "cmd")
|
||||
robotgo.KeyToggle("a", fpid[0], "cmd", "up")
|
||||
}
|
||||
|
||||
// Windows
|
||||
// hwnd := robotgo.FindWindow("google")
|
||||
// hwnd := robotgo.GetHWND()
|
||||
robotgo.MinWindow(fpid[0])
|
||||
robotgo.MaxWindow(fpid[0])
|
||||
robotgo.CloseWindow(fpid[0])
|
||||
|
||||
robotgo.Kill(fpid[0])
|
||||
fmt.Println("pids...", fpid)
|
||||
if len(fpid) > 0 {
|
||||
err = robotgo.ActivePid(fpid[0])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
tl := robotgo.GetTitle(fpid[0])
|
||||
fmt.Println("pid[0] title is: ", tl)
|
||||
|
||||
x, y, w, h := robotgo.GetBounds(fpid[0])
|
||||
fmt.Println("GetBounds is: ", x, y, w, h)
|
||||
|
||||
// Windows
|
||||
// hwnd := robotgo.FindWindow("google")
|
||||
// hwnd := robotgo.GetHWND()
|
||||
robotgo.MinWindow(fpid[0])
|
||||
robotgo.MaxWindow(fpid[0])
|
||||
robotgo.CloseWindow(fpid[0])
|
||||
|
||||
robotgo.Kill(fpid[0])
|
||||
}
|
||||
}
|
||||
|
||||
func active() {
|
||||
robotgo.ActivePID(100)
|
||||
robotgo.ActivePid(100)
|
||||
// robotgo.Sleep(2)
|
||||
robotgo.ActiveName("code")
|
||||
robotgo.Sleep(1)
|
||||
|
50
go.mod
50
go.mod
@ -1,32 +1,38 @@
|
||||
module github.com/go-vgo/robotgo
|
||||
|
||||
go 1.17
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.6
|
||||
|
||||
require (
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e
|
||||
github.com/otiai10/gosseract v2.2.1+incompatible
|
||||
github.com/robotn/gohook v0.31.3
|
||||
github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934
|
||||
github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770
|
||||
github.com/vcaesar/gops v0.21.3
|
||||
github.com/vcaesar/imgo v0.30.0
|
||||
github.com/vcaesar/keycode v0.10.0
|
||||
github.com/vcaesar/tt v0.20.0
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect
|
||||
github.com/otiai10/gosseract/v2 v2.4.1
|
||||
// github.com/robotn/gohook v0.31.3
|
||||
github.com/robotn/xgb v0.10.0
|
||||
github.com/robotn/xgbutil v0.10.0
|
||||
github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35
|
||||
github.com/vcaesar/gops v0.41.0
|
||||
github.com/vcaesar/imgo v0.41.0
|
||||
github.com/vcaesar/keycode v0.10.1
|
||||
github.com/vcaesar/tt v0.20.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/otiai10/mint v1.3.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/shirou/gopsutil v3.21.10+incompatible // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||
github.com/tklauser/numcpus v0.3.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e // indirect
|
||||
github.com/ebitengine/purego v0.8.3 // indirect
|
||||
github.com/gen2brain/shm v0.1.1 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/jezek/xgb v1.1.1 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.25.4 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
||||
github.com/tklauser/numcpus v0.10.0 // indirect
|
||||
github.com/vcaesar/screenshot v0.11.1
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
|
||||
golang.org/x/image v0.27.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
)
|
||||
|
||||
// replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb
|
||||
|
119
go.sum
119
go.sum
@ -1,66 +1,71 @@
|
||||
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ=
|
||||
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0=
|
||||
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e h1:L+XrFvD0vBIBm+Wf9sFN6aU395t7JROoai0qXZraA4U=
|
||||
github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e/go.mod h1:SUxUaAK/0UG5lYyZR1L1nC4AaYYvSSYTWQSH3FPcxKU=
|
||||
github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc=
|
||||
github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/gen2brain/shm v0.1.1 h1:1cTVA5qcsUFixnDHl14TmRoxgfWEEZlTezpUj1vm5uQ=
|
||||
github.com/gen2brain/shm v0.1.1/go.mod h1:UgIcVtvmOu+aCJpqJX7GOtiN7X2ct+TKLg4RTxwPIUA=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc=
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
||||
github.com/otiai10/gosseract v2.2.1+incompatible h1:Ry5ltVdpdp4LAa2bMjsSJH34XHVOV7XMi41HtzL8X2I=
|
||||
github.com/otiai10/gosseract v2.2.1+incompatible/go.mod h1:XrzWItCzCpFRZ35n3YtVTgq5bLAhFIkascoRo8G32QE=
|
||||
github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc=
|
||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4=
|
||||
github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc=
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/otiai10/gosseract/v2 v2.4.1 h1:G8AyBpXEeSlcq8TI85LH/pM5SXk8Djy2GEXisgyblRw=
|
||||
github.com/otiai10/gosseract/v2 v2.4.1/go.mod h1:1gNWP4Hgr2o7yqWfs6r5bZxAatjOIdqWxJLWsTsembk=
|
||||
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
|
||||
github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/robotn/gohook v0.31.3 h1:kGX8iukJ9ensVRwRKnTtdojAMQOpa6KFnXDi4OA4RaI=
|
||||
github.com/robotn/gohook v0.31.3/go.mod h1:wyGik0yb4iwCfJjDprtNkTyxkgQWuKoVPQ3hkz6+6js=
|
||||
github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ=
|
||||
github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk=
|
||||
github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU=
|
||||
github.com/shirou/gopsutil v3.21.10+incompatible h1:AL2kpVykjkqeN+MFe1WcwSBVUjGjvdU8/ubvCuXAjrU=
|
||||
github.com/shirou/gopsutil v3.21.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
|
||||
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
|
||||
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
|
||||
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
|
||||
github.com/vcaesar/gops v0.21.3 h1:VR7amkxVv9CQfsotkXrmMyT19dVuNTa1PM/oopJeIc0=
|
||||
github.com/vcaesar/gops v0.21.3/go.mod h1:3e2EnlZTI9/44bqzRwkeZ3s0ZQwK2Cn4QPLx8Ii8Agk=
|
||||
github.com/vcaesar/imgo v0.30.0 h1:ODQVX0EFJEh+WkKahCBtE0SqcDCIjl/kjiOplR0Ouh8=
|
||||
github.com/vcaesar/imgo v0.30.0/go.mod h1:8TGnt5hjaMgwDByvMFIzUDSh5uSea4n1tAbSvnhvA6U=
|
||||
github.com/vcaesar/keycode v0.10.0 h1:Qx5QE8ZXHyRyjoA2QOxBp25OKMKB+zxMVqm0FWGV0d4=
|
||||
github.com/vcaesar/keycode v0.10.0/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ=
|
||||
github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA=
|
||||
github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
github.com/robotn/xgb v0.10.0 h1:O3kFbIwtwZ3pgLbp1h5slCQ4OpY8BdwugJLrUe6GPIM=
|
||||
github.com/robotn/xgb v0.10.0/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ=
|
||||
github.com/robotn/xgbutil v0.10.0 h1:gvf7mGQqCWQ68aHRtCxgdewRk+/KAJui6l3MJQQRCKw=
|
||||
github.com/robotn/xgbutil v0.10.0/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU=
|
||||
github.com/shirou/gopsutil/v4 v4.25.4 h1:cdtFO363VEOOFrUCjZRh4XVJkb548lyF0q0uTeMqYPw=
|
||||
github.com/shirou/gopsutil/v4 v4.25.4/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35 h1:wAZbkTZkqDzWsqxPh2qkBd3KvFU7tcxV0BP0Rnhkxog=
|
||||
github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35/go.mod h1:aMd4yDHLjbOuYP6fMxj1d9ACDQlSWwYztcpybGHCQc8=
|
||||
github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA=
|
||||
github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk=
|
||||
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
|
||||
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
|
||||
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
|
||||
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
|
||||
github.com/vcaesar/gops v0.41.0 h1:FG748Jyw3FOuZnbzSgB+CQSx2e5LbLCPWV2JU1brFdc=
|
||||
github.com/vcaesar/gops v0.41.0/go.mod h1:/3048L7Rj7QjQKTSB+kKc7hDm63YhTWy5QJ10TCP37A=
|
||||
github.com/vcaesar/imgo v0.41.0 h1:kNLYGrThXhB9Dd6IwFmfPnxq9P6yat2g7dpPjr7OWO8=
|
||||
github.com/vcaesar/imgo v0.41.0/go.mod h1:/LGOge8etlzaVu/7l+UfhJxR6QqaoX5yeuzGIMfWb4I=
|
||||
github.com/vcaesar/keycode v0.10.1 h1:0DesGmMAPWpYTCYddOFiCMKCDKgNnwiQa2QXindVUHw=
|
||||
github.com/vcaesar/keycode v0.10.1/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ=
|
||||
github.com/vcaesar/screenshot v0.11.1 h1:GgPuN89XC4Yh38dLx4quPlSo3YiWWhwIria/j3LtrqU=
|
||||
github.com/vcaesar/screenshot v0.11.1/go.mod h1:gJNwHBiP1v1v7i8TQ4yV1XJtcyn2I/OJL7OziVQkwjs=
|
||||
github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4=
|
||||
github.com/vcaesar/tt v0.20.1/go.mod h1:cH2+AwGAJm19Wa6xvEa+0r+sXDJBT0QgNQey6mwqLeU=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
||||
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
|
||||
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw=
|
||||
golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
195
hook.go
195
hook.go
@ -1,195 +0,0 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
package robotgo
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
hook "github.com/robotn/gohook"
|
||||
)
|
||||
|
||||
/*
|
||||
___________ ____ _______ .__ __. .___________.
|
||||
| ____\ \ / / | ____|| \ | | | |
|
||||
| |__ \ \/ / | |__ | \| | `---| |----`
|
||||
| __| \ / | __| | . ` | | |
|
||||
| |____ \ / | |____ | |\ | | |
|
||||
|_______| \__/ |_______||__| \__| |__|
|
||||
*/
|
||||
|
||||
// EventStart start global event hook
|
||||
// return event channel
|
||||
func EventStart() chan hook.Event {
|
||||
return hook.Start()
|
||||
}
|
||||
|
||||
// EventEnd removes global event hook
|
||||
func EventEnd() {
|
||||
hook.End()
|
||||
}
|
||||
|
||||
// Deprecated: use the EventStart(),
|
||||
//
|
||||
// Start start global event hook
|
||||
// return event channel
|
||||
func Start() chan hook.Event {
|
||||
return hook.Start()
|
||||
}
|
||||
|
||||
// Deprecated: use the EventEnd(),
|
||||
//
|
||||
// End removes global event hook
|
||||
func End() {
|
||||
hook.End()
|
||||
}
|
||||
|
||||
// StopEvent stop event listener, use by AddEvent()
|
||||
func StopEvent() {
|
||||
hook.StopEvent()
|
||||
}
|
||||
|
||||
// EventProcess return go hook process
|
||||
func EventProcess(events chan hook.Event) chan bool {
|
||||
return hook.Process(events)
|
||||
}
|
||||
|
||||
// EventHook register gohook event
|
||||
func EventHook(when uint8, keysPressed []string, callback func(hook.Event)) {
|
||||
hook.Register(when, keysPressed, callback)
|
||||
}
|
||||
|
||||
// AddEvent add event listener,
|
||||
//
|
||||
// parameters for the string type,
|
||||
// the keyboard corresponding key parameters,
|
||||
//
|
||||
// mouse arguments: mleft, center, mright, wheelDown, wheelUp,
|
||||
// wheelLeft, wheelRight.
|
||||
//
|
||||
// Use "robotgo.AddEvents()" or "gohook" add asynchronous event listener
|
||||
func AddEvent(key string) bool {
|
||||
var (
|
||||
// cs *C.char
|
||||
mArr = []string{"mleft", "center", "mright", "wheelDown",
|
||||
"wheelUp", "wheelLeft", "wheelRight"}
|
||||
mouseBool bool
|
||||
)
|
||||
|
||||
for i := 0; i < len(mArr); i++ {
|
||||
if key == mArr[i] {
|
||||
mouseBool = true
|
||||
}
|
||||
}
|
||||
|
||||
if len(key) > 1 && !mouseBool {
|
||||
key = strconv.Itoa(int(Keycode[key]))
|
||||
}
|
||||
|
||||
geve := hook.AddEvent(key)
|
||||
// defer C.free(unsafe.Pointer(cs))
|
||||
return geve == 0
|
||||
}
|
||||
|
||||
// AddEvents add global event hook
|
||||
//
|
||||
// robotgo.AddEvents("q")
|
||||
// robotgo.AddEvents("q", "ctrl")
|
||||
// robotgo.AddEvents("q", "ctrl", "shift")
|
||||
func AddEvents(key string, arr ...string) bool {
|
||||
s := hook.Start()
|
||||
// defer hook.End()
|
||||
|
||||
ct := false
|
||||
k := 0
|
||||
for {
|
||||
e := <-s
|
||||
|
||||
l := len(arr)
|
||||
if l > 0 {
|
||||
for i := 0; i < l; i++ {
|
||||
ukey := Keycode[arr[i]]
|
||||
|
||||
if e.Kind == hook.KeyHold && e.Keycode == ukey {
|
||||
k++
|
||||
}
|
||||
|
||||
if k == l {
|
||||
ct = true
|
||||
}
|
||||
|
||||
if e.Kind == hook.KeyUp && e.Keycode == ukey {
|
||||
if k > 0 {
|
||||
k--
|
||||
}
|
||||
// time.Sleep(10 * time.Microsecond)
|
||||
ct = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ct = true
|
||||
}
|
||||
|
||||
if ct && e.Kind == hook.KeyUp && e.Keycode == Keycode[key] {
|
||||
hook.End()
|
||||
// k = 0
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// AddMouse add mouse event hook
|
||||
//
|
||||
// mouse arguments: left, center, right, wheelDown, wheelUp,
|
||||
// wheelLeft, wheelRight.
|
||||
//
|
||||
// robotgo.AddMouse("left")
|
||||
// robotgo.AddMouse("left", 100, 100)
|
||||
func AddMouse(btn string, x ...int16) bool {
|
||||
s := hook.Start()
|
||||
ukey := MouseMap[btn]
|
||||
|
||||
ct := false
|
||||
for {
|
||||
e := <-s
|
||||
|
||||
if len(x) > 1 {
|
||||
if e.Kind == hook.MouseMove && e.X == x[0] && e.Y == x[1] {
|
||||
ct = true
|
||||
}
|
||||
} else {
|
||||
ct = true
|
||||
}
|
||||
|
||||
if ct && e.Kind == hook.MouseDown && e.Button == ukey {
|
||||
hook.End()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// AddMousePos add listen mouse event pos hook
|
||||
func AddMousePos(x, y int16) bool {
|
||||
s := hook.Start()
|
||||
|
||||
for {
|
||||
e := <-s
|
||||
if e.Kind == hook.MouseMove && e.X == x && e.Y == y {
|
||||
hook.End()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
14
img.go
14
img.go
@ -34,8 +34,8 @@ func Read(path string) (image.Image, error) {
|
||||
}
|
||||
|
||||
// Save create a image file with the image.Image
|
||||
func Save(img image.Image, path string) error {
|
||||
return imgo.Save(path, img)
|
||||
func Save(img image.Image, path string, quality ...int) error {
|
||||
return imgo.Save(path, img, quality...)
|
||||
}
|
||||
|
||||
// SaveImg save the image by []byte
|
||||
@ -49,13 +49,13 @@ func SavePng(img image.Image, path string) error {
|
||||
}
|
||||
|
||||
// SaveJpeg save the image by image.Image
|
||||
func SaveJpeg(img image.Image, path string) error {
|
||||
return imgo.SaveToJpeg(path, img)
|
||||
func SaveJpeg(img image.Image, path string, quality ...int) error {
|
||||
return imgo.SaveToJpeg(path, img, quality...)
|
||||
}
|
||||
|
||||
// ToByteImg convert image.Image to []byte
|
||||
func ToByteImg(img image.Image, fm ...string) []byte {
|
||||
return imgo.ToByteImg(img, fm...)
|
||||
return imgo.ToByte(img, fm...)
|
||||
}
|
||||
|
||||
// ToStringImg convert image.Image to string
|
||||
@ -122,7 +122,7 @@ func ImgToBitmap(m image.Image) (bit Bitmap) {
|
||||
// ToUint8p convert the []uint8 to uint8 pointer
|
||||
func ToUint8p(dst []uint8) *uint8 {
|
||||
src := make([]uint8, len(dst)+10)
|
||||
for i := 0; i < len(dst)-4; i += 4 {
|
||||
for i := 0; i <= len(dst)-4; i += 4 {
|
||||
src[i+3] = dst[i+3]
|
||||
src[i] = dst[i+2]
|
||||
src[i+1] = dst[i+1]
|
||||
@ -151,7 +151,7 @@ func val(p *uint8, n int) uint8 {
|
||||
}
|
||||
|
||||
func copyToVUint8A(dst []uint8, src *uint8) {
|
||||
for i := 0; i < len(dst)-4; i += 4 {
|
||||
for i := 0; i <= len(dst)-4; i += 4 {
|
||||
dst[i] = val(src, i+2)
|
||||
dst[i+1] = val(src, i+1)
|
||||
dst[i+2] = val(src, i)
|
||||
|
739
key.go
Normal file
739
key.go
Normal file
@ -0,0 +1,739 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
package robotgo
|
||||
|
||||
/*
|
||||
// #include "key/keycode.h"
|
||||
#include "key/keypress_c.h"
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-vgo/robotgo/clipboard"
|
||||
)
|
||||
|
||||
// Defining a bunch of constants.
|
||||
const (
|
||||
// KeyA define key "a"
|
||||
KeyA = "a"
|
||||
KeyB = "b"
|
||||
KeyC = "c"
|
||||
KeyD = "d"
|
||||
KeyE = "e"
|
||||
KeyF = "f"
|
||||
KeyG = "g"
|
||||
KeyH = "h"
|
||||
KeyI = "i"
|
||||
KeyJ = "j"
|
||||
KeyK = "k"
|
||||
KeyL = "l"
|
||||
KeyM = "m"
|
||||
KeyN = "n"
|
||||
KeyO = "o"
|
||||
KeyP = "p"
|
||||
KeyQ = "q"
|
||||
KeyR = "r"
|
||||
KeyS = "s"
|
||||
KeyT = "t"
|
||||
KeyU = "u"
|
||||
KeyV = "v"
|
||||
KeyW = "w"
|
||||
KeyX = "x"
|
||||
KeyY = "y"
|
||||
KeyZ = "z"
|
||||
//
|
||||
CapA = "A"
|
||||
CapB = "B"
|
||||
CapC = "C"
|
||||
CapD = "D"
|
||||
CapE = "E"
|
||||
CapF = "F"
|
||||
CapG = "G"
|
||||
CapH = "H"
|
||||
CapI = "I"
|
||||
CapJ = "J"
|
||||
CapK = "K"
|
||||
CapL = "L"
|
||||
CapM = "M"
|
||||
CapN = "N"
|
||||
CapO = "O"
|
||||
CapP = "P"
|
||||
CapQ = "Q"
|
||||
CapR = "R"
|
||||
CapS = "S"
|
||||
CapT = "T"
|
||||
CapU = "U"
|
||||
CapV = "V"
|
||||
CapW = "W"
|
||||
CapX = "X"
|
||||
CapY = "Y"
|
||||
CapZ = "Z"
|
||||
//
|
||||
Key0 = "0"
|
||||
Key1 = "1"
|
||||
Key2 = "2"
|
||||
Key3 = "3"
|
||||
Key4 = "4"
|
||||
Key5 = "5"
|
||||
Key6 = "6"
|
||||
Key7 = "7"
|
||||
Key8 = "8"
|
||||
Key9 = "9"
|
||||
|
||||
// Backspace backspace key string
|
||||
Backspace = "backspace"
|
||||
Delete = "delete"
|
||||
Enter = "enter"
|
||||
Tab = "tab"
|
||||
Esc = "esc"
|
||||
Escape = "escape"
|
||||
Up = "up" // Up arrow key
|
||||
Down = "down" // Down arrow key
|
||||
Right = "right" // Right arrow key
|
||||
Left = "left" // Left arrow key
|
||||
Home = "home"
|
||||
End = "end"
|
||||
Pageup = "pageup"
|
||||
Pagedown = "pagedown"
|
||||
|
||||
F1 = "f1"
|
||||
F2 = "f2"
|
||||
F3 = "f3"
|
||||
F4 = "f4"
|
||||
F5 = "f5"
|
||||
F6 = "f6"
|
||||
F7 = "f7"
|
||||
F8 = "f8"
|
||||
F9 = "f9"
|
||||
F10 = "f10"
|
||||
F11 = "f11"
|
||||
F12 = "f12"
|
||||
F13 = "f13"
|
||||
F14 = "f14"
|
||||
F15 = "f15"
|
||||
F16 = "f16"
|
||||
F17 = "f17"
|
||||
F18 = "f18"
|
||||
F19 = "f19"
|
||||
F20 = "f20"
|
||||
F21 = "f21"
|
||||
F22 = "f22"
|
||||
F23 = "f23"
|
||||
F24 = "f24"
|
||||
|
||||
Cmd = "cmd" // is the "win" key for windows
|
||||
Lcmd = "lcmd" // left command
|
||||
Rcmd = "rcmd" // right command
|
||||
// "command"
|
||||
Alt = "alt"
|
||||
Lalt = "lalt" // left alt
|
||||
Ralt = "ralt" // right alt
|
||||
Ctrl = "ctrl"
|
||||
Lctrl = "lctrl" // left ctrl
|
||||
Rctrl = "rctrl" // right ctrl
|
||||
Control = "control"
|
||||
Shift = "shift"
|
||||
Lshift = "lshift" // left shift
|
||||
Rshift = "rshift" // right shift
|
||||
// "right_shift"
|
||||
Capslock = "capslock"
|
||||
Space = "space"
|
||||
Print = "print"
|
||||
Printscreen = "printscreen" // No Mac support
|
||||
Insert = "insert"
|
||||
Menu = "menu" // Windows only
|
||||
|
||||
AudioMute = "audio_mute" // Mute the volume
|
||||
AudioVolDown = "audio_vol_down" // Lower the volume
|
||||
AudioVolUp = "audio_vol_up" // Increase the volume
|
||||
AudioPlay = "audio_play"
|
||||
AudioStop = "audio_stop"
|
||||
AudioPause = "audio_pause"
|
||||
AudioPrev = "audio_prev" // Previous Track
|
||||
AudioNext = "audio_next" // Next Track
|
||||
AudioRewind = "audio_rewind" // Linux only
|
||||
AudioForward = "audio_forward" // Linux only
|
||||
AudioRepeat = "audio_repeat" // Linux only
|
||||
AudioRandom = "audio_random" // Linux only
|
||||
|
||||
Num0 = "num0" // numpad 0
|
||||
Num1 = "num1"
|
||||
Num2 = "num2"
|
||||
Num3 = "num3"
|
||||
Num4 = "num4"
|
||||
Num5 = "num5"
|
||||
Num6 = "num6"
|
||||
Num7 = "num7"
|
||||
Num8 = "num8"
|
||||
Num9 = "num9"
|
||||
NumLock = "num_lock"
|
||||
|
||||
NumDecimal = "num."
|
||||
NumPlus = "num+"
|
||||
NumMinus = "num-"
|
||||
NumMul = "num*"
|
||||
NumDiv = "num/"
|
||||
NumClear = "num_clear"
|
||||
NumEnter = "num_enter"
|
||||
NumEqual = "num_equal"
|
||||
|
||||
LightsMonUp = "lights_mon_up" // Turn up monitor brightness No Windows support
|
||||
LightsMonDown = "lights_mon_down" // Turn down monitor brightness No Windows support
|
||||
LightsKbdToggle = "lights_kbd_toggle" // Toggle keyboard backlight on/off No Windows support
|
||||
LightsKbdUp = "lights_kbd_up" // Turn up keyboard backlight brightness No Windows support
|
||||
LightsKbdDown = "lights_kbd_down"
|
||||
)
|
||||
|
||||
// keyNames define a map of key names to MMKeyCode
|
||||
var keyNames = map[string]C.MMKeyCode{
|
||||
"backspace": C.K_BACKSPACE,
|
||||
"delete": C.K_DELETE,
|
||||
"enter": C.K_RETURN,
|
||||
"tab": C.K_TAB,
|
||||
"esc": C.K_ESCAPE,
|
||||
"escape": C.K_ESCAPE,
|
||||
"up": C.K_UP,
|
||||
"down": C.K_DOWN,
|
||||
"right": C.K_RIGHT,
|
||||
"left": C.K_LEFT,
|
||||
"home": C.K_HOME,
|
||||
"end": C.K_END,
|
||||
"pageup": C.K_PAGEUP,
|
||||
"pagedown": C.K_PAGEDOWN,
|
||||
//
|
||||
"f1": C.K_F1,
|
||||
"f2": C.K_F2,
|
||||
"f3": C.K_F3,
|
||||
"f4": C.K_F4,
|
||||
"f5": C.K_F5,
|
||||
"f6": C.K_F6,
|
||||
"f7": C.K_F7,
|
||||
"f8": C.K_F8,
|
||||
"f9": C.K_F9,
|
||||
"f10": C.K_F10,
|
||||
"f11": C.K_F11,
|
||||
"f12": C.K_F12,
|
||||
"f13": C.K_F13,
|
||||
"f14": C.K_F14,
|
||||
"f15": C.K_F15,
|
||||
"f16": C.K_F16,
|
||||
"f17": C.K_F17,
|
||||
"f18": C.K_F18,
|
||||
"f19": C.K_F19,
|
||||
"f20": C.K_F20,
|
||||
"f21": C.K_F21,
|
||||
"f22": C.K_F22,
|
||||
"f23": C.K_F23,
|
||||
"f24": C.K_F24,
|
||||
//
|
||||
"cmd": C.K_META,
|
||||
"lcmd": C.K_LMETA,
|
||||
"rcmd": C.K_RMETA,
|
||||
"command": C.K_META,
|
||||
"alt": C.K_ALT,
|
||||
"lalt": C.K_LALT,
|
||||
"ralt": C.K_RALT,
|
||||
"ctrl": C.K_CONTROL,
|
||||
"lctrl": C.K_LCONTROL,
|
||||
"rctrl": C.K_RCONTROL,
|
||||
"control": C.K_CONTROL,
|
||||
"shift": C.K_SHIFT,
|
||||
"lshift": C.K_LSHIFT,
|
||||
"rshift": C.K_RSHIFT,
|
||||
"right_shift": C.K_RSHIFT,
|
||||
"capslock": C.K_CAPSLOCK,
|
||||
"space": C.K_SPACE,
|
||||
"print": C.K_PRINTSCREEN,
|
||||
"printscreen": C.K_PRINTSCREEN,
|
||||
"insert": C.K_INSERT,
|
||||
"menu": C.K_MENU,
|
||||
|
||||
"audio_mute": C.K_AUDIO_VOLUME_MUTE,
|
||||
"audio_vol_down": C.K_AUDIO_VOLUME_DOWN,
|
||||
"audio_vol_up": C.K_AUDIO_VOLUME_UP,
|
||||
"audio_play": C.K_AUDIO_PLAY,
|
||||
"audio_stop": C.K_AUDIO_STOP,
|
||||
"audio_pause": C.K_AUDIO_PAUSE,
|
||||
"audio_prev": C.K_AUDIO_PREV,
|
||||
"audio_next": C.K_AUDIO_NEXT,
|
||||
"audio_rewind": C.K_AUDIO_REWIND,
|
||||
"audio_forward": C.K_AUDIO_FORWARD,
|
||||
"audio_repeat": C.K_AUDIO_REPEAT,
|
||||
"audio_random": C.K_AUDIO_RANDOM,
|
||||
|
||||
"num0": C.K_NUMPAD_0,
|
||||
"num1": C.K_NUMPAD_1,
|
||||
"num2": C.K_NUMPAD_2,
|
||||
"num3": C.K_NUMPAD_3,
|
||||
"num4": C.K_NUMPAD_4,
|
||||
"num5": C.K_NUMPAD_5,
|
||||
"num6": C.K_NUMPAD_6,
|
||||
"num7": C.K_NUMPAD_7,
|
||||
"num8": C.K_NUMPAD_8,
|
||||
"num9": C.K_NUMPAD_9,
|
||||
"num_lock": C.K_NUMPAD_LOCK,
|
||||
|
||||
// todo: removed
|
||||
"numpad_0": C.K_NUMPAD_0,
|
||||
"numpad_1": C.K_NUMPAD_1,
|
||||
"numpad_2": C.K_NUMPAD_2,
|
||||
"numpad_3": C.K_NUMPAD_3,
|
||||
"numpad_4": C.K_NUMPAD_4,
|
||||
"numpad_5": C.K_NUMPAD_5,
|
||||
"numpad_6": C.K_NUMPAD_6,
|
||||
"numpad_7": C.K_NUMPAD_7,
|
||||
"numpad_8": C.K_NUMPAD_8,
|
||||
"numpad_9": C.K_NUMPAD_9,
|
||||
"numpad_lock": C.K_NUMPAD_LOCK,
|
||||
|
||||
"num.": C.K_NUMPAD_DECIMAL,
|
||||
"num+": C.K_NUMPAD_PLUS,
|
||||
"num-": C.K_NUMPAD_MINUS,
|
||||
"num*": C.K_NUMPAD_MUL,
|
||||
"num/": C.K_NUMPAD_DIV,
|
||||
"num_clear": C.K_NUMPAD_CLEAR,
|
||||
"num_enter": C.K_NUMPAD_ENTER,
|
||||
"num_equal": C.K_NUMPAD_EQUAL,
|
||||
|
||||
"lights_mon_up": C.K_LIGHTS_MON_UP,
|
||||
"lights_mon_down": C.K_LIGHTS_MON_DOWN,
|
||||
"lights_kbd_toggle": C.K_LIGHTS_KBD_TOGGLE,
|
||||
"lights_kbd_up": C.K_LIGHTS_KBD_UP,
|
||||
"lights_kbd_down": C.K_LIGHTS_KBD_DOWN,
|
||||
|
||||
// { NULL: C.K_NOT_A_KEY }
|
||||
}
|
||||
|
||||
// CmdCtrl If the operating system is macOS, return the key string "cmd",
|
||||
// otherwise return the key string "ctrl
|
||||
func CmdCtrl() string {
|
||||
if runtime.GOOS == "darwin" {
|
||||
return "cmd"
|
||||
}
|
||||
return "ctrl"
|
||||
}
|
||||
|
||||
// It sends a key press and release to the active application
|
||||
func tapKeyCode(code C.MMKeyCode, flags C.MMKeyFlags, pid C.uintptr) {
|
||||
C.toggleKeyCode(code, true, flags, pid)
|
||||
MilliSleep(3)
|
||||
C.toggleKeyCode(code, false, flags, pid)
|
||||
}
|
||||
|
||||
var keyErr = errors.New("Invalid key flag specified.")
|
||||
|
||||
func checkKeyCodes(k string) (key C.MMKeyCode, err error) {
|
||||
if k == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if len(k) == 1 {
|
||||
val1 := C.CString(k)
|
||||
defer C.free(unsafe.Pointer(val1))
|
||||
|
||||
key = C.keyCodeForChar(*val1)
|
||||
if key == C.K_NOT_A_KEY {
|
||||
err = keyErr
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if v, ok := keyNames[k]; ok {
|
||||
key = v
|
||||
if key == C.K_NOT_A_KEY {
|
||||
err = keyErr
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func checkKeyFlags(f string) (flags C.MMKeyFlags) {
|
||||
m := map[string]C.MMKeyFlags{
|
||||
"alt": C.MOD_ALT,
|
||||
"ralt": C.MOD_ALT,
|
||||
"lalt": C.MOD_ALT,
|
||||
"cmd": C.MOD_META,
|
||||
"rcmd": C.MOD_META,
|
||||
"lcmd": C.MOD_META,
|
||||
"ctrl": C.MOD_CONTROL,
|
||||
"rctrl": C.MOD_CONTROL,
|
||||
"lctrl": C.MOD_CONTROL,
|
||||
"shift": C.MOD_SHIFT,
|
||||
"rshift": C.MOD_SHIFT,
|
||||
"lshift": C.MOD_SHIFT,
|
||||
"none": C.MOD_NONE,
|
||||
}
|
||||
|
||||
if v, ok := m[f]; ok {
|
||||
return v
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getFlagsFromValue(value []string) (flags C.MMKeyFlags) {
|
||||
if len(value) <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len(value); i++ {
|
||||
var f C.MMKeyFlags = C.MOD_NONE
|
||||
|
||||
f = checkKeyFlags(value[i])
|
||||
flags = (C.MMKeyFlags)(flags | f)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func keyTaps(k string, keyArr []string, pid int) error {
|
||||
flags := getFlagsFromValue(keyArr)
|
||||
key, err := checkKeyCodes(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tapKeyCode(key, flags, C.uintptr(pid))
|
||||
MilliSleep(KeySleep)
|
||||
return nil
|
||||
}
|
||||
|
||||
func keyToggles(k string, keyArr []string, pid int) error {
|
||||
if len(keyArr) <= 0 {
|
||||
keyArr = append(keyArr, "down")
|
||||
}
|
||||
|
||||
down := true
|
||||
if keyArr[0] == "up" {
|
||||
down = false
|
||||
}
|
||||
|
||||
if keyArr[0] == "up" || keyArr[0] == "down" {
|
||||
keyArr = keyArr[1:]
|
||||
}
|
||||
flags := getFlagsFromValue(keyArr)
|
||||
|
||||
key, err := checkKeyCodes(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
C.toggleKeyCode(key, C.bool(down), flags, C.uintptr(pid))
|
||||
MilliSleep(KeySleep)
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
__ ___ ___________ ____ .______ ______ ___ .______ _______
|
||||
| |/ / | ____\ \ / / | _ \ / __ \ / \ | _ \ | \
|
||||
| ' / | |__ \ \/ / | |_) | | | | | / ^ \ | |_) | | .--. |
|
||||
| < | __| \_ _/ | _ < | | | | / /_\ \ | / | | | |
|
||||
| . \ | |____ | | | |_) | | `--' | / _____ \ | |\ \----.| '--' |
|
||||
|__|\__\ |_______| |__| |______/ \______/ /__/ \__\ | _| `._____||_______/
|
||||
|
||||
*/
|
||||
|
||||
// ToInterfaces convert []string to []interface{}
|
||||
func ToInterfaces(fields []string) []interface{} {
|
||||
res := make([]interface{}, 0, len(fields))
|
||||
for _, s := range fields {
|
||||
res = append(res, s)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ToStrings convert []interface{} to []string
|
||||
func ToStrings(fields []interface{}) []string {
|
||||
res := make([]string, 0, len(fields))
|
||||
for _, s := range fields {
|
||||
res = append(res, s.(string))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// toErr it converts a C string to a Go error
|
||||
func toErr(str *C.char) error {
|
||||
gstr := C.GoString(str)
|
||||
if gstr == "" {
|
||||
return nil
|
||||
}
|
||||
return errors.New(gstr)
|
||||
}
|
||||
|
||||
// KeyTap taps the keyboard code;
|
||||
//
|
||||
// See keys supported:
|
||||
//
|
||||
// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md#keys
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// robotgo.KeySleep = 100 // 100 millisecond
|
||||
// robotgo.KeyTap("a")
|
||||
// robotgo.KeyTap("i", "alt", "command")
|
||||
//
|
||||
// arr := []string{"alt", "command"}
|
||||
// robotgo.KeyTap("i", arr)
|
||||
//
|
||||
// robotgo.KeyTap("k", pid int)
|
||||
func KeyTap(key string, args ...interface{}) error {
|
||||
var keyArr []string
|
||||
|
||||
if len(key) > 0 && unicode.IsUpper([]rune(key)[0]) {
|
||||
args = append(args, "shift")
|
||||
}
|
||||
|
||||
key = strings.ToLower(key)
|
||||
if _, ok := Special[key]; ok {
|
||||
key = Special[key]
|
||||
if len(args) <= 0 {
|
||||
args = append(args, "shift")
|
||||
}
|
||||
}
|
||||
|
||||
pid := 0
|
||||
if len(args) > 0 {
|
||||
if reflect.TypeOf(args[0]) == reflect.TypeOf(keyArr) {
|
||||
keyArr = args[0].([]string)
|
||||
} else {
|
||||
if reflect.TypeOf(args[0]) == reflect.TypeOf(pid) {
|
||||
pid = args[0].(int)
|
||||
keyArr = ToStrings(args[1:])
|
||||
} else {
|
||||
keyArr = ToStrings(args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return keyTaps(key, keyArr, pid)
|
||||
}
|
||||
|
||||
// KeyToggle toggles the keyboard, if there not have args default is "down"
|
||||
//
|
||||
// See keys:
|
||||
//
|
||||
// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md#keys
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// robotgo.KeyToggle("a")
|
||||
// robotgo.KeyToggle("a", "up")
|
||||
//
|
||||
// robotgo.KeyToggle("a", "up", "alt", "cmd")
|
||||
// robotgo.KeyToggle("k", pid int)
|
||||
func KeyToggle(key string, args ...interface{}) error {
|
||||
|
||||
if len(key) > 0 && unicode.IsUpper([]rune(key)[0]) {
|
||||
args = append(args, "shift")
|
||||
}
|
||||
|
||||
key = strings.ToLower(key)
|
||||
if _, ok := Special[key]; ok {
|
||||
key = Special[key]
|
||||
if len(args) <= 1 {
|
||||
args = append(args, "shift")
|
||||
}
|
||||
}
|
||||
|
||||
pid := 0
|
||||
var keyArr []string
|
||||
if len(args) > 0 && reflect.TypeOf(args[0]) == reflect.TypeOf(pid) {
|
||||
pid = args[0].(int)
|
||||
keyArr = ToStrings(args[1:])
|
||||
} else {
|
||||
keyArr = ToStrings(args)
|
||||
}
|
||||
|
||||
return keyToggles(key, keyArr, pid)
|
||||
}
|
||||
|
||||
// KeyPress press key string
|
||||
func KeyPress(key string, args ...interface{}) error {
|
||||
err := KeyDown(key, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
MilliSleep(1 + rand.Intn(3))
|
||||
return KeyUp(key, args...)
|
||||
}
|
||||
|
||||
// KeyDown press down a key
|
||||
func KeyDown(key string, args ...interface{}) error {
|
||||
return KeyToggle(key, args...)
|
||||
}
|
||||
|
||||
// KeyUp press up a key
|
||||
func KeyUp(key string, args ...interface{}) error {
|
||||
arr := []interface{}{"up"}
|
||||
arr = append(arr, args...)
|
||||
return KeyToggle(key, arr...)
|
||||
}
|
||||
|
||||
// ReadAll read string from clipboard
|
||||
func ReadAll() (string, error) {
|
||||
return clipboard.ReadAll()
|
||||
}
|
||||
|
||||
// WriteAll write string to clipboard
|
||||
func WriteAll(text string) error {
|
||||
return clipboard.WriteAll(text)
|
||||
}
|
||||
|
||||
// CharCodeAt char code at utf-8
|
||||
func CharCodeAt(s string, n int) rune {
|
||||
i := 0
|
||||
for _, r := range s {
|
||||
if i == n {
|
||||
return r
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// UnicodeType tap the uint32 unicode
|
||||
func UnicodeType(str uint32, args ...int) {
|
||||
cstr := C.uint(str)
|
||||
pid := 0
|
||||
if len(args) > 0 {
|
||||
pid = args[0]
|
||||
}
|
||||
|
||||
isPid := 0
|
||||
if len(args) > 1 {
|
||||
isPid = args[1]
|
||||
}
|
||||
|
||||
C.unicodeType(cstr, C.uintptr(pid), C.int8_t(isPid))
|
||||
}
|
||||
|
||||
// ToUC trans string to unicode []string
|
||||
func ToUC(text string) []string {
|
||||
var uc []string
|
||||
|
||||
for _, r := range text {
|
||||
textQ := strconv.QuoteToASCII(string(r))
|
||||
textUnQ := textQ[1 : len(textQ)-1]
|
||||
|
||||
st := strings.Replace(textUnQ, "\\u", "U", -1)
|
||||
if st == "\\\\" {
|
||||
st = "\\"
|
||||
}
|
||||
if st == `\"` {
|
||||
st = `"`
|
||||
}
|
||||
uc = append(uc, st)
|
||||
}
|
||||
|
||||
return uc
|
||||
}
|
||||
|
||||
func inputUTF(str string) {
|
||||
cstr := C.CString(str)
|
||||
C.input_utf(cstr)
|
||||
|
||||
C.free(unsafe.Pointer(cstr))
|
||||
}
|
||||
|
||||
// TypeStr send a string (supported UTF-8)
|
||||
//
|
||||
// robotgo.TypeStr(string: "The string to send", int: pid, "milli_sleep time", "x11 option")
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// robotgo.TypeStr("abc@123, Hi galaxy, こんにちは")
|
||||
// robotgo.TypeStr("To be or not to be, this is questions.", pid int)
|
||||
func TypeStr(str string, args ...int) {
|
||||
var tm, tm1 = 0, 7
|
||||
|
||||
if len(args) > 1 {
|
||||
tm = args[1]
|
||||
}
|
||||
if len(args) > 2 {
|
||||
tm1 = args[2]
|
||||
}
|
||||
pid := 0
|
||||
if len(args) > 0 {
|
||||
pid = args[0]
|
||||
}
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
strUc := ToUC(str)
|
||||
for i := 0; i < len(strUc); i++ {
|
||||
ru := []rune(strUc[i])
|
||||
if len(ru) <= 1 {
|
||||
ustr := uint32(CharCodeAt(strUc[i], 0))
|
||||
UnicodeType(ustr, pid)
|
||||
} else {
|
||||
inputUTF(strUc[i])
|
||||
MilliSleep(tm1)
|
||||
}
|
||||
|
||||
MilliSleep(tm)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len([]rune(str)); i++ {
|
||||
ustr := uint32(CharCodeAt(str, i))
|
||||
UnicodeType(ustr, pid)
|
||||
// if len(args) > 0 {
|
||||
MilliSleep(tm)
|
||||
// }
|
||||
}
|
||||
MilliSleep(KeySleep)
|
||||
}
|
||||
|
||||
// PasteStr paste a string (support UTF-8),
|
||||
// write the string to clipboard and tap `cmd + v`
|
||||
func PasteStr(str string) error {
|
||||
err := clipboard.WriteAll(str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
return KeyTap("v", "command")
|
||||
}
|
||||
|
||||
return KeyTap("v", "control")
|
||||
}
|
||||
|
||||
// TypeStrDelay type string with delayed
|
||||
// And you can use robotgo.KeySleep = 100 to delayed not this function
|
||||
func TypeStrDelay(str string, delay int) {
|
||||
TypeStr(str)
|
||||
MilliSleep(delay)
|
||||
}
|
||||
|
||||
// SetDelay sets the key and mouse delay
|
||||
// robotgo.SetDelay(100) option the robotgo.KeySleep and robotgo.MouseSleep = d
|
||||
func SetDelay(d ...int) {
|
||||
v := 10
|
||||
if len(d) > 0 {
|
||||
v = d[0]
|
||||
}
|
||||
|
||||
KeySleep = v
|
||||
MouseSleep = v
|
||||
}
|
403
key/goKey.h
403
key/goKey.h
@ -1,403 +0,0 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#include "../base/types.h"
|
||||
// #include "keycode.h"
|
||||
// #include "keypress.h"
|
||||
#include "keypress_c.h"
|
||||
#include "keycode_c.h"
|
||||
|
||||
|
||||
int keyboardDelay = 0;
|
||||
|
||||
struct KeyNames{
|
||||
const char* name;
|
||||
MMKeyCode key;
|
||||
}key_names[] = {
|
||||
{ "backspace", K_BACKSPACE },
|
||||
{ "delete", K_DELETE },
|
||||
{ "enter", K_RETURN },
|
||||
{ "tab", K_TAB },
|
||||
{ "esc", K_ESCAPE },
|
||||
{ "escape", K_ESCAPE },
|
||||
{ "up", K_UP },
|
||||
{ "down", K_DOWN },
|
||||
{ "right", K_RIGHT },
|
||||
{ "left", K_LEFT },
|
||||
{ "home", K_HOME },
|
||||
{ "end", K_END },
|
||||
{ "pageup", K_PAGEUP },
|
||||
{ "pagedown", K_PAGEDOWN },
|
||||
//
|
||||
{ "f1", K_F1 },
|
||||
{ "f2", K_F2 },
|
||||
{ "f3", K_F3 },
|
||||
{ "f4", K_F4 },
|
||||
{ "f5", K_F5 },
|
||||
{ "f6", K_F6 },
|
||||
{ "f7", K_F7 },
|
||||
{ "f8", K_F8 },
|
||||
{ "f9", K_F9 },
|
||||
{ "f10", K_F10 },
|
||||
{ "f11", K_F11 },
|
||||
{ "f12", K_F12 },
|
||||
{ "f13", K_F13 },
|
||||
{ "f14", K_F14 },
|
||||
{ "f15", K_F15 },
|
||||
{ "f16", K_F16 },
|
||||
{ "f17", K_F17 },
|
||||
{ "f18", K_F18 },
|
||||
{ "f19", K_F19 },
|
||||
{ "f20", K_F20 },
|
||||
{ "f21", K_F21 },
|
||||
{ "f22", K_F22 },
|
||||
{ "f23", K_F23 },
|
||||
{ "f24", K_F24 },
|
||||
//
|
||||
{ "cmd", K_META },
|
||||
{ "lcmd", K_LMETA },
|
||||
{ "rcmd", K_RMETA },
|
||||
{ "command", K_META },
|
||||
{ "alt", K_ALT },
|
||||
{ "lalt", K_LALT },
|
||||
{ "ralt", K_RALT },
|
||||
{ "ctrl", K_CONTROL },
|
||||
{ "lctrl", K_LCONTROL },
|
||||
{ "rctrl", K_RCONTROL },
|
||||
{ "control", K_CONTROL },
|
||||
{ "shift", K_SHIFT },
|
||||
{ "lshift", K_LSHIFT },
|
||||
{ "rshift", K_RSHIFT },
|
||||
{ "right_shift", K_RSHIFT },
|
||||
{ "capslock", K_CAPSLOCK },
|
||||
{ "space", K_SPACE },
|
||||
{ "print", K_PRINTSCREEN },
|
||||
{ "printscreen", K_PRINTSCREEN },
|
||||
{ "insert", K_INSERT },
|
||||
{ "menu", K_MENU },
|
||||
|
||||
{ "audio_mute", K_AUDIO_VOLUME_MUTE },
|
||||
{ "audio_vol_down", K_AUDIO_VOLUME_DOWN },
|
||||
{ "audio_vol_up", K_AUDIO_VOLUME_UP },
|
||||
{ "audio_play", K_AUDIO_PLAY },
|
||||
{ "audio_stop", K_AUDIO_STOP },
|
||||
{ "audio_pause", K_AUDIO_PAUSE },
|
||||
{ "audio_prev", K_AUDIO_PREV },
|
||||
{ "audio_next", K_AUDIO_NEXT },
|
||||
{ "audio_rewind", K_AUDIO_REWIND },
|
||||
{ "audio_forward", K_AUDIO_FORWARD },
|
||||
{ "audio_repeat", K_AUDIO_REPEAT },
|
||||
{ "audio_random", K_AUDIO_RANDOM },
|
||||
|
||||
{ "num0", K_NUMPAD_0 },
|
||||
{ "num1", K_NUMPAD_1 },
|
||||
{ "num2", K_NUMPAD_2 },
|
||||
{ "num3", K_NUMPAD_3 },
|
||||
{ "num4", K_NUMPAD_4 },
|
||||
{ "num5", K_NUMPAD_5 },
|
||||
{ "num6", K_NUMPAD_6 },
|
||||
{ "num7", K_NUMPAD_7 },
|
||||
{ "num8", K_NUMPAD_8 },
|
||||
{ "num9", K_NUMPAD_9 },
|
||||
{ "num_lock", K_NUMPAD_LOCK },
|
||||
|
||||
// todo: removed
|
||||
{ "numpad_0", K_NUMPAD_0 },
|
||||
{ "numpad_1", K_NUMPAD_1 },
|
||||
{ "numpad_2", K_NUMPAD_2 },
|
||||
{ "numpad_3", K_NUMPAD_3 },
|
||||
{ "numpad_4", K_NUMPAD_4 },
|
||||
{ "numpad_5", K_NUMPAD_5 },
|
||||
{ "numpad_6", K_NUMPAD_6 },
|
||||
{ "numpad_7", K_NUMPAD_7 },
|
||||
{ "numpad_8", K_NUMPAD_8 },
|
||||
{ "numpad_9", K_NUMPAD_9 },
|
||||
{ "numpad_lock", K_NUMPAD_LOCK },
|
||||
|
||||
{"num.", K_NUMPAD_DECIMAL },
|
||||
{"num+", K_NUMPAD_PLUS },
|
||||
{"num-", K_NUMPAD_MINUS },
|
||||
{"num*", K_NUMPAD_MUL },
|
||||
{"num/", K_NUMPAD_DIV },
|
||||
{"num_clear", K_NUMPAD_CLEAR },
|
||||
{"num_enter", K_NUMPAD_ENTER },
|
||||
{"num_equal", K_NUMPAD_EQUAL },
|
||||
|
||||
{ "lights_mon_up", K_LIGHTS_MON_UP },
|
||||
{ "lights_mon_down", K_LIGHTS_MON_DOWN },
|
||||
{ "lights_kbd_toggle",K_LIGHTS_KBD_TOGGLE },
|
||||
{ "lights_kbd_up", K_LIGHTS_KBD_UP },
|
||||
{ "lights_kbd_down", K_LIGHTS_KBD_DOWN },
|
||||
|
||||
{ NULL, K_NOT_A_KEY } /* end marker */
|
||||
};
|
||||
|
||||
int CheckKeyCodes(char* k, MMKeyCode *key){
|
||||
if (!key) { return -1; }
|
||||
|
||||
if (strlen(k) == 1) {
|
||||
*key = keyCodeForChar(*k);
|
||||
if (*key == K_NOT_A_KEY) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
*key = K_NOT_A_KEY;
|
||||
|
||||
struct KeyNames* kn = key_names;
|
||||
while (kn->name) {
|
||||
if (strcmp(k, kn->name) == 0){
|
||||
*key = kn->key;
|
||||
break;
|
||||
}
|
||||
kn++;
|
||||
}
|
||||
|
||||
if (*key == K_NOT_A_KEY) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CheckKeyFlags(char* f, MMKeyFlags* flags){
|
||||
if (!flags) { return -1; }
|
||||
|
||||
if ( strcmp(f, "alt") == 0 || strcmp(f, "ralt") == 0 ||
|
||||
strcmp(f, "lalt") == 0 ) {
|
||||
*flags = MOD_ALT;
|
||||
}
|
||||
else if( strcmp(f, "command") == 0 || strcmp(f, "cmd") == 0 ||
|
||||
strcmp(f, "rcmd") == 0 || strcmp(f, "lcmd") == 0 ) {
|
||||
*flags = MOD_META;
|
||||
}
|
||||
else if( strcmp(f, "control") == 0 || strcmp(f, "ctrl") == 0 ||
|
||||
strcmp(f, "rctrl") == 0 || strcmp(f, "lctrl") == 0 ) {
|
||||
*flags = MOD_CONTROL;
|
||||
}
|
||||
else if( strcmp(f, "shift") == 0 || strcmp(f, "right_shift") == 0 ||
|
||||
strcmp(f, "rshift") == 0 || strcmp(f, "lshift") == 0 ) {
|
||||
*flags = MOD_SHIFT;
|
||||
}
|
||||
else if( strcmp(f, "none") == 0 ) {
|
||||
*flags = (MMKeyFlags) MOD_NONE;
|
||||
} else {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetFlagsFromValue(char* value[], MMKeyFlags* flags, int num){
|
||||
if (!flags) {return -1;}
|
||||
|
||||
int i;
|
||||
for ( i= 0; i <num; i++) {
|
||||
MMKeyFlags f = MOD_NONE;
|
||||
const int rv = CheckKeyFlags(value[i], &f);
|
||||
if (rv) { return rv; }
|
||||
|
||||
*flags = (MMKeyFlags)(*flags | f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
// return CheckKeyFlags(fstr, flags);
|
||||
}
|
||||
|
||||
// If it's not an array, it should be a single string value.
|
||||
char* key_Taps(char *k, char* keyArr[], int num, int keyDelay){
|
||||
MMKeyFlags flags = MOD_NONE;
|
||||
// MMKeyFlags flags = 0;
|
||||
MMKeyCode key;
|
||||
|
||||
switch(GetFlagsFromValue(keyArr, &flags, num)) {
|
||||
// switch (CheckKeyFlags(akey, &flags)){
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
|
||||
switch(CheckKeyCodes(k, &key)) {
|
||||
case -1:
|
||||
return "Null pointer in key code.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key code specified.";
|
||||
break;
|
||||
default:
|
||||
tapKeyCode(key, flags);
|
||||
microsleep(keyDelay);
|
||||
}
|
||||
|
||||
// return "0";
|
||||
return "";
|
||||
}
|
||||
|
||||
char* key_tap(char *k, char *akey, char *keyT, int keyDelay){
|
||||
MMKeyFlags flags = (MMKeyFlags) MOD_NONE;
|
||||
// MMKeyFlags flags = 0;
|
||||
MMKeyCode key;
|
||||
|
||||
// char *k;
|
||||
// k = *kstr;
|
||||
if (strcmp(akey, "null") != 0) {
|
||||
if (strcmp(keyT, "null") == 0) {
|
||||
switch (CheckKeyFlags(akey, &flags)) {
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
char* akeyArr[2] = {akey, keyT};
|
||||
switch(GetFlagsFromValue(akeyArr, &flags, 2)) {
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(CheckKeyCodes(k, &key)) {
|
||||
case -1:
|
||||
return "Null pointer in key code.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key code specified.";
|
||||
break;
|
||||
default:
|
||||
tapKeyCode(key, flags);
|
||||
microsleep(keyDelay);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
char* key_Toggles(char* k, char* keyArr[], int num) {
|
||||
MMKeyFlags flags = (MMKeyFlags) MOD_NONE;
|
||||
MMKeyCode key;
|
||||
|
||||
bool down;
|
||||
char* d = keyArr[0];
|
||||
if (d != 0) {
|
||||
// char *d;
|
||||
// d = *dstr;
|
||||
if (strcmp(d, "down") == 0) {
|
||||
down = true;
|
||||
} else if (strcmp(d, "up") == 0) {
|
||||
down = false;
|
||||
} else {
|
||||
return "Invalid key state specified.";
|
||||
}
|
||||
}
|
||||
|
||||
switch (GetFlagsFromValue(keyArr, &flags, num)) {
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
|
||||
switch(CheckKeyCodes(k, &key)) {
|
||||
case -1:
|
||||
return "Null pointer in key code.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key code specified.";
|
||||
break;
|
||||
default:
|
||||
toggleKeyCode(key, down, flags);
|
||||
microsleep(keyboardDelay);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
char* key_toggle(char* k, char* d, char* akey, char* keyT){
|
||||
MMKeyFlags flags = (MMKeyFlags) MOD_NONE;
|
||||
MMKeyCode key;
|
||||
|
||||
bool down;
|
||||
// char *k;
|
||||
// k = *kstr;
|
||||
|
||||
if (d != 0) {
|
||||
// char *d;
|
||||
// d = *dstr;
|
||||
if (strcmp(d, "down") == 0) {
|
||||
down = true;
|
||||
} else if (strcmp(d, "up") == 0) {
|
||||
down = false;
|
||||
} else {
|
||||
return "Invalid key state specified.";
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(akey, "null") != 0) {
|
||||
if (strcmp(keyT, "null") == 0) {
|
||||
switch (CheckKeyFlags(akey, &flags)) {
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
char* akeyArr[2] = {akey, keyT};
|
||||
switch (GetFlagsFromValue(akeyArr, &flags, 2)) {
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(CheckKeyCodes(k, &key)) {
|
||||
case -1:
|
||||
return "Null pointer in key code.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key code specified.";
|
||||
break;
|
||||
default:
|
||||
toggleKeyCode(key, down, flags);
|
||||
microsleep(keyboardDelay);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void type_string(char *str){
|
||||
typeStringDelayed(str, 0);
|
||||
}
|
||||
|
||||
void type_string_delayed(char *str, size_t cpm){
|
||||
typeStringDelayed(str, cpm);
|
||||
}
|
||||
|
||||
void set_keyboard_delay(size_t val){
|
||||
keyboardDelay = val;
|
||||
}
|
11
key/key.go
Normal file
11
key/key.go
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
package key
|
4
key/key_windows.go
Normal file
4
key/key_windows.go
Normal file
@ -0,0 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package key
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user