A27两个不同版本的UI合并到同一个工程

This commit is contained in:
2025-07-10 15:16:58 +08:00
parent caf35e2429
commit f0d004e8c5
542 changed files with 53381 additions and 32365 deletions

View File

@ -0,0 +1,115 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 600
PenaltyBreakFirstLessLess: 100
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Language: TextProto
BasedOnStyle: google
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 2
UseTab: Never
...

View File

@ -0,0 +1,33 @@
*.o
*.a
*.so
*.swp
*.pdb
*.ilk
*.idb
*.obj
*.exe
*.pyc
/bin
/lib
.sconsign.dblite
lua/demo1
lua/lftk_run
tags
bin/demo1*
bin/demo_animator*
bin/demo_thread*
bin/demotr*
bin/demovg*
bin/fontgen*
bin/preview_ui*
bin/resgen*
bin/runLua*
bin/runTest*
bin/strgen*
bin/image*
bin/hello*
.vscode
.vs
*.os
res

View File

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random
Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -0,0 +1,99 @@
# awtk-widget-number-label
number_label 控件。用于显示数值的文本控件。
![](docs/images/ui.jpg)
## 准备
1. 获取 awtk 并编译
```
git clone https://github.com/zlgopen/awtk.git
cd awtk; scons; cd -
```
2. 获取 awtk-widget-number-label
```
git clone https://github.com/zlgopen/awtk-widget-number-label.git
cd awtk-widget-number-label
```
## 运行
1. 生成示例代码的资源
```
python scripts/update_res.py all
```
> 也可以使用 Designer 打开项目,之后点击 “打包” 按钮进行生成;
> 如果资源发生修改,则需要重新生成资源。
如果 PIL 没有安装,执行上述脚本可能会出现如下错误:
```cmd
Traceback (most recent call last):
...
ModuleNotFoundError: No module named 'PIL'
```
请用 pip 安装:
```cmd
pip install Pillow
```
2. 编译
* 编译 PC 版本
```
scons
```
* 编译 LINUX FB 版本
```
scons LINUX_FB=true
```
> 完整编译选项请参考 [编译选项](https://github.com/zlgopen/awtk-widget-generator/blob/master/docs/build_options.md)
3. 运行
```
./bin/demo
```
## 如何使用 number-label 控件
在 xml 文件中创建 number-label 控件
```xml
<number_label name="number_label" x="c" y="m" w="100" h="50" value="200.2" format="%.2lf" decimal_font_size_scale="0.5"/>
```
number_label 各属性的功能如下表所示:
| 属性名 | 作用 |
| ----------------------- | -------------------------------------------- |
| value | 数值 |
| format | 格式化显示的值 |
| decimal_font_size_scale | 小数部分字体大小与整数部分字体大小之比 |
| min | 最小值 |
| max | 最大值 |
| step | 步长,用于上下键修改时,一次增加或减少的数值 |
| loop | 用上下键修改时,值是否循环 |
| readonly | 编辑器是否只读 |
如果需要修改字体大小或颜色,可以通过修改 `font_size``text_color` 样式来修改。
**注意事项**
当 readonly 属性不为 true 时,可以用方向键修改控件的值。如果同时使用方向键切换焦点,会存在焦点进入本控件后无法出来的问题。为了避免这个问题,可以采用以下几种措施之一:
* readonly 设置为 true
* 把按键事件重新映射。请参考 [键值映射](https://github.com/zlgopen/awtk/blob/master/docs/map_key.md)。
* 使用极简键盘。请参考 [支持极简键盘](https://github.com/zlgopen/awtk/blob/master/docs/how_to_support_5keys_3keys.md)。
## 文档
[完善自定义控件](https://github.com/zlgopen/awtk-widget-generator/blob/master/docs/improve_generated_widget.md)

View File

@ -0,0 +1,8 @@
import os
import scripts.app_helper as app
helper = app.Helper(ARGUMENTS)
helper.set_dll_def('src/number_label.def').set_libs(['number_label']).call(DefaultEnvironment)
SConscriptFiles = ['src/SConscript']
helper.SConscript(SConscriptFiles)

View File

@ -0,0 +1,460 @@
<window>
<style name="default">
<normal bg_color="#ffffff"/>
</style>
</window>
<dialog>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</dialog>
<popup>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</popup>
<overlay>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</overlay>
<system_bar>
<style name="default" border="bottom" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</system_bar>
<system_bar_bottom>
<style name="default" border="top" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</system_bar_bottom>
<keyboard>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#e1e1e1"/>
</style>
</keyboard>
<button>
<style name="default" round_radius="4">
<normal text_color="#444444" bg_color="#f4f4f4" border_color="#c2c2c2"/>
<pressed text_color="#ffffff" bg_color="#1971dd" border_color="#1971dd"/>
<over text_color="#ffffff" bg_color="#338fff" border_color="#338fff"/>
<focused text_color="#444444" bg_color="#f4f4f4" border_color="#338fff" />
<disable text_color="#44444466" bg_color="#f4f4f466" border_color="#c2c2c266" />
</style>
<style name="combobox_down" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_down_n"/>
<pressed icon="arrow_down_p"/>
<over icon="arrow_down_o"/>
<disable icon="arrow_down_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_down" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_down_n"/>
<pressed icon="arrow_down_p"/>
<over icon="arrow_down_o"/>
<disable icon="arrow_down_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_up" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_up_n"/>
<pressed icon="arrow_up_p"/>
<over icon="arrow_up_o"/>
<disable icon="arrow_up_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_left" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_left_n"/>
<pressed icon="arrow_left_p"/>
<over icon="arrow_left_o"/>
<disable icon="arrow_left_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_right" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_right_n"/>
<pressed icon="arrow_right_p"/>
<over icon="arrow_right_o"/>
<disable icon="arrow_right_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="scroll_down" bg_color="#f2f2f2">
<normal icon="arrow_down_n"/>
<pressed icon="arrow_down_p"/>
<over icon="arrow_down_o"/>
<disable icon="arrow_down_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="scroll_up" bg_color="#f2f2f2">
<normal icon="arrow_up_n"/>
<pressed icon="arrow_up_p"/>
<over icon="arrow_up_o"/>
<disable icon="arrow_up_d" bg_color="#f2f2f266"/>
</style>
<style name="scroll_left" bg_color="#f2f2f2">
<normal icon="arrow_left_n"/>
<pressed icon="arrow_left_p"/>
<over icon="arrow_left_o"/>
<disable icon="arrow_left_d" bg_color="#f2f2f266"/>
</style>
<style name="scroll_right" bg_color="#f2f2f2">
<normal icon="arrow_right_n"/>
<pressed icon="arrow_right_p"/>
<over icon="arrow_right_o"/>
<disable icon="arrow_right_d" bg_color="#f2f2f266"/>
</style>
</button>
<edit selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466" />
<error border_color="#ff0000" />
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
</style>
</edit>
<spin_box selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466"/>
<error border_color="#ff0000"/>
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
<has_value has_value="1"/>
</style>
</spin_box>
<digit_clock>
<style name="default">
<normal text_color="#444444" />
</style>
</digit_clock>
<label>
<style name="default">
<normal text_color="#444444"/>
<disable text_color="#44444466"/>
</style>
</label>
<progress_bar>
<style name="default" round_radius="5">
<normal text_color="#444444" bg_color="#d8d8d8" fg_color="#338fff" border_color="#d8d8d8"/>
<disable text_color="#44444466" bg_color="#d8d8d866" fg_color="#338fff66" border_color="#d8d8d866"/>
</style>
</progress_bar>
<slider>
<style name="default" round_radius="5">
<normal bg_color="#d8d8d8" fg_color="#338fff" border_color="#bfbfbf"/>
<pressed bg_color="#d8d8d8" fg_color="#338fff" border_color="#1456d6"/>
<over bg_color="#d8d8d8" fg_color="#338fff" border_color="#54d8ff"/>
<focused bg_color="#d8d8d8" fg_color="#338fff" border_color="#54d8ff"/>
<disable bg_color="#d8d8d866" fg_color="#338fff66" border_color="#ececec"/>
</style>
</slider>
<check_button>
<style name="default" icon_at="left" text_color="#444444">
<normal icon="check_unchecked" />
<pressed icon="check_unchecked" />
<over icon="check_unchecked" />
<focused icon="check_unchecked" />
<disable icon="check_unchecked_d" text_color="#44444466"/>
<normal_of_checked icon="check_checked" />
<pressed_of_checked icon="check_checked" />
<over_of_checked icon="check_checked" />
<focused_of_checked icon="check_checked" />
<disable_of_checked icon="check_checked_d" text_color="#44444466"/>
</style>
</check_button>
<radio_button>
<style name="default" text_color="#444444" icon_at="left">
<normal icon="radio_unchecked" />
<pressed icon="radio_unchecked" />
<over icon="radio_unchecked" />
<focused icon="radio_unchecked" />
<disable icon="radio_unchecked_d" text_color="#44444466"/>
<normal_of_checked icon="radio_checked"/>
<pressed_of_checked icon="radio_checked"/>
<over_of_checked icon="radio_checked"/>
<focused_of_checked icon="radio_checked" />
<disable_of_checked icon="radio_checked_d" text_color="#44444466"/>
</style>
</radio_button>
<image>
<style name="default" text_color="#444444">
<normal />
</style>
</image>
<scroll_bar_m>
<style name="default">
<normal fg_color="#808080"/>
<disable fg_color="#80808066"/>
</style>
</scroll_bar_m>
<scroll_bar_d>
<style name="default" border_color="#bebebe">
<normal bg_color="#f0f0f0"/>
<over bg_color="#f0f0f0" />
<pressed bg_color="#f0f0f0" />
<disable bg_color="#f0f0f066" border_color="#bebebe66"/>
</style>
</scroll_bar_d>
<dragger>
<style name="default" bg_color="#9e9e9e">
<normal />
<pressed />
<over />
</style>
<style name="scroll_bar">
<normal bg_color="#d0d0d0" />
<pressed bg_color="#c0c0c0" />
<over bg_color="#c0c0c0" />
<disable bg_color="#c0c0c066" />
</style>
</dragger>
<list_item>
<style name="default" border_color="#e9e9e9" text_color="#444444">
<normal bg_color="#ffffff" />
<pressed bg_color="#338fff" text_color="#ffffff" />
<over bg_color="#ffffff" border_color="#338fff"/>
<disable border_color="#e9e9e966" text_color="#44444466"/>
</style>
</list_item>
<tab_button>
<style name="default" border_color="#c2c2c2" text_color="#444444">
<normal bg_color="#f4f4f4" />
<pressed bg_color="#cecdcd" />
<over bg_color="#ffffff" text_color="#1971dd"/>
<normal_of_active bg_color="#ffffff" border="top|left|right"/>
<pressed_of_active bg_color="#ffffff" text_color="#1971dd" border="top|left|right"/>
<over_of_active bg_color="#ffffff" text_color="#1971dd" border="top|left|right"/>
<disable_of_active border_color="#c2c2c266" bg_color="#f4f4f466" text_color="#44444466" border="top|left|right"/>
<disable border_color="#c2c2c266" bg_color="#f4f4f466" text_color="#44444466"/>
</style>
</tab_button>
<tab_button_group >
<style name="default">
<normal/>
</style>
<style name="scrollable" border_color="#a0a0a0" border="left|right">
<normal/>
</style>
</tab_button_group>
<combo_box selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left" border_color="#c2c2c2">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466"/>
<error border_color="#ff0000"/>
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
</style>
</combo_box>
<combo_box_ex selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left" border_color="#c2c2c2">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466"/>
<error border_color="#ff0000"/>
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
</style>
</combo_box_ex>
<combo_box_item>
<style name="default" icon_at="left" text_color="#444444" bg_color="#ffffff">
<normal />
<pressed bg_color="#338fff" text_color="#ffffff" />
<over bg_color="#1971dd" text_color="#ffffff" />
<focused bg_color="#1296db" text_color="#ffffff" />
<normal_of_checked bg_color="#338fff" text_color="#ffffff"/>
<focused_of_checked bg_color="#338fff" text_color="#ffffff"/>
<pressed_of_checked bg_color="#338fff" text_color="#ffffff" />
<over_of_checked bg_color="#1971dd" text_color="#ffffff" />
<disable_of_checked bg_color="#f4f4f466" text_color="#44444466" />
<disable bg_color="#f4f4f466" text_color="#44444466"/>
</style>
</combo_box_item>
<text_selector>
<style name="default" fg_color="#c2c2c2" text_color="#444444" text_align_h="center" bg_color="#ffffff">
<normal mask_color="#404040" border_color="#c2c2c2"/>
<disable mask_color="#c0c0c0" border_color="#c2c2c266" text_color="#44444466" />
</style>
</text_selector>
<switch>
<style name="default" margin="2" round_radius="11" fg_color="#ffffff">
<normal bg_color="#828282" selected_bg_color="#338fff"/>
<disable bg_color="#82828266" selected_bg_color="#338fff66"/>
</style>
</switch>
<slide_indicator>
<style name="default">
<normal fg_color="#338fff40" selected_fg_color="#338fff"/>
<disable fg_color="#338fff20" selected_fg_color="#338fff66"/>
</style>
</slide_indicator>
<slide_indicator_arc>
<style name="default">
<normal fg_color="#338fff40" selected_fg_color="#338fff"/>
<disable fg_color="#338fff20" selected_fg_color="#338fff66"/>
</style>
</slide_indicator_arc>
<progress_circle>
<style name="default">
<normal text_color="#444444" fg_color="#338fff"/>
<disable text_color="#44444466" fg_color="#338fff66"/>
</style>
</progress_circle>
<svg>
<style name="default" text_color="#444444">
<normal/>
</style>
</svg>
<gif>
<style name="default">
<normal/>
</style>
</gif>
<slide_menu>
<style name="default">
<normal/>
</style>
</slide_menu>
<mledit selected_fg_color="#020202" selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" border_color="#a0a0a0" text_color="#444444" text_align_h="left">
<normal bg_color="#ffffff" />
<focused bg_color="#ffffff"/>
<disable bg_color="gray" text_color="#44444466" />
<error bg_color="#ffffff" text_color="red" />
<empty bg_color="#ffffff" text_color="#a0a0a0" />
<empty_focus bg_color="#ffffff" text_color="#a0a0a0"/>
</style>
</mledit>
<line_number>
<style name="default" text_align_h="center">
<normal text_color="#444444" bg_color="#d0d0d0"/>
<disable text_color="#44444466" bg_color="#d0d0d066"/>
</style>
</line_number>
<hscroll_label>
<style name="default" text_color="#444444">
<normal />
<disable text_color="#44444466"/>
</style>
</hscroll_label>
<color_tile>
<style name="default">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable border_color="#c2c2c266"/>
</style>
</color_tile>
<view>
<style name="default">
<normal />
</style>
</view>
<tab_control>
<style name="default">
<normal />
</style>
</tab_control>
<scroll_view>
<style name="default">
<normal />
</style>
</scroll_view>
<list_view>
<style name="default" border_color="#c2c2c2" bg_color="#f4f4f4">
<normal />
<disable border_color="#c2c2c266" bg_color="#f4f4f466"/>
</style>
</list_view>
<list_view_h>
<style name="default" border_color="#c2c2c2" bg_color="#f4f4f4">
<normal />
<disable border_color="#c2c2c266" bg_color="#f4f4f466"/>
</style>
</list_view_h>
<pages>
<style name="default" border_color="#c2c2c2">
<normal />
</style>
</pages>
<slide_view>
<style name="default">
<normal />
</style>
</slide_view>
<color_picker>
<style name="default">
<normal />
</style>
</color_picker>
<color_component>
<style name="default" border_color="#c2c2c2">
<normal />
</style>
</color_component>
<candidates>
<style name="default" text_color="#444444" bg_color="#fafafa">
<normal />
</style>
</candidates>

View File

@ -0,0 +1,14 @@
<number_label>
<style name="default" font_size="32">
<normal text_color="black" />
</style>
<style name="green" font_name="led" font_size="32">
<normal text_color="green" />
</style>
<style name="grab_focus" font_size="32">
<normal text_color="black" />
<focused text_color="black" border_color="green"/>
</style>
</number_label>

View File

@ -0,0 +1,20 @@
<window theme="main" move_focus_prev_key="up" move_focus_next_key="down">
<view x="c" y="m" w="100%" h="100%" children_layout="default(h=40,c=2,s=10,m=10)">
<number_label name="num1" format="%d" value="100"/>
<number_label name="num2" format="%d" value="200"/>
<number_label name="num3" format="%.1lf" value="100.20"/>
<number_label name="num4" format="%.2lf" value="100.20"/>
<number_label name="num5" format="%.3lf" value="200.20"/>
<number_label name="num6" format="%.4lf" value="300.33" style="green"/>
<label text="Focusable:" />
<number_label name="num7" style="grab_focus" format="%d"
focusable="true" value="100"/>
<label text="Focusable:" />
<number_label name="num8" style="grab_focus" format="%.1lf" loop="true"
focusable="true" value="5" min="0" max="10" step="0.1"/>
<button name="close" text="Close" floating="true" x="c" y="b:10" w="128" h="30" />
</view>
</window>

View File

@ -0,0 +1,57 @@
# AWTK 如何集成第三方库
AWTK 集成第三方库非常简单,这里以集成 sqlite3 介绍一下具体方法。
## 一、编译第三方库
* 优先使用第三方库自己的构建方法。
* 如果第三方使用autoconf等方法构建在Windows平台上就会遇到问题。此时可以使用scons重写构建脚本。
比如:
> 以下是给sqlite3写的scons构建脚本。
```
import os
import platform
env=DefaultEnvironment().Clone()
LIB_DIR=os.environ['LIB_DIR'];
BIN_DIR=os.environ['BIN_DIR'];
env.Library(os.path.join(LIB_DIR, 'sqlite3'), Glob("sqlite3.c"))
env.Program(os.path.join(BIN_DIR, 'sqlite3'), Glob("shell.c"))
```
> 请参考 awtk-hello 中的 [3rd/sqlite3/SConscript](https://github.com/zlgopen/awtk-hello/blob/master/3rd/sqlite3/SConscript)
## 二、在SConstruct中引入第三方库
* 在 APP_LIBPATH 变量中加入库的路径
* 在 APP_LIBS 变量中加入库的名称。
* 在 APP_CPPPATH 变量中加头文件路径。
比如:
```
APP_CCFLAGS = ''
APP_LINKFLAGS=''
APP_LIBPATH = [APP_LIB_DIR]
APP_LIBS = ['assets', 'sqlite3']
APP_CPPPATH=[os.path.join(APP_ROOT, '3rd/sqlite3')]
DefaultEnvironment(
LINKFLAGS = APP_LINKFLAGS + awtk.LINKFLAGS,
CPPPATH = APP_CPPPATH + awtk.CPPPATH,
LIBS = APP_LIBS + awtk.LIBS,
LIBPATH = APP_LIBPATH + awtk.LIBPATH,
CCFLAGS = APP_CCFLAGS + awtk.CCFLAGS,
OS_SUBSYSTEM_CONSOLE=awtk.OS_SUBSYSTEM_CONSOLE,
OS_SUBSYSTEM_WINDOWS=awtk.OS_SUBSYSTEM_WINDOWS)
```
> 请参考 awtk-hello 中的 [SConstruct](https://github.com/zlgopen/awtk-hello/blob/master/SConstruct)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1,6 @@
find src -name \*.c -exec clang-format -i {} \;
find src -name \*.h -exec clang-format -i {} \;
find src -name \*.cc -exec clang-format -i {} \;
find src -name \*.cpp -exec clang-format -i {} \;
find src -name \*.inc -exec clang-format -i {} \;

View File

@ -0,0 +1,3 @@
node ../awtk/tools/idl_gen/index.js idl/idl.json src/
node ../awtk/tools/dll_def_gen/index.js idl/idl.json src/number_label.def

View File

@ -0,0 +1,360 @@
[
{
"params": [],
"annotation": {
"global": true
},
"desc": "注册数值文本控件。",
"name": "number_label_register",
"return": {
"type": "ret_t",
"desc": "返回RET_OK表示成功否则表示失败。"
},
"type": "method",
"header": "src/number_label_register.h",
"level": 1
},
{
"params": [],
"annotation": {
"global": true
},
"desc": "获取支持的渲染模式。",
"name": "number_label_supported_render_mode",
"return": {
"type": "const char*",
"desc": "返回渲染模式。"
},
"type": "method",
"header": "src/number_label_register.h",
"level": 1
},
{
"type": "class",
"methods": [
{
"params": [
{
"type": "widget_t*",
"name": "parent",
"desc": "父控件"
},
{
"type": "xy_t",
"name": "x",
"desc": "x坐标"
},
{
"type": "xy_t",
"name": "y",
"desc": "y坐标"
},
{
"type": "wh_t",
"name": "w",
"desc": "宽度"
},
{
"type": "wh_t",
"name": "h",
"desc": "高度"
}
],
"annotation": {
"constructor": true,
"scriptable": true
},
"desc": "创建number_label对象",
"name": "number_label_create",
"return": {
"type": "widget_t*",
"desc": "对象。"
}
},
{
"params": [
{
"type": "widget_t*",
"name": "widget",
"desc": "number_label对象。"
}
],
"annotation": {
"cast": true,
"scriptable": true
},
"desc": "转换为number_label对象(供脚本语言使用)。",
"name": "number_label_cast",
"return": {
"type": "widget_t*",
"desc": "number_label对象。"
}
},
{
"params": [
{
"type": "widget_t*",
"name": "widget",
"desc": "控件对象。"
},
{
"type": "const char*",
"name": "format",
"desc": "格式字符串。"
}
],
"annotation": {
"scriptable": true
},
"desc": "设置格式字符串(用于将浮点数转换为字符串)。",
"name": "number_label_set_format",
"return": {
"type": "ret_t",
"desc": "返回RET_OK表示成功否则表示失败。"
}
},
{
"params": [
{
"type": "widget_t*",
"name": "widget",
"desc": "控件对象。"
},
{
"type": "double",
"name": "decimal_font_size_scale",
"desc": "小数部分字体大小与整数部分字体大小之比。"
}
],
"annotation": {
"scriptable": true
},
"desc": "设置小数部分字体大小与整数部分字体大小之比。",
"name": "number_label_set_decimal_font_size_scale",
"return": {
"type": "ret_t",
"desc": "返回RET_OK表示成功否则表示失败。"
}
},
{
"params": [
{
"type": "widget_t*",
"name": "widget",
"desc": "widget对象。"
},
{
"type": "bool_t",
"name": "readonly",
"desc": "只读。"
}
],
"annotation": {
"scriptable": true
},
"desc": "设置控件是否为只读。",
"name": "number_label_set_readonly",
"return": {
"type": "ret_t",
"desc": "返回RET_OK表示成功否则表示失败。"
}
},
{
"params": [
{
"type": "widget_t*",
"name": "widget",
"desc": "widget对象。"
},
{
"type": "bool_t",
"name": "loop",
"desc": "值是否循环。"
}
],
"annotation": {
"scriptable": true
},
"desc": "设置 值是否循环",
"name": "number_label_set_loop",
"return": {
"type": "ret_t",
"desc": "返回RET_OK表示成功否则表示失败。"
}
},
{
"params": [
{
"type": "widget_t*",
"name": "widget",
"desc": "widget对象。"
},
{
"type": "double",
"name": "min",
"desc": "最小值。"
},
{
"type": "double",
"name": "max",
"desc": "最大值。"
},
{
"type": "double",
"name": "step",
"desc": "步长。"
}
],
"annotation": {
"scriptable": true
},
"desc": "设置取值范围和步长。",
"name": "number_label_set_limit",
"return": {
"type": "ret_t",
"desc": "返回RET_OK表示成功否则表示失败。"
}
},
{
"params": [
{
"type": "widget_t*",
"name": "widget",
"desc": "控件对象。"
},
{
"type": "double",
"name": "value",
"desc": "数值。"
}
],
"annotation": {
"scriptable": true
},
"desc": "设置数值。",
"name": "number_label_set_value",
"return": {
"type": "ret_t",
"desc": "返回RET_OK表示成功否则表示失败。"
}
}
],
"events": [],
"properties": [
{
"name": "format",
"desc": "格式字符串。",
"type": "char*",
"annotation": {
"set_prop": true,
"get_prop": true,
"readable": true,
"persitent": true,
"design": true,
"scriptable": true
}
},
{
"name": "decimal_font_size_scale",
"desc": "小数部分字体大小与整数部分字体大小之比。\n通常设置为0.5到1之间让小数部分字体变小用于强调整数部分。",
"type": "double",
"annotation": {
"set_prop": true,
"get_prop": true,
"readable": true,
"persitent": true,
"design": true,
"scriptable": true
}
},
{
"name": "value",
"desc": "数值。",
"type": "double",
"annotation": {
"set_prop": true,
"get_prop": true,
"readable": true,
"persitent": true,
"design": true,
"scriptable": true
}
},
{
"name": "readonly",
"desc": "编辑器是否为只读。",
"type": "bool_t",
"annotation": {
"set_prop": true,
"get_prop": true,
"readable": true,
"persitent": true,
"design": true,
"scriptable": true
}
},
{
"name": "loop",
"desc": "值是否循环。用上下键修改时,到达最小值时是否跳到最大值,到达最大值时是否跳到最小值。",
"type": "bool_t",
"annotation": {
"set_prop": true,
"get_prop": true,
"readable": true,
"persitent": true,
"design": true,
"scriptable": true
}
},
{
"name": "min",
"desc": "最小值。",
"type": "double",
"annotation": {
"set_prop": true,
"get_prop": true,
"readable": true,
"persitent": true,
"design": true,
"scriptable": true
}
},
{
"name": "max",
"desc": "最大值。",
"type": "double",
"annotation": {
"set_prop": true,
"get_prop": true,
"readable": true,
"persitent": true,
"design": true,
"scriptable": true
}
},
{
"name": "step",
"desc": "步长。\n用上下键修改时一次增加和减少时的数值。",
"type": "double",
"annotation": {
"set_prop": true,
"get_prop": true,
"readable": true,
"persitent": true,
"design": true,
"scriptable": true
}
}
],
"header": "number_label/number_label.h",
"desc": "数值文本控件。\n\n用于显示数值的文本控件。\n\n可以通过指定属性 format 来改变小数的有效位数。\n可以通过指定属性 decimal\\_font\\_size\\_scale 来减小小数部分的字体大小,以强调整数部分的重要性。\n\nnumber\\_label\\_t是[widget\\_t](widget_t.md)的子类控件widget\\_t的函数均适用于number\\_label\\_t控件。\n\n在xml中使用\"number\\_label\"标签创建数值文本控件。如:\n\n```xml\n<!-- ui -->\n<number_label x=\"c\" y=\"50\" w=\"100\" h=\"40\" value=\"-128\" format=\"%.4lf\" decimal_font_size_scale=\"0.5\"/>\n```\n\n在c代码中使用函数number\\_label\\_create创建数值文本控件。如\n\n```c\nwidget_t* number_label = number_label_create(win, 10, 10, 128, 30);\n```\n\n可用通过style来设置控件的显示风格如字体的大小和颜色等等。如\n\n```xml\n<!-- style -->\n<number_label>\n<style name=\"default\" font_size=\"32\">\n<normal text_color=\"black\" />\n</style>\n</number_label>\n```",
"name": "number_label_t",
"parent": "widget_t",
"annotation": {
"scriptable": true,
"design": true,
"widget": true
},
"level": 2
}
]

View File

@ -0,0 +1,43 @@
{
"name": "number_label",
"version": "1.0.1",
"date":"2020-05-31",
"team":"AWTK Develop Team",
"author":"Li XianJing <xianjimli@hotmail.com>",
"desc":"用于显示数值的文本控件。",
"copyright":"Guangzhou ZHIYUAN Electronics Co.,Ltd.",
"type": "PROJECT_CUSTOM_WIDGET",
"entry": "main",
"assets": {
"activedTheme": "default",
"outputDir": "res",
"loadFrom": "any",
"const": "resource_data",
"screenDPR": "x1",
"defaultLanguage": "zh",
"defaultCountry": "CN",
"themes": {
"default": {
"activedSystemBar": "system_bar",
"activedBottomSystemBar": "system_bar_b",
"packaged": true,
"fonts": {
"default": {
"text": " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~,。?!确定取消"
}
},
"lcd": {
"width": "320",
"height": "480",
"colorDepth": "16bit",
"colorFormat": "BGR(A)"
}
}
}
},
"creator": {
"name": "AWTK Designer",
"version": "1.0.0"
},
"awtkRoot": "${DesignerPath}/SDK/awtk"
}

View File

@ -0,0 +1,2 @@
__pycache__
*.pyc

View File

@ -0,0 +1,7 @@
import os
import sys
APP_SCRIPTS_ROOT = os.path.abspath(os.path.dirname(__file__))
print('APP_SCRIPTS_ROOT:' + APP_SCRIPTS_ROOT)
sys.path.insert(0, APP_SCRIPTS_ROOT)

View File

@ -0,0 +1,7 @@
import awtk_locator as locator
def Helper(ARGUMENTS):
locator.init(ARGUMENTS)
from app_helper_base import AppHelperBase
return AppHelperBase(ARGUMENTS)

View File

@ -0,0 +1,62 @@
import os
import sys
AWTK_ROOT = ''
def getAwtkRoot():
return AWTK_ROOT
def getAwtkSDKPath():
env = os.environ
if 'AWTK_SDK_PATH' in env:
return env['AWTK_SDK_PATH']
else:
return ''
def getAwtkOrAwtkLinuxFbRoot(is_linux_fb):
if is_linux_fb:
return locateAWTK('awtk-linux-fb')
else:
return locateAWTK('awtk')
def locateAWTK(awtk):
awtk_root = ''
if not os.path.exists(awtk_root):
dirnames = ['../'+awtk, '../../'+awtk, '../../../'+awtk]
for dirname in dirnames:
if os.path.exists(dirname):
awtk_root = dirname
break
if not os.path.exists(awtk_root):
awtk_sdk_path = getAwtkSDKPath();
if os.path.exists(awtk_sdk_path):
awtk_root = awtk_sdk_path + '/' + awtk
return os.path.abspath(awtk_root)
def init(ARGUMENTS = None):
global AWTK_ROOT
global LINUX_FB
if ARGUMENTS:
AWTK_ROOT = ARGUMENTS.get('AWTK_ROOT', '')
LINUX_FB = ARGUMENTS.get('LINUX_FB', '')
else:
LINUX_FB = ''
if not os.path.exists(AWTK_ROOT):
AWTK_ROOT = getAwtkOrAwtkLinuxFbRoot(LINUX_FB != '')
elif os.path.exists(LINUX_FB):
print(' do not set LINUX_FB and AWTK_ROOT !!!')
sys.exit()
if LINUX_FB:
AWTK_SCRIPTS_ROOT = os.path.join(AWTK_ROOT, '../awtk/scripts')
else:
AWTK_SCRIPTS_ROOT = os.path.join(AWTK_ROOT, 'scripts')
sys.path.insert(0, AWTK_SCRIPTS_ROOT)
print('AWTK_ROOT: ' + AWTK_ROOT)
print('AWTK_SCRIPTS_ROOT: ' + AWTK_SCRIPTS_ROOT)

View File

@ -0,0 +1,41 @@
import sys
import awtk_locator as locator
LONGSOPTS = ['awtk_root=', 'AWTK_ROOT=']
def get_args(args, longsopts = []) :
list_opts = []
for arg in args:
if arg.startswith('--') :
tmp_opt = '';
for opt in longsopts:
if arg.find(opt) > 0 :
tmp_opt = opt;
break
if tmp_opt != '' :
list_opts.append(arg.split(tmp_opt)[1])
continue
else :
print(arg + " not find command, command :")
print(longsopts)
sys.exit()
return list_opts
def update_res(ARGUMENTS, is_new_usage):
locator.init(ARGUMENTS)
import update_res_app as updater
if is_new_usage and not hasattr(updater, "getopt") :
print(" must update awtk !!!")
sys.exit()
updater.run(locator.getAwtkRoot())
is_new_usage = False
opts = get_args(sys.argv[1:], LONGSOPTS)
ARGUMENTS = dict()
if len(opts) > 0 :
is_new_usage = True
ARGUMENTS['AWTK_ROOT'] = opts[0]
else :
ARGUMENTS['AWTK_ROOT'] = ''
update_res(ARGUMENTS, is_new_usage)

View File

@ -0,0 +1,22 @@
import os
import sys
import platform
OS_NAME = platform.system();
LIB_DIR=os.environ['LIB_DIR'];
BIN_DIR=os.environ['BIN_DIR'];
env=DefaultEnvironment().Clone()
SOURCES=Glob('number_label/*.c') + Glob('*.c')
EXPORT_DEF=''
if OS_NAME == 'Windows' and os.environ['TOOLS_NAME'] == '':
EXPORT_DEF = ' /DEF:"src/number_label.def" '
if 'BUILD_SHARED' in os.environ and os.environ['BUILD_SHARED'] == 'True':
LIBS=['awtk'];
LINKFLAGS=env['LINKFLAGS'] + EXPORT_DEF
env.SharedLibrary(os.path.join(BIN_DIR, 'number_label'), SOURCES, LIBS=LIBS, LINKFLAGS=LINKFLAGS);
else:
env.Library(os.path.join(LIB_DIR, 'number_label'), SOURCES);

View File

@ -0,0 +1,12 @@
LIBRARY number_label
EXPORTS
number_label_register
number_label_supported_render_mode
number_label_create
number_label_cast
number_label_set_format
number_label_set_decimal_font_size_scale
number_label_set_readonly
number_label_set_loop
number_label_set_limit
number_label_set_value

View File

@ -0,0 +1,362 @@
/**
* File: number_label.h
* Author: AWTK Develop Team
* Brief: number_label
*
* Copyright (c) 2020 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-05-19 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/widget_vtable.h"
#include "number_label.h"
ret_t number_label_set_format(widget_t* widget, const char* format) {
number_label_t* number_label = NUMBER_LABEL(widget);
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
return_value_if_fail(format != NULL, RET_BAD_PARAMS);
number_label->format = tk_str_copy(number_label->format, format);
return widget_invalidate(widget, NULL);
}
ret_t number_label_set_value(widget_t* widget, double value) {
number_label_t* number_label = NUMBER_LABEL(widget);
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
number_label->value = value;
return widget_invalidate(widget, NULL);
}
ret_t number_label_set_decimal_font_size_scale(widget_t* widget, double decimal_font_size_scale) {
number_label_t* number_label = NUMBER_LABEL(widget);
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
number_label->decimal_font_size_scale = decimal_font_size_scale;
return widget_invalidate(widget, NULL);
}
static ret_t number_label_get_prop(widget_t* widget, const char* name, value_t* v) {
number_label_t* number_label = NUMBER_LABEL(widget);
return_value_if_fail(widget != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
if (tk_str_eq(name, WIDGET_PROP_MIN)) {
value_set_double(v, number_label->min);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_MAX)) {
value_set_double(v, number_label->max);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_STEP)) {
value_set_double(v, number_label->step);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_READONLY)) {
value_set_bool(v, number_label->readonly);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_LOOP)) {
value_set_bool(v, number_label->loop);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_VALUE)) {
value_set_double(v, number_label->value);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_FORMAT)) {
value_set_str(v, number_label->format);
return RET_OK;
} else if (tk_str_eq(name, NUMBER_LABEL_PROP_DECIMAL_FONT_SIZE_SCALE)) {
value_set_double(v, number_label->decimal_font_size_scale);
return RET_OK;
}
return RET_NOT_FOUND;
}
static ret_t number_label_set_prop(widget_t* widget, const char* name, const value_t* v) {
number_label_t* number_label = NUMBER_LABEL(widget);
return_value_if_fail(widget != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
if (tk_str_eq(name, WIDGET_PROP_MIN)) {
number_label->min = value_double(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_MAX)) {
number_label->max = value_double(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_STEP)) {
number_label->step = value_double(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_READONLY)) {
number_label->readonly = value_bool(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_LOOP)) {
number_label->loop = value_bool(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_VALUE)) {
number_label_set_value(widget, value_double(v));
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_FORMAT)) {
number_label_set_format(widget, value_str(v));
return RET_OK;
} else if (tk_str_eq(name, NUMBER_LABEL_PROP_DECIMAL_FONT_SIZE_SCALE)) {
number_label_set_decimal_font_size_scale(widget, value_double(v));
return RET_OK;
}
return RET_NOT_FOUND;
}
static ret_t number_label_on_destroy(widget_t* widget) {
number_label_t* number_label = NUMBER_LABEL(widget);
return_value_if_fail(widget != NULL && number_label != NULL, RET_BAD_PARAMS);
TKMEM_FREE(number_label->format);
return RET_OK;
}
static ret_t number_label_paint_text(widget_t* widget, canvas_t* c, wstr_t* text) {
int32_t x = 0;
int32_t y = 0;
int32_t w = widget->w;
int32_t h = widget->h;
float_t font_height = 0;
float_t text_width = 0;
float_t int_part_width = 0;
float_t decimal_part_width = 0;
int32_t int_part_len = 0;
int32_t decimal_part_len = 0;
style_t* style = widget->astyle;
color_t trans = color_init(0, 0, 0, 0);
number_label_t* number_label = NUMBER_LABEL(widget);
color_t tc = style_get_color(style, STYLE_ID_TEXT_COLOR, trans);
const char* font_name = style_get_str(style, STYLE_ID_FONT_NAME, NULL);
int32_t margin = style_get_int(style, STYLE_ID_MARGIN, 0);
int32_t margin_top = style_get_int(style, STYLE_ID_MARGIN_TOP, margin);
int32_t margin_left = style_get_int(style, STYLE_ID_MARGIN_LEFT, margin);
int32_t margin_bottom = style_get_int(style, STYLE_ID_MARGIN_BOTTOM, margin);
uint16_t font_size = style_get_int(style, STYLE_ID_FONT_SIZE, TK_DEFAULT_FONT_SIZE);
uint16_t decimal_font_size = font_size * number_label->decimal_font_size_scale;
align_h_t align_h = (align_h_t)style_get_int(style, STYLE_ID_TEXT_ALIGN_H, ALIGN_H_CENTER);
align_v_t align_v = (align_v_t)style_get_int(style, STYLE_ID_TEXT_ALIGN_V, ALIGN_V_MIDDLE);
while (text->str[int_part_len] != 0 && text->str[int_part_len] != '.') {
int_part_len++;
}
int_part_len++;
decimal_part_len = text->size - int_part_len;
decimal_part_len = tk_max(decimal_part_len, 0);
canvas_set_text_color(c, tc);
canvas_set_text_align(c, align_h, align_v);
canvas_set_font(c, font_name, font_size);
int_part_width = canvas_measure_text(c, text->str, int_part_len);
canvas_set_font(c, font_name, decimal_font_size);
decimal_part_width = canvas_measure_text(c, text->str + int_part_len, decimal_part_len);
text_width = int_part_width + decimal_part_width;
switch (align_h) {
case ALIGN_H_LEFT: {
x = margin_left;
break;
}
case ALIGN_H_RIGHT: {
x = w - margin_left - text_width;
break;
}
default: {
x = (w - text_width) / 2;
break;
}
}
canvas_set_font(c, font_name, font_size);
font_height = canvas_get_font_height(c);
switch (align_v) {
case ALIGN_V_TOP: {
y = margin_top;
canvas_draw_text(c, text->str, int_part_len, x, y);
break;
}
case ALIGN_V_BOTTOM: {
y = h - margin_bottom - font_height;
canvas_draw_text(c, text->str, int_part_len, x, y);
break;
}
default: {
y = (h - font_height) / 2;
canvas_draw_text(c, text->str, int_part_len, x, y);
break;
}
}
canvas_set_font(c, font_name, decimal_font_size);
y += font_height * (1 - number_label->decimal_font_size_scale) - 1;
x += int_part_width;
canvas_draw_text(c, text->str + int_part_len, decimal_part_len, x, y);
return RET_OK;
}
static ret_t number_label_on_paint_self(widget_t* widget, canvas_t* c) {
char buff[64];
wstr_t* text = &(widget->text);
number_label_t* number_label = NUMBER_LABEL(widget);
const char* format =
number_label->format != NULL ? number_label->format : NUMBER_LABEL_DEFAULT_FORMAT;
return_value_if_fail(widget->astyle != NULL, RET_BAD_PARAMS);
memset(buff, 0x00, sizeof(buff));
if (strchr(format, 'd') != NULL) {
tk_snprintf(buff, sizeof(buff) - 1, format, (int)(number_label->value));
} else {
tk_snprintf(buff, sizeof(buff) - 1, format, number_label->value);
}
wstr_set_utf8(text, buff);
return number_label_paint_text(widget, c, text);
}
ret_t number_label_set_limit(widget_t* widget, double min, double max, double step) {
number_label_t* number_label = NUMBER_LABEL(widget);
return_value_if_fail(number_label != NULL, RET_BAD_PARAMS);
number_label->min = min;
number_label->max = max;
number_label->step = step;
return RET_OK;
}
ret_t number_label_set_readonly(widget_t* widget, bool_t readonly) {
number_label_t* number_label = NUMBER_LABEL(widget);
return_value_if_fail(number_label != NULL, RET_BAD_PARAMS);
number_label->readonly = readonly;
return RET_OK;
}
ret_t number_label_set_loop(widget_t* widget, bool_t loop) {
number_label_t* number_label = NUMBER_LABEL(widget);
return_value_if_fail(number_label != NULL, RET_BAD_PARAMS);
number_label->loop = loop;
return RET_OK;
}
static ret_t number_label_add_delta(widget_t* widget, double delta) {
number_label_t* number_label = NUMBER_LABEL(widget);
double value = number_label->value + delta;
if (number_label->min < number_label->max) {
if (value < number_label->min) {
value = number_label->loop ? number_label->max : number_label->min;
}
if (value > number_label->max) {
value = number_label->loop ? number_label->min : number_label->max;
}
}
if (!tk_fequal(number_label->value, value)) {
value_change_event_t evt;
value_change_event_init(&evt, EVT_VALUE_WILL_CHANGE, widget);
value_set_double(&(evt.old_value), number_label->value);
value_set_double(&(evt.new_value), value);
if (widget_dispatch(widget, (event_t*)&evt) != RET_STOP) {
number_label->value = value;
evt.e.type = EVT_VALUE_CHANGED;
widget_dispatch(widget, (event_t*)&evt);
widget_invalidate(widget, NULL);
}
}
return RET_OK;
}
ret_t number_label_on_event(widget_t* widget, event_t* e) {
ret_t ret = RET_OK;
number_label_t* number_label = NUMBER_LABEL(widget);
switch (e->type) {
case EVT_KEY_DOWN: {
key_event_t* evt = (key_event_t*)e;
if (!(number_label->readonly)) {
return_value_if_fail(number_label->step != 0, RET_FAIL);
if (evt->key == TK_KEY_UP || evt->key == TK_KEY_LEFT) {
number_label_add_delta(widget, number_label->step);
ret = RET_STOP;
} else if (evt->key == TK_KEY_DOWN || evt->key == TK_KEY_RIGHT) {
number_label_add_delta(widget, -number_label->step);
ret = RET_STOP;
}
}
break;
}
}
return ret;
}
static const char* s_number_label_properties[] = {NUMBER_LABEL_PROP_DECIMAL_FONT_SIZE_SCALE,
WIDGET_PROP_MIN,
WIDGET_PROP_MAX,
WIDGET_PROP_STEP,
WIDGET_PROP_LOOP,
WIDGET_PROP_READONLY,
WIDGET_PROP_FORMAT,
WIDGET_PROP_VALUE,
NULL};
TK_DECL_VTABLE(number_label) = {.size = sizeof(number_label_t),
.type = WIDGET_TYPE_NUMBER_LABEL,
.parent = NULL,
.clone_properties = s_number_label_properties,
.persistent_properties = s_number_label_properties,
.create = number_label_create,
.on_paint_self = number_label_on_paint_self,
.set_prop = number_label_set_prop,
.get_prop = number_label_get_prop,
.on_event = number_label_on_event,
.on_destroy = number_label_on_destroy};
widget_t* number_label_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
number_label_t* number_label =
NUMBER_LABEL(widget_create(parent, TK_REF_VTABLE(number_label), x, y, w, h));
number_label->format = tk_strdup(NUMBER_LABEL_DEFAULT_FORMAT);
number_label->min = 0;
number_label->max = 0;
number_label->step = 1;
number_label->readonly = FALSE;
number_label->decimal_font_size_scale = 0.6;
return (widget_t*)number_label;
}
widget_t* number_label_cast(widget_t* widget) {
return_value_if_fail(WIDGET_IS_INSTANCE_OF(widget, number_label), NULL);
return widget;
}

View File

@ -0,0 +1,238 @@
/**
* File: number_label.h
* Author: AWTK Develop Team
* Brief: number_label
*
* Copyright (c) 2020 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-05-19 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_NUMBER_LABEL_H
#define TK_NUMBER_LABEL_H
#include "base/widget.h"
BEGIN_C_DECLS
/**
* @class number_label_t
* @parent widget_t
* @annotation ["scriptable","design","widget"]
* 数值文本控件。
*
* 用于显示数值的文本控件。
*
* 可以通过指定属性 format 来改变小数的有效位数。
* 可以通过指定属性 decimal\_font\_size\_scale 来减小小数部分的字体大小,以强调整数部分的重要性。
*
* number\_label\_t是[widget\_t](widget_t.md)的子类控件widget\_t的函数均适用于number\_label\_t控件。
*
* 在xml中使用"number\_label"标签创建数值文本控件。如:
*
* ```xml
* <!-- ui -->
* <number_label x="c" y="50" w="100" h="40" value="-128" format="%.4lf" decimal_font_size_scale="0.5"/>
* ```
*
* 在c代码中使用函数number\_label\_create创建数值文本控件。如
*
* ```c
* widget_t* number_label = number_label_create(win, 10, 10, 128, 30);
* ```
*
* 可用通过style来设置控件的显示风格如字体的大小和颜色等等。如
*
* ```xml
* <!-- style -->
* <number_label>
* <style name="default" font_size="32">
* <normal text_color="black" />
* </style>
* </number_label>
* ```
*/
typedef struct _number_label_t {
widget_t widget;
/**
* @property {char*} format
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
*
* 格式字符串。
*
*/
char* format;
/**
* @property {double} decimal_font_size_scale
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
*
* 小数部分字体大小与整数部分字体大小之比。
* 通常设置为0.5到1之间让小数部分字体变小用于强调整数部分。
*
*/
double decimal_font_size_scale;
/**
* @property {double} value
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 数值。
*
*/
double value;
/**
* @property {bool_t} readonly
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 编辑器是否为只读。
*/
bool_t readonly;
/**
* @property {bool_t} loop
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 值是否循环。用上下键修改时,到达最小值时是否跳到最大值,到达最大值时是否跳到最小值。
*/
bool_t loop;
/**
* @property {double} min
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 最小值。
*/
double min;
/**
* @property {double} max
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 最大值。
*/
double max;
/**
* @property {double} step
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 步长。
* 用上下键修改时,一次增加和减少时的数值。
*/
double step;
/*private*/
} number_label_t;
/**
* @method number_label_create
* 创建number_label对象
* @annotation ["constructor", "scriptable"]
* @param {widget_t*} parent 父控件
* @param {xy_t} x x坐标
* @param {xy_t} y y坐标
* @param {wh_t} w 宽度
* @param {wh_t} h 高度
*
* @return {widget_t*} 对象。
*/
widget_t* number_label_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method number_label_cast
* 转换为number_label对象(供脚本语言使用)。
* @annotation ["cast", "scriptable"]
* @param {widget_t*} widget number_label对象。
*
* @return {widget_t*} number_label对象。
*/
widget_t* number_label_cast(widget_t* widget);
/**
* @method number_label_set_format
* 设置格式字符串(用于将浮点数转换为字符串)。
* @annotation ["scriptable"]
* @param {widget_t*} widget 控件对象。
* @param {const char*} format 格式字符串。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t number_label_set_format(widget_t* widget, const char* format);
/**
* @method number_label_set_decimal_font_size_scale
* 设置小数部分字体大小与整数部分字体大小之比。
*
* @annotation ["scriptable"]
* @param {widget_t*} widget 控件对象。
* @param {double} decimal_font_size_scale 小数部分字体大小与整数部分字体大小之比。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t number_label_set_decimal_font_size_scale(widget_t* widget, double decimal_font_size_scale);
/**
* @method number_label_set_readonly
* 设置控件是否为只读。
* @annotation ["scriptable"]
* @param {widget_t*} widget widget对象。
* @param {bool_t} readonly 只读。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t number_label_set_readonly(widget_t* widget, bool_t readonly);
/**
* @method number_label_set_loop
* 设置 值是否循环
* @annotation ["scriptable"]
* @param {widget_t*} widget widget对象。
* @param {bool_t} loop 值是否循环。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t number_label_set_loop(widget_t* widget, bool_t loop);
/**
* @method number_label_set_limit
* 设置取值范围和步长。
* @annotation ["scriptable"]
* @param {widget_t*} widget widget对象。
* @param {double} min 最小值。
* @param {double} max 最大值。
* @param {double} step 步长。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t number_label_set_limit(widget_t* widget, double min, double max, double step);
/**
* @method number_label_set_value
* 设置数值。
*
* @annotation ["scriptable"]
* @param {widget_t*} widget 控件对象。
* @param {double} value 数值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t number_label_set_value(widget_t* widget, double value);
#define NUMBER_LABEL_PROP_FORMAT "format"
#define NUMBER_LABEL_PROP_DECIMAL_FONT_SIZE_SCALE "decimal_font_size_scale"
#define WIDGET_TYPE_NUMBER_LABEL "number_label"
#define NUMBER_LABEL(widget) ((number_label_t*)(number_label_cast(WIDGET(widget))))
#define NUMBER_LABEL_DEFAULT_FORMAT "%.02lf"
END_C_DECLS
#endif /*TK_NUMBER_LABEL_H*/

View File

@ -0,0 +1,34 @@
/**
* File: number_label_register.c
* Author: AWTK Develop Team
* Brief: number label register
*
* Copyright (c) 2020 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-05-19 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/widget_factory.h"
#include "number_label_register.h"
#include "number_label/number_label.h"
ret_t number_label_register(void) {
return widget_factory_register(widget_factory(), WIDGET_TYPE_NUMBER_LABEL, number_label_create);
}
const char* number_label_supported_render_mode(void) {
return "OpenGL|AGGE-BGR565|AGGE-BGRA8888|AGGE-MONO";
}

View File

@ -0,0 +1,51 @@
/**
* File: number_label_register.h
* Author: AWTK Develop Team
* Brief: number label register
*
* Copyright (c) 2020 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-05-19 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_NUMBER_LABEL_REGISTER_H
#define TK_NUMBER_LABEL_REGISTER_H
#include "base/widget.h"
BEGIN_C_DECLS
/**
* @method number_label_register
* 注册数值文本控件。
*
* @annotation ["global"]
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t number_label_register(void);
/**
* @method number_label_supported_render_mode
* 获取支持的渲染模式。
*
* @annotation ["global"]
*
* @return {const char*} 返回渲染模式。
*/
const char* number_label_supported_render_mode(void);
END_C_DECLS
#endif /*TK_NUMBER_LABEL_REGISTER_H*/

View File

@ -0,0 +1,115 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 600
PenaltyBreakFirstLessLess: 100
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Language: TextProto
BasedOnStyle: google
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 2
UseTab: Never
...

View File

@ -0,0 +1,34 @@
*.o
*.a
*.so
*.swp
*.pdb
*.ilk
*.idb
*.obj
*.exe
*.os
*.pyc
/bin
/lib
.sconsign.dblite
lua/demo1
lua/lftk_run
tags
bin/demo1*
bin/demo_animator*
bin/demo_thread*
bin/demotr*
bin/demovg*
bin/fontgen*
bin/preview_ui*
bin/resgen*
bin/runLua*
bin/runTest*
bin/strgen*
bin/image*
bin/hello*
.vscode
.vs
*.os
res

View File

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random
Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -0,0 +1,143 @@
# awtk-widget-qr
qr 控件。用于显示二维码控件。
![](docs/images/ui.jpg)
* 本项目使用 [libqrencode](https://github.com/fukuchi/libqrencode) 生成二维码。
* 本项目使用 [awtk-widget-generator](https://github.com/zlgopen/awtk-widget-generator) 生成代码框架。
## 准备
1. 获取 awtk 并编译
```
git clone https://github.com/zlgopen/awtk.git
cd awtk; scons; cd -
```
2. 获取 awtk-widget-qr 并编译
```
git clone https://github.com/zlgopen/awtk-widget-qr.git
cd awtk-widget-qr; scons
```
## 运行
1. 生成示例代码的资源
```
python scripts/update_res.py all
```
> 也可以使用 Designer 打开项目,之后点击 “打包” 按钮进行生成;
> 如果资源发生修改,则需要重新生成资源。
如果 PIL 没有安装,执行上述脚本可能会出现如下错误:
```cmd
Traceback (most recent call last):
...
ModuleNotFoundError: No module named 'PIL'
```
请用 pip 安装:
```cmd
pip install Pillow
```
2. 编译
* 编译PC版本
```
scons
```
* 编译LINUX FB版本
```
scons LINUX_FB=true
```
> 完整编译选项请参考[编译选项](https://github.com/zlgopen/awtk-widget-generator/blob/master/docs/build_options.md)
3. 运行
```
./bin/demo
```
## 如何使用二维码控件
### 设置需要转成二维码的字符串
qr 控件 `value` 属性内容就是转成二维码的字符串内容。
在界面描述文件设置:
```xml
<window theme="main" name="main">
<qr name="qr" x="c" y="m" w="50%" h="50%" value="https://github.com/zlgopen/awtk"/>
</window>
```
或在代码中设置:
```c
widget_t* win = window_open("main");
widget_t* qr = widget_lookup(win, "qr", TRUE);
qr_set_value(qr, "https://github.com/zlgopen/awtk");
```
按照上述例子设置完成后,用手机扫该二维码就会打开[ https://github.com/zlgopen/awtk ](https://github.com/zlgopen/awtk)网址。
### 设置二维码中的颜色与图片
添加图片资源到项目中:
![](./design/default/images/x1/message.png)
在样式文件中设置 qr 控件样式在对应状态设置 `fg_color` `bg_color``bg_image` 属性:
```xml
<qr>
<style name="default">
<!-- fg_color 为二维码颜色bg_color 为二维码背景色 -->
<normal fg_color="black" bg_color="white" bg_image="message"/>
<!-- disable 状态用于模拟 被扫描 状态 -->
<!-- 不设置 bg_image 属性,则该状态二维码中间没有图片 -->
<disable fg_color="gray" bg_color="#f0f0f0"/>
</style>
</qr>
```
从上述例子得到的效果为:
正常状态:
![](./docs/images/normal_style.png)
被扫描状态:
![](./docs/images/scanned_style.png)
**注意**:图片大小不可以大于二维码的 `45%` ,否则图片将会被裁剪:
图片资源:
![](./design/default/images/x3/message.png)
得到的二维码:
![](./docs/images/clip_image.png)
qr 控件的属性名及作用如下表所示:
| 属性名 | 作用 |
| ------ | ---------------------- |
| value | 要转换为二维码的字符串 |
## 文档
[完善自定义控件](https://github.com/zlgopen/awtk-widget-generator/blob/master/docs/improve_generated_widget.md)

View File

@ -0,0 +1,8 @@
import os
import scripts.app_helper as app
helper = app.Helper(ARGUMENTS)
helper.set_dll_def('src/qr.def').set_libs(['qr']).call(DefaultEnvironment)
SConscriptFiles = ['src/SConscript']
SConscript(SConscriptFiles)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,459 @@
<window>
<style name="default">
<normal bg_color="#ffffff"/>
</style>
</window>
<dialog>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</dialog>
<popup>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</popup>
<overlay>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</overlay>
<system_bar>
<style name="default" border="bottom" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</system_bar>
<system_bar_bottom>
<style name="default" border="top" border_color="#c2c2c2">
<normal bg_color="#ffffff"/>
</style>
</system_bar_bottom>
<keyboard>
<style name="default" border_color="#c2c2c2">
<normal bg_color="#e1e1e1"/>
</style>
</keyboard>
<button>
<style name="default" round_radius="4">
<normal text_color="#444444" bg_color="#f4f4f4" border_color="#c2c2c2"/>
<pressed text_color="#ffffff" bg_color="#1971dd" border_color="#1971dd"/>
<over text_color="#ffffff" bg_color="#338fff" border_color="#338fff"/>
<focused text_color="#444444" bg_color="#f4f4f4" border_color="#338fff" />
<disable text_color="#44444466" bg_color="#f4f4f466" border_color="#c2c2c266" />
</style>
<style name="combobox_down" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_down_n"/>
<pressed icon="arrow_down_p"/>
<over icon="arrow_down_o"/>
<disable icon="arrow_down_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_down" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_down_n"/>
<pressed icon="arrow_down_p"/>
<over icon="arrow_down_o"/>
<disable icon="arrow_down_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_up" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_up_n"/>
<pressed icon="arrow_up_p"/>
<over icon="arrow_up_o"/>
<disable icon="arrow_up_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_left" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_left_n"/>
<pressed icon="arrow_left_p"/>
<over icon="arrow_left_o"/>
<disable icon="arrow_left_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="spinbox_right" border_color="#c2c2c2" bg_color="#f2f2f2">
<normal icon="arrow_right_n"/>
<pressed icon="arrow_right_p"/>
<over icon="arrow_right_o"/>
<disable icon="arrow_right_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="scroll_down" bg_color="#f2f2f2">
<normal icon="arrow_down_n"/>
<pressed icon="arrow_down_p"/>
<over icon="arrow_down_o"/>
<disable icon="arrow_down_d" border_color="#c2c2c266" bg_color="#f2f2f266"/>
</style>
<style name="scroll_up" bg_color="#f2f2f2">
<normal icon="arrow_up_n"/>
<pressed icon="arrow_up_p"/>
<over icon="arrow_up_o"/>
<disable icon="arrow_up_d" bg_color="#f2f2f266"/>
</style>
<style name="scroll_left" bg_color="#f2f2f2">
<normal icon="arrow_left_n"/>
<pressed icon="arrow_left_p"/>
<over icon="arrow_left_o"/>
<disable icon="arrow_left_d" bg_color="#f2f2f266"/>
</style>
<style name="scroll_right" bg_color="#f2f2f2">
<normal icon="arrow_right_n"/>
<pressed icon="arrow_right_p"/>
<over icon="arrow_right_o"/>
<disable icon="arrow_right_d" bg_color="#f2f2f266"/>
</style>
</button>
<edit selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466" />
<error border_color="#ff0000" />
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
</style>
</edit>
<spin_box selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466"/>
<error border_color="#ff0000"/>
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
<has_value has_value="1"/>
</style>
</spin_box>
<digit_clock>
<style name="default">
<normal text_color="#444444" />
</style>
</digit_clock>
<label>
<style name="default">
<normal text_color="#444444"/>
<disable text_color="#44444466"/>
</style>
</label>
<progress_bar>
<style name="default" round_radius="5">
<normal text_color="#444444" bg_color="#d8d8d8" fg_color="#338fff" border_color="#d8d8d8"/>
<disable text_color="#44444466" bg_color="#d8d8d866" fg_color="#338fff66" border_color="#d8d8d866"/>
</style>
</progress_bar>
<slider>
<style name="default" round_radius="5">
<normal bg_color="#d8d8d8" fg_color="#338fff" border_color="#bfbfbf"/>
<pressed bg_color="#d8d8d8" fg_color="#338fff" border_color="#1456d6"/>
<over bg_color="#d8d8d8" fg_color="#338fff" border_color="#54d8ff"/>
<focused bg_color="#d8d8d8" fg_color="#338fff" border_color="#54d8ff"/>
<disable bg_color="#d8d8d866" fg_color="#338fff66" border_color="#ececec"/>
</style>
</slider>
<check_button>
<style name="default" icon_at="left" text_color="#444444">
<normal icon="check_unchecked" />
<pressed icon="check_unchecked" />
<over icon="check_unchecked" />
<focused icon="check_unchecked" />
<disable icon="check_unchecked_d" text_color="#44444466"/>
<normal_of_checked icon="check_checked" />
<pressed_of_checked icon="check_checked" />
<over_of_checked icon="check_checked" />
<focused_of_checked icon="check_checked" />
<disable_of_checked icon="check_checked_d" text_color="#44444466"/>
</style>
</check_button>
<radio_button>
<style name="default" text_color="#444444" icon_at="left">
<normal icon="radio_unchecked" />
<pressed icon="radio_unchecked" />
<over icon="radio_unchecked" />
<focused icon="radio_unchecked" />
<disable icon="radio_unchecked_d" text_color="#44444466"/>
<normal_of_checked icon="radio_checked"/>
<pressed_of_checked icon="radio_checked"/>
<over_of_checked icon="radio_checked"/>
<focused_of_checked icon="radio_checked" />
<disable_of_checked icon="radio_checked_d" text_color="#44444466"/>
</style>
</radio_button>
<image>
<style name="default" text_color="#444444">
<normal />
</style>
</image>
<scroll_bar_m>
<style name="default">
<normal fg_color="#808080"/>
<disable fg_color="#80808066"/>
</style>
</scroll_bar_m>
<scroll_bar_d>
<style name="default" border_color="#bebebe">
<normal bg_color="#f0f0f0"/>
<over bg_color="#f0f0f0" />
<pressed bg_color="#f0f0f0" />
<disable bg_color="#f0f0f066" border_color="#bebebe66"/>
</style>
</scroll_bar_d>
<dragger>
<style name="default" bg_color="#9e9e9e">
<normal />
<pressed />
<over />
</style>
<style name="scroll_bar">
<normal bg_color="#d0d0d0" />
<pressed bg_color="#c0c0c0" />
<over bg_color="#c0c0c0" />
<disable bg_color="#c0c0c066" />
</style>
</dragger>
<list_item>
<style name="default" border_color="#e9e9e9" text_color="#444444">
<normal bg_color="#ffffff" />
<pressed bg_color="#338fff" text_color="#ffffff" />
<over bg_color="#ffffff" border_color="#338fff"/>
<disable border_color="#e9e9e966" text_color="#44444466"/>
</style>
</list_item>
<tab_button>
<style name="default" border_color="#c2c2c2" text_color="#444444">
<normal bg_color="#f4f4f4" />
<pressed bg_color="#cecdcd" />
<over bg_color="#ffffff" text_color="#1971dd"/>
<normal_of_active bg_color="#ffffff" border="top|left|right"/>
<pressed_of_active bg_color="#ffffff" text_color="#1971dd" border="top|left|right"/>
<over_of_active bg_color="#ffffff" text_color="#1971dd" border="top|left|right"/>
<disable_of_active border_color="#c2c2c266" bg_color="#f4f4f466" text_color="#44444466" border="top|left|right"/>
<disable border_color="#c2c2c266" bg_color="#f4f4f466" text_color="#44444466"/>
</style>
</tab_button>
<tab_button_group >
<style name="default">
<normal/>
</style>
<style name="scrollable" border_color="#a0a0a0" border="left|right">
<normal/>
</style>
</tab_button_group>
<combo_box selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left" border_color="#c2c2c2">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466"/>
<error border_color="#ff0000"/>
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
</style>
</combo_box>
<combo_box_ex selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" bg_color="#f7f7f7" text_color="#444444" text_align_h="left" border_color="#c2c2c2">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable bg_color="#f7f7f766" border_color="#c2c2c266" text_color="#44444466"/>
<error border_color="#ff0000"/>
<empty border_color="#c2c2c2" text_color="#959494"/>
<empty_focus border_color="#c2c2c2" text_color="#959494"/>
<over border_color="#338fff"/>
</style>
</combo_box_ex>
<combo_box_item>
<style name="default" icon_at="left" text_color="#444444" bg_color="#ffffff">
<normal />
<pressed bg_color="#338fff" text_color="#ffffff" />
<over bg_color="#1971dd" text_color="#ffffff" />
<focused bg_color="#1296db" text_color="#ffffff" />
<normal_of_checked bg_color="#338fff" text_color="#ffffff"/>
<focused_of_checked bg_color="#338fff" text_color="#ffffff"/>
<pressed_of_checked bg_color="#338fff" text_color="#ffffff" />
<over_of_checked bg_color="#1971dd" text_color="#ffffff" />
<disable_of_checked bg_color="#f4f4f466" text_color="#44444466" />
<disable bg_color="#f4f4f466" text_color="#44444466"/>
</style>
</combo_box_item>
<text_selector>
<style name="default" fg_color="#c2c2c2" text_color="#444444" text_align_h="center" bg_color="#ffffff">
<normal mask_color="#404040" border_color="#c2c2c2"/>
<disable mask_color="#c0c0c0" border_color="#c2c2c266" text_color="#44444466" />
</style>
</text_selector>
<switch>
<style name="default" margin="2" round_radius="11" fg_color="#ffffff">
<normal bg_color="#828282" selected_bg_color="#338fff"/>
<disable bg_color="#82828266" selected_bg_color="#338fff66"/>
</style>
</switch>
<slide_indicator>
<style name="default">
<normal fg_color="#338fff40" selected_fg_color="#338fff"/>
<disable fg_color="#338fff20" selected_fg_color="#338fff66"/>
</style>
</slide_indicator>
<slide_indicator_arc>
<style name="default">
<normal fg_color="#338fff40" selected_fg_color="#338fff"/>
<disable fg_color="#338fff20" selected_fg_color="#338fff66"/>
</style>
</slide_indicator_arc>
<progress_circle>
<style name="default">
<normal text_color="#444444" fg_color="#338fff"/>
<disable text_color="#44444466" fg_color="#338fff66"/>
</style>
</progress_circle>
<svg>
<style name="default" text_color="#444444">
<normal/>
</style>
</svg>
<gif>
<style name="default">
<normal/>
</style>
</gif>
<slide_menu>
<style name="default">
<normal/>
</style>
</slide_menu>
<mledit selected_fg_color="#020202" selected_text_color="#010101" selected_bg_color="#b5d7fd">
<style name="default" border_color="#a0a0a0" text_color="#444444" text_align_h="left">
<normal bg_color="#ffffff" />
<focused bg_color="#ffffff"/>
<disable bg_color="gray" text_color="#44444466" />
<error bg_color="#ffffff" text_color="red" />
<empty bg_color="#ffffff" text_color="#a0a0a0" />
<empty_focus bg_color="#ffffff" text_color="#a0a0a0"/>
</style>
</mledit>
<line_number>
<style name="default" text_align_h="center">
<normal text_color="#444444" bg_color="#d0d0d0"/>
<disable text_color="#44444466" bg_color="#d0d0d066"/>
</style>
</line_number>
<hscroll_label>
<style name="default" text_color="#444444">
<normal />
<disable text_color="#44444466"/>
</style>
</hscroll_label>
<color_tile>
<style name="default">
<normal border_color="#c2c2c2"/>
<focused border_color="#338fff"/>
<disable border_color="#c2c2c266"/>
</style>
</color_tile>
<view>
<style name="default">
<normal />
</style>
</view>
<tab_control>
<style name="default">
<normal />
</style>
</tab_control>
<scroll_view>
<style name="default">
<normal />
</style>
</scroll_view>
<list_view>
<style name="default" border_color="#c2c2c2" bg_color="#f4f4f4">
<normal />
<disable border_color="#c2c2c266" bg_color="#f4f4f466"/>
</style>
</list_view>
<list_view_h>
<style name="default" border_color="#c2c2c2" bg_color="#f4f4f4">
<normal />
<disable border_color="#c2c2c266" bg_color="#f4f4f466"/>
</style>
</list_view_h>
<pages>
<style name="default" border_color="#c2c2c2">
<normal />
</style>
</pages>
<slide_view>
<style name="default">
<normal />
</style>
</slide_view>
<color_picker>
<style name="default">
<normal />
</style>
</color_picker>
<color_component>
<style name="default" border_color="#c2c2c2">
<normal />
</style>
</color_component>
<candidates>
<style name="default" text_color="#444444" bg_color="#fafafa">
<normal />
</style>
</candidates>

View File

@ -0,0 +1,6 @@
<qr>
<style name="default" >
<normal fg_color="black" bg_color="white" bg_image="message"/>
<disable fg_color="gray" bg_color="#f0f0f0"/>
</style>
</qr>

View File

@ -0,0 +1,4 @@
<window theme="main">
<qr x="c" y="m" w="240" h="240" value="https://github.com/zlgopen/awtk"/>
<button x="c" y="b:30" w="80" h="30" name="close" text="Close"/>
</window>

View File

@ -0,0 +1,6 @@
### 2021/11/25
* 去除没有使用到的宏和变量(感谢兆坤提供补丁)
* 修复logo裁剪区域未还原导致的界面显示问题感谢兆坤提供补丁
### 2021/10/26
* 中间支持LOGO感谢兆坤提供补丁

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -0,0 +1,6 @@
find src -name \*.c -exec clang-format -i {} \;
find src -name \*.h -exec clang-format -i {} \;
find src -name \*.cc -exec clang-format -i {} \;
find src -name \*.cpp -exec clang-format -i {} \;
find src -name \*.inc -exec clang-format -i {} \;

View File

@ -0,0 +1,3 @@
node ../awtk/tools/idl_gen/index.js idl/idl.json src/
node ../awtk/tools/dll_def_gen/index.js idl/idl.json src/qr.def

View File

@ -0,0 +1,154 @@
[
{
"params": [],
"annotation": {
"global": true
},
"desc": "注册控件。",
"name": "qr_register",
"return": {
"type": "ret_t",
"desc": "返回RET_OK表示成功否则表示失败。"
},
"type": "method",
"header": "src/qr_register.h",
"level": 1
},
{
"params": [],
"annotation": {
"global": true
},
"desc": "获取支持的渲染模式。",
"name": "qr_supported_render_mode",
"return": {
"type": "const char*",
"desc": "返回渲染模式。"
},
"type": "method",
"header": "src/qr_register.h",
"level": 1
},
{
"type": "class",
"methods": [
{
"params": [
{
"type": "widget_t*",
"name": "parent",
"desc": "父控件"
},
{
"type": "xy_t",
"name": "x",
"desc": "x坐标"
},
{
"type": "xy_t",
"name": "y",
"desc": "y坐标"
},
{
"type": "wh_t",
"name": "w",
"desc": "宽度"
},
{
"type": "wh_t",
"name": "h",
"desc": "高度"
}
],
"annotation": {
"constructor": true,
"scriptable": true
},
"desc": "创建qr对象",
"name": "qr_create",
"return": {
"type": "widget_t*",
"desc": "qr对象。"
}
},
{
"params": [
{
"type": "widget_t*",
"name": "widget",
"desc": "qr对象。"
}
],
"annotation": {
"cast": true,
"scriptable": true
},
"desc": "转换为qr对象(供脚本语言使用)。",
"name": "qr_cast",
"return": {
"type": "widget_t*",
"desc": "qr对象。"
}
},
{
"params": [
{
"type": "widget_t*",
"name": "widget",
"desc": "widget对象。"
},
{
"type": "const char*",
"name": "value",
"desc": "格式字符串。"
}
],
"annotation": {
"scriptable": true
},
"desc": "设置要转成二维码的字符串。",
"name": "new_qr_set_value",
"return": {
"type": "ret_t",
"desc": "返回RET_OK表示成功否则表示失败。"
}
},
{
"params": [],
"annotation": {},
"desc": "获取 qr 虚表。",
"name": "qr_get_widget_vtable",
"return": {
"type": "const widget_vtable_t*",
"desc": "成功返回 qr 虚表。"
}
}
],
"events": [],
"properties": [
{
"name": "value",
"desc": "要转成二维码的字符串。值。",
"type": "char*",
"annotation": {
"set_prop": true,
"get_prop": true,
"readable": true,
"persitent": true,
"design": true,
"scriptable": true
}
}
],
"header": "qr/qr.h",
"desc": "显示二维码的控件\nqr\\_t是[widget\\_t](widget_t.md)的子类控件widget\\_t的函数均适用于qr\\_t控件。\n\n在xml中使用\"qr\"标签创建数值文本控件。如:\n\n```xml\n<!-- ui -->\n<qr x=\"c\" y=\"m\" w=\"240\" h=\"240\" value=\"https://github.com/zlgopen/awtk\"/>\n```\n在c代码中使用函数qr\\_create创建数值文本控件。如\n\n```c\nwidget_t* qr = qr_create(win, 10, 10, 128, 128);\n```\n可用通过style来设置控件的显示风格如字体的大小和颜色等等。如\n\n```xml\n<!-- style -->\n<qr>\n<style name=\"default\" >\n<normal fg_color=\"black\" bg_color=\"white\" bg_image=\"message\"/>\n<disable fg_color=\"gray\" bg_color=\"#f0f0f0\"/>\n</style>\n</qr>\n```",
"name": "qr_t",
"parent": "widget_t",
"annotation": {
"scriptable": true,
"design": true,
"widget": true
},
"level": 2
}
]

View File

@ -0,0 +1,46 @@
{
"name": "qr",
"version": "1.0.1",
"date": "2020-06-01",
"team": "AWTK Develop Team",
"author": "Li XianJing <xianjimli@hotmail.com>",
"desc": "显示二维码的控件",
"copyright": "Guangzhou ZHIYUAN Electronics Co.,Ltd.",
"type": "PROJECT_CUSTOM_WIDGET",
"entry": "main",
"assets": {
"activedTheme": "default",
"outputDir": "res",
"loadFrom": "any",
"const": "resource_data",
"screenDPR": "x1",
"defaultLanguage": "zh",
"defaultCountry": "CN",
"themes": {
"default": {
"activedSystemBar": "system_bar",
"activedBottomSystemBar": "system_bar_b",
"packaged": true,
"fonts": {
"default": {
"text": " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~,。?!确定取消"
}
},
"lcd": {
"width": "320",
"height": "480",
"colorDepth": "16bit",
"colorFormat": "BGR(A)"
}
}
}
},
"creator": {
"name": "AWTK Designer",
"version": "2.0.21"
},
"awtkRoot": "${AWTK_SDK_PATH}/awtk",
"dependencies": {
"awtk": ">=2112"
}
}

View File

@ -0,0 +1,2 @@
__pycache__
*.pyc

View File

@ -0,0 +1,7 @@
import os
import sys
APP_SCRIPTS_ROOT = os.path.abspath(os.path.dirname(__file__))
print('APP_SCRIPTS_ROOT:' + APP_SCRIPTS_ROOT)
sys.path.insert(0, APP_SCRIPTS_ROOT)

View File

@ -0,0 +1,7 @@
import awtk_locator as locator
def Helper(ARGUMENTS):
locator.init(ARGUMENTS)
from app_helper_base import AppHelperBase
return AppHelperBase(ARGUMENTS)

View File

@ -0,0 +1,62 @@
import os
import sys
AWTK_ROOT = ''
def getAwtkRoot():
return AWTK_ROOT
def getAwtkSDKPath():
env = os.environ
if 'AWTK_SDK_PATH' in env:
return env['AWTK_SDK_PATH']
else:
return ''
def getAwtkOrAwtkLinuxFbRoot(is_linux_fb):
if is_linux_fb:
return locateAWTK('awtk-linux-fb')
else:
return locateAWTK('awtk')
def locateAWTK(awtk):
awtk_root = ''
if not os.path.exists(awtk_root):
dirnames = ['../'+awtk, '../../'+awtk, '../../../'+awtk]
for dirname in dirnames:
if os.path.exists(dirname):
awtk_root = dirname
break
if not os.path.exists(awtk_root):
awtk_sdk_path = getAwtkSDKPath();
if os.path.exists(awtk_sdk_path):
awtk_root = awtk_sdk_path + '/' + awtk
return os.path.abspath(awtk_root)
def init(ARGUMENTS = None):
global AWTK_ROOT
global LINUX_FB
if ARGUMENTS:
AWTK_ROOT = ARGUMENTS.get('AWTK_ROOT', '')
LINUX_FB = ARGUMENTS.get('LINUX_FB', '')
else:
LINUX_FB = ''
if not os.path.exists(AWTK_ROOT):
AWTK_ROOT = getAwtkOrAwtkLinuxFbRoot(LINUX_FB != '')
elif os.path.exists(LINUX_FB):
print(' do not set LINUX_FB and AWTK_ROOT !!!')
sys.exit()
if LINUX_FB:
AWTK_SCRIPTS_ROOT = os.path.join(AWTK_ROOT, '../awtk/scripts')
else:
AWTK_SCRIPTS_ROOT = os.path.join(AWTK_ROOT, 'scripts')
sys.path.insert(0, AWTK_SCRIPTS_ROOT)
print('AWTK_ROOT: ' + AWTK_ROOT)
print('AWTK_SCRIPTS_ROOT: ' + AWTK_SCRIPTS_ROOT)

View File

@ -0,0 +1,41 @@
import sys
import awtk_locator as locator
LONGSOPTS = ['awtk_root=', 'AWTK_ROOT=']
def get_args(args, longsopts = []) :
list_opts = []
for arg in args:
if arg.startswith('--') :
tmp_opt = '';
for opt in longsopts:
if arg.find(opt) > 0 :
tmp_opt = opt;
break
if tmp_opt != '' :
list_opts.append(arg.split(tmp_opt)[1])
continue
else :
print(arg + " not find command, command :")
print(longsopts)
sys.exit()
return list_opts
def update_res(ARGUMENTS, is_new_usage):
locator.init(ARGUMENTS)
import update_res_app as updater
if is_new_usage and not hasattr(updater, "getopt") :
print(" must update awtk !!!")
sys.exit()
updater.run(locator.getAwtkRoot())
is_new_usage = False
opts = get_args(sys.argv[1:], LONGSOPTS)
ARGUMENTS = dict()
if len(opts) > 0 :
is_new_usage = True
ARGUMENTS['AWTK_ROOT'] = opts[0]
else :
ARGUMENTS['AWTK_ROOT'] = ''
update_res(ARGUMENTS, is_new_usage)

View File

@ -0,0 +1,22 @@
import os
import sys
import platform
OS_NAME = platform.system();
LIB_DIR=os.environ['LIB_DIR'];
BIN_DIR=os.environ['BIN_DIR'];
env=DefaultEnvironment().Clone()
SOURCES=Glob('qr/*.cpp') + Glob('qr/*.c') + Glob('*.c')
EXPORT_DEF=''
if OS_NAME == 'Windows' and os.environ['TOOLS_NAME'] == '':
EXPORT_DEF = ' /DEF:"src/qr.def" '
if 'BUILD_SHARED' in os.environ and os.environ['BUILD_SHARED'] == 'True':
LIBS=['awtk'];
LINKFLAGS=env['LINKFLAGS'] + EXPORT_DEF
env.SharedLibrary(os.path.join(BIN_DIR, 'qr'), SOURCES, LIBS=LIBS, LINKFLAGS=LINKFLAGS);
else:
env.Library(os.path.join(LIB_DIR, 'qr'), SOURCES);

View File

@ -0,0 +1,8 @@
LIBRARY qr
EXPORTS
qr_register
qr_supported_render_mode
qr_create
qr_cast
new_qr_set_value
qr_get_widget_vtable

View File

@ -0,0 +1,229 @@
/*
* qrencode - QR Code encoder
*
* Binary sequence class.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bitstream.h"
#define DEFAULT_BUFSIZE (128)
BitStream *BitStream_new(void)
{
BitStream *bstream;
bstream = (BitStream *)malloc(sizeof(BitStream));
if(bstream == NULL) return NULL;
bstream->length = 0;
bstream->data = (unsigned char *)malloc(DEFAULT_BUFSIZE);
if(bstream->data == NULL) {
free(bstream);
return NULL;
}
bstream->datasize = DEFAULT_BUFSIZE;
return bstream;
}
#ifdef WITH_TESTS
BitStream *BitStream_newWithBits(size_t size, unsigned char *bits)
{
BitStream *bstream;
if(size == 0) return BitStream_new();
bstream = (BitStream *)malloc(sizeof(BitStream));
if(bstream == NULL) return NULL;
bstream->data = (unsigned char *)malloc(size);
if(bstream->data == NULL) {
free(bstream);
return NULL;
}
bstream->length = size;
bstream->datasize = size;
memcpy(bstream->data, bits, size);
return bstream;
}
#endif
static int BitStream_expand(BitStream *bstream)
{
unsigned char *data;
data = (unsigned char *)realloc(bstream->data, bstream->datasize * 2);
if(data == NULL) {
return -1;
}
bstream->data = data;
bstream->datasize *= 2;
return 0;
}
static void BitStream_writeNum(unsigned char *dest, size_t bits, unsigned int num)
{
unsigned int mask;
size_t i;
unsigned char *p;
p = dest;
mask = 1U << (bits - 1);
for(i = 0; i < bits; i++) {
if(num & mask) {
*p = 1;
} else {
*p = 0;
}
p++;
mask = mask >> 1;
}
}
static void BitStream_writeBytes(unsigned char *dest, size_t size, unsigned char *data)
{
unsigned char mask;
size_t i, j;
unsigned char *p;
p = dest;
for(i = 0; i < size; i++) {
mask = 0x80;
for(j = 0; j < 8; j++) {
if(data[i] & mask) {
*p = 1;
} else {
*p = 0;
}
p++;
mask = mask >> 1;
}
}
}
int BitStream_append(BitStream *bstream, BitStream *arg)
{
int ret;
if(arg == NULL) {
return -1;
}
if(arg->length == 0) {
return 0;
}
while(bstream->length + arg->length > bstream->datasize) {
ret = BitStream_expand(bstream);
if(ret < 0) return ret;
}
memcpy(bstream->data + bstream->length, arg->data, arg->length);
bstream->length += arg->length;
return 0;
}
int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num)
{
int ret;
if(bits == 0) return 0;
while(bstream->datasize - bstream->length < bits) {
ret = BitStream_expand(bstream);
if(ret < 0) return ret;
}
BitStream_writeNum(bstream->data + bstream->length, bits, num);
bstream->length += bits;
return 0;
}
int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data)
{
int ret;
if(size == 0) return 0;
while(bstream->datasize - bstream->length < size * 8) {
ret = BitStream_expand(bstream);
if(ret < 0) return ret;
}
BitStream_writeBytes(bstream->data + bstream->length, size, data);
bstream->length += size * 8;
return 0;
}
unsigned char *BitStream_toByte(BitStream *bstream)
{
size_t i, j, size, bytes, oddbits;
unsigned char *data, v;
unsigned char *p;
size = BitStream_size(bstream);
if(size == 0) {
return NULL;
}
data = (unsigned char *)malloc((size + 7) / 8);
if(data == NULL) {
return NULL;
}
bytes = size / 8;
p = bstream->data;
for(i = 0; i < bytes; i++) {
v = 0;
for(j = 0; j < 8; j++) {
v = (unsigned char)(v << 1);
v |= *p;
p++;
}
data[i] = v;
}
oddbits = size & 7;
if(oddbits > 0) {
v = 0;
for(j = 0; j < oddbits; j++) {
v = (unsigned char)(v << 1);
v |= *p;
p++;
}
data[bytes] = (unsigned char)(v << (8 - oddbits));
}
return data;
}
void BitStream_free(BitStream *bstream)
{
if(bstream != NULL) {
free(bstream->data);
free(bstream);
}
}

View File

@ -0,0 +1,43 @@
/*
* qrencode - QR Code encoder
*
* Binary sequence class.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef BITSTREAM_H
#define BITSTREAM_H
typedef struct {
size_t length;
size_t datasize;
unsigned char *data;
} BitStream;
extern BitStream *BitStream_new(void);
#ifdef WITH_TESTS
extern BitStream *BitStream_newWithBits(size_t size, unsigned char *bits);
#endif
extern int BitStream_append(BitStream *bstream, BitStream *arg);
extern int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num);
extern int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data);
#define BitStream_size(__bstream__) (__bstream__->length)
#define BitStream_reset(__bstream__) (__bstream__->length = 0)
extern unsigned char *BitStream_toByte(BitStream *bstream);
extern void BitStream_free(BitStream *bstream);
#endif /* BITSTREAM_H */

View File

@ -0,0 +1,13 @@
#ifndef QRENCODER_CONFIG_H
#define QRENCODER_CONFIG_H
#include "awtk.h"
#include "tkc/mem.h"
#define STATIC_IN_RELEASE static
#define MAJOR_VERSION 4
#define MINOR_VERSION 1
#define MICRO_VERSION 0
#define VERSION "1.0"
#endif/*QRENCODER_CONFIG_H*/

View File

@ -0,0 +1,355 @@
/*
* qrencode - QR Code encoder
*
* Masking.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "qrencode.h"
#include "qrspec.h"
#include "mask.h"
STATIC_IN_RELEASE int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level)
{
unsigned int format;
unsigned char v;
int i;
int blacks = 0;
format = QRspec_getFormatInfo(mask, level);
for(i = 0; i < 8; i++) {
if(format & 1) {
blacks += 2;
v = 0x85;
} else {
v = 0x84;
}
frame[width * 8 + width - 1 - i] = v;
if(i < 6) {
frame[width * i + 8] = v;
} else {
frame[width * (i + 1) + 8] = v;
}
format= format >> 1;
}
for(i = 0; i < 7; i++) {
if(format & 1) {
blacks += 2;
v = 0x85;
} else {
v = 0x84;
}
frame[width * (width - 7 + i) + 8] = v;
if(i == 0) {
frame[width * 8 + 7] = v;
} else {
frame[width * 8 + 6 - i] = v;
}
format= format >> 1;
}
return blacks;
}
/**
* Demerit coefficients.
* See Section 8.8.2, pp.45, JIS X0510:2004.
*/
#define N1 (3)
#define N2 (3)
#define N3 (40)
#define N4 (10)
#define MASKMAKER(__exp__) \
int x, y;\
int b = 0;\
\
for(y = 0; y < width; y++) {\
for(x = 0; x < width; x++) {\
if(*s & 0x80) {\
*d = *s;\
} else {\
*d = *s ^ ((__exp__) == 0);\
}\
b += (int)(*d & 1);\
s++; d++;\
}\
}\
return b;
static int Mask_mask0(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((x+y)&1)
}
static int Mask_mask1(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(y&1)
}
static int Mask_mask2(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(x%3)
}
static int Mask_mask3(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((x+y)%3)
}
static int Mask_mask4(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(((y/2)+(x/3))&1)
}
static int Mask_mask5(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(((x*y)&1)+(x*y)%3)
}
static int Mask_mask6(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x*y)&1)+(x*y)%3)&1)
}
static int Mask_mask7(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x*y)%3)+((x+y)&1))&1)
}
#define maskNum (8)
typedef int MaskMaker(int, const unsigned char *, unsigned char *);
static MaskMaker *maskMakers[maskNum] = {
Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3,
Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7
};
#ifdef WITH_TESTS
unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask)
{
unsigned char *masked;
masked = (unsigned char *)malloc((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
return masked;
}
#endif
unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level)
{
unsigned char *masked;
if(mask < 0 || mask >= maskNum) {
errno = EINVAL;
return NULL;
}
masked = (unsigned char *)malloc((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
Mask_writeFormatInformation(width, masked, mask, level);
return masked;
}
//static int n1;
//static int n2;
//static int n3;
//static int n4;
STATIC_IN_RELEASE int Mask_calcN1N3(int length, int *runLength)
{
int i;
int demerit = 0;
int fact;
for(i = 0; i < length; i++) {
if(runLength[i] >= 5) {
demerit += N1 + (runLength[i] - 5);
//n1 += N1 + (runLength[i] - 5);
}
if((i & 1)) {
if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) {
fact = runLength[i] / 3;
if(runLength[i-2] == fact &&
runLength[i-1] == fact &&
runLength[i+1] == fact &&
runLength[i+2] == fact) {
if(i == 3 || runLength[i-3] >= 4 * fact) {
demerit += N3;
//n3 += N3;
} else if(i+4 >= length || runLength[i+3] >= 4 * fact) {
demerit += N3;
//n3 += N3;
}
}
}
}
}
return demerit;
}
STATIC_IN_RELEASE int Mask_calcN2(int width, unsigned char *frame)
{
int x, y;
unsigned char *p;
unsigned char b22, w22;
int demerit = 0;
p = frame + width + 1;
for(y = 1; y < width; y++) {
for(x = 1; x < width; x++) {
b22 = p[0] & p[-1] & p[-width] & p [-width-1];
w22 = p[0] | p[-1] | p[-width] | p [-width-1];
if((b22 | (w22 ^ 1))&1) {
demerit += N2;
}
p++;
}
p++;
}
return demerit;
}
STATIC_IN_RELEASE int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength)
{
int head;
int i;
unsigned char prev;
if(frame[0] & 1) {
runLength[0] = -1;
head = 1;
} else {
head = 0;
}
runLength[head] = 1;
prev = frame[0];
for(i = 1; i < width; i++) {
if((frame[i] ^ prev) & 1) {
head++;
runLength[head] = 1;
prev = frame[i];
} else {
runLength[head]++;
}
}
return head + 1;
}
STATIC_IN_RELEASE int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength)
{
int head;
int i;
unsigned char prev;
if(frame[0] & 1) {
runLength[0] = -1;
head = 1;
} else {
head = 0;
}
runLength[head] = 1;
prev = frame[0];
for(i = 1; i < width; i++) {
if((frame[i * width] ^ prev) & 1) {
head++;
runLength[head] = 1;
prev = frame[i * width];
} else {
runLength[head]++;
}
}
return head + 1;
}
STATIC_IN_RELEASE int Mask_evaluateSymbol(int width, unsigned char *frame)
{
int x, y;
int demerit = 0;
int runLength[QRSPEC_WIDTH_MAX + 1];
int length;
demerit += Mask_calcN2(width, frame);
for(y = 0; y < width; y++) {
length = Mask_calcRunLengthH(width, frame + y * width, runLength);
demerit += Mask_calcN1N3(length, runLength);
}
for(x = 0; x < width; x++) {
length = Mask_calcRunLengthV(width, frame + x, runLength);
demerit += Mask_calcN1N3(length, runLength);
}
return demerit;
}
unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level)
{
int i;
unsigned char *mask, *bestMask;
int minDemerit = INT_MAX;
int blacks;
int bratio;
int demerit;
int w2 = width * width;
mask = (unsigned char *)malloc((size_t)w2);
if(mask == NULL) return NULL;
bestMask = (unsigned char *)malloc((size_t)w2);
if(bestMask == NULL) {
free(mask);
return NULL;
}
for(i = 0; i < maskNum; i++) {
// n1 = n2 = n3 = n4 = 0;
demerit = 0;
blacks = maskMakers[i](width, frame, mask);
blacks += Mask_writeFormatInformation(width, mask, i, level);
bratio = (200 * blacks + w2) / w2 / 2; /* (int)(100*blacks/w2+0.5) */
demerit = (abs(bratio - 50) / 5) * N4;
// n4 = demerit;
demerit += Mask_evaluateSymbol(width, mask);
// printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, demerit);
if(demerit < minDemerit) {
minDemerit = demerit;
memcpy(bestMask, mask, (size_t)w2);
}
}
free(mask);
return bestMask;
}

View File

@ -0,0 +1,38 @@
/*
* qrencode - QR Code encoder
*
* Masking.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MASK_H
#define MASK_H
extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level);
#ifdef WITH_TESTS
extern int Mask_calcN2(int width, unsigned char *frame);
extern int Mask_calcN1N3(int length, int *runLength);
extern int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength);
extern int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength);
extern int Mask_evaluateSymbol(int width, unsigned char *frame);
extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask);
#endif
#endif /* MASK_H */

View File

@ -0,0 +1,175 @@
/*
* qrencode - QR Code encoder
*
* Masking for Micro QR Code.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "qrencode.h"
#include "mqrspec.h"
#include "mmask.h"
STATIC_IN_RELEASE void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level)
{
unsigned int format;
unsigned char v;
int i;
format = MQRspec_getFormatInfo(mask, version, level);
for(i = 0; i < 8; i++) {
v = 0x84 | (format & 1);
frame[width * (i + 1) + 8] = v;
format = format >> 1;
}
for(i = 0; i < 7; i++) {
v = 0x84 | (format & 1);
frame[width * 8 + 7 - i] = v;
format = format >> 1;
}
}
#define MASKMAKER(__exp__) \
int x, y;\
\
for(y = 0; y < width; y++) {\
for(x = 0; x < width; x++) {\
if(*s & 0x80) {\
*d = *s;\
} else {\
*d = *s ^ ((__exp__) == 0);\
}\
s++; d++;\
}\
}
static void Mask_mask0(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(y&1)
}
static void Mask_mask1(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(((y/2)+(x/3))&1)
}
static void Mask_mask2(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x*y)&1)+(x*y)%3)&1)
}
static void Mask_mask3(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x+y)&1)+((x*y)%3))&1)
}
#define maskNum (4)
typedef void MaskMaker(int, const unsigned char *, unsigned char *);
static MaskMaker *maskMakers[maskNum] = {
Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3
};
#ifdef WITH_TESTS
unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask)
{
unsigned char *masked;
masked = (unsigned char *)malloc((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
return masked;
}
#endif
unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level)
{
unsigned char *masked;
int width;
if(mask < 0 || mask >= maskNum) {
errno = EINVAL;
return NULL;
}
width = MQRspec_getWidth(version);
masked = (unsigned char *)malloc((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
MMask_writeFormatInformation(version, width, masked, mask, level);
return masked;
}
STATIC_IN_RELEASE int MMask_evaluateSymbol(int width, unsigned char *frame)
{
int x, y;
unsigned char *p;
int sum1 = 0, sum2 = 0;
p = frame + width * (width - 1);
for(x = 1; x < width; x++) {
sum1 += (p[x] & 1);
}
p = frame + width * 2 - 1;
for(y = 1; y < width; y++) {
sum2 += (*p & 1);
p += width;
}
return (sum1 <= sum2)?(sum1 * 16 + sum2):(sum2 * 16 + sum1);
}
unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level)
{
int i;
unsigned char *mask, *bestMask;
int maxScore = 0;
int score;
int width;
width = MQRspec_getWidth(version);
mask = (unsigned char *)malloc((size_t)(width * width));
if(mask == NULL) return NULL;
bestMask = NULL;
for(i = 0; i < maskNum; i++) {
score = 0;
maskMakers[i](width, frame, mask);
MMask_writeFormatInformation(version, width, mask, i, level);
score = MMask_evaluateSymbol(width, mask);
if(score > maxScore) {
maxScore = score;
free(bestMask);
bestMask = mask;
mask = (unsigned char *)malloc((size_t)(width * width));
if(mask == NULL) break;
}
}
free(mask);
return bestMask;
}

View File

@ -0,0 +1,34 @@
/*
* qrencode - QR Code encoder
*
* Masking for Micro QR Code.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MMASK_H
#define MMASK_H
extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level);
#ifdef WITH_TESTS
extern int MMask_evaluateSymbol(int width, unsigned char *frame);
extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask);
#endif
#endif /* MMASK_H */

View File

@ -0,0 +1,230 @@
/*
* qrencode - QR Code encoder
*
* Micro QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "mqrspec.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
typedef struct {
int width; ///< Edge length of the symbol
int ec[4]; ///< Number of ECC code (bytes)
} MQRspec_Capacity;
/**
* Table of the capacity of symbols
* See Table 1 (pp.106) and Table 8 (pp.113) of Appendix 1, JIS X0510:2004.
*/
static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = {
{ 0, {0, 0, 0, 0}},
{ 11, {2, 0, 0, 0}},
{ 13, {5, 6, 0, 0}},
{ 15, {6, 8, 0, 0}},
{ 17, {8, 10, 14, 0}}
};
int MQRspec_getDataLengthBit(int version, QRecLevel level)
{
int w;
int ecc;
w = mqrspecCapacity[version].width - 1;
ecc = mqrspecCapacity[version].ec[level];
if(ecc == 0) return 0;
return w * w - 64 - ecc * 8;
}
int MQRspec_getDataLength(int version, QRecLevel level)
{
return (MQRspec_getDataLengthBit(version, level) + 4) / 8;
}
int MQRspec_getECCLength(int version, QRecLevel level)
{
return mqrspecCapacity[version].ec[level];
}
int MQRspec_getWidth(int version)
{
return mqrspecCapacity[version].width;
}
/******************************************************************************
* Length indicator
*****************************************************************************/
/**
* See Table 3 (pp.107) of Appendix 1, JIS X0510:2004.
*/
static const int lengthTableBits[4][4] = {
{ 3, 4, 5, 6},
{ 0, 3, 4, 5},
{ 0, 0, 4, 5},
{ 0, 0, 3, 4}
};
int MQRspec_lengthIndicator(QRencodeMode mode, int version)
{
return lengthTableBits[mode][version - 1];
}
int MQRspec_maximumWords(QRencodeMode mode, int version)
{
int bits;
int words;
bits = lengthTableBits[mode][version - 1];
words = (1 << bits) - 1;
if(mode == QR_MODE_KANJI) {
words *= 2; // the number of bytes is required
}
return words;
}
/******************************************************************************
* Format information
*****************************************************************************/
/* See calcFormatInfo in tests/test_mqrspec.c */
static const unsigned int formatInfo[4][8] = {
{0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3},
{0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4},
{0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d},
{0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba}
};
/* See Table 10 of Appendix 1. (pp.115) */
static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = {
{-1, -1, -1},
{ 0, -1, -1},
{ 1, 2, -1},
{ 3, 4, -1},
{ 5, 6, 7}
};
unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level)
{
int type;
if(mask < 0 || mask > 3) return 0;
if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0;
if(level == QR_ECLEVEL_H) return 0;
type = typeTable[version][level];
if(type < 0) return 0;
return formatInfo[mask][type];
}
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Put a finder pattern.
* @param frame
* @param width
* @param ox,oy upper-left coordinate of the pattern
*/
static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
{
static const unsigned char finder[] = {
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
};
int x, y;
const unsigned char *s;
frame += oy * width + ox;
s = finder;
for(y = 0; y < 7; y++) {
for(x = 0; x < 7; x++) {
frame[x] = s[x];
}
frame += width;
s += 7;
}
}
static unsigned char *MQRspec_createFrame(int version)
{
unsigned char *frame, *p, *q;
int width;
int x, y;
width = mqrspecCapacity[version].width;
frame = (unsigned char *)malloc((size_t)(width * width));
if(frame == NULL) return NULL;
memset(frame, 0, (size_t)(width * width));
/* Finder pattern */
putFinderPattern(frame, width, 0, 0);
/* Separator */
p = frame;
for(y = 0; y < 7; y++) {
p[7] = 0xc0;
p += width;
}
memset(frame + width * 7, 0xc0, 8);
/* Mask format information area */
memset(frame + width * 8 + 1, 0x84, 8);
p = frame + width + 8;
for(y = 0; y < 7; y++) {
*p = 0x84;
p += width;
}
/* Timing pattern */
p = frame + 8;
q = frame + width * 8;
for(x = 1; x < width-7; x++) {
*p = 0x90 | (x & 1);
*q = 0x90 | (x & 1);
p++;
q += width;
}
return frame;
}
unsigned char *MQRspec_newFrame(int version)
{
if(version < 1 || version > MQRSPEC_VERSION_MAX) return NULL;
return MQRspec_createFrame(version);
}

View File

@ -0,0 +1,150 @@
/*
* qrencode - QR Code encoder
*
* Micro QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MQRSPEC_H
#define MQRSPEC_H
#include "qrencode.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
/**
* Maximum width of a symbol
*/
#define MQRSPEC_WIDTH_MAX 17
/**
* Return maximum data code length (bits) for the version.
* @param version version of the symbol
* @param level error correction level
* @return maximum size (bits)
*/
extern int MQRspec_getDataLengthBit(int version, QRecLevel level);
/**
* Return maximum data code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return maximum size (bytes)
*/
extern int MQRspec_getDataLength(int version, QRecLevel level);
/**
* Return maximum error correction code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return ECC size (bytes)
*/
extern int MQRspec_getECCLength(int version, QRecLevel level);
/**
* Return a version number that satisfies the input code length.
* @param size input code length (byte)
* @param level error correction level
* @return version number
*/
extern int MQRspec_getMinimumVersion(int size, QRecLevel level);
/**
* Return the width of the symbol for the version.
* @param version version of the symbol
* @return width
*/
extern int MQRspec_getWidth(int version);
/**
* Return the numer of remainder bits.
* @param version version of the symbol
* @return number of remainder bits
*/
extern int MQRspec_getRemainder(int version);
/******************************************************************************
* Length indicator
*****************************************************************************/
/**
* Return the size of length indicator for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the size of the appropriate length indicator (bits).
*/
extern int MQRspec_lengthIndicator(QRencodeMode mode, int version);
/**
* Return the maximum length for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the maximum length (bytes)
*/
extern int MQRspec_maximumWords(QRencodeMode mode, int version);
/******************************************************************************
* Version information pattern
*****************************************************************************/
/**
* Return BCH encoded version information pattern that is used for the symbol
* of version 7 or greater. Use lower 18 bits.
* @param version vesion of the symbol
* @return BCH encoded version information pattern
*/
extern unsigned int MQRspec_getVersionPattern(int version);
/******************************************************************************
* Format information
*****************************************************************************/
/**
* Return BCH encoded format information pattern.
* @param mask mask number
* @param version version of the symbol
* @param level error correction level
* @return BCH encoded format information pattern
*/
extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level);
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Return a copy of initialized frame.
* @param version version of the symbol
* @return Array of unsigned char. You can free it by free().
*/
extern unsigned char *MQRspec_newFrame(int version);
/******************************************************************************
* Mode indicator
*****************************************************************************/
/**
* Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, pp.107.
*/
#define MQRSPEC_MODEID_NUM 0
#define MQRSPEC_MODEID_AN 1
#define MQRSPEC_MODEID_8 2
#define MQRSPEC_MODEID_KANJI 3
#endif /* MQRSPEC_H */

View File

@ -0,0 +1,207 @@
/**
* File: qr.c
* Author: AWTK Develop Team
* Brief: 显示二维码的控件
*
* Copyright (c) 2020 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-06-01 Li XianJing <xianjimli@hotmail.com> created
* 2023-01-16 Tiniration modified for libqrencode v4.1.1
* 2023-02-01 Tiniration modified for bitmap cache
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/widget_vtable.h"
#include "qr.h"
static ret_t qr_ensure_qrcode(widget_t* widget);
ret_t qr_set_value(widget_t* widget, const char* value) {
qr_t* qr = QR(widget);
return_value_if_fail(qr, RET_BAD_PARAMS);
if (!value || tk_str_eq(qr->value, value)) return RET_FAIL;
if (qr->value) {
tk_free(qr->value);
qr->value = NULL;
}
qr->value = tk_strdup(value);
if (qr->qrcode) {
QRcode_free(qr->qrcode);
qr->qrcode = NULL;
}
if (qr->bmp) {
bitmap_destroy(qr->bmp);
qr->bmp = NULL;
}
return (qr_ensure_qrcode(widget) == RET_OK) ? widget_invalidate(widget, NULL) : RET_FAIL;
}
static ret_t qr_get_prop(widget_t* widget, const char* name, value_t* v) {
qr_t* qr = QR(widget);
return_value_if_fail(qr && name && v, RET_BAD_PARAMS);
if (tk_str_eq(WIDGET_PROP_VALUE, name) || tk_str_eq(WIDGET_PROP_TEXT, name)) {
value_set_str(v, qr->value);
return RET_OK;
}
return RET_NOT_FOUND;
}
static ret_t qr_set_prop(widget_t* widget, const char* name, const value_t* v) {
qr_t* qr = QR(widget);
return_value_if_fail(widget && name && v, RET_BAD_PARAMS);
if (tk_str_eq(WIDGET_PROP_VALUE, name) || tk_str_eq(WIDGET_PROP_TEXT, name)) {
if (RET_OK == qr_set_value(widget, value_str(v)) && qr->qrcode) {
QRcode_free(qr->qrcode);
qr->qrcode = NULL;
}
return RET_OK;
}
return RET_NOT_FOUND;
}
static ret_t qr_on_destroy(widget_t* widget) {
qr_t* qr = QR(widget);
return_value_if_fail(widget && qr, RET_BAD_PARAMS);
TKMEM_FREE(qr->value);
if (qr->qrcode) {
QRcode_free(qr->qrcode);
qr->qrcode = NULL;
}
if (qr->bmp) {
bitmap_destroy(qr->bmp);
qr->bmp = NULL;
}
return RET_OK;
}
#define MIN_SIZE 21
static ret_t qr_process_bitmap(widget_t* widget) {
qr_t* qr = QR(widget);
style_t* style = widget->astyle;
int w = qr->qrcode->width;
int h = qr->qrcode->width;
return_value_if_fail(style && w && h, RET_FAIL);
if (qr->bmp) bitmap_destroy(qr->bmp);
uint32_t margin = style_get_int(style, STYLE_ID_MARGIN, 2);
uint32_t pix_size = (tk_min(widget->w, widget->h) - 2 * margin) / w;
int dw = w * pix_size;
int dh = h * pix_size;
qr->bmp = bitmap_create_ex(dw, dh, dw * 4, BITMAP_FMT_RGBA8888);
if (!qr->bmp) {
log_warn("oom for bitmap_create_ex");
return RET_FAIL;
}
uint32_t* pd = (uint32_t*)bitmap_lock_buffer_for_write(qr->bmp);
uint8_t* pIn = qr->qrcode->data;
uint32_t a_w = (qr->bmp->line_length >> 2); // align the width for 16
int size = w * h; // the total of qrcode pixel data
for (int i = 0; i < size; ++i) {
int row_x = (i / h); // the row index
int col_y = (i % w); // the col index
// white and black, color_order is [argb]
uint32_t tmp = ((*pIn++ & 0x01)) ? (0xff000000) : (0xffffffff);
for (int r_j = 0; r_j < pix_size; ++r_j) {
for (int c_k = 0; c_k < pix_size; ++c_k) {
// row index * width + col index
pd[(row_x * pix_size + r_j) * a_w + (c_k + pix_size * col_y)] = tmp;
}
}
}
bitmap_unlock_buffer(qr->bmp);
return RET_OK;
}
static ret_t qr_ensure_qrcode(widget_t* widget) {
qr_t* qr = QR(widget);
int32_t size = tk_min(widget->w, widget->h) - 5;
return_value_if_fail(size >= MIN_SIZE, RET_FAIL);
// if found cache, use the cache
if (qr->qrcode || qr->bmp) {
return RET_OK;
}
qr->qrcode = QRcode_encodeString(qr->value, 4, QR_ECLEVEL_Q, QR_MODE_8, 1);
return (qr->qrcode) ? (qr_process_bitmap(widget)) : (RET_FAIL);
}
static ret_t qr_on_paint_self(widget_t* widget, canvas_t* c) {
if (qr_ensure_qrcode(widget) == RET_OK) {
bitmap_t* bmp = QR(widget)->bmp;
rect_t r_wd = {4, 4, (widget->w)-8, (widget->h)-8};
rect_t r_qd = {0, 0, bmp->w, bmp->h};
canvas_draw_image(c, bmp, &r_qd, &r_wd);
}
return RET_OK;
}
static ret_t qr_on_event(widget_t* widget, event_t* e) {
qr_t* qr = QR(widget);
return_value_if_fail(widget && qr, RET_BAD_PARAMS);
(void)qr;
return RET_OK;
}
const char* s_qr_properties[] = {WIDGET_PROP_VALUE, NULL};
TK_DECL_VTABLE(qr) = {.size = sizeof(qr_t),
.type = WIDGET_TYPE_QR,
.clone_properties = s_qr_properties,
.persistent_properties = s_qr_properties,
.parent = TK_PARENT_VTABLE(widget),
.create = qr_create,
.on_paint_self = qr_on_paint_self,
.set_prop = qr_set_prop,
.get_prop = qr_get_prop,
.on_event = qr_on_event,
.on_destroy = qr_on_destroy};
widget_t* qr_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
widget_t* widget = widget_create(parent, TK_REF_VTABLE(qr), x, y, w, h);
qr_t* qr = QR(widget);
return_value_if_fail(qr, NULL);
qr->bmp = NULL;
qr->value = NULL;
qr->qrcode = NULL;
return widget;
}
widget_t* qr_cast(widget_t* widget) {
return_value_if_fail(WIDGET_IS_INSTANCE_OF(widget, qr), NULL);
return widget;
}

View File

@ -0,0 +1,117 @@
/**
* File: qr.h
* Author: AWTK Develop Team
* Brief: 显示二维码的控件
*
* Copyright (c) 2020 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-06-01 Li XianJing <xianjimli@hotmail.com> created
* 2023-02-01 Tiniration modified for add bitmap cache
*
*/
#ifndef TK_QR_H
#define TK_QR_H
#include "qrencode.h"
#include "base/widget.h"
BEGIN_C_DECLS
/**
* @class qr_t
* @parent widget_t
* @annotation ["scriptable","design","widget"]
* 显示二维码的控件
* qr\_t是[widget\_t](widget_t.md)的子类控件widget\_t的函数均适用于qr\_t控件。
*
* 在xml中使用"qr"标签创建数值文本控件。如:
*
* ```xml
* <!-- ui -->
* <qr x="c" y="m" w="240" h="240" value="https://github.com/zlgopen/awtk"/>
* ```
* 在c代码中使用函数qr\_create创建数值文本控件。如
*
* ```c
* widget_t* qr = qr_create(win, 10, 10, 128, 128);
* ```
* 可用通过style来设置控件的显示风格如字体的大小和颜色等等。如
*
* ```xml
* <!-- style -->
* <qr>
* <style name="default" >
* <normal fg_color="black" bg_color="white" bg_image="message"/>
* <disable fg_color="gray" bg_color="#f0f0f0"/>
* </style>
* </qr>
* ```
*/
typedef struct _qr_t {
widget_t widget;
/**
* @property {char*} value
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 要转成二维码的字符串。值。
*/
char* value;
/*private*/
QRcode* qrcode;
bitmap_t* bmp;
} qr_t;
/**
* @method qr_create
* @annotation ["constructor", "scriptable"]
* 创建qr对象
* @param {widget_t*} parent 父控件
* @param {xy_t} x x坐标
* @param {xy_t} y y坐标
* @param {wh_t} w 宽度
* @param {wh_t} h 高度
*
* @return {widget_t*} qr对象。
*/
widget_t* qr_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method qr_cast
* 转换为qr对象(供脚本语言使用)。
* @annotation ["cast", "scriptable"]
* @param {widget_t*} widget qr对象。
*
* @return {widget_t*} qr对象。
*/
widget_t* qr_cast(widget_t* widget);
/**
* @method qr_set_value
* 设置要转成二维码的字符串。
* @annotation ["scriptable"]
* @param {widget_t*} widget widget对象。
* @param {const char*} value 格式字符串。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t qr_set_value(widget_t* widget, const char* value);
#define WIDGET_TYPE_QR "qr"
#define QR(widget) ((qr_t*)(qr_cast(WIDGET(widget))))
/*public for subclass and runtime type check*/
TK_EXTERN_VTABLE(qr);
END_C_DECLS
#endif /*TK_QR_H*/

View File

@ -0,0 +1,915 @@
/*
* qrencode - QR Code encoder
*
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdio.h>
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include <string.h>
#include <errno.h>
#include "qrencode.h"
#include "qrspec.h"
#include "mqrspec.h"
#include "bitstream.h"
#include "qrinput.h"
#include "rsecc.h"
#include "split.h"
#include "mask.h"
#include "mmask.h"
/******************************************************************************
* Raw code
*****************************************************************************/
typedef struct {
int dataLength;
int eccLength;
unsigned char *data;
unsigned char *ecc;
} RSblock;
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
int b1;
int blocks;
RSblock *rsblock;
int count;
} QRRawCode;
static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc)
{
block->dataLength = dl;
block->data = data;
block->eccLength = el;
block->ecc = ecc;
RSECC_encode((size_t)dl, (size_t)el, data, ecc);
}
static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc)
{
int i;
RSblock *block;
unsigned char *dp, *ep;
int el, dl;
dl = QRspec_rsDataCodes1(spec);
el = QRspec_rsEccCodes1(spec);
block = blocks;
dp = data;
ep = ecc;
for(i = 0; i < QRspec_rsBlockNum1(spec); i++) {
RSblock_initBlock(block, dl, dp, el, ep);
dp += dl;
ep += el;
block++;
}
if(QRspec_rsBlockNum2(spec) == 0) return 0;
dl = QRspec_rsDataCodes2(spec);
el = QRspec_rsEccCodes2(spec);
for(i = 0; i < QRspec_rsBlockNum2(spec); i++) {
RSblock_initBlock(block, dl, dp, el, ep);
dp += dl;
ep += el;
block++;
}
return 0;
}
STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw);
STATIC_IN_RELEASE QRRawCode *QRraw_new(QRinput *input)
{
QRRawCode *raw;
int spec[5], ret;
raw = (QRRawCode *)malloc(sizeof(QRRawCode));
if(raw == NULL) return NULL;
raw->datacode = QRinput_getByteStream(input);
if(raw->datacode == NULL) {
free(raw);
return NULL;
}
QRspec_getEccSpec(input->version, input->level, spec);
raw->version = input->version;
raw->b1 = QRspec_rsBlockNum1(spec);
raw->dataLength = QRspec_rsDataLength(spec);
raw->eccLength = QRspec_rsEccLength(spec);
raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength);
if(raw->ecccode == NULL) {
free(raw->datacode);
free(raw);
return NULL;
}
raw->blocks = QRspec_rsBlockNum(spec);
//raw->rsblock = (RSblock *)calloc((size_t)(raw->blocks), sizeof(RSblock));
size_t size = raw->blocks*sizeof(RSblock);
//raw->rsblock = (RSblock *)mbedtls_calloc((size_t)(raw->blocks), sizeof(RSblock));
raw->rsblock = (RSblock *)malloc(size);
if(raw->rsblock == NULL) {
QRraw_free(raw);
return NULL;
}
ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode);
if(ret < 0) {
QRraw_free(raw);
return NULL;
}
raw->count = 0;
return raw;
}
/**
* Return a code (byte).
* This function can be called iteratively.
* @param raw raw code.
* @return code
*/
STATIC_IN_RELEASE unsigned char QRraw_getCode(QRRawCode *raw)
{
int col, row;
unsigned char ret;
if(raw->count < raw->dataLength) {
row = raw->count % raw->blocks;
col = raw->count / raw->blocks;
if(col >= raw->rsblock[0].dataLength) {
row += raw->b1;
}
ret = raw->rsblock[row].data[col];
} else if(raw->count < raw->dataLength + raw->eccLength) {
row = (raw->count - raw->dataLength) % raw->blocks;
col = (raw->count - raw->dataLength) / raw->blocks;
ret = raw->rsblock[row].ecc[col];
} else {
return 0;
}
raw->count++;
return ret;
}
STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw)
{
if(raw != NULL) {
free(raw->datacode);
free(raw->ecccode);
free(raw->rsblock);
free(raw);
}
}
/******************************************************************************
* Raw code for Micro QR Code
*****************************************************************************/
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
RSblock *rsblock;
int oddbits;
int count;
} MQRRawCode;
STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw);
STATIC_IN_RELEASE MQRRawCode *MQRraw_new(QRinput *input)
{
MQRRawCode *raw;
raw = (MQRRawCode *)malloc(sizeof(MQRRawCode));
if(raw == NULL) return NULL;
raw->version = input->version;
raw->dataLength = MQRspec_getDataLength(input->version, input->level);
raw->eccLength = MQRspec_getECCLength(input->version, input->level);
raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level);
raw->datacode = QRinput_getByteStream(input);
if(raw->datacode == NULL) {
free(raw);
return NULL;
}
raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength);
if(raw->ecccode == NULL) {
free(raw->datacode);
free(raw);
return NULL;
}
raw->rsblock = (RSblock *)calloc(1, sizeof(RSblock));
if(raw->rsblock == NULL) {
MQRraw_free(raw);
return NULL;
}
RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode);
raw->count = 0;
return raw;
}
/**
* Return a code (byte).
* This function can be called iteratively.
* @param raw raw code.
* @return code
*/
STATIC_IN_RELEASE unsigned char MQRraw_getCode(MQRRawCode *raw)
{
unsigned char ret;
if(raw->count < raw->dataLength) {
ret = raw->datacode[raw->count];
} else if(raw->count < raw->dataLength + raw->eccLength) {
ret = raw->ecccode[raw->count - raw->dataLength];
} else {
return 0;
}
raw->count++;
return ret;
}
STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw)
{
if(raw != NULL) {
free(raw->datacode);
free(raw->ecccode);
free(raw->rsblock);
free(raw);
}
}
/******************************************************************************
* Frame filling
*****************************************************************************/
typedef struct {
int width;
unsigned char *frame;
int x, y;
int dir;
int bit;
int mqr;
} FrameFiller;
static void FrameFiller_set(FrameFiller *filler, int width, unsigned char *frame, int mqr)
{
filler->width = width;
filler->frame = frame;
filler->x = width - 1;
filler->y = width - 1;
filler->dir = -1;
filler->bit = -1;
filler->mqr = mqr;
}
static unsigned char *FrameFiller_next(FrameFiller *filler)
{
unsigned char *p;
int x, y, w;
if(filler->bit == -1) {
filler->bit = 0;
return filler->frame + filler->y * filler->width + filler->x;
}
x = filler->x;
y = filler->y;
p = filler->frame;
w = filler->width;
if(filler->bit == 0) {
x--;
filler->bit++;
} else {
x++;
y += filler->dir;
filler->bit--;
}
if(filler->dir < 0) {
if(y < 0) {
y = 0;
x -= 2;
filler->dir = 1;
if(!filler->mqr && x == 6) {
x--;
y = 9;
}
}
} else if(y == w) {
y = w - 1;
x -= 2;
filler->dir = -1;
if(!filler->mqr && x == 6) {
x--;
y -= 8;
}
}
if(x < 0 || y < 0) return NULL;
filler->x = x;
filler->y = y;
if(p[y * w + x] & 0x80) {
// This tail recursion could be optimized.
return FrameFiller_next(filler);
}
return &p[y * w + x];
}
#ifdef WITH_TESTS
unsigned char *FrameFiller_test(int version)
{
int width;
unsigned char *frame, *p;
int i, length;
FrameFiller filler;
width = QRspec_getWidth(version);
frame = QRspec_newFrame(version);
if(frame == NULL) return NULL;
FrameFiller_set(&filler, width, frame, 0);
length = QRspec_getDataLength(version, QR_ECLEVEL_L) * 8
+ QRspec_getECCLength(version, QR_ECLEVEL_L) * 8
+ QRspec_getRemainder(version);
for(i = 0; i < length; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) {
free(frame);
return NULL;
}
*p = (unsigned char)(i & 0x7f) | 0x80;
}
return frame;
}
unsigned char *FrameFiller_testMQR(int version)
{
int width;
unsigned char *frame, *p;
int i, length;
FrameFiller filler;
width = MQRspec_getWidth(version);
frame = MQRspec_newFrame(version);
if(frame == NULL) return NULL;
FrameFiller_set(&filler, width, frame, 1);
length = MQRspec_getDataLengthBit(version, QR_ECLEVEL_L)
+ MQRspec_getECCLength(version, QR_ECLEVEL_L) * 8;
for(i = 0; i < length; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) {
fprintf(stderr, "Frame filler run over the frame!\n");
return frame;
}
*p = (unsigned char)(i & 0x7f) | 0x80;
}
return frame;
}
#endif
/******************************************************************************
* QR-code encoding
*****************************************************************************/
STATIC_IN_RELEASE QRcode *QRcode_new(int version, int width, unsigned char *data)
{
QRcode *qrcode;
qrcode = (QRcode *)malloc(sizeof(QRcode));
if(qrcode == NULL) return NULL;
qrcode->version = version;
qrcode->width = width;
qrcode->data = data;
return qrcode;
}
void QRcode_free(QRcode *qrcode)
{
if(qrcode != NULL) {
free(qrcode->data);
free(qrcode);
}
}
STATIC_IN_RELEASE QRcode *QRcode_encodeMask(QRinput *input, int mask)
{
int width, version;
QRRawCode *raw;
unsigned char *frame, *masked, *p, code, bit;
int i, j;
QRcode *qrcode = NULL;
FrameFiller filler;
if(input->mqr) {
errno = EINVAL;
return NULL;
}
if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) {
errno = EINVAL;
return NULL;
}
if(input->level > QR_ECLEVEL_H) {
errno = EINVAL;
return NULL;
}
raw = QRraw_new(input);
if(raw == NULL) return NULL;
version = raw->version;
width = QRspec_getWidth(version);
frame = QRspec_newFrame(version);
if(frame == NULL) {
QRraw_free(raw);
return NULL;
}
FrameFiller_set(&filler, width, frame, 0);
/* interleaved data and ecc codes */
for(i = 0; i < raw->dataLength; i++) {
code = QRraw_getCode(raw);
bit = 0x80;
for(j = 0; j < 8; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = ((bit & code) != 0);
bit = bit >> 1;
}
}
for(i = 0; i < raw->eccLength; i++) {
code = QRraw_getCode(raw);
bit = 0x80;
for(j = 0; j < 8; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02 | ((bit & code) != 0);
bit = bit >> 1;
}
}
QRraw_free(raw);
raw = NULL;
/* remainder bits */
j = QRspec_getRemainder(version);
for(i = 0; i < j; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02;
}
/* masking */
if(mask == -2) { // just for debug purpose
masked = (unsigned char *)malloc((size_t)(width * width));
memcpy(masked, frame, (size_t)(width * width));
} else if(mask < 0) {
masked = Mask_mask(width, frame, input->level);
} else {
masked = Mask_makeMask(width, frame, mask, input->level);
}
if(masked == NULL) {
goto EXIT;
}
qrcode = QRcode_new(version, width, masked);
if(qrcode == NULL) {
free(masked);
}
EXIT:
QRraw_free(raw);
free(frame);
return qrcode;
}
STATIC_IN_RELEASE QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask)
{
int width, version;
MQRRawCode *raw;
unsigned char *frame, *masked, *p, code, bit;
int i, j, length;
QRcode *qrcode = NULL;
FrameFiller filler;
if(!input->mqr) {
errno = EINVAL;
return NULL;
}
if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) {
errno = EINVAL;
return NULL;
}
if(input->level > QR_ECLEVEL_Q) {
errno = EINVAL;
return NULL;
}
raw = MQRraw_new(input);
if(raw == NULL) return NULL;
version = raw->version;
width = MQRspec_getWidth(version);
frame = MQRspec_newFrame(version);
if(frame == NULL) {
MQRraw_free(raw);
return NULL;
}
FrameFiller_set(&filler, width, frame, 1);
/* interleaved data and ecc codes */
for(i = 0; i < raw->dataLength; i++) {
code = MQRraw_getCode(raw);
bit = 0x80;
if(raw->oddbits && i == raw->dataLength - 1) {
length = raw->oddbits;
} else {
length = 8;
}
for(j = 0; j < length; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = ((bit & code) != 0);
bit = bit >> 1;
}
}
for(i = 0; i < raw->eccLength; i++) {
code = MQRraw_getCode(raw);
bit = 0x80;
length = 8;
for(j = 0; j < length; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02 | ((bit & code) != 0);
bit = bit >> 1;
}
}
MQRraw_free(raw);
raw = NULL;
/* masking */
if(mask == -2) { // just for debug purpose
masked = (unsigned char *)malloc((size_t)(width * width));
memcpy(masked, frame, (size_t)(width * width));
} else if(mask < 0) {
masked = MMask_mask(version, frame, input->level);
} else {
masked = MMask_makeMask(version, frame, mask, input->level);
}
if(masked == NULL) {
goto EXIT;
}
qrcode = QRcode_new(version, width, masked);
if(qrcode == NULL) {
free(masked);
}
EXIT:
MQRraw_free(raw);
free(frame);
return qrcode;
}
QRcode *QRcode_encodeInput(QRinput *input)
{
if(input->mqr) {
return QRcode_encodeMaskMQR(input, -1);
} else {
return QRcode_encodeMask(input, -1);
}
}
static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive)
{
QRinput *input;
QRcode *code;
int ret;
if(string == NULL) {
errno = EINVAL;
return NULL;
}
if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) {
errno = EINVAL;
return NULL;
}
if(mqr) {
input = QRinput_newMQR(version, level);
} else {
input = QRinput_new2(version, level);
}
if(input == NULL) return NULL;
ret = Split_splitStringToQRinput(string, input, hint, casesensitive);
if(ret < 0) {
QRinput_free(input);
return NULL;
}
code = QRcode_encodeInput(input);
QRinput_free(input);
return code;
}
QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive);
}
QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
return QRcode_encodeStringReal(string, version, level, 1, hint, casesensitive);
}
static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr)
{
QRinput *input;
QRcode *code;
int ret;
if(data == NULL || length == 0) {
errno = EINVAL;
return NULL;
}
if(mqr) {
input = QRinput_newMQR(version, level);
} else {
input = QRinput_new2(version, level);
}
if(input == NULL) return NULL;
ret = QRinput_append(input, QR_MODE_8, length, data);
if(ret < 0) {
QRinput_free(input);
return NULL;
}
code = QRcode_encodeInput(input);
QRinput_free(input);
return code;
}
QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level)
{
return QRcode_encodeDataReal(data, size, version, level, 0);
}
QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level)
{
if(string == NULL) {
errno = EINVAL;
return NULL;
}
return QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), version, level, 0);
}
QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level)
{
return QRcode_encodeDataReal(data, size, version, level, 1);
}
QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level)
{
if(string == NULL) {
errno = EINVAL;
return NULL;
}
return QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), version, level, 1);
}
/******************************************************************************
* Structured QR-code encoding
*****************************************************************************/
static QRcode_List *QRcode_List_newEntry(void)
{
QRcode_List *entry;
entry = (QRcode_List *)malloc(sizeof(QRcode_List));
if(entry == NULL) return NULL;
entry->next = NULL;
entry->code = NULL;
return entry;
}
static void QRcode_List_freeEntry(QRcode_List *entry)
{
if(entry != NULL) {
QRcode_free(entry->code);
free(entry);
}
}
void QRcode_List_free(QRcode_List *qrlist)
{
QRcode_List *list = qrlist, *next;
while(list != NULL) {
next = list->next;
QRcode_List_freeEntry(list);
list = next;
}
}
int QRcode_List_size(QRcode_List *qrlist)
{
QRcode_List *list = qrlist;
int size = 0;
while(list != NULL) {
size++;
list = list->next;
}
return size;
}
#if 0
static unsigned char QRcode_parity(const char *str, int size)
{
unsigned char parity = 0;
int i;
for(i = 0; i < size; i++) {
parity ^= str[i];
}
return parity;
}
#endif
QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s)
{
QRcode_List *head = NULL;
QRcode_List *tail = NULL;
QRcode_List *entry;
QRinput_InputList *list = s->head;
while(list != NULL) {
if(head == NULL) {
entry = QRcode_List_newEntry();
if(entry == NULL) goto ABORT;
head = entry;
tail = head;
} else {
entry = QRcode_List_newEntry();
if(entry == NULL) goto ABORT;
tail->next = entry;
tail = tail->next;
}
tail->code = QRcode_encodeInput(list->input);
if(tail->code == NULL) {
goto ABORT;
}
list = list->next;
}
return head;
ABORT:
QRcode_List_free(head);
return NULL;
}
static QRcode_List *QRcode_encodeInputToStructured(QRinput *input)
{
QRinput_Struct *s;
QRcode_List *codes;
s = QRinput_splitQRinputToStruct(input);
if(s == NULL) return NULL;
codes = QRcode_encodeInputStructured(s);
QRinput_Struct_free(s);
return codes;
}
static QRcode_List *QRcode_encodeDataStructuredReal(
int size, const unsigned char *data,
int version, QRecLevel level,
int eightbit, QRencodeMode hint, int casesensitive)
{
QRinput *input;
QRcode_List *codes;
int ret;
if(version <= 0) {
errno = EINVAL;
return NULL;
}
if(!eightbit && (hint != QR_MODE_8 && hint != QR_MODE_KANJI)) {
errno = EINVAL;
return NULL;
}
input = QRinput_new2(version, level);
if(input == NULL) return NULL;
if(eightbit) {
ret = QRinput_append(input, QR_MODE_8, size, data);
} else {
ret = Split_splitStringToQRinput((char *)data, input, hint, casesensitive);
}
if(ret < 0) {
QRinput_free(input);
return NULL;
}
codes = QRcode_encodeInputToStructured(input);
QRinput_free(input);
return codes;
}
QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level) {
return QRcode_encodeDataStructuredReal(size, data, version, level, 1, QR_MODE_NUL, 0);
}
QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level) {
if(string == NULL) {
errno = EINVAL;
return NULL;
}
return QRcode_encodeDataStructured((int)strlen(string), (unsigned char *)string, version, level);
}
QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
if(string == NULL) {
errno = EINVAL;
return NULL;
}
return QRcode_encodeDataStructuredReal((int)strlen(string), (unsigned char *)string, version, level, 0, hint, casesensitive);
}
/******************************************************************************
* System utilities
*****************************************************************************/
void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version)
{
if(major_version != NULL) {
*major_version = MAJOR_VERSION;
}
if(minor_version != NULL) {
*minor_version = MINOR_VERSION;
}
if(micro_version != NULL) {
*micro_version = MICRO_VERSION;
}
}
char *QRcode_APIVersionString(void)
{
return VERSION;
}
void QRcode_clearCache(void)
{
return;
}

View File

@ -0,0 +1,568 @@
/**
* qrencode - QR Code encoder
*
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** \mainpage
* Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D
* symbology.
*
* \section encoding Encoding
*
* There are two methods to encode data: <b>encoding a string/data</b> or
* <b>encoding a structured data</b>.
*
* \subsection encoding-string Encoding a string/data
* You can encode a string by calling QRcode_encodeString().
* The given string is parsed automatically and encoded. If you want to encode
* data that can be represented as a C string style (NUL terminated), you can
* simply use this way.
*
* If the input data contains Kanji (Shift-JIS) characters and you want to
* encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint.
* Otherwise, all of non-alphanumeric characters are encoded as 8 bit data.
* If you want to encode a whole string in 8 bit mode, you can use
* QRcode_encodeString8bit() instead.
*
* Please note that a C string can not contain NUL characters. If your data
* contains NUL, you must use QRcode_encodeData().
*
* \subsection encoding-input Encoding a structured data
* You can construct a structured input data manually. If the structure of the
* input data is known, you can use this way.
* At first, create a ::QRinput object by QRinput_new(). Then add input data
* to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput()
* to encode the QRinput data.
* You can reuse the QRinput data again to encode it in other symbols with
* different parameters.
*
* \section result Result
* The encoded symbol is resulted as a ::QRcode object. It will contain
* its version number, width of the symbol and an array represents the symbol.
* See ::QRcode for the details. You can free the object by QRcode_free().
*
* Please note that the version of the result may be larger than specified.
* In such cases, the input data would be too large to be encoded in a
* symbol of the specified version.
*
* \section structured Structured append
* Libqrencode can generate "Structured-appended" symbols that enables to split
* a large data set into mulitple QR codes. A QR code reader concatenates
* multiple QR code symbols into a string.
* Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured()
* to generate structured-appended symbols. This functions returns an instance
* of ::QRcode_List. The returned list is a singly-linked list of QRcode: you
* can retrieve each QR code in this way:
*
* \code
* QRcode_List *qrcodes;
* QRcode_List *entry;
* QRcode *qrcode;
*
* qrcodes = QRcode_encodeStringStructured(...);
* entry = qrcodes;
* while(entry != NULL) {
* qrcode = entry->code;
* // do something
* entry = entry->next;
* }
* QRcode_List_free(entry);
* \endcode
*
* Instead of using auto-parsing functions, you can construct your own
* structured input. At first, instantiate an object of ::QRinput_Struct
* by calling QRinput_Struct_new(). This object can hold multiple ::QRinput,
* and one QR code is generated for a ::QRinput.
* QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct
* object. In order to generate structured-appended symbols, it is required to
* embed headers to each symbol. You can use
* QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate
* headers to each symbol. You should call this function just once before
* encoding symbols.
*/
#ifndef QRENCODE_H
#define QRENCODE_H
#if defined(__cplusplus)
extern "C" {
#endif
/**
* Encoding mode.
*/
typedef enum {
QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only
QR_MODE_NUM = 0, ///< Numeric mode
QR_MODE_AN, ///< Alphabet-numeric mode
QR_MODE_8, ///< 8-bit data mode
QR_MODE_KANJI, ///< Kanji (shift-jis) mode
QR_MODE_STRUCTURE, ///< Internal use only
QR_MODE_ECI, ///< ECI mode
QR_MODE_FNC1FIRST, ///< FNC1, first position
QR_MODE_FNC1SECOND, ///< FNC1, second position
} QRencodeMode;
/**
* Level of error correction.
*/
typedef enum {
QR_ECLEVEL_L = 0, ///< lowest
QR_ECLEVEL_M,
QR_ECLEVEL_Q,
QR_ECLEVEL_H ///< highest
} QRecLevel;
/**
* Maximum version (size) of QR-code symbol.
*/
#define QRSPEC_VERSION_MAX 40
/**
* Maximum version (size) of QR-code symbol.
*/
#define MQRSPEC_VERSION_MAX 4
/******************************************************************************
* Input data (qrinput.c)
*****************************************************************************/
/**
* Singly linked list to contain input strings. An instance of this class
* contains its version and error correction level too. It is required to
* set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(),
* or use QRinput_new2() to instantiate an object.
*/
typedef struct _QRinput QRinput;
/**
* Instantiate an input data object. The version is set to 0 (auto-select)
* and the error correction level is set to QR_ECLEVEL_L.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput *QRinput_new(void);
/**
* Instantiate an input data object.
* @param version version number.
* @param level Error correction level.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw EINVAL invalid arguments.
*/
extern QRinput *QRinput_new2(int version, QRecLevel level);
/**
* Instantiate an input data object. Object's Micro QR Code flag is set.
* Unlike with full-sized QR Code, version number must be specified (>0).
* @param version version number (1--4).
* @param level Error correction level.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw EINVAL invalid arguments.
*/
extern QRinput *QRinput_newMQR(int version, QRecLevel level);
/**
* Append data to an input object.
* The data is copied and appended to the input object.
* @param input input object.
* @param mode encoding mode.
* @param size size of data (byte).
* @param data a pointer to the memory area of the input data.
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL input data is invalid.
*
*/
extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data);
/**
* Append ECI header.
* @param input input object.
* @param ecinum ECI indicator number (0 - 999999)
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL input data is invalid.
*
*/
extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum);
/**
* Get current version.
* @param input input object.
* @return current version.
*/
extern int QRinput_getVersion(QRinput *input);
/**
* Set version of the QR code that is to be encoded.
* This function cannot be applied to Micro QR Code.
* @param input input object.
* @param version version number (0 = auto)
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setVersion(QRinput *input, int version);
/**
* Get current error correction level.
* @param input input object.
* @return Current error correcntion level.
*/
extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input);
/**
* Set error correction level of the QR code that is to be encoded.
* This function cannot be applied to Micro QR Code.
* @param input input object.
* @param level Error correction level.
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level);
/**
* Set version and error correction level of the QR code at once.
* This function is recommened for Micro QR Code.
* @param input input object.
* @param version version number (0 = auto)
* @param level Error correction level.
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level);
/**
* Free the input object.
* All of data chunks in the input object are freed too.
* @param input input object.
*/
extern void QRinput_free(QRinput *input);
/**
* Validate the input data.
* @param mode encoding mode.
* @param size size of data (byte).
* @param data a pointer to the memory area of the input data.
* @retval 0 success.
* @retval -1 invalid arguments.
*/
extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data);
/**
* Set of QRinput for structured symbols.
*/
typedef struct _QRinput_Struct QRinput_Struct;
/**
* Instantiate a set of input data object.
* @return an instance of QRinput_Struct. On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput_Struct *QRinput_Struct_new(void);
/**
* Set parity of structured symbols.
* @param s structured input object.
* @param parity parity of s.
*/
extern void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity);
/**
* Append a QRinput object to the set. QRinput created by QRinput_newMQR()
* will be rejected.
* @warning never append the same QRinput object twice or more.
* @param s structured input object.
* @param input an input object.
* @retval >0 number of input objects in the structure.
* @retval -1 an error occurred. See Exceptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL invalid arguments.
*/
extern int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input);
/**
* Free all of QRinput in the set.
* @param s a structured input object.
*/
extern void QRinput_Struct_free(QRinput_Struct *s);
/**
* Split a QRinput to QRinput_Struct. It calculates a parity, set it, then
* insert structured-append headers. QRinput created by QRinput_newMQR() will
* be rejected.
* @param input input object. Version number and error correction level must be
* set.
* @return a set of input data. On error, NULL is returned, and errno is set
* to indicate the error. See Exceptions for the details.
* @throw ERANGE input data is too large.
* @throw EINVAL invalid input data.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input);
/**
* Insert structured-append headers to the input structure. It calculates
* a parity and set it if the parity is not set yet.
* @param s input structure
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory.
*/
extern int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s);
/**
* Set FNC1-1st position flag.
*/
extern int QRinput_setFNC1First(QRinput *input);
/**
* Set FNC1-2nd position flag and application identifier.
*/
extern int QRinput_setFNC1Second(QRinput *input, unsigned char appid);
/******************************************************************************
* QRcode output (qrencode.c)
*****************************************************************************/
/**
* QRcode class.
* Symbol data is represented as an array contains width*width uchars.
* Each uchar represents a module (dot). If the less significant bit of
* the uchar is 1, the corresponding module is black. The other bits are
* meaningless for usual applications, but here its specification is described.
*
* @verbatim
MSB 76543210 LSB
|||||||`- 1=black/0=white
||||||`-- 1=ecc/0=data code area
|||||`--- format information
||||`---- version information
|||`----- timing pattern
||`------ alignment pattern
|`------- finder pattern and separator
`-------- non-data modules (format, timing, etc.)
@endverbatim
*/
typedef struct {
int version; ///< version of the symbol
int width; ///< width of the symbol
unsigned char *data; ///< symbol data
} QRcode;
/**
* Singly-linked list of QRcode. Used to represent a structured symbols.
* A list is terminated with NULL.
*/
typedef struct _QRcode_List {
QRcode *code;
struct _QRcode_List *next;
} QRcode_List;
/**
* Create a symbol from the input data.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param input input data.
* @return an instance of QRcode class. The version of the result QRcode may
* be larger than the designated version. On error, NULL is returned,
* and errno is set to indicate the error. See Exceptions for the
* details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
*/
extern QRcode *QRcode_encodeInput(QRinput *input);
/**
* Create a symbol from the string. The library automatically parses the input
* string and encodes in a QR Code symbol.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param string input string. It must be NUL terminated.
* @param version version of the symbol. If 0, the library chooses the minimum
* version for the given input data.
* @param level error correction level.
* @param hint tell the library how Japanese Kanji characters should be
* encoded. If QR_MODE_KANJI is given, the library assumes that the
* given string contains Shift-JIS characters and encodes them in
* Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical
* characters will be encoded as is. If you want to embed UTF-8
* string, choose this. Other mode will cause EINVAL error.
* @param casesensitive case-sensitive(1) or not(0).
* @return an instance of QRcode class. The version of the result QRcode may
* be larger than the designated version. On error, NULL is returned,
* and errno is set to indicate the error. See Exceptions for the
* details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw ERANGE input data is too large.
*/
extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Same to QRcode_encodeString(), but encode whole data in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level);
/**
* Micro QR Code version of QRcode_encodeString().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Micro QR Code version of QRcode_encodeString8bit().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level);
/**
* Encode byte stream (may include '\0') in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param size size of the input data.
* @param data input data.
* @param version version of the symbol. If 0, the library chooses the minimum
* version for the given input data.
* @param level error correction level.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw ERANGE input data is too large.
*/
extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Micro QR Code version of QRcode_encodeData().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Free the instance of QRcode class.
* @param qrcode an instance of QRcode class.
*/
extern void QRcode_free(QRcode *qrcode);
/**
* Create structured symbols from the input data.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param s input data, structured.
* @return a singly-linked list of QRcode.
*/
extern QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s);
/**
* Create structured symbols from the string. The library automatically parses
* the input string and encodes in a QR Code symbol.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param string input string. It must be NUL terminated.
* @param version version of the symbol.
* @param level error correction level.
* @param hint tell the library how Japanese Kanji characters should be
* encoded. If QR_MODE_KANJI is given, the library assumes that the
* given string contains Shift-JIS characters and encodes them in
* Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical
* characters will be encoded as is. If you want to embed UTF-8
* string, choose this. Other mode will cause EINVAL error.
* @param casesensitive case-sensitive(1) or not(0).
* @return a singly-linked list of QRcode. On error, NULL is returned, and
* errno is set to indicate the error. See Exceptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
*/
extern QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Same to QRcode_encodeStringStructured(), but encode whole data in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level);
/**
* Create structured symbols from byte stream (may include '\0'). Wholde data
* are encoded in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param size size of the input data.
* @param data input dat.
* @param version version of the symbol.
* @param level error correction level.
* @return a singly-linked list of QRcode. On error, NULL is returned, and
* errno is set to indicate the error. See Exceptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
*/
extern QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Return the number of symbols included in a QRcode_List.
* @param qrlist a head entry of a QRcode_List.
* @return number of symbols in the list.
*/
extern int QRcode_List_size(QRcode_List *qrlist);
/**
* Free the QRcode_List.
* @param qrlist a head entry of a QRcode_List.
*/
extern void QRcode_List_free(QRcode_List *qrlist);
/******************************************************************************
* System utilities
*****************************************************************************/
/**
* Return a string that identifies the library version.
* @param major_version major version number
* @param minor_version minor version number
* @param micro_version micro version number
*/
extern void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version);
/**
* Return a string that identifies the library version.
* @return a string identifies the library version. The string is held by the
* library. Do NOT free it.
*/
extern char *QRcode_APIVersionString(void);
/**
* @deprecated
*/
#ifndef _MSC_VER
extern void QRcode_clearCache(void) __attribute__ ((deprecated));
#else
extern void QRcode_clearCache(void);
#endif
#if defined(__cplusplus)
}
#endif
#endif /* QRENCODE_H */

View File

@ -0,0 +1,88 @@
/**
* qrencode - QR Code encoder
*
* Header for test use
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef QRENCODE_INNER_H
#define QRENCODE_INNER_H
/**
* This header file includes definitions for test use.
*/
/******************************************************************************
* Raw code
*****************************************************************************/
typedef struct {
int dataLength;
int eccLength;
unsigned char *data;
unsigned char *ecc;
} RSblock;
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
int b1;
int blocks;
RSblock *rsblock;
int count;
} QRRawCode;
extern QRRawCode *QRraw_new(QRinput *input);
extern unsigned char QRraw_getCode(QRRawCode *raw);
extern void QRraw_free(QRRawCode *raw);
/******************************************************************************
* Raw code for Micro QR Code
*****************************************************************************/
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
RSblock *rsblock;
int oddbits;
int count;
} MQRRawCode;
extern MQRRawCode *MQRraw_new(QRinput *input);
extern unsigned char MQRraw_getCode(MQRRawCode *raw);
extern void MQRraw_free(MQRRawCode *raw);
/******************************************************************************
* Frame filling
*****************************************************************************/
extern unsigned char *FrameFiller_test(int version);
extern unsigned char *FrameFiller_testMQR(int version);
/******************************************************************************
* QR-code encoding
*****************************************************************************/
extern QRcode *QRcode_encodeMask(QRinput *input, int mask);
extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask);
extern QRcode *QRcode_new(int version, int width, unsigned char *data);
#endif /* QRENCODE_INNER_H */

View File

@ -0,0 +1,123 @@
/*
* qrencode - QR Code encoder
*
* Input data chunk class
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef QRINPUT_H
#define QRINPUT_H
#include "qrencode.h"
#include "bitstream.h"
int QRinput_isSplittableMode(QRencodeMode mode);
/******************************************************************************
* Entry of input data
*****************************************************************************/
typedef struct _QRinput_List QRinput_List;
struct _QRinput_List {
QRencodeMode mode;
int size; ///< Size of data chunk (byte).
unsigned char *data; ///< Data chunk.
BitStream *bstream;
QRinput_List *next;
};
/******************************************************************************
* Input Data
*****************************************************************************/
struct _QRinput {
int version;
QRecLevel level;
QRinput_List *head;
QRinput_List *tail;
int mqr;
int fnc1;
unsigned char appid;
};
/******************************************************************************
* Structured append input data
*****************************************************************************/
typedef struct _QRinput_InputList QRinput_InputList;
struct _QRinput_InputList {
QRinput *input;
QRinput_InputList *next;
};
struct _QRinput_Struct {
int size; ///< number of structured symbols
int parity;
QRinput_InputList *head;
QRinput_InputList *tail;
};
/**
* Pack all bit streams padding bits into a byte array.
* @param input input data.
* @return padded merged byte stream
*/
extern unsigned char *QRinput_getByteStream(QRinput *input);
extern int QRinput_estimateBitsModeNum(int size);
extern int QRinput_estimateBitsModeAn(int size);
extern int QRinput_estimateBitsMode8(int size);
extern int QRinput_estimateBitsModeKanji(int size);
extern QRinput *QRinput_dup(QRinput *input);
extern const signed char QRinput_anTable[128];
/**
* Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19).
* @param __c__ character
* @return value
*/
#define QRinput_lookAnTable(__c__) \
((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__])
/**
* Length of a standard mode indicator in bits.
*/
#define MODE_INDICATOR_SIZE 4
/**
* Length of a segment of structured-append header.
*/
#define STRUCTURE_HEADER_SIZE 20
/**
* Maximum number of symbols in a set of structured-appended symbols.
*/
#define MAX_STRUCTURED_SYMBOLS 16
#ifdef WITH_TESTS
extern int QRinput_mergeBitStream(QRinput *input, BitStream *bstream);
extern int QRinput_getBitStream(QRinput *input, BitStream *bstream);
extern int QRinput_estimateBitStreamSize(QRinput *input, int version);
extern int QRinput_splitEntry(QRinput_List *entry, int bytes);
extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits);
extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity);
#endif
#endif /* QRINPUT_H */

View File

@ -0,0 +1,512 @@
/*
* qrencode - QR Code encoder
*
* QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "qrspec.h"
#include "qrinput.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
typedef struct {
int width; //< Edge length of the symbol
int words; //< Data capacity (bytes)
int remainder; //< Remainder bit (bits)
int ec[4]; //< Number of ECC code (bytes)
} QRspec_Capacity;
/**
* Table of the capacity of symbols
* See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004.
*/
static const QRspec_Capacity qrspecCapacity[QRSPEC_VERSION_MAX + 1] = {
{ 0, 0, 0, { 0, 0, 0, 0}},
{ 21, 26, 0, { 7, 10, 13, 17}}, // 1
{ 25, 44, 7, { 10, 16, 22, 28}},
{ 29, 70, 7, { 15, 26, 36, 44}},
{ 33, 100, 7, { 20, 36, 52, 64}},
{ 37, 134, 7, { 26, 48, 72, 88}}, // 5
{ 41, 172, 7, { 36, 64, 96, 112}},
{ 45, 196, 0, { 40, 72, 108, 130}},
{ 49, 242, 0, { 48, 88, 132, 156}},
{ 53, 292, 0, { 60, 110, 160, 192}},
{ 57, 346, 0, { 72, 130, 192, 224}}, //10
{ 61, 404, 0, { 80, 150, 224, 264}},
{ 65, 466, 0, { 96, 176, 260, 308}},
{ 69, 532, 0, { 104, 198, 288, 352}},
{ 73, 581, 3, { 120, 216, 320, 384}},
{ 77, 655, 3, { 132, 240, 360, 432}}, //15
{ 81, 733, 3, { 144, 280, 408, 480}},
{ 85, 815, 3, { 168, 308, 448, 532}},
{ 89, 901, 3, { 180, 338, 504, 588}},
{ 93, 991, 3, { 196, 364, 546, 650}},
{ 97, 1085, 3, { 224, 416, 600, 700}}, //20
{101, 1156, 4, { 224, 442, 644, 750}},
{105, 1258, 4, { 252, 476, 690, 816}},
{109, 1364, 4, { 270, 504, 750, 900}},
{113, 1474, 4, { 300, 560, 810, 960}},
{117, 1588, 4, { 312, 588, 870, 1050}}, //25
{121, 1706, 4, { 336, 644, 952, 1110}},
{125, 1828, 4, { 360, 700, 1020, 1200}},
{129, 1921, 3, { 390, 728, 1050, 1260}},
{133, 2051, 3, { 420, 784, 1140, 1350}},
{137, 2185, 3, { 450, 812, 1200, 1440}}, //30
{141, 2323, 3, { 480, 868, 1290, 1530}},
{145, 2465, 3, { 510, 924, 1350, 1620}},
{149, 2611, 3, { 540, 980, 1440, 1710}},
{153, 2761, 3, { 570, 1036, 1530, 1800}},
{157, 2876, 0, { 570, 1064, 1590, 1890}}, //35
{161, 3034, 0, { 600, 1120, 1680, 1980}},
{165, 3196, 0, { 630, 1204, 1770, 2100}},
{169, 3362, 0, { 660, 1260, 1860, 2220}},
{173, 3532, 0, { 720, 1316, 1950, 2310}},
{177, 3706, 0, { 750, 1372, 2040, 2430}} //40
};
int QRspec_getDataLength(int version, QRecLevel level)
{
return qrspecCapacity[version].words - qrspecCapacity[version].ec[level];
}
int QRspec_getECCLength(int version, QRecLevel level)
{
return qrspecCapacity[version].ec[level];
}
int QRspec_getMinimumVersion(int size, QRecLevel level)
{
int i;
int words;
for(i = 1; i <= QRSPEC_VERSION_MAX; i++) {
words = qrspecCapacity[i].words - qrspecCapacity[i].ec[level];
if(words >= size) return i;
}
return QRSPEC_VERSION_MAX;
}
int QRspec_getWidth(int version)
{
return qrspecCapacity[version].width;
}
int QRspec_getRemainder(int version)
{
return qrspecCapacity[version].remainder;
}
/******************************************************************************
* Length indicator
*****************************************************************************/
static const int lengthTableBits[4][3] = {
{10, 12, 14},
{ 9, 11, 13},
{ 8, 16, 16},
{ 8, 10, 12}
};
int QRspec_lengthIndicator(QRencodeMode mode, int version)
{
int l;
if(!QRinput_isSplittableMode(mode)) return 0;
if(version <= 9) {
l = 0;
} else if(version <= 26) {
l = 1;
} else {
l = 2;
}
return lengthTableBits[mode][l];
}
int QRspec_maximumWords(QRencodeMode mode, int version)
{
int l;
int bits;
int words;
if(!QRinput_isSplittableMode(mode)) return 0;
if(version <= 9) {
l = 0;
} else if(version <= 26) {
l = 1;
} else {
l = 2;
}
bits = lengthTableBits[mode][l];
words = (1 << bits) - 1;
if(mode == QR_MODE_KANJI) {
words *= 2; // the number of bytes is required
}
return words;
}
/******************************************************************************
* Error correction code
*****************************************************************************/
/**
* Table of the error correction code (Reed-Solomon block)
* See Table 12-16 (pp.30-36), JIS X0510:2004.
*/
static const int eccTable[QRSPEC_VERSION_MAX+1][4][2] = {
{{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}},
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, // 1
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}},
{{ 1, 0}, { 1, 0}, { 2, 0}, { 2, 0}},
{{ 1, 0}, { 2, 0}, { 2, 0}, { 4, 0}},
{{ 1, 0}, { 2, 0}, { 2, 2}, { 2, 2}}, // 5
{{ 2, 0}, { 4, 0}, { 4, 0}, { 4, 0}},
{{ 2, 0}, { 4, 0}, { 2, 4}, { 4, 1}},
{{ 2, 0}, { 2, 2}, { 4, 2}, { 4, 2}},
{{ 2, 0}, { 3, 2}, { 4, 4}, { 4, 4}},
{{ 2, 2}, { 4, 1}, { 6, 2}, { 6, 2}}, //10
{{ 4, 0}, { 1, 4}, { 4, 4}, { 3, 8}},
{{ 2, 2}, { 6, 2}, { 4, 6}, { 7, 4}},
{{ 4, 0}, { 8, 1}, { 8, 4}, {12, 4}},
{{ 3, 1}, { 4, 5}, {11, 5}, {11, 5}},
{{ 5, 1}, { 5, 5}, { 5, 7}, {11, 7}}, //15
{{ 5, 1}, { 7, 3}, {15, 2}, { 3, 13}},
{{ 1, 5}, {10, 1}, { 1, 15}, { 2, 17}},
{{ 5, 1}, { 9, 4}, {17, 1}, { 2, 19}},
{{ 3, 4}, { 3, 11}, {17, 4}, { 9, 16}},
{{ 3, 5}, { 3, 13}, {15, 5}, {15, 10}}, //20
{{ 4, 4}, {17, 0}, {17, 6}, {19, 6}},
{{ 2, 7}, {17, 0}, { 7, 16}, {34, 0}},
{{ 4, 5}, { 4, 14}, {11, 14}, {16, 14}},
{{ 6, 4}, { 6, 14}, {11, 16}, {30, 2}},
{{ 8, 4}, { 8, 13}, { 7, 22}, {22, 13}}, //25
{{10, 2}, {19, 4}, {28, 6}, {33, 4}},
{{ 8, 4}, {22, 3}, { 8, 26}, {12, 28}},
{{ 3, 10}, { 3, 23}, { 4, 31}, {11, 31}},
{{ 7, 7}, {21, 7}, { 1, 37}, {19, 26}},
{{ 5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30
{{13, 3}, { 2, 29}, {42, 1}, {23, 28}},
{{17, 0}, {10, 23}, {10, 35}, {19, 35}},
{{17, 1}, {14, 21}, {29, 19}, {11, 46}},
{{13, 6}, {14, 23}, {44, 7}, {59, 1}},
{{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35
{{ 6, 14}, { 6, 34}, {46, 10}, { 2, 64}},
{{17, 4}, {29, 14}, {49, 10}, {24, 46}},
{{ 4, 18}, {13, 32}, {48, 14}, {42, 32}},
{{20, 4}, {40, 7}, {43, 22}, {10, 67}},
{{19, 6}, {18, 31}, {34, 34}, {20, 61}},//40
};
void QRspec_getEccSpec(int version, QRecLevel level, int spec[5])
{
int b1, b2;
int data, ecc;
b1 = eccTable[version][level][0];
b2 = eccTable[version][level][1];
data = QRspec_getDataLength(version, level);
ecc = QRspec_getECCLength(version, level);
if(b2 == 0) {
spec[0] = b1;
spec[1] = data / b1;
spec[2] = ecc / b1;
spec[3] = spec[4] = 0;
} else {
spec[0] = b1;
spec[1] = data / (b1 + b2);
spec[2] = ecc / (b1 + b2);
spec[3] = b2;
spec[4] = spec[1] + 1;
}
}
/******************************************************************************
* Alignment pattern
*****************************************************************************/
/**
* Positions of alignment patterns.
* This array includes only the second and the third position of the alignment
* patterns. Rest of them can be calculated from the distance between them.
*
* See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
*/
static const int alignmentPattern[QRSPEC_VERSION_MAX+1][2] = {
{ 0, 0},
{ 0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5
{34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10
{30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15
{26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20
{28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25
{30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30
{30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35
{24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40
};
/**
* Put an alignment marker.
* @param frame
* @param width
* @param ox,oy center coordinate of the pattern
*/
static void QRspec_putAlignmentMarker(unsigned char *frame, int width, int ox, int oy)
{
static const unsigned char finder[] = {
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
0xa1, 0xa0, 0xa1, 0xa0, 0xa1,
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
};
int x, y;
const unsigned char *s;
frame += (oy - 2) * width + ox - 2;
s = finder;
for(y = 0; y < 5; y++) {
for(x = 0; x < 5; x++) {
frame[x] = s[x];
}
frame += width;
s += 5;
}
}
static void QRspec_putAlignmentPattern(int version, unsigned char *frame, int width)
{
int d, w, x, y, cx, cy;
if(version < 2) return;
d = alignmentPattern[version][1] - alignmentPattern[version][0];
if(d < 0) {
w = 2;
} else {
w = (width - alignmentPattern[version][0]) / d + 2;
}
if(w * w - 3 == 1) {
x = alignmentPattern[version][0];
y = alignmentPattern[version][0];
QRspec_putAlignmentMarker(frame, width, x, y);
return;
}
cx = alignmentPattern[version][0];
for(x = 1; x < w - 1; x++) {
QRspec_putAlignmentMarker(frame, width, 6, cx);
QRspec_putAlignmentMarker(frame, width, cx, 6);
cx += d;
}
cy = alignmentPattern[version][0];
for(y = 0; y < w-1; y++) {
cx = alignmentPattern[version][0];
for(x = 0; x < w-1; x++) {
QRspec_putAlignmentMarker(frame, width, cx, cy);
cx += d;
}
cy += d;
}
}
/******************************************************************************
* Version information pattern
*****************************************************************************/
/**
* Version information pattern (BCH coded).
* See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
*/
static const unsigned int versionPattern[QRSPEC_VERSION_MAX - 6] = {
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
0x27541, 0x28c69
};
unsigned int QRspec_getVersionPattern(int version)
{
if(version < 7 || version > QRSPEC_VERSION_MAX) return 0;
return versionPattern[version - 7];
}
/******************************************************************************
* Format information
*****************************************************************************/
/* See calcFormatInfo in tests/test_qrspec.c */
static const unsigned int formatInfo[4][8] = {
{0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976},
{0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0},
{0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed},
{0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b}
};
unsigned int QRspec_getFormatInfo(int mask, QRecLevel level)
{
if(mask < 0 || mask > 7) return 0;
return formatInfo[level][mask];
}
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Put a finder pattern.
* @param frame
* @param width
* @param ox,oy upper-left coordinate of the pattern
*/
static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
{
static const unsigned char finder[] = {
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
};
int x, y;
const unsigned char *s;
frame += oy * width + ox;
s = finder;
for(y = 0; y < 7; y++) {
for(x = 0; x < 7; x++) {
frame[x] = s[x];
}
frame += width;
s += 7;
}
}
static unsigned char *QRspec_createFrame(int version)
{
unsigned char *frame, *p, *q;
int width;
int x, y;
unsigned int verinfo, v;
width = qrspecCapacity[version].width;
frame = (unsigned char *)malloc((size_t)(width * width));
if(frame == NULL) return NULL;
memset(frame, 0, (size_t)(width * width));
/* Finder pattern */
putFinderPattern(frame, width, 0, 0);
putFinderPattern(frame, width, width - 7, 0);
putFinderPattern(frame, width, 0, width - 7);
/* Separator */
p = frame;
q = frame + width * (width - 7);
for(y = 0; y < 7; y++) {
p[7] = 0xc0;
p[width - 8] = 0xc0;
q[7] = 0xc0;
p += width;
q += width;
}
memset(frame + width * 7, 0xc0, 8);
memset(frame + width * 8 - 8, 0xc0, 8);
memset(frame + width * (width - 8), 0xc0, 8);
/* Mask format information area */
memset(frame + width * 8, 0x84, 9);
memset(frame + width * 9 - 8, 0x84, 8);
p = frame + 8;
for(y = 0; y < 8; y++) {
*p = 0x84;
p += width;
}
p = frame + width * (width - 7) + 8;
for(y = 0; y < 7; y++) {
*p = 0x84;
p += width;
}
/* Timing pattern */
p = frame + width * 6 + 8;
q = frame + width * 8 + 6;
for(x = 1; x < width-15; x++) {
*p = 0x90 | (x & 1);
*q = 0x90 | (x & 1);
p++;
q += width;
}
/* Alignment pattern */
QRspec_putAlignmentPattern(version, frame, width);
/* Version information */
if(version >= 7) {
verinfo = QRspec_getVersionPattern(version);
p = frame + width * (width - 11);
v = verinfo;
for(x = 0; x < 6; x++) {
for(y = 0; y < 3; y++) {
p[width * y + x] = 0x88 | (v & 1);
v = v >> 1;
}
}
p = frame + width - 11;
v = verinfo;
for(y = 0; y < 6; y++) {
for(x = 0; x < 3; x++) {
p[x] = 0x88 | (v & 1);
v = v >> 1;
}
p += width;
}
}
/* and a little bit... */
frame[width * (width - 8) + 8] = 0x81;
return frame;
}
unsigned char *QRspec_newFrame(int version)
{
if(version < 1 || version > QRSPEC_VERSION_MAX) return NULL;
return QRspec_createFrame(version);
}

View File

@ -0,0 +1,174 @@
/*
* qrencode - QR Code encoder
*
* QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef QRSPEC_H
#define QRSPEC_H
#include "qrencode.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
/**
* Maximum width of a symbol
*/
#define QRSPEC_WIDTH_MAX 177
/**
* Return maximum data code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return maximum size (bytes)
*/
extern int QRspec_getDataLength(int version, QRecLevel level);
/**
* Return maximum error correction code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return ECC size (bytes)
*/
extern int QRspec_getECCLength(int version, QRecLevel level);
/**
* Return a version number that satisfies the input code length.
* @param size input code length (byte)
* @param level error correction level
* @return version number
*/
extern int QRspec_getMinimumVersion(int size, QRecLevel level);
/**
* Return the width of the symbol for the version.
* @param version vesion of the symbol
* @return width of the symbol
*/
extern int QRspec_getWidth(int version);
/**
* Return the numer of remainder bits.
* @param version vesion of the symbol
* @return number of remainder bits
*/
extern int QRspec_getRemainder(int version);
/******************************************************************************
* Length indicator
*****************************************************************************/
/**
* Return the size of length indicator for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the size of the appropriate length indicator (bits).
*/
extern int QRspec_lengthIndicator(QRencodeMode mode, int version);
/**
* Return the maximum length for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the maximum length (bytes)
*/
extern int QRspec_maximumWords(QRencodeMode mode, int version);
/******************************************************************************
* Error correction code
*****************************************************************************/
/**
* Return an array of ECC specification.
* @param version version of the symbol
* @param level error correction level
* @param spec an array of ECC specification contains as following:
* {# of type1 blocks, # of data code, # of ecc code,
* # of type2 blocks, # of data code}
*/
void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]);
#define QRspec_rsBlockNum(__spec__) (__spec__[0] + __spec__[3])
#define QRspec_rsBlockNum1(__spec__) (__spec__[0])
#define QRspec_rsDataCodes1(__spec__) (__spec__[1])
#define QRspec_rsEccCodes1(__spec__) (__spec__[2])
#define QRspec_rsBlockNum2(__spec__) (__spec__[3])
#define QRspec_rsDataCodes2(__spec__) (__spec__[4])
#define QRspec_rsEccCodes2(__spec__) (__spec__[2])
#define QRspec_rsDataLength(__spec__) \
((QRspec_rsBlockNum1(__spec__) * QRspec_rsDataCodes1(__spec__)) + \
(QRspec_rsBlockNum2(__spec__) * QRspec_rsDataCodes2(__spec__)))
#define QRspec_rsEccLength(__spec__) \
(QRspec_rsBlockNum(__spec__) * QRspec_rsEccCodes1(__spec__))
/******************************************************************************
* Version information pattern
*****************************************************************************/
/**
* Return BCH encoded version information pattern that is used for the symbol
* of version 7 or greater. Use lower 18 bits.
* @param version version of the symbol
* @return BCH encoded version information pattern
*/
extern unsigned int QRspec_getVersionPattern(int version);
/******************************************************************************
* Format information
*****************************************************************************/
/**
* Return BCH encoded format information pattern.
* @param mask mask number
* @param level error correction level
* @return BCH encoded format information pattern
*/
extern unsigned int QRspec_getFormatInfo(int mask, QRecLevel level);
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Return a copy of initialized frame.
* @param version version of the symbol
* @return Array of unsigned char. You can free it by free().
*/
extern unsigned char *QRspec_newFrame(int version);
/******************************************************************************
* Mode indicator
*****************************************************************************/
/**
* Mode indicator. See Table 2 of JIS X0510:2004, pp.16.
*/
#define QRSPEC_MODEID_ECI 7
#define QRSPEC_MODEID_NUM 1
#define QRSPEC_MODEID_AN 2
#define QRSPEC_MODEID_8 4
#define QRSPEC_MODEID_KANJI 8
#define QRSPEC_MODEID_FNC1FIRST 5
#define QRSPEC_MODEID_FNC1SECOND 9
#define QRSPEC_MODEID_STRUCTURE 3
#define QRSPEC_MODEID_TERMINATOR 0
#endif /* QRSPEC_H */

View File

@ -0,0 +1,149 @@
/*
* qrencode - QR Code encoder
*
* Reed solomon error correction code encoder specialized for QR code.
* This code is rewritten by Kentaro Fukuchi, referring to the FEC library
* developed by Phil Karn (KA9Q).
*
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
* Copyright (C) 2014-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#if HAVE_LIBPTHREAD
#include <pthread.h>
#endif
#include "rsecc.h"
#if HAVE_LIBPTHREAD
static pthread_mutex_t RSECC_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
static int initialized = 0;
#define SYMBOL_SIZE (8)
#define symbols ((1U << SYMBOL_SIZE) - 1)
static const unsigned int proot = 0x11d; /* stands for x^8+x^4+x^3+x^2+1 (see pp.37 of JIS X0510:2004) */
/* min/max codeword length of ECC, calculated from the specification. */
#define min_length (2)
#define max_length (30)
#define max_generatorSize (max_length)
static unsigned char alpha[symbols + 1];
static unsigned char aindex[symbols + 1];
static unsigned char generator[max_length - min_length + 1][max_generatorSize + 1];
static unsigned char generatorInitialized[max_length - min_length + 1];
static void RSECC_initLookupTable(void)
{
unsigned int i, b;
alpha[symbols] = 0;
aindex[0] = symbols;
b = 1;
for(i = 0; i < symbols; i++) {
alpha[i] = b;
aindex[b] = i;
b <<= 1;
if(b & (symbols + 1)) {
b ^= proot;
}
b &= symbols;
}
}
static void RSECC_init(void)
{
RSECC_initLookupTable();
memset(generatorInitialized, 0, (max_length - min_length + 1));
initialized = 1;
}
static void generator_init(size_t length)
{
size_t i, j;
int g[max_generatorSize + 1];
g[0] = 1;
for(i = 0; i < length; i++) {
g[i + 1] = 1;
/* Because g[0] never be zero, skipped some conditional checks. */
for(j = i; j > 0; j--) {
g[j] = g[j - 1] ^ alpha[(aindex[g[j]] + i) % symbols];
}
g[0] = alpha[(aindex[g[0]] + i) % symbols];
}
for(i = 0; i <= length; i++) {
generator[length - min_length][i] = aindex[g[i]];
}
generatorInitialized[length - min_length] = 1;
}
int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc)
{
size_t i, j;
unsigned char feedback;
unsigned char *gen;
#if HAVE_LIBPTHREAD
pthread_mutex_lock(&RSECC_mutex);
#endif
if(!initialized) {
RSECC_init();
}
#if HAVE_LIBPTHREAD
pthread_mutex_unlock(&RSECC_mutex);
#endif
if(ecc_length > max_length) return -1;
memset(ecc, 0, ecc_length);
#if HAVE_LIBPTHREAD
pthread_mutex_lock(&RSECC_mutex);
#endif
if(!generatorInitialized[ecc_length - min_length]) generator_init(ecc_length);
#if HAVE_LIBPTHREAD
pthread_mutex_unlock(&RSECC_mutex);
#endif
gen = generator[ecc_length - min_length];
for(i = 0; i < data_length; i++) {
feedback = aindex[data[i] ^ ecc[0]];
if(feedback != symbols) {
for(j = 1; j < ecc_length; j++) {
ecc[j] ^= alpha[(unsigned int)(feedback + gen[ecc_length - j]) % symbols];
}
}
memmove(&ecc[0], &ecc[1], ecc_length - 1);
if(feedback != symbols) {
ecc[ecc_length - 1] = alpha[(unsigned int)(feedback + gen[0]) % symbols];
} else {
ecc[ecc_length - 1] = 0;
}
}
return 0;
}

View File

@ -0,0 +1,31 @@
/*
* qrencode - QR Code encoder
*
* Reed solomon error correction code encoder specialized for QR code.
* This code is rewritten by Kentaro Fukuchi, referring to the FEC library
* developed by Phil Karn (KA9Q).
*
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
* Copyright (C) 2014-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef RSECC_H
#define RSECC_H
extern int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc);
#endif /* RSECC_H */

View File

@ -0,0 +1,319 @@
/*
* qrencode - QR Code encoder
*
* Input data splitter.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "config.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "qrencode.h"
#include "qrinput.h"
#include "qrspec.h"
#include "split.h"
#define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10)
#define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0)
#if !HAVE_STRDUP
#undef strdup
char *strdup(const char *s)
{
size_t len = strlen(s) + 1;
void *newstring = malloc(len);
if(newstring == NULL) return NULL;
return (char *)memcpy(newstring, s, len);
}
#endif
static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint)
{
unsigned char c, d;
unsigned int word;
c = (unsigned char)string[0];
if(c == '\0') return QR_MODE_NUL;
if(isdigit(c)) {
return QR_MODE_NUM;
} else if(isalnum(c)) {
return QR_MODE_AN;
} else if(hint == QR_MODE_KANJI) {
d = (unsigned char)string[1];
if(d != '\0') {
word = ((unsigned int)c << 8) | d;
if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) {
return QR_MODE_KANJI;
}
}
}
return QR_MODE_8;
}
static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint);
static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint);
static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint)
{
const char *p;
int ret;
int run;
int dif;
int ln;
QRencodeMode mode;
ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
p = string;
while(isdigit(*p)) {
p++;
}
run = (int)(p - string);
mode = Split_identifyMode(p, hint);
if(mode == QR_MODE_8) {
dif = QRinput_estimateBitsModeNum(run) + 4 + ln
+ QRinput_estimateBitsMode8(1) /* + 4 + l8 */
- QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
if(dif > 0) {
return Split_eat8(string, input, hint);
}
}
if(mode == QR_MODE_AN) {
dif = QRinput_estimateBitsModeNum(run) + 4 + ln
+ QRinput_estimateBitsModeAn(1) /* + 4 + la */
- QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */;
if(dif > 0) {
return Split_eatAn(string, input, hint);
}
}
ret = QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string);
if(ret < 0) return -1;
return run;
}
static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint)
{
const char *p, *q;
int ret;
int run;
int dif;
int la, ln;
la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
p = string;
while(isalnum(*p)) {
if(isdigit(*p)) {
q = p;
while(isdigit(*q)) {
q++;
}
dif = QRinput_estimateBitsModeAn((int)(p - string)) /* + 4 + la */
+ QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln
+ (isalnum(*q)?(4 + ln):0)
- QRinput_estimateBitsModeAn((int)(q - string)) /* - 4 - la */;
if(dif < 0) {
break;
}
p = q;
} else {
p++;
}
}
run = (int)(p - string);
if(*p && !isalnum(*p)) {
dif = QRinput_estimateBitsModeAn(run) + 4 + la
+ QRinput_estimateBitsMode8(1) /* + 4 + l8 */
- QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
if(dif > 0) {
return Split_eat8(string, input, hint);
}
}
ret = QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string);
if(ret < 0) return -1;
return run;
}
static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint)
{
const char *p;
int ret;
int run;
p = string;
while(Split_identifyMode(p, hint) == QR_MODE_KANJI) {
p += 2;
}
run = (int)(p - string);
ret = QRinput_append(input, QR_MODE_KANJI, run, (unsigned char *)string);
if(ret < 0) return -1;
return run;
}
static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint)
{
const char *p, *q;
QRencodeMode mode;
int ret;
int run;
int dif;
int la, ln, l8;
int swcost;
la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
l8 = QRspec_lengthIndicator(QR_MODE_8, input->version);
p = string + 1;
while(*p != '\0') {
mode = Split_identifyMode(p, hint);
if(mode == QR_MODE_KANJI) {
break;
}
if(mode == QR_MODE_NUM) {
q = p;
while(isdigit(*q)) {
q++;
}
if(Split_identifyMode(q, hint) == QR_MODE_8) {
swcost = 4 + l8;
} else {
swcost = 0;
}
dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */
+ QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln
+ swcost
- QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */;
if(dif < 0) {
break;
}
p = q;
} else if(mode == QR_MODE_AN) {
q = p;
while(isalnum(*q)) {
q++;
}
if(Split_identifyMode(q, hint) == QR_MODE_8) {
swcost = 4 + l8;
} else {
swcost = 0;
}
dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */
+ QRinput_estimateBitsModeAn((int)(q - p)) + 4 + la
+ swcost
- QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */;
if(dif < 0) {
break;
}
p = q;
} else {
p++;
}
}
run = (int)(p - string);
ret = QRinput_append(input, QR_MODE_8, run, (unsigned char *)string);
if(ret < 0) return -1;
return run;
}
static int Split_splitString(const char *string, QRinput *input,
QRencodeMode hint)
{
int length;
QRencodeMode mode;
if(*string == '\0') return 0;
mode = Split_identifyMode(string, hint);
if(mode == QR_MODE_NUM) {
length = Split_eatNum(string, input, hint);
} else if(mode == QR_MODE_AN) {
length = Split_eatAn(string, input, hint);
} else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) {
length = Split_eatKanji(string, input, hint);
} else {
length = Split_eat8(string, input, hint);
}
if(length == 0) return 0;
if(length < 0) return -1;
return Split_splitString(&string[length], input, hint);
}
static char *dupAndToUpper(const char *str, QRencodeMode hint)
{
char *newstr, *p;
QRencodeMode mode;
newstr = strdup(str);
if(newstr == NULL) return NULL;
p = newstr;
while(*p != '\0') {
mode = Split_identifyMode(p, hint);
if(mode == QR_MODE_KANJI) {
p += 2;
} else {
if (*p >= 'a' && *p <= 'z') {
*p = (char)((int)*p - 32);
}
p++;
}
}
return newstr;
}
int Split_splitStringToQRinput(const char *string, QRinput *input,
QRencodeMode hint, int casesensitive)
{
char *newstr;
int ret;
if(string == NULL || *string == '\0') {
errno = EINVAL;
return -1;
}
if(!casesensitive) {
newstr = dupAndToUpper(string, hint);
if(newstr == NULL) return -1;
ret = Split_splitString(newstr, input, hint);
free(newstr);
} else {
ret = Split_splitString(string, input, hint);
}
return ret;
}

View File

@ -0,0 +1,47 @@
/*
* qrencode - QR Code encoder
*
* Input data splitter.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef SPLIT_H
#define SPLIT_H
#include "qrencode.h"
/**
* Split the input string (null terminated) into QRinput.
* @param string input string
* @param hint give QR_MODE_KANJI if the input string contains Kanji character encoded in Shift-JIS. If not, give QR_MODE_8.
* @param casesensitive 0 for case-insensitive encoding (all alphabet characters are replaced to UPPER-CASE CHARACTERS.
* @retval 0 success.
* @retval -1 an error occurred. errno is set to indicate the error. See
* Exceptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
*/
extern int Split_splitStringToQRinput(const char *string, QRinput *input,
QRencodeMode hint, int casesensitive);
#endif /* SPLIT_H */

View File

@ -0,0 +1,34 @@
/**
* File: qr_register.c
* Author: AWTK Develop Team
* Brief: qr register
*
* Copyright (c) 2020 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-06-01 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/widget_factory.h"
#include "qr_register.h"
#include "qr/qr.h"
ret_t qr_register(void) {
return widget_factory_register(widget_factory(), WIDGET_TYPE_QR, qr_create);
}
const char* qr_supported_render_mode(void) {
return "OpenGL|AGGE-BGR565|AGGE-BGRA8888|AGGE-MONO";
}

View File

@ -0,0 +1,51 @@
/**
* File: qr_register.h
* Author: AWTK Develop Team
* Brief: qr register
*
* Copyright (c) 2020 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-06-01 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_QR_REGISTER_H
#define TK_QR_REGISTER_H
#include "base/widget.h"
BEGIN_C_DECLS
/**
* @method qr_register
* 注册控件。
*
* @annotation ["global"]
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t qr_register(void);
/**
* @method qr_supported_render_mode
* 获取支持的渲染模式。
*
* @annotation ["global"]
*
* @return {const char*} 返回渲染模式。
*/
const char* qr_supported_render_mode(void);
END_C_DECLS
#endif /*TK_QR_REGISTER_H*/

View File

@ -0,0 +1,111 @@
# AWTK 应用程序
## 准备
获取 awtk 并编译,可以通过以下两种方法:
1. 安装 [AWStudio](https://awtk.zlg.cn/awstudio/download.html)
安装完 AWStudio 后,打开 AWTK Designer 后新建或打开一个项目在插件管理页面的已安装列表可以看到AWTK插件选择编译或重新编译即可。
2. 前往 GitHub 获取
打开 Git Bash执行如下命令
```
git clone https://github.com/zlgopen/awtk.git
cd awtk; scons; cd -
```
## 运行
1. 编译
```
scons
```
2. 生成项目的资源文件
```
python ./scripts/update_res.py all
```
3. 运行
```
./bin/demo
```
## FAQ
### 设置 APP 运行时是否显示控制台窗口
如果 Windows 平台不想在运行程序时弹出控制台窗口,请在当前项目目录下的 `src/main.c` 文件中添加宏定义,如下所示:
```c
#define APP_ENABLE_CONSOLE FALSE
```
> 该定义需要在`#include "awtk_main.inc"`前添加。
### 设置 APP 标题栏的标题
如果需要修改 APP 标题栏的标题(运行程序时窗口左上角显示的名称),请在当前项目目录下的 `src/main.c` 添加宏定义,例如:
```c
#define APP_NAME "HelloWorld"
```
> 该定义需要在`#include "awtk_main.inc"`前添加。
### 设置 APP 可执行文件的名称
如果需要修改生成的可执行文件名称,请修改`src/SConscript`文件里的内容,如下所示
```python
env.Program(os.path.join(BIN_DIR, 'HelloWorld'), sources, LIBS = env['LIBS'])
```
将上述代码中的"HelloWorld"修改成想要的名称再进行编译即可。
### 设置 APP 依赖的库
如果需要设置依赖的库,可以打开项目目录中的`Sconstruct`文件,修改 DEPENDS_LIBS。关于 DEPENDS_LIBS 的更多信息,请参阅 [如何添加第三方库](http://awtk.zlg.cn/docs/awtk_docs/HowTo/how_to_use_3rd_libs.html)。
### 设置 APP 的图标
如果需要修改应用程序的图标,有两种方法(只适用于 Windows 平台):
1. 用 VC 创建的 .res 文件代替 当前依赖的 awtk 的SDK 包中的 `awtk/win32_res`里的 awtk.res 文件;
2. 用 [ResEdit](http://rsdt.free.fr/ResEdit-x64.7z) 直接编辑上述文件。
**1. 生成兼容 [mingw](https://sourceforge.net/projects/mingw-w64) 的 res**
1. awtk.rc 转为 utf8或者 utf8 with BOM 的编码;
2. 注释 rc 文件中的 #include "targetver.h" 代码;
3. windres 工具重新导出 res 文件。windres 是 mingw 提供的 exe
```bash
windres awtk.rc -O coff awtk.res
```
**2. 生成兼容 mingw 的 x86 格式 res**
步骤与上一小节一致,但最后使用 windres 工具导出 res 文件时,需要加上 `--target=pe-i386` 参数,命令如下:
```bash
windres awtk.rc -O coff awtk_x86.res --target=pe-i386
```
### scripts目录的文件介绍
`scripts`目录下,存放着几个脚本,下面简单介绍一下几个脚本的作用。
| 文件 | 作用 |
| -------------------------------------------- | ------------------------------------------------------------ |
| [update_res.py](./scripts/update_res.py) | 用于打包资源,使用方法可以查看该目录下的 [README.md](./scripts/README.md) 文档。 |
| [awtk_locator.py](./scripts/awtk_locator.py) | 帮助搜索依赖的 AWTK更多信息请参阅 [如何查找AWTK SDK](http://awtk.zlg.cn/docs/awtk_docs/FAQ/2.AWTK%20Designer.html#编译项目时-是如何搜索awtk-sdk的-搜索的顺序是什么样的)。 |
| [app_helper.py](./scripts/app_helper.py) | 帮助加载 AWTK 应用的公共编译参数,完成编译设置,以及编译 APP 依赖的库。 |
| [release.py](./scripts/release.py) | 用于生成发布包,执行程序后会在项目目录生成 release 文件夹。 |

View File

@ -0,0 +1,15 @@
import os
import scripts.app_helper as app
CUSTOM_WIDGET_LIBS = []
DEPENDS_LIBS = CUSTOM_WIDGET_LIBS + []
helper = app.Helper(ARGUMENTS)
helper.set_deps(DEPENDS_LIBS)
app.prepare_depends_libs(ARGUMENTS, helper, DEPENDS_LIBS)
helper.call(DefaultEnvironment)
SConscriptFiles = ['src/SConscript', 'tests/SConscript']
helper.SConscript(SConscriptFiles)

View File

@ -0,0 +1 @@
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~设置主题切换亮度调节蓝牙其他车辆信息返回时间自适应开启关闭英公制当前历史故障码语言单位选择背景中英文动白天黑夜请扫下载亿联骑行手机热点,使用扫连接名称互搜索需按任意键或二维码控件测试胎压学习未传感器丢失习中升级拷贝过程请勿断电!准备完善通话模式光钟保养里确定取消是否清除?快排功能

View File

@ -0,0 +1 @@
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

View File

@ -0,0 +1 @@
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~设置主题切换亮度调节蓝牙其他车辆信息返回时间自适应开启关闭英公制当前历史故障码语言单位选择背景中英文动白天黑夜请扫下载亿联骑行手机热点,使用扫连接名称互搜索需按任意键或二维码控件测试胎压学习未传感器丢失习中升级拷贝过程请勿断电!准备完善通话模式光钟保养里确定取消是否清除?快排功能

View File

@ -0,0 +1 @@
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~设置主题切换亮度调节蓝牙其他车辆信息返回时间自适应开启关闭英公制当前历史故障码语言单位选择背景中英文动白天黑夜请扫下载亿联骑行手机热点,使用扫连接名称互搜索需按任意键或二维码控件测试胎压学习未传感器丢失习中升级拷贝过程请勿断电!准备完善通话

View File

@ -0,0 +1 @@
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

View File

@ -0,0 +1 @@
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~设置主题切换亮度调节蓝牙其他车辆信息返回时间自适应开启关闭英公制当前历史故障码语言单位选择背景中英文动白天黑夜请扫下载亿联骑行手机热点,使用扫连接名称互搜索需按任意键或二维码控件测试胎压学习未传感器丢失习中升级拷贝过程请勿断电!准备完善通话

View File

@ -0,0 +1 @@
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

Some files were not shown because too many files have changed in this diff Show More