first commit
|
@ -0,0 +1,44 @@
|
|||
"""
|
||||
Tools
|
||||
=====
|
||||
|
||||
The tools module provides various utility scripts, modules and examples.
|
||||
|
||||
Scripts
|
||||
-------
|
||||
|
||||
Some useful scripts include:
|
||||
|
||||
* :file:`kviewer.py`: for viewing kv files with automatic updating
|
||||
* :file:`benchmark.py`: provides detailed OpenGL hardware information as well
|
||||
as some benchmarks measuring kivy specific performance
|
||||
* :file:`reports.py`: provides a comprehensive report covering your systems
|
||||
providers, libraries, configuration, environment, input devices and options
|
||||
* :file:`texturecompress.py`: a command line utility for compressing images
|
||||
into PVRTC or ETC1 formats
|
||||
* :file:`generate-icons.py`: generates set of icons suitable for the various
|
||||
store and package formats
|
||||
* :file:`gles_compat/subset_gles.py`: examines compatibility between GLEXT and
|
||||
GLES2 headers for finding compatible subsets
|
||||
|
||||
Modules
|
||||
-------
|
||||
|
||||
Tool modules provide various resources for:
|
||||
|
||||
* :mod:`~kivy.tools.packaging`
|
||||
* :mod:`text editor highlighting <kivy.tools.highlight>`
|
||||
|
||||
|
||||
Other
|
||||
-----
|
||||
|
||||
Other miscellaneous resources include
|
||||
|
||||
* :file:`pep8checker`: pep8 checking scripts and git hook
|
||||
* :file:`theming`: demonstrates an alternative theme for kivy
|
||||
* :file:`travis`: travis continuous integration
|
||||
|
||||
This help document is a work-in-progress and currently under construction.
|
||||
|
||||
"""
|
286
kivy_venv/lib/python3.11/site-packages/kivy/tools/benchmark.py
Normal file
|
@ -0,0 +1,286 @@
|
|||
'''
|
||||
Benchmark
|
||||
=========
|
||||
|
||||
This script performs and displays the results of a set of benchmarks. These
|
||||
provide a set of metrics mainly aimed at gauging the OpenGL performance of your
|
||||
system.
|
||||
|
||||
It also provides more specs regarding your graphics card setup together with
|
||||
more comprehensive system information.
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
benchmark_version = '1'
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import kivy
|
||||
import gc
|
||||
from time import clock, time, ctime
|
||||
from random import randint
|
||||
|
||||
from kivy.uix.label import Label
|
||||
from kivy.uix.button import Button
|
||||
from kivy.uix.widget import Widget
|
||||
from kivy.graphics import RenderContext
|
||||
from kivy.input.motionevent import MotionEvent
|
||||
from kivy.cache import Cache
|
||||
from kivy.clock import Clock
|
||||
from kivy.compat import PY2
|
||||
|
||||
if not PY2:
|
||||
xrange = range
|
||||
|
||||
clockfn = time
|
||||
if sys.platform == 'win32':
|
||||
clockfn = clock
|
||||
|
||||
|
||||
class FakeMotionEvent(MotionEvent):
|
||||
pass
|
||||
|
||||
|
||||
class bench_widget_creation:
|
||||
'''Widget: creation (10000 Widget)'''
|
||||
|
||||
def run(self):
|
||||
o = []
|
||||
for x in range(10000):
|
||||
o.append(Widget())
|
||||
|
||||
|
||||
class bench_widget_creation_with_root:
|
||||
'''Widget: creation (10000 Widget + 1 root)'''
|
||||
|
||||
def run(self):
|
||||
o = Widget()
|
||||
for x in range(10000):
|
||||
o.add_widget(Widget())
|
||||
|
||||
|
||||
class bench_widget_draw:
|
||||
'''Widget: empty drawing (10000 Widget + 1 root)'''
|
||||
|
||||
def __init__(self):
|
||||
self.ctx = RenderContext()
|
||||
self.root = root = Widget()
|
||||
for x in range(10000):
|
||||
root.add_widget(Widget())
|
||||
self.ctx.add(self.root.canvas)
|
||||
|
||||
def run(self):
|
||||
self.ctx.draw()
|
||||
|
||||
|
||||
class bench_widget_dispatch:
|
||||
'''Widget: event dispatch (1000 on_update in 10*1000 Widget)'''
|
||||
|
||||
def __init__(self):
|
||||
root = Widget()
|
||||
for x in range(10):
|
||||
parent = Widget()
|
||||
for y in range(1000):
|
||||
parent.add_widget(Widget())
|
||||
root.add_widget(parent)
|
||||
self.root = root
|
||||
|
||||
def run(self):
|
||||
touch = FakeMotionEvent('fake', 1, [])
|
||||
self.root.dispatch('on_touch_down', touch)
|
||||
self.root.dispatch('on_touch_move', touch)
|
||||
self.root.dispatch('on_touch_up', touch)
|
||||
|
||||
|
||||
class bench_label_creation:
|
||||
'''Core: label creation (10000 * 10 a-z)'''
|
||||
|
||||
def __init__(self):
|
||||
labels = []
|
||||
for x in range(10000):
|
||||
label = [chr(randint(ord('a'), ord('z'))) for x in range(10)]
|
||||
labels.append(''.join(label))
|
||||
self.labels = labels
|
||||
|
||||
def run(self):
|
||||
o = []
|
||||
for x in self.labels:
|
||||
o.append(Label(text=x))
|
||||
|
||||
|
||||
class bench_button_creation:
|
||||
'''Core: button creation (10000 * 10 a-z)'''
|
||||
|
||||
def __init__(self):
|
||||
labels = []
|
||||
for x in xrange(10000):
|
||||
button = map(lambda x: chr(randint(ord('a'), ord('z'))),
|
||||
xrange(10))
|
||||
labels.append(''.join(button))
|
||||
self.labels = labels
|
||||
|
||||
def run(self):
|
||||
o = []
|
||||
for x in self.labels:
|
||||
o.append(Button(text=x))
|
||||
|
||||
|
||||
class bench_label_creation_with_tick:
|
||||
'''Core: label creation (10000 * 10 a-z), with Clock.tick'''
|
||||
|
||||
def __init__(self):
|
||||
labels = []
|
||||
for x in range(10000):
|
||||
label = [chr(randint(ord('a'), ord('z'))) for x in range(10)]
|
||||
labels.append(''.join(label))
|
||||
self.labels = labels
|
||||
|
||||
def run(self):
|
||||
o = []
|
||||
for x in self.labels:
|
||||
o.append(Label(text=x))
|
||||
# tick for texture creation
|
||||
Clock.tick()
|
||||
|
||||
|
||||
class bench_button_creation_with_tick:
|
||||
'''Core: button creation (10000 * 10 a-z), with Clock.tick'''
|
||||
|
||||
def __init__(self):
|
||||
labels = []
|
||||
for x in xrange(10000):
|
||||
button = map(lambda x: chr(randint(ord('a'), ord('z'))),
|
||||
xrange(10))
|
||||
labels.append(''.join(button))
|
||||
self.labels = labels
|
||||
|
||||
def run(self):
|
||||
o = []
|
||||
for x in self.labels:
|
||||
o.append(Button(text=x))
|
||||
# tick for texture creation
|
||||
Clock.tick()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
report = []
|
||||
report_newline = True
|
||||
Clock.start_clock()
|
||||
|
||||
def log(s, newline=True):
|
||||
global report_newline
|
||||
if not report_newline:
|
||||
report[-1] = '%s %s' % (report[-1], s)
|
||||
else:
|
||||
report.append(s)
|
||||
if newline:
|
||||
print(s)
|
||||
report_newline = True
|
||||
else:
|
||||
print(s, end=' ')
|
||||
report_newline = False
|
||||
sys.stdout.flush()
|
||||
|
||||
clock_total = 0
|
||||
benchs = list(globals().keys())
|
||||
benchs.sort()
|
||||
benchs = [globals()[x] for x in benchs if x.startswith('bench_')]
|
||||
|
||||
log('')
|
||||
log('=' * 70)
|
||||
log('Kivy Benchmark v%s' % benchmark_version)
|
||||
log('=' * 70)
|
||||
log('')
|
||||
log('System information')
|
||||
log('-------------------')
|
||||
|
||||
log('OS platform : %s' % sys.platform)
|
||||
log('Python EXE : %s' % sys.executable)
|
||||
log('Python Version : %s' % sys.version)
|
||||
log('Python API : %s' % sys.api_version)
|
||||
log('Kivy Version : %s' % kivy.__version__)
|
||||
log('Install path : %s' % os.path.dirname(kivy.__file__))
|
||||
log('Install date : %s' % ctime(os.path.getctime(kivy.__file__)))
|
||||
|
||||
log('')
|
||||
log('OpenGL information')
|
||||
log('-------------------')
|
||||
|
||||
from kivy.core.gl import glGetString, GL_VENDOR, GL_RENDERER, GL_VERSION
|
||||
log('GL Vendor: %s' % glGetString(GL_VENDOR))
|
||||
log('GL Renderer: %s' % glGetString(GL_RENDERER))
|
||||
log('GL Version: %s' % glGetString(GL_VERSION))
|
||||
log('')
|
||||
|
||||
log('Benchmark')
|
||||
log('---------')
|
||||
|
||||
for x in benchs:
|
||||
# clean cache to prevent weird case
|
||||
for cat in Cache._categories:
|
||||
Cache.remove(cat)
|
||||
|
||||
# force gc before next test
|
||||
gc.collect()
|
||||
|
||||
log('%2d/%-2d %-60s' % (benchs.index(x) + 1,
|
||||
len(benchs), x.__doc__), False)
|
||||
try:
|
||||
sys.stderr.write('.')
|
||||
test = x()
|
||||
except Exception as e:
|
||||
log('failed %s' % str(e))
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
continue
|
||||
|
||||
clock_start = clockfn()
|
||||
|
||||
try:
|
||||
sys.stderr.write('.')
|
||||
test.run()
|
||||
clock_end = clockfn() - clock_start
|
||||
log('%.6f' % clock_end)
|
||||
except Exception as e:
|
||||
log('failed %s' % str(e))
|
||||
continue
|
||||
|
||||
clock_total += clock_end
|
||||
|
||||
log('')
|
||||
log('Result: %.6f' % clock_total)
|
||||
log('')
|
||||
Clock.stop_clock()
|
||||
|
||||
try:
|
||||
reply = input(
|
||||
'Do you want to send benchmark to gist.github.com (Y/n) : ')
|
||||
except EOFError:
|
||||
sys.exit(0)
|
||||
|
||||
if reply.lower().strip() in ('', 'y'):
|
||||
print('Please wait while sending the benchmark...')
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
print("`requests` module not found, no benchmark posted.")
|
||||
sys.exit(1)
|
||||
|
||||
payload = {
|
||||
'public': True, 'files': {
|
||||
'benchmark.txt': {
|
||||
'content': '\n'.join(report)}}}
|
||||
|
||||
r = requests.post('https://api.github.com/gists', data=json.dumps(payload))
|
||||
|
||||
print()
|
||||
print()
|
||||
print('REPORT posted at {0}'.format(r.json['html_url']))
|
||||
print()
|
||||
print()
|
||||
else:
|
||||
print('No benchmark posted.')
|
|
@ -0,0 +1,120 @@
|
|||
"""
|
||||
Changelog parser
|
||||
================
|
||||
|
||||
This generates a changelog from a json file of the PRs of a given milestone,
|
||||
dumped to json, using the [GitHub CLI](https://github.com/cli/cli).
|
||||
|
||||
First, in the command line, create the following alias::
|
||||
|
||||
gh alias set --shell viewMilestone "gh api graphql -F owner='kivy' \
|
||||
-F name='kivy' -F number=\\$1 -f query='
|
||||
query GetMilestones(\\$name: String!, \\$owner: String!, \\$number: \
|
||||
Int!) {
|
||||
repository(owner: \\$owner, name: \\$name) {
|
||||
milestone(number: \\$number) {
|
||||
pullRequests(states: MERGED, first: 1000) {
|
||||
nodes {
|
||||
number
|
||||
title
|
||||
labels (first: 25) {
|
||||
nodes {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'"
|
||||
|
||||
Then, log in using ``gh`` and run::
|
||||
|
||||
gh viewMilestone 26 > prs.json
|
||||
|
||||
This will generate ``prs.json``. Then, to generate the changelog, run::
|
||||
|
||||
python -m kivy.tools.changelog_parser prs.json changelog.md
|
||||
|
||||
to generate a markdown changelog at ``changelog.md``. Then, edit as desired
|
||||
and paste into the
|
||||
[changelog here](https://github.com/kivy/kivy/blob/master/doc/sources\
|
||||
/changelog.rst).
|
||||
"""
|
||||
from os.path import exists
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
import json
|
||||
|
||||
__all__ = ('process_changelog', )
|
||||
|
||||
|
||||
def write_special_section(fh, items, header):
|
||||
items = sorted(items, key=lambda x: x[0])
|
||||
if items:
|
||||
fh.write(f'{header}\n{"-" * len(header)}\n\n')
|
||||
for n, title in items:
|
||||
fh.write(f'- [:repo:`{n}`]: {title}\n')
|
||||
fh.write('\n')
|
||||
|
||||
|
||||
def process_changelog(filename_in, filename_out):
|
||||
if exists(filename_out):
|
||||
raise ValueError(
|
||||
'{} already exists and would be overwritten'.format(filename_out))
|
||||
|
||||
with open(filename_in, 'r') as fh:
|
||||
data = json.load(fh)
|
||||
prs = data["data"]["repository"]["milestone"]["pullRequests"]["nodes"]
|
||||
|
||||
bad_pr = False
|
||||
grouped = defaultdict(list)
|
||||
highlighted = []
|
||||
api_breaks = []
|
||||
deprecates = []
|
||||
for item in prs:
|
||||
n = item['number']
|
||||
title = item['title']
|
||||
labels = [label['name'] for label in item['labels']['nodes']]
|
||||
api_break = 'Notes: API-break' in labels
|
||||
highlight = 'Notes: Release-highlight' in labels
|
||||
deprecated = 'Notes: API-deprecation' in labels
|
||||
component_str = 'Component: '
|
||||
components = [
|
||||
label[len(component_str):]
|
||||
for label in labels if label.startswith(component_str)
|
||||
]
|
||||
|
||||
if not components:
|
||||
print(f'Found no component label for #{n}')
|
||||
bad_pr = True
|
||||
continue
|
||||
if len(components) > 1:
|
||||
print(f'Found more than one component label for #{n}')
|
||||
bad_pr = True
|
||||
continue
|
||||
|
||||
grouped[components[0]].append((n, title))
|
||||
if highlight:
|
||||
highlighted.append((n, title))
|
||||
if api_break:
|
||||
api_breaks.append((n, title))
|
||||
if deprecated:
|
||||
deprecates.append((n, title))
|
||||
|
||||
if bad_pr:
|
||||
raise ValueError(
|
||||
'One or more PRs have no, or more than one component label')
|
||||
|
||||
with open(filename_out, 'w') as fh:
|
||||
write_special_section(fh, highlighted, 'Highlights')
|
||||
write_special_section(fh, deprecates, 'Deprecated')
|
||||
write_special_section(fh, api_breaks, 'Breaking changes')
|
||||
|
||||
for group, items in sorted(grouped.items(), key=lambda x: x[0]):
|
||||
write_special_section(fh, items, group.capitalize())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
process_changelog(*sys.argv[1:])
|
135
kivy_venv/lib/python3.11/site-packages/kivy/tools/coverage.py
Normal file
|
@ -0,0 +1,135 @@
|
|||
"""Kivy coverage plugin
|
||||
=======================
|
||||
|
||||
This provides a coverage plugin to measure code execution in kv files. To use,
|
||||
create and add::
|
||||
|
||||
[run]
|
||||
plugins =
|
||||
kivy.tools.coverage
|
||||
|
||||
to the ``.coveragerc`` file in the root of your project. Or::
|
||||
|
||||
[coverage:run]
|
||||
plugins =
|
||||
kivy.tools.coverage
|
||||
|
||||
in ``setup.cfg``.
|
||||
|
||||
Then you can test your project with e.g. ``pip install coverage`` followed by
|
||||
``coverage run --source=./ kivy_app.py`` and ``coverage report``.
|
||||
|
||||
Or to use with pytest, ``pip install pytest-cov`` followed by something like
|
||||
``pytest --cov=./ .``
|
||||
|
||||
TODO: Expand kv statements measured.
|
||||
|
||||
Currently, it ignores rules such as Widget creation or graphics object
|
||||
creation from being measured. Similarly for import statements.
|
||||
|
||||
KV code created as strings within a python file is also not measured. To
|
||||
support the above, deeper changes will be required.
|
||||
"""
|
||||
|
||||
import os
|
||||
import coverage
|
||||
from kivy.lang.parser import Parser
|
||||
|
||||
|
||||
class CoverageKVParser(Parser):
|
||||
|
||||
def execute_directives(self):
|
||||
# don't actually execute anything
|
||||
pass
|
||||
|
||||
def get_coverage_lines(self):
|
||||
lines = set()
|
||||
for parser_prop in walk_parser(self):
|
||||
for line_num, line in enumerate(
|
||||
parser_prop.value.splitlines(),
|
||||
start=parser_prop.line + 1):
|
||||
if line.strip():
|
||||
lines.add(line_num)
|
||||
|
||||
return lines
|
||||
|
||||
|
||||
def walk_parser_rules(parser_rule):
|
||||
yield parser_rule
|
||||
|
||||
for child in parser_rule.children:
|
||||
for rule in walk_parser_rules(child):
|
||||
yield rule
|
||||
|
||||
if parser_rule.canvas_before is not None:
|
||||
for rule in walk_parser_rules(parser_rule.canvas_before):
|
||||
yield rule
|
||||
yield parser_rule.canvas_before
|
||||
if parser_rule.canvas_root is not None:
|
||||
for rule in walk_parser_rules(parser_rule.canvas_root):
|
||||
yield rule
|
||||
if parser_rule.canvas_after is not None:
|
||||
for rule in walk_parser_rules(parser_rule.canvas_after):
|
||||
yield rule
|
||||
|
||||
|
||||
def walk_parser_rules_properties(parser_rule):
|
||||
for rule in parser_rule.properties.values():
|
||||
yield rule
|
||||
for rule in parser_rule.handlers:
|
||||
yield rule
|
||||
|
||||
|
||||
def walk_parser(parser):
|
||||
if parser.root is not None:
|
||||
for rule in walk_parser_rules(parser.root):
|
||||
for prop in walk_parser_rules_properties(rule):
|
||||
yield prop
|
||||
|
||||
for _, cls_rule in parser.rules:
|
||||
for rule in walk_parser_rules(cls_rule):
|
||||
for prop in walk_parser_rules_properties(rule):
|
||||
yield prop
|
||||
|
||||
|
||||
class KivyCoveragePlugin(coverage.plugin.CoveragePlugin):
|
||||
|
||||
def file_tracer(self, filename):
|
||||
if filename.endswith('.kv'):
|
||||
return KivyFileTracer(filename=filename)
|
||||
return None
|
||||
|
||||
def file_reporter(self, filename):
|
||||
return KivyFileReporter(filename=filename)
|
||||
|
||||
def find_executable_files(self, src_dir):
|
||||
for (dirpath, dirnames, filenames) in os.walk(src_dir):
|
||||
for filename in filenames:
|
||||
if filename.endswith('.kv'):
|
||||
yield os.path.join(dirpath, filename)
|
||||
|
||||
|
||||
class KivyFileTracer(coverage.plugin.FileTracer):
|
||||
|
||||
filename = ''
|
||||
|
||||
def __init__(self, filename, **kwargs):
|
||||
super(KivyFileTracer, self).__init__(**kwargs)
|
||||
self.filename = filename
|
||||
|
||||
def source_filename(self):
|
||||
return self.filename
|
||||
|
||||
|
||||
class KivyFileReporter(coverage.plugin.FileReporter):
|
||||
|
||||
def lines(self):
|
||||
with open(self.filename) as fh:
|
||||
source = fh.read()
|
||||
|
||||
parser = CoverageKVParser(content=source, filename=self.filename)
|
||||
return parser.get_coverage_lines()
|
||||
|
||||
|
||||
def coverage_init(reg, options):
|
||||
reg.add_file_tracer(KivyCoveragePlugin())
|
323
kivy_venv/lib/python3.11/site-packages/kivy/tools/gallery.py
Normal file
|
@ -0,0 +1,323 @@
|
|||
''' Create rst documentation of the examples directory.
|
||||
|
||||
This uses screenshots in the screenshots_dir
|
||||
(currently doc/sources/images/examples) along with source code and files
|
||||
in the examples/ directory to create rst files in the generation_dir
|
||||
(doc/sources/examples) gallery.rst, index.rst, and gen__*.rst
|
||||
|
||||
'''
|
||||
|
||||
|
||||
import os
|
||||
import re
|
||||
from os.path import sep
|
||||
from os.path import join as slash # just like that name better
|
||||
from os.path import dirname, abspath
|
||||
import kivy
|
||||
from kivy.logger import Logger
|
||||
import textwrap
|
||||
|
||||
# from here to the kivy top
|
||||
base_dir = dirname(dirname(abspath(kivy.__file__)))
|
||||
examples_dir = slash(base_dir, 'examples')
|
||||
screenshots_dir = slash(base_dir, 'doc/sources/images/examples')
|
||||
generation_dir = slash(base_dir, 'doc/sources/examples')
|
||||
|
||||
image_dir = "../images/examples/" # relative to generation_dir
|
||||
gallery_filename = slash(generation_dir, 'gallery.rst')
|
||||
|
||||
|
||||
# Info is a dict built up from
|
||||
# straight filename information, more from reading the docstring,
|
||||
# and more from parsing the description text. Errors are often
|
||||
# shown by setting the key 'error' with the value being the error message.
|
||||
#
|
||||
# It doesn't quite meet the requirements for a class, but is a vocabulary
|
||||
# word in this module.
|
||||
|
||||
def iter_filename_info(dir_name):
|
||||
"""
|
||||
Yield info (dict) of each matching screenshot found walking the
|
||||
directory dir_name. A matching screenshot uses double underscores to
|
||||
separate fields, i.e. path__to__filename__py.png as the screenshot for
|
||||
examples/path/to/filename.py.
|
||||
|
||||
Files not ending with .png are ignored, others are either parsed or
|
||||
yield an error.
|
||||
|
||||
Info fields 'dunder', 'dir', 'file', 'ext', 'source' if not 'error'
|
||||
"""
|
||||
pattern = re.compile(r'^((.+)__(.+)__([^-]+))\.png')
|
||||
for t in os.walk(dir_name):
|
||||
for filename in t[2]:
|
||||
if filename.endswith('.png'):
|
||||
m = pattern.match(filename)
|
||||
if m is None:
|
||||
yield {'error': 'png filename not following screenshot'
|
||||
' pattern: {}'.format(filename)}
|
||||
else:
|
||||
d = m.group(2).replace('__', sep)
|
||||
yield {'dunder': m.group(1),
|
||||
'dir': d,
|
||||
'file': m.group(3),
|
||||
'ext': m.group(4),
|
||||
'source': slash(d, m.group(3) + '.' + m.group(4))
|
||||
}
|
||||
|
||||
|
||||
def parse_docstring_info(text):
|
||||
''' parse docstring from text (normal string with '\n's) and return an info
|
||||
dict. A docstring should the first triple quoted string, have a title
|
||||
followed by a line of equal signs, and then a description at
|
||||
least one sentence long.
|
||||
|
||||
fields are 'docstring', 'title', and 'first_sentence' if not 'error'
|
||||
'first_sentence' is a single line without newlines.
|
||||
'''
|
||||
q = '\"\"\"|\'\'\''
|
||||
p = r'({})\s+([^\n]+)\s+\=+\s+(.*?)(\1)'.format(q)
|
||||
m = re.search(p, text, re.S)
|
||||
if m:
|
||||
comment = m.group(3).replace('\n', ' ')
|
||||
first_sentence = comment[:comment.find('.') + 1]
|
||||
return {'docstring': m.group(0), 'title': m.group(2),
|
||||
'description': m.group(3), 'first_sentence': first_sentence}
|
||||
else:
|
||||
return {'error': 'Did not find docstring with title at top of file.'}
|
||||
|
||||
|
||||
def iter_docstring_info(dir_name):
|
||||
''' Iterate over screenshots in directory, yield info from the file
|
||||
name and initial parse of the docstring. Errors are logged, but
|
||||
files with errors are skipped.
|
||||
'''
|
||||
for file_info in iter_filename_info(dir_name):
|
||||
if 'error' in file_info:
|
||||
Logger.error(file_info['error'])
|
||||
continue
|
||||
source = slash(examples_dir, file_info['dir'],
|
||||
file_info['file'] + '.' + file_info['ext'])
|
||||
if not os.path.exists(source):
|
||||
Logger.error('Screen shot references source code that does '
|
||||
'not exist: %s', source)
|
||||
continue
|
||||
with open(source) as f:
|
||||
text = f.read()
|
||||
docstring_info = parse_docstring_info(text)
|
||||
if 'error' in docstring_info:
|
||||
Logger.error(docstring_info['error'] + ' File: ' + source)
|
||||
continue # don't want to show ugly entries
|
||||
else:
|
||||
file_info.update(docstring_info)
|
||||
yield file_info
|
||||
|
||||
|
||||
def enhance_info_description(info, line_length=79):
|
||||
''' Using the info['description'], add fields to info.
|
||||
|
||||
info['files'] is the source filename and any filenames referenced by the
|
||||
magic words in the description, e.g. 'the file xxx.py' or
|
||||
'The image this.png'. These are as written in the description, do
|
||||
not allow ../dir notation, and are relative to the source directory.
|
||||
|
||||
info['enhanced_description'] is the description, as an array of
|
||||
paragraphs where each paragraph is an array of lines wrapped to width
|
||||
line_length. This enhanced description include the rst links to
|
||||
the files of info['files'].
|
||||
'''
|
||||
|
||||
# make text a set of long lines, one per paragraph.
|
||||
paragraphs = info['description'].split('\n\n')
|
||||
lines = [
|
||||
paragraph.replace('\n', '$newline$')
|
||||
for paragraph in paragraphs
|
||||
]
|
||||
text = '\n'.join(lines)
|
||||
|
||||
info['files'] = [info['file'] + '.' + info['ext']]
|
||||
regex = r'[tT]he (?:file|image) ([\w\/]+\.\w+)'
|
||||
for name in re.findall(regex, text):
|
||||
if name not in info['files']:
|
||||
info['files'].append(name)
|
||||
|
||||
# add links where the files are referenced
|
||||
folder = '_'.join(info['source'].split(sep)[:-1]) + '_'
|
||||
text = re.sub(r'([tT]he (?:file|image) )([\w\/]+\.\w+)',
|
||||
r'\1:ref:`\2 <$folder$\2>`', text)
|
||||
text = text.replace('$folder$', folder)
|
||||
|
||||
# now break up text into array of paragraphs, each an array of lines.
|
||||
lines = [line.replace('$newline$', '\n') for line in text.split('\n')]
|
||||
paragraphs = [
|
||||
textwrap.wrap(line, line_length)
|
||||
# ignore wrapping if .. note:: or similar block
|
||||
if not line.startswith(' ') else [line]
|
||||
for line in lines
|
||||
]
|
||||
info['enhanced_description'] = paragraphs
|
||||
|
||||
|
||||
def get_infos(dir_name):
|
||||
''' return infos, an array info dicts for each matching screenshot in the
|
||||
dir, sorted by source file name, and adding the field 'num' as he unique
|
||||
order in this array of dicts'.
|
||||
|
||||
'''
|
||||
infos = [i for i in iter_docstring_info(dir_name)]
|
||||
infos.sort(key=lambda x: x['source'])
|
||||
for num, info in enumerate(infos):
|
||||
info['num'] = num
|
||||
enhance_info_description(info)
|
||||
return infos
|
||||
|
||||
|
||||
def make_gallery_page(infos):
|
||||
''' return string of the rst (Restructured Text) of the gallery page,
|
||||
showing information on all screenshots found.
|
||||
'''
|
||||
|
||||
gallery_top = '''
|
||||
Gallery
|
||||
-------
|
||||
|
||||
.. _Tutorials: ../tutorials-index.html
|
||||
|
||||
.. container:: title
|
||||
|
||||
This gallery lets you explore the many examples included with Kivy.
|
||||
Click on any screenshot to see the code.
|
||||
|
||||
This gallery contains:
|
||||
|
||||
* Examples from the examples/ directory that show specific capabilities of
|
||||
different libraries and features of Kivy.
|
||||
* Demonstrations from the examples/demos/ directory that explore many of
|
||||
Kivy's abilities.
|
||||
|
||||
There are more Kivy programs elsewhere:
|
||||
|
||||
* Tutorials_ walks through the development of complete Kivy applications.
|
||||
* Unit tests found in the source code under the subdirectory kivy/tests/
|
||||
can also be useful.
|
||||
|
||||
We hope your journey into learning Kivy is exciting and fun!
|
||||
|
||||
'''
|
||||
output = [gallery_top]
|
||||
|
||||
for info in infos:
|
||||
output.append(
|
||||
"\n**{title}** (:doc:`{source}<gen__{dunder}>`)\n"
|
||||
"\n{description}"
|
||||
"\n.. image:: ../images/examples/{dunder}.png"
|
||||
"\n :width: 216pt"
|
||||
"\n :align: left"
|
||||
"\n :target: gen__{dunder}.html".format(**info))
|
||||
return "\n".join(output) + "\n"
|
||||
|
||||
|
||||
def make_detail_page(info):
|
||||
''' return str of the rst text for the detail page of the file in info. '''
|
||||
|
||||
def a(s=''):
|
||||
''' append formatted s to output, which will be joined into lines '''
|
||||
output.append(s.format(**info))
|
||||
|
||||
output = []
|
||||
a('{title}')
|
||||
a('=' * len(info['title']))
|
||||
a('\n.. |pic{num}| image:: /images/examples/{dunder}.png'
|
||||
'\n :width: 50%'
|
||||
'\n :align: middle')
|
||||
a('\n|pic{num}|')
|
||||
a()
|
||||
for paragraph in info['enhanced_description']:
|
||||
for line in paragraph:
|
||||
a(line)
|
||||
a()
|
||||
|
||||
# include images
|
||||
last_lang = '.py'
|
||||
for fname in info['files']:
|
||||
full_name = slash(info['dir'], fname)
|
||||
ext = re.search(r'\.\w+$', fname).group(0)
|
||||
a('\n.. _`' + full_name.replace(sep, '_') + '`:')
|
||||
# double separator if building on windows (sphinx skips backslash)
|
||||
if '\\' in full_name:
|
||||
full_name = full_name.replace(sep, sep * 2)
|
||||
|
||||
if ext in ['.png', '.jpg', '.jpeg']:
|
||||
title = 'Image **' + full_name + '**'
|
||||
a('\n' + title)
|
||||
a('~' * len(title))
|
||||
a('\n.. image:: ../../../examples/' + full_name)
|
||||
a(' :align: ' ' center')
|
||||
else: # code
|
||||
title = 'File **' + full_name + '**'
|
||||
a('\n' + title)
|
||||
a('~' * len(title))
|
||||
if ext != last_lang and ext != '.txt':
|
||||
a('\n.. highlight:: ' + ext[1:])
|
||||
a(' :linenothreshold: 3')
|
||||
last_lang = ext
|
||||
# prevent highlight errors with 'none'
|
||||
elif ext == '.txt':
|
||||
a('\n.. highlight:: none')
|
||||
a(' :linenothreshold: 3')
|
||||
last_lang = ext
|
||||
a('\n.. include:: ../../../examples/' + full_name)
|
||||
a(' :code:')
|
||||
return '\n'.join(output) + '\n'
|
||||
|
||||
|
||||
def write_file(name, s):
|
||||
''' write the string to the filename '''
|
||||
|
||||
# Make sure all the directories has been created before
|
||||
# trying to write to the file
|
||||
directory = os.path.dirname(name)
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
with open(name, 'w') as f:
|
||||
f.write(s)
|
||||
|
||||
|
||||
def make_index(infos):
|
||||
''' return string of the rst for the gallery's index.rst file. '''
|
||||
start_string = '''
|
||||
Gallery of Examples
|
||||
===================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
gallery'''
|
||||
output = [start_string]
|
||||
for info in infos:
|
||||
output.append(' gen__{}'.format(info['dunder']))
|
||||
return '\n'.join(output) + '\n'
|
||||
|
||||
|
||||
def write_all_rst_pages():
|
||||
''' Do the main task of writing the gallery,
|
||||
detail, and index rst pages.
|
||||
'''
|
||||
infos = get_infos(screenshots_dir)
|
||||
s = make_gallery_page(infos)
|
||||
write_file(gallery_filename, s)
|
||||
|
||||
for info in infos:
|
||||
s = make_detail_page(info)
|
||||
detail_name = slash(generation_dir,
|
||||
'gen__{}.rst'.format(info['dunder']))
|
||||
write_file(detail_name, s)
|
||||
|
||||
s = make_index(infos)
|
||||
index_name = slash(generation_dir, 'index.rst')
|
||||
write_file(index_name, s)
|
||||
Logger.info('gallery.py: Created gallery rst documentation pages.')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
write_all_rst_pages()
|
|
@ -0,0 +1,117 @@
|
|||
'''
|
||||
Icon generator
|
||||
==============
|
||||
|
||||
This tool will help you to generate all the icons wanted for Google Play Store,
|
||||
App Store, Amazon store.
|
||||
'''
|
||||
|
||||
import sys
|
||||
from PIL import Image
|
||||
from os.path import exists, join, realpath, basename, dirname
|
||||
from os import makedirs
|
||||
from argparse import ArgumentParser
|
||||
|
||||
|
||||
class Converter(object):
|
||||
|
||||
converters = {
|
||||
'appstore': {
|
||||
'directory_name': 'ios',
|
||||
'sizes': [
|
||||
('App store high resolution', '{}-appstore-1024.png', 1024),
|
||||
('App store normal resolution', '{}-appstore-512.png', 512),
|
||||
# iOS 7
|
||||
('iPhone (iOS 7)', '{}-60.png', 120),
|
||||
('iPhone @2 (iOS 7)', '{}-60@2x.png', 120),
|
||||
('iPad (iOS 7)', '{}-76.png', 76),
|
||||
('iPad @2 (iOS 7)', '{}-60@2x.png', 152),
|
||||
# iOS 6.1 and earlier
|
||||
('iPhone (iOS >= 6.1)', '{}-57.png', 57),
|
||||
('iPhone @2 (iOS >= 6.1)', '{}-57@2x.png', 114),
|
||||
('iPad (iOS >= 6.1)', '{}-72.png', 72),
|
||||
('iPad @2 (iOS >= 6.1)', '{}-72@2x.png', 114),
|
||||
# iTunes artwork (ad-hoc)
|
||||
('iTunes Artwork (ad-hoc)', 'iTunesArtwork', 512),
|
||||
('iTunes Artwork @2 (ad-hoc)', 'iTunesArtwork@2x', 1024),
|
||||
]},
|
||||
'playstore': {
|
||||
'directory_name': 'android',
|
||||
'sizes': [
|
||||
('Google Play icon', '{}-googleplay-512.png', 512),
|
||||
('Launcher icon MDPI', '{}-48.png', 48),
|
||||
('Launcher icon HDPI', '{}-72.png', 72),
|
||||
('Launcher icon XHDPI', '{}-96.png', 96),
|
||||
('Launcher icon XXHDPI', '{}-144.png', 48),
|
||||
('Launcher icon XXXHDPI', '{}-192.png', 192),
|
||||
]},
|
||||
'amazonstore': {
|
||||
'directory_name': 'amazon',
|
||||
'sizes': [
|
||||
('Small icon', '{}-114.png', 114),
|
||||
('Large icon', '{}-512.png', 512),
|
||||
]}}
|
||||
|
||||
def run(self):
|
||||
parser = ArgumentParser(
|
||||
description='Generate icons for various stores')
|
||||
parser.add_argument('--dir', type=str, default=None,
|
||||
help=('Output directory to generate all the icons,'
|
||||
'defaults to the directory of the source icon'))
|
||||
parser.add_argument('--force', type=bool, default=False,
|
||||
help=('Generate all icons even if the source is not perfect.'))
|
||||
parser.add_argument('icon', type=str,
|
||||
help='Base icon (must be 1024x1024 or 512x512)')
|
||||
|
||||
args = parser.parse_args()
|
||||
if not exists(args.icon):
|
||||
print('Error: No such icon file')
|
||||
sys.exit(1)
|
||||
|
||||
# ensure the destination directory will be set
|
||||
if args.dir is None:
|
||||
args.dir = dirname(args.icon)
|
||||
|
||||
# read the source image, and do some quality checks
|
||||
base_fn = basename(args.icon).rsplit('.', 1)[0]
|
||||
source = Image.open(args.icon)
|
||||
self.ensure_quality(source, args.force)
|
||||
|
||||
for directory_name, sizeinfo in self.iterate():
|
||||
description, pattern_fn, size = sizeinfo
|
||||
print('Generate {}: {}x{}'.format(description, size, size))
|
||||
dest_dir = realpath(join(args.dir, directory_name))
|
||||
if not exists(dest_dir):
|
||||
makedirs(dest_dir)
|
||||
icon_fn = join(dest_dir, pattern_fn.format('Icon'))
|
||||
self.convert_to(source, icon_fn, size)
|
||||
|
||||
def convert_to(self, source, icon_fn, size):
|
||||
dest = source.resize((size, size))
|
||||
dest.save(icon_fn, 'png')
|
||||
|
||||
def ensure_quality(self, image, force=False):
|
||||
messages = []
|
||||
w, h = image.size
|
||||
if w != h:
|
||||
messages.append('Width and height should be the same')
|
||||
if w not in (512, 1024):
|
||||
messages.append(
|
||||
'Source image is recommended to be 1024 (512 minimum)')
|
||||
if not messages:
|
||||
return
|
||||
|
||||
print('Quality check failed')
|
||||
for message in messages:
|
||||
print('- {}'.format(message))
|
||||
if not force:
|
||||
sys.exit(1)
|
||||
|
||||
def iterate(self):
|
||||
for store, infos in Converter.converters.items():
|
||||
for size in infos['sizes']:
|
||||
yield infos['directory_name'], size
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
Converter().run()
|
|
@ -0,0 +1,621 @@
|
|||
#ifndef __gl2_h_
|
||||
#define __gl2_h_
|
||||
|
||||
/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
|
||||
|
||||
#include <GLES2/gl2platform.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This document is licensed under the SGI Free Software B License Version
|
||||
* 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Data type definitions
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
typedef void GLvoid;
|
||||
typedef char GLchar;
|
||||
typedef unsigned int GLenum;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef khronos_int8_t GLbyte;
|
||||
typedef short GLshort;
|
||||
typedef int GLint;
|
||||
typedef int GLsizei;
|
||||
typedef khronos_uint8_t GLubyte;
|
||||
typedef unsigned short GLushort;
|
||||
typedef unsigned int GLuint;
|
||||
typedef khronos_float_t GLfloat;
|
||||
typedef khronos_float_t GLclampf;
|
||||
typedef khronos_int32_t GLfixed;
|
||||
|
||||
/* GL types for handling large vertex buffer objects */
|
||||
typedef khronos_intptr_t GLintptr;
|
||||
typedef khronos_ssize_t GLsizeiptr;
|
||||
|
||||
/* OpenGL ES core versions */
|
||||
#define GL_ES_VERSION_2_0 1
|
||||
|
||||
/* ClearBufferMask */
|
||||
#define GL_DEPTH_BUFFER_BIT 0x00000100
|
||||
#define GL_STENCIL_BUFFER_BIT 0x00000400
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
|
||||
/* Boolean */
|
||||
#define GL_FALSE 0
|
||||
#define GL_TRUE 1
|
||||
|
||||
/* BeginMode */
|
||||
#define GL_POINTS 0x0000
|
||||
#define GL_LINES 0x0001
|
||||
#define GL_LINE_LOOP 0x0002
|
||||
#define GL_LINE_STRIP 0x0003
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_TRIANGLE_STRIP 0x0005
|
||||
#define GL_TRIANGLE_FAN 0x0006
|
||||
|
||||
/* AlphaFunction (not supported in ES20) */
|
||||
/* GL_NEVER */
|
||||
/* GL_LESS */
|
||||
/* GL_EQUAL */
|
||||
/* GL_LEQUAL */
|
||||
/* GL_GREATER */
|
||||
/* GL_NOTEQUAL */
|
||||
/* GL_GEQUAL */
|
||||
/* GL_ALWAYS */
|
||||
|
||||
/* BlendingFactorDest */
|
||||
#define GL_ZERO 0
|
||||
#define GL_ONE 1
|
||||
#define GL_SRC_COLOR 0x0300
|
||||
#define GL_ONE_MINUS_SRC_COLOR 0x0301
|
||||
#define GL_SRC_ALPHA 0x0302
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
||||
#define GL_DST_ALPHA 0x0304
|
||||
#define GL_ONE_MINUS_DST_ALPHA 0x0305
|
||||
|
||||
/* BlendingFactorSrc */
|
||||
/* GL_ZERO */
|
||||
/* GL_ONE */
|
||||
#define GL_DST_COLOR 0x0306
|
||||
#define GL_ONE_MINUS_DST_COLOR 0x0307
|
||||
#define GL_SRC_ALPHA_SATURATE 0x0308
|
||||
/* GL_SRC_ALPHA */
|
||||
/* GL_ONE_MINUS_SRC_ALPHA */
|
||||
/* GL_DST_ALPHA */
|
||||
/* GL_ONE_MINUS_DST_ALPHA */
|
||||
|
||||
/* BlendEquationSeparate */
|
||||
#define GL_FUNC_ADD 0x8006
|
||||
#define GL_BLEND_EQUATION 0x8009
|
||||
#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */
|
||||
#define GL_BLEND_EQUATION_ALPHA 0x883D
|
||||
|
||||
/* BlendSubtract */
|
||||
#define GL_FUNC_SUBTRACT 0x800A
|
||||
#define GL_FUNC_REVERSE_SUBTRACT 0x800B
|
||||
|
||||
/* Separate Blend Functions */
|
||||
#define GL_BLEND_DST_RGB 0x80C8
|
||||
#define GL_BLEND_SRC_RGB 0x80C9
|
||||
#define GL_BLEND_DST_ALPHA 0x80CA
|
||||
#define GL_BLEND_SRC_ALPHA 0x80CB
|
||||
#define GL_CONSTANT_COLOR 0x8001
|
||||
#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
|
||||
#define GL_CONSTANT_ALPHA 0x8003
|
||||
#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
|
||||
#define GL_BLEND_COLOR 0x8005
|
||||
|
||||
/* Buffer Objects */
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#define GL_ARRAY_BUFFER_BINDING 0x8894
|
||||
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
|
||||
|
||||
#define GL_STREAM_DRAW 0x88E0
|
||||
#define GL_STATIC_DRAW 0x88E4
|
||||
#define GL_DYNAMIC_DRAW 0x88E8
|
||||
|
||||
#define GL_BUFFER_SIZE 0x8764
|
||||
#define GL_BUFFER_USAGE 0x8765
|
||||
|
||||
#define GL_CURRENT_VERTEX_ATTRIB 0x8626
|
||||
|
||||
/* CullFaceMode */
|
||||
#define GL_FRONT 0x0404
|
||||
#define GL_BACK 0x0405
|
||||
#define GL_FRONT_AND_BACK 0x0408
|
||||
|
||||
/* DepthFunction */
|
||||
/* GL_NEVER */
|
||||
/* GL_LESS */
|
||||
/* GL_EQUAL */
|
||||
/* GL_LEQUAL */
|
||||
/* GL_GREATER */
|
||||
/* GL_NOTEQUAL */
|
||||
/* GL_GEQUAL */
|
||||
/* GL_ALWAYS */
|
||||
|
||||
/* EnableCap */
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_CULL_FACE 0x0B44
|
||||
#define GL_BLEND 0x0BE2
|
||||
#define GL_DITHER 0x0BD0
|
||||
#define GL_STENCIL_TEST 0x0B90
|
||||
#define GL_DEPTH_TEST 0x0B71
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
#define GL_POLYGON_OFFSET_FILL 0x8037
|
||||
#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
|
||||
#define GL_SAMPLE_COVERAGE 0x80A0
|
||||
|
||||
/* ErrorCode */
|
||||
#define GL_NO_ERROR 0
|
||||
#define GL_INVALID_ENUM 0x0500
|
||||
#define GL_INVALID_VALUE 0x0501
|
||||
#define GL_INVALID_OPERATION 0x0502
|
||||
#define GL_OUT_OF_MEMORY 0x0505
|
||||
|
||||
/* FrontFaceDirection */
|
||||
#define GL_CW 0x0900
|
||||
#define GL_CCW 0x0901
|
||||
|
||||
/* GetPName */
|
||||
#define GL_LINE_WIDTH 0x0B21
|
||||
#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
|
||||
#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
|
||||
#define GL_CULL_FACE_MODE 0x0B45
|
||||
#define GL_FRONT_FACE 0x0B46
|
||||
#define GL_DEPTH_RANGE 0x0B70
|
||||
#define GL_DEPTH_WRITEMASK 0x0B72
|
||||
#define GL_DEPTH_CLEAR_VALUE 0x0B73
|
||||
#define GL_DEPTH_FUNC 0x0B74
|
||||
#define GL_STENCIL_CLEAR_VALUE 0x0B91
|
||||
#define GL_STENCIL_FUNC 0x0B92
|
||||
#define GL_STENCIL_FAIL 0x0B94
|
||||
#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
|
||||
#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
|
||||
#define GL_STENCIL_REF 0x0B97
|
||||
#define GL_STENCIL_VALUE_MASK 0x0B93
|
||||
#define GL_STENCIL_WRITEMASK 0x0B98
|
||||
#define GL_STENCIL_BACK_FUNC 0x8800
|
||||
#define GL_STENCIL_BACK_FAIL 0x8801
|
||||
#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
|
||||
#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
|
||||
#define GL_STENCIL_BACK_REF 0x8CA3
|
||||
#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
|
||||
#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
|
||||
#define GL_VIEWPORT 0x0BA2
|
||||
#define GL_SCISSOR_BOX 0x0C10
|
||||
/* GL_SCISSOR_TEST */
|
||||
#define GL_COLOR_CLEAR_VALUE 0x0C22
|
||||
#define GL_COLOR_WRITEMASK 0x0C23
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
#define GL_PACK_ALIGNMENT 0x0D05
|
||||
#define GL_MAX_TEXTURE_SIZE 0x0D33
|
||||
#define GL_MAX_VIEWPORT_DIMS 0x0D3A
|
||||
#define GL_SUBPIXEL_BITS 0x0D50
|
||||
#define GL_RED_BITS 0x0D52
|
||||
#define GL_GREEN_BITS 0x0D53
|
||||
#define GL_BLUE_BITS 0x0D54
|
||||
#define GL_ALPHA_BITS 0x0D55
|
||||
#define GL_DEPTH_BITS 0x0D56
|
||||
#define GL_STENCIL_BITS 0x0D57
|
||||
#define GL_POLYGON_OFFSET_UNITS 0x2A00
|
||||
/* GL_POLYGON_OFFSET_FILL */
|
||||
#define GL_POLYGON_OFFSET_FACTOR 0x8038
|
||||
#define GL_TEXTURE_BINDING_2D 0x8069
|
||||
#define GL_SAMPLE_BUFFERS 0x80A8
|
||||
#define GL_SAMPLES 0x80A9
|
||||
#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
|
||||
#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
|
||||
|
||||
/* GetTextureParameter */
|
||||
/* GL_TEXTURE_MAG_FILTER */
|
||||
/* GL_TEXTURE_MIN_FILTER */
|
||||
/* GL_TEXTURE_WRAP_S */
|
||||
/* GL_TEXTURE_WRAP_T */
|
||||
|
||||
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
|
||||
#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
|
||||
|
||||
/* HintMode */
|
||||
#define GL_DONT_CARE 0x1100
|
||||
#define GL_FASTEST 0x1101
|
||||
#define GL_NICEST 0x1102
|
||||
|
||||
/* HintTarget */
|
||||
#define GL_GENERATE_MIPMAP_HINT 0x8192
|
||||
|
||||
/* DataType */
|
||||
#define GL_BYTE 0x1400
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_SHORT 0x1402
|
||||
#define GL_UNSIGNED_SHORT 0x1403
|
||||
#define GL_INT 0x1404
|
||||
#define GL_UNSIGNED_INT 0x1405
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_FIXED 0x140C
|
||||
|
||||
/* PixelFormat */
|
||||
#define GL_DEPTH_COMPONENT 0x1902
|
||||
#define GL_ALPHA 0x1906
|
||||
#define GL_RGB 0x1907
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_LUMINANCE 0x1909
|
||||
#define GL_LUMINANCE_ALPHA 0x190A
|
||||
|
||||
/* PixelType */
|
||||
/* GL_UNSIGNED_BYTE */
|
||||
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
|
||||
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
|
||||
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
|
||||
|
||||
/* Shaders */
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_MAX_VERTEX_ATTRIBS 0x8869
|
||||
#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
|
||||
#define GL_MAX_VARYING_VECTORS 0x8DFC
|
||||
#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
|
||||
#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
|
||||
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
|
||||
#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
|
||||
#define GL_SHADER_TYPE 0x8B4F
|
||||
#define GL_DELETE_STATUS 0x8B80
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#define GL_VALIDATE_STATUS 0x8B83
|
||||
#define GL_ATTACHED_SHADERS 0x8B85
|
||||
#define GL_ACTIVE_UNIFORMS 0x8B86
|
||||
#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
|
||||
#define GL_ACTIVE_ATTRIBUTES 0x8B89
|
||||
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
|
||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||
#define GL_CURRENT_PROGRAM 0x8B8D
|
||||
|
||||
/* StencilFunction */
|
||||
#define GL_NEVER 0x0200
|
||||
#define GL_LESS 0x0201
|
||||
#define GL_EQUAL 0x0202
|
||||
#define GL_LEQUAL 0x0203
|
||||
#define GL_GREATER 0x0204
|
||||
#define GL_NOTEQUAL 0x0205
|
||||
#define GL_GEQUAL 0x0206
|
||||
#define GL_ALWAYS 0x0207
|
||||
|
||||
/* StencilOp */
|
||||
/* GL_ZERO */
|
||||
#define GL_KEEP 0x1E00
|
||||
#define GL_REPLACE 0x1E01
|
||||
#define GL_INCR 0x1E02
|
||||
#define GL_DECR 0x1E03
|
||||
#define GL_INVERT 0x150A
|
||||
#define GL_INCR_WRAP 0x8507
|
||||
#define GL_DECR_WRAP 0x8508
|
||||
|
||||
/* StringName */
|
||||
#define GL_VENDOR 0x1F00
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
|
||||
/* TextureMagFilter */
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
|
||||
/* TextureMinFilter */
|
||||
/* GL_NEAREST */
|
||||
/* GL_LINEAR */
|
||||
#define GL_NEAREST_MIPMAP_NEAREST 0x2700
|
||||
#define GL_LINEAR_MIPMAP_NEAREST 0x2701
|
||||
#define GL_NEAREST_MIPMAP_LINEAR 0x2702
|
||||
#define GL_LINEAR_MIPMAP_LINEAR 0x2703
|
||||
|
||||
/* TextureParameterName */
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
|
||||
/* TextureTarget */
|
||||
/* GL_TEXTURE_2D */
|
||||
#define GL_TEXTURE 0x1702
|
||||
|
||||
#define GL_TEXTURE_CUBE_MAP 0x8513
|
||||
#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
|
||||
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
|
||||
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
|
||||
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
|
||||
#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
|
||||
|
||||
/* TextureUnit */
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_TEXTURE1 0x84C1
|
||||
#define GL_TEXTURE2 0x84C2
|
||||
#define GL_TEXTURE3 0x84C3
|
||||
#define GL_TEXTURE4 0x84C4
|
||||
#define GL_TEXTURE5 0x84C5
|
||||
#define GL_TEXTURE6 0x84C6
|
||||
#define GL_TEXTURE7 0x84C7
|
||||
#define GL_TEXTURE8 0x84C8
|
||||
#define GL_TEXTURE9 0x84C9
|
||||
#define GL_TEXTURE10 0x84CA
|
||||
#define GL_TEXTURE11 0x84CB
|
||||
#define GL_TEXTURE12 0x84CC
|
||||
#define GL_TEXTURE13 0x84CD
|
||||
#define GL_TEXTURE14 0x84CE
|
||||
#define GL_TEXTURE15 0x84CF
|
||||
#define GL_TEXTURE16 0x84D0
|
||||
#define GL_TEXTURE17 0x84D1
|
||||
#define GL_TEXTURE18 0x84D2
|
||||
#define GL_TEXTURE19 0x84D3
|
||||
#define GL_TEXTURE20 0x84D4
|
||||
#define GL_TEXTURE21 0x84D5
|
||||
#define GL_TEXTURE22 0x84D6
|
||||
#define GL_TEXTURE23 0x84D7
|
||||
#define GL_TEXTURE24 0x84D8
|
||||
#define GL_TEXTURE25 0x84D9
|
||||
#define GL_TEXTURE26 0x84DA
|
||||
#define GL_TEXTURE27 0x84DB
|
||||
#define GL_TEXTURE28 0x84DC
|
||||
#define GL_TEXTURE29 0x84DD
|
||||
#define GL_TEXTURE30 0x84DE
|
||||
#define GL_TEXTURE31 0x84DF
|
||||
#define GL_ACTIVE_TEXTURE 0x84E0
|
||||
|
||||
/* TextureWrapMode */
|
||||
#define GL_REPEAT 0x2901
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#define GL_MIRRORED_REPEAT 0x8370
|
||||
|
||||
/* Uniform Types */
|
||||
#define GL_FLOAT_VEC2 0x8B50
|
||||
#define GL_FLOAT_VEC3 0x8B51
|
||||
#define GL_FLOAT_VEC4 0x8B52
|
||||
#define GL_INT_VEC2 0x8B53
|
||||
#define GL_INT_VEC3 0x8B54
|
||||
#define GL_INT_VEC4 0x8B55
|
||||
#define GL_BOOL 0x8B56
|
||||
#define GL_BOOL_VEC2 0x8B57
|
||||
#define GL_BOOL_VEC3 0x8B58
|
||||
#define GL_BOOL_VEC4 0x8B59
|
||||
#define GL_FLOAT_MAT2 0x8B5A
|
||||
#define GL_FLOAT_MAT3 0x8B5B
|
||||
#define GL_FLOAT_MAT4 0x8B5C
|
||||
#define GL_SAMPLER_2D 0x8B5E
|
||||
#define GL_SAMPLER_CUBE 0x8B60
|
||||
|
||||
/* Vertex Arrays */
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
|
||||
|
||||
/* Read Format */
|
||||
#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
|
||||
#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
|
||||
|
||||
/* Shader Source */
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||
#define GL_SHADER_SOURCE_LENGTH 0x8B88
|
||||
#define GL_SHADER_COMPILER 0x8DFA
|
||||
|
||||
/* Shader Binary */
|
||||
#define GL_SHADER_BINARY_FORMATS 0x8DF8
|
||||
#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
|
||||
|
||||
/* Shader Precision-Specified Types */
|
||||
#define GL_LOW_FLOAT 0x8DF0
|
||||
#define GL_MEDIUM_FLOAT 0x8DF1
|
||||
#define GL_HIGH_FLOAT 0x8DF2
|
||||
#define GL_LOW_INT 0x8DF3
|
||||
#define GL_MEDIUM_INT 0x8DF4
|
||||
#define GL_HIGH_INT 0x8DF5
|
||||
|
||||
/* Framebuffer Object. */
|
||||
#define GL_FRAMEBUFFER 0x8D40
|
||||
#define GL_RENDERBUFFER 0x8D41
|
||||
|
||||
#define GL_RGBA4 0x8056
|
||||
#define GL_RGB5_A1 0x8057
|
||||
#define GL_RGB565 0x8D62
|
||||
#define GL_DEPTH_COMPONENT16 0x81A5
|
||||
#define GL_STENCIL_INDEX 0x1901
|
||||
#define GL_STENCIL_INDEX8 0x8D48
|
||||
|
||||
#define GL_RENDERBUFFER_WIDTH 0x8D42
|
||||
#define GL_RENDERBUFFER_HEIGHT 0x8D43
|
||||
#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
|
||||
#define GL_RENDERBUFFER_RED_SIZE 0x8D50
|
||||
#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
|
||||
#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
|
||||
#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
|
||||
#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
|
||||
#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
|
||||
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
|
||||
|
||||
#define GL_COLOR_ATTACHMENT0 0x8CE0
|
||||
#define GL_DEPTH_ATTACHMENT 0x8D00
|
||||
#define GL_STENCIL_ATTACHMENT 0x8D20
|
||||
|
||||
#define GL_NONE 0
|
||||
|
||||
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
|
||||
#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
|
||||
|
||||
#define GL_FRAMEBUFFER_BINDING 0x8CA6
|
||||
#define GL_RENDERBUFFER_BINDING 0x8CA7
|
||||
#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
|
||||
|
||||
#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* GL core functions.
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
|
||||
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
|
||||
GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode );
|
||||
GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
|
||||
GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
|
||||
GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
|
||||
GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
|
||||
GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth);
|
||||
GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
|
||||
GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
|
||||
GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
|
||||
GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
|
||||
GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
|
||||
GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
|
||||
GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
|
||||
GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
|
||||
GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
|
||||
GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glFinish (void);
|
||||
GL_APICALL void GL_APIENTRY glFlush (void);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
|
||||
GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
|
||||
GL_APICALL int GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
|
||||
GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
|
||||
GL_APICALL GLenum GL_APIENTRY glGetError (void);
|
||||
GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
|
||||
GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
|
||||
GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
|
||||
GL_APICALL int GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
|
||||
GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
|
||||
GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
|
||||
GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
|
||||
GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
|
||||
GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
|
||||
GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
|
||||
GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
|
||||
GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
|
||||
GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
|
||||
GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
|
||||
GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x);
|
||||
GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x);
|
||||
GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
|
||||
GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
|
||||
GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
|
||||
GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
|
||||
GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
|
||||
GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
|
||||
GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __gl2_h_ */
|
|
@ -0,0 +1,125 @@
|
|||
'''
|
||||
Common GLES Subset Extraction Script
|
||||
====================================
|
||||
|
||||
In Kivy, our goal is to use OpenGL ES 2.0 (GLES2) for all drawing on all
|
||||
platforms. The problem is that GLES2 is not a proper subset of any OpenGL
|
||||
Desktop (GL) version prior to version 4.1.
|
||||
However, to keep all our drawing cross-platform compatible, we're
|
||||
restricting the Kivy drawing core to a real subset of GLES2 that is
|
||||
available on all platforms.
|
||||
|
||||
This script therefore parses the GL and GL Extension (GLEXT) headers and
|
||||
compares them with the GLES2 header. It then generates a header that only
|
||||
contains symbols that are common to GLES2 and at least either GL or GLEXT.
|
||||
However, since GLES2 doesn't support double values, we also need to do some
|
||||
renaming, because functions in GL that took doubles as arguments now take
|
||||
floats in GLES2, with their function name being suffixed with 'f'.
|
||||
|
||||
Furthermore, sometimes the pure symbol name doesn't match because there
|
||||
might be an _EXT or _ARB or something akin to that at the end of a symbol
|
||||
name. In that case, we take the symbol from the original header and add
|
||||
a #define directive to redirect to that symbol from the symbol name without
|
||||
extension.
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
gl = open("/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/" +
|
||||
"OpenGL.framework/Versions/A/Headers/gl.h", 'r')
|
||||
glext = open("/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/" +
|
||||
"OpenGL.framework/Versions/A/Headers/glext.h", 'r')
|
||||
gles = open("gl2.h", 'r')
|
||||
|
||||
|
||||
def add_defines_to_set(header):
|
||||
symbols = []
|
||||
lineno = 0
|
||||
for line in header:
|
||||
symbol = None
|
||||
hexcode = None
|
||||
lineno += 1
|
||||
line = line.strip()
|
||||
try:
|
||||
elements = line.split()
|
||||
if line.startswith("#define"):
|
||||
symbol = elements[1]
|
||||
for element in elements:
|
||||
if element.startswith("0x"):
|
||||
hexcode = element
|
||||
elif line.startswith("typedef"):
|
||||
symbol = elements[-1]
|
||||
else:
|
||||
for element in elements:
|
||||
if element.startswith("gl"):
|
||||
symbol = element
|
||||
if symbol:
|
||||
symbols.append((symbol, lineno, line, hexcode))
|
||||
except Exception as e:
|
||||
print('error:', lineno, ':', line)
|
||||
print(e)
|
||||
|
||||
return symbols
|
||||
|
||||
|
||||
def extract_common_symbols(symbols1, symbols2, already_extracted):
|
||||
for symbol1, lineno1, line1, hexcode1 in symbols1:
|
||||
for symbol2, lineno2, line2, hexcode2 in symbols2:
|
||||
if symbol1 in already_extracted or symbol2 in already_extracted:
|
||||
continue
|
||||
if symbol1 == symbol2 + 'f':
|
||||
# There is no `double` type in GLES; Functions that were using
|
||||
# a double were renamed with the suffix 'f'.
|
||||
print("// Different Name; Redefine")
|
||||
print(line2)
|
||||
print("#define %s %s" % (symbol1, symbol2))
|
||||
elif symbol1 == symbol2:
|
||||
already_extracted.append(symbol1)
|
||||
print(line1)
|
||||
if symbol1 == 'GLclampf;':
|
||||
# See explanation about doubles on GLES above.
|
||||
print('typedef GLclampf GLclampd;')
|
||||
elif hexcode1 and hexcode2 and hexcode1 == hexcode2:
|
||||
already_extracted.append(symbol1)
|
||||
already_extracted.append(symbol2)
|
||||
print("// Different Name; Redefine")
|
||||
print(line2)
|
||||
print("#define %s %s" % (symbol1, symbol2))
|
||||
|
||||
|
||||
# Generate ------------------------------------------------
|
||||
# pipe to kivy/kivy/graphics/common_subset.h
|
||||
|
||||
gl_symbols = add_defines_to_set(gl)
|
||||
glext_symbols = add_defines_to_set(glext)
|
||||
gles_symbols = add_defines_to_set(gles)
|
||||
|
||||
print('// GLES 2.0 Header file, generated for Kivy')
|
||||
print('// Check kivy/kivy/tools/gles_compat/subset_gles.py')
|
||||
print('#pragma once')
|
||||
print('#include "gl2platform.h"')
|
||||
print('#ifdef __cplusplus')
|
||||
print('extern "C" {')
|
||||
print('#endif')
|
||||
|
||||
# Don't add the same symbol more than once
|
||||
already_extracted = []
|
||||
|
||||
print('\n// Subset common to GLES and GL: ===================================')
|
||||
extract_common_symbols(gles_symbols, gl_symbols, already_extracted)
|
||||
|
||||
print('\n// Subset common to GLES and GLEXT: ================================')
|
||||
extract_common_symbols(gles_symbols, glext_symbols, already_extracted)
|
||||
|
||||
print()
|
||||
print('// What follows was manually extracted from the GLES2 headers because')
|
||||
print('// it was not present in any other header.', end=' ')
|
||||
print('''
|
||||
#define GL_SHADER_BINARY_FORMATS 0x8DF8
|
||||
#define GL_RGB565 0x8D62
|
||||
''')
|
||||
|
||||
print('#ifdef __cplusplus')
|
||||
print('}')
|
||||
print('#endif')
|
||||
print('\n')
|
|
@ -0,0 +1,9 @@
|
|||
'''
|
||||
Syntax Highlighting
|
||||
===================
|
||||
|
||||
This module contains various files for providing Kivy syntax highlighting in
|
||||
some popular text editors. Please see the contents of this folder for the
|
||||
provided resources.
|
||||
|
||||
'''
|
|
@ -0,0 +1,293 @@
|
|||
;;; kivy-mode.el --- Emacs major mode for editing Kivy files
|
||||
;;
|
||||
;; Author: Dean Serenevy <dean@serenevy.net>
|
||||
;; Version: 0.1.0
|
||||
;;
|
||||
;; This document borrowed heavily from yaml-mode.el by Yoshiki Kurihara and
|
||||
;; Marshall Vandegrift.
|
||||
;;
|
||||
;; This file is not part of Emacs
|
||||
|
||||
|
||||
;; This file is free software; you can redistribute it and/or modify it
|
||||
;; under the terms of the GNU General Public License as published by the
|
||||
;; Free Software Foundation; version 3.
|
||||
|
||||
;; This file is distributed in the hope that it will be useful, but WITHOUT
|
||||
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
;; more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License along
|
||||
;; with GNU Emacs; see the file COPYING. If not, write to the Free Software
|
||||
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
;; USA.
|
||||
|
||||
;;; Installation:
|
||||
|
||||
;; To install, just drop this file into a directory in your `load-path' and
|
||||
;; (optionally) byte-compile it. To automatically handle files ending in
|
||||
;; '.kv', add something like:
|
||||
;;
|
||||
;; (require 'kivy-mode)
|
||||
;; (add-to-list 'auto-mode-alist '("\\.kv$" . kivy-mode))
|
||||
;;
|
||||
;; to your .emacs file.
|
||||
;;
|
||||
;; This mode does not enable electric-indent by default. To get this
|
||||
;; behavior, either enable electric-indent-mode globally or enable it only
|
||||
;; for kivy buffers using `kivy-mode-hook':
|
||||
;;
|
||||
;; (add-hook 'kivy-mode-hook
|
||||
;; '(lambda ()
|
||||
;; (electric-indent-local-mode t)))
|
||||
|
||||
|
||||
;; User definable variables
|
||||
|
||||
(defgroup kivy nil
|
||||
"Support for the kivy user interface definition format"
|
||||
:group 'languages
|
||||
:prefix "kivy-")
|
||||
|
||||
(defcustom kivy-mode-hook nil
|
||||
"*Hook run by `kivy-mode'."
|
||||
:type 'hook
|
||||
:group 'kivy)
|
||||
|
||||
(defcustom kivy-indent-offset 4
|
||||
"*Amount of offset per level of indentation."
|
||||
:type 'integer
|
||||
:group 'kivy)
|
||||
|
||||
(defcustom kivy-backspace-function 'backward-delete-char-untabify
|
||||
"*Function called by `kivy-electric-backspace' when deleting backwards."
|
||||
:type 'function
|
||||
:group 'kivy)
|
||||
|
||||
(defface kivy-tab-face
|
||||
'((((class color)) (:background "red" :foreground "red" :bold t))
|
||||
(t (:reverse-video t)))
|
||||
"Face to use for highlighting tabs in kivy files."
|
||||
:group 'faces
|
||||
:group 'kivy)
|
||||
|
||||
(defcustom kivy-imenu-generic-expression
|
||||
'((nil "^\\([<>a-zA-Z_-]+\\):" 1))
|
||||
"The imenu regex to parse an outline of the kivy file."
|
||||
:type 'string
|
||||
:group 'kivy)
|
||||
|
||||
|
||||
;; Constants
|
||||
|
||||
(defconst kivy-mode-version "0.1.0" "Version of `kivy-mode.'")
|
||||
|
||||
(defconst kivy-blank-line-re "^ *$"
|
||||
"Regexp matching a line containing only (valid) whitespace.")
|
||||
|
||||
(defconst kivy-comment-re "\\(?:^\\|\\s-+\\)\\(#.*\\)"
|
||||
"Regexp matching a line containing a kivy comment or delimiter.")
|
||||
|
||||
(defconst kivy-directive-re "^\\(?:#:\\)\\(\\w+ +.*\\)"
|
||||
"Regexp matching a line containing a kivy directive.")
|
||||
|
||||
(defconst kivy-tag-re "^ *id: *\\([^ \n]+\\)$"
|
||||
"Rexexp matching a kivy tag.")
|
||||
|
||||
(defconst kivy-bare-scalar-re
|
||||
"\\(?:[^-:,#!\n{\\[ ]\\|[^#!\n{\\[ ]\\S-\\)[^#\n]*?"
|
||||
"Rexexp matching a kivy bare scalar.")
|
||||
|
||||
(defconst kivy-hash-key-re
|
||||
(concat "^ *"
|
||||
"\\(" kivy-bare-scalar-re "\\) *:"
|
||||
"\\(?: +\\|$\\)")
|
||||
"Regexp matching a single kivy hash key.")
|
||||
|
||||
(defconst kivy-nested-map-re
|
||||
(concat ".*: *$")
|
||||
"Regexp matching a line beginning a kivy nested structure.")
|
||||
|
||||
(defconst kivy-constant-scalars-re
|
||||
(concat "\\(?:^\\|\\(?::\\|-\\|,\\|{\\|\\[\\) +\\) *"
|
||||
(regexp-opt
|
||||
'("True" "False" "None") t)
|
||||
" *$")
|
||||
"Regexp matching certain scalar constants in scalar context")
|
||||
|
||||
|
||||
|
||||
;; Mode setup
|
||||
|
||||
(defvar kivy-mode-map ()
|
||||
"Keymap used in `kivy-mode' buffers.")
|
||||
(if kivy-mode-map
|
||||
nil
|
||||
(setq kivy-mode-map (make-sparse-keymap))
|
||||
(define-key kivy-mode-map [backspace] 'kivy-electric-backspace)
|
||||
(define-key kivy-mode-map "\C-c<" 'kivy-indent-shift-left)
|
||||
(define-key kivy-mode-map "\C-c>" 'kivy-indent-shift-right)
|
||||
)
|
||||
|
||||
(defvar kivy-mode-syntax-table nil
|
||||
"Syntax table in use in kivy-mode buffers.")
|
||||
(if kivy-mode-syntax-table
|
||||
nil
|
||||
(setq kivy-mode-syntax-table (make-syntax-table))
|
||||
(modify-syntax-entry ?\' "\"" kivy-mode-syntax-table)
|
||||
(modify-syntax-entry ?\" "\"" kivy-mode-syntax-table)
|
||||
(modify-syntax-entry ?# "<" kivy-mode-syntax-table)
|
||||
(modify-syntax-entry ?\n ">" kivy-mode-syntax-table)
|
||||
(modify-syntax-entry ?\\ "\\" kivy-mode-syntax-table)
|
||||
(modify-syntax-entry ?- "_" kivy-mode-syntax-table)
|
||||
(modify-syntax-entry ?_ "w" kivy-mode-syntax-table)
|
||||
(modify-syntax-entry ?< "." kivy-mode-syntax-table)
|
||||
(modify-syntax-entry ?> "." kivy-mode-syntax-table)
|
||||
(modify-syntax-entry ?_ "_" kivy-mode-syntax-table)
|
||||
)
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'auto-mode-alist '("\\.kv$" . kivy-mode))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode kivy-mode fundamental-mode "kivy"
|
||||
"Simple mode to edit kivy.
|
||||
|
||||
\\{kivy-mode-map}"
|
||||
(set (make-local-variable 'comment-start) "# ")
|
||||
(set (make-local-variable 'comment-start-skip) "#+ *")
|
||||
(set (make-local-variable 'indent-line-function) 'kivy-indent-line)
|
||||
(set (make-local-variable 'font-lock-defaults)
|
||||
'(kivy-font-lock-keywords
|
||||
nil nil nil nil
|
||||
(font-lock-syntactic-keywords))))
|
||||
|
||||
|
||||
;; Font-lock support
|
||||
|
||||
(defvar kivy-font-lock-keywords
|
||||
(list
|
||||
(cons kivy-comment-re '(1 font-lock-comment-face))
|
||||
(cons kivy-constant-scalars-re '(1 font-lock-constant-face))
|
||||
(cons kivy-tag-re '(1 font-lock-function-name-face))
|
||||
(cons kivy-hash-key-re '(1 font-lock-variable-name-face t))
|
||||
(cons kivy-directive-re '(1 font-lock-builtin-face))
|
||||
'("^[\t]+" 0 'kivy-tab-face t))
|
||||
"Additional expressions to highlight in kivy mode.")
|
||||
|
||||
(defvar kivy-font-lock-syntactic-keywords
|
||||
(list '())
|
||||
"Additional syntax features to highlight in kivy mode.")
|
||||
|
||||
|
||||
;; Indentation and electric keys
|
||||
|
||||
(defun kivy-compute-indentation ()
|
||||
"Calculate the maximum sensible indentation for the current line."
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(forward-line -1)
|
||||
(while (and (looking-at kivy-blank-line-re)
|
||||
(> (point) (point-min)))
|
||||
(forward-line -1))
|
||||
(+ (current-indentation)
|
||||
(if (looking-at kivy-nested-map-re) kivy-indent-offset 0)
|
||||
)))
|
||||
|
||||
(defun kivy-indent-line ()
|
||||
"Indent the current line.
|
||||
The first time this command is used, the line will be indented to the
|
||||
maximum sensible indentation. Each immediately subsequent usage will
|
||||
back-dent the line by `kivy-indent-offset' spaces. On reaching column
|
||||
0, it will cycle back to the maximum sensible indentation."
|
||||
(interactive "*")
|
||||
(let ((ci (current-indentation))
|
||||
(cc (current-column))
|
||||
(need (kivy-compute-indentation)))
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(delete-horizontal-space)
|
||||
(if (and (equal last-command this-command) (/= ci 0))
|
||||
(indent-to (* (/ (- ci 1) kivy-indent-offset) kivy-indent-offset))
|
||||
(indent-to need)))
|
||||
(if (< (current-column) (current-indentation))
|
||||
(forward-to-indentation 0))))
|
||||
|
||||
(defun kivy-electric-backspace (arg)
|
||||
"Delete characters or back-dent the current line.
|
||||
If invoked following only whitespace on a line, will back-dent to the
|
||||
immediately previous multiple of `kivy-indent-offset' spaces."
|
||||
(interactive "*p")
|
||||
(if (or (/= (current-indentation) (current-column)) (bolp))
|
||||
(funcall kivy-backspace-function arg)
|
||||
(let ((ci (current-column)))
|
||||
(beginning-of-line)
|
||||
(delete-horizontal-space)
|
||||
(indent-to (* (/ (- ci (* arg kivy-indent-offset))
|
||||
kivy-indent-offset)
|
||||
kivy-indent-offset)))))
|
||||
|
||||
|
||||
(defun kivy-set-imenu-generic-expression ()
|
||||
(make-local-variable 'imenu-generic-expression)
|
||||
(make-local-variable 'imenu-create-index-function)
|
||||
(setq imenu-create-index-function 'imenu-default-create-index-function)
|
||||
(setq imenu-generic-expression kivy-imenu-generic-expression))
|
||||
|
||||
(add-hook 'kivy-mode-hook 'kivy-set-imenu-generic-expression)
|
||||
(add-hook 'kivy-mode-hook
|
||||
'(lambda ()
|
||||
(setq indent-tabs-mode 'nil)))
|
||||
|
||||
|
||||
(defun kivy-mode-version ()
|
||||
"Display version of `kivy-mode'."
|
||||
(interactive)
|
||||
(message "kivy-mode %s" kivy-mode-version)
|
||||
kivy-mode-version)
|
||||
|
||||
(defun kivy-indent-shift-left (start end &optional count)
|
||||
"Shift lines contained in region START END by COUNT columns to the left.
|
||||
COUNT defaults to `kivy-indent-offset'. If region isn't
|
||||
active, the current line is shifted. The shifted region includes
|
||||
the lines in which START and END lie. An error is signaled if
|
||||
any lines in the region are indented less than COUNT columns."
|
||||
(interactive
|
||||
(if mark-active
|
||||
(list (region-beginning) (region-end) current-prefix-arg)
|
||||
(list (line-beginning-position) (line-end-position) current-prefix-arg)))
|
||||
(if count
|
||||
(setq count (prefix-numeric-value count))
|
||||
(setq count kivy-indent-offset))
|
||||
(when (> count 0)
|
||||
(let ((deactivate-mark nil))
|
||||
(save-excursion
|
||||
(goto-char start)
|
||||
(while (< (point) end)
|
||||
(if (and (< (current-indentation) count)
|
||||
(not (looking-at "[ \t]*$")))
|
||||
(error "Can't shift all lines enough"))
|
||||
(forward-line))
|
||||
(indent-rigidly start end (- count))))))
|
||||
|
||||
(defun kivy-indent-shift-right (start end &optional count)
|
||||
"Shift lines contained in region START END by COUNT columns to the left.
|
||||
COUNT defaults to `kivy-indent-offset'. If region isn't
|
||||
active, the current line is shifted. The shifted region includes
|
||||
the lines in which START and END lie."
|
||||
(interactive
|
||||
(if mark-active
|
||||
(list (region-beginning) (region-end) current-prefix-arg)
|
||||
(list (line-beginning-position) (line-end-position) current-prefix-arg)))
|
||||
(let ((deactivate-mark nil))
|
||||
(if count
|
||||
(setq count (prefix-numeric-value count))
|
||||
(setq count kivy-indent-offset))
|
||||
(indent-rigidly start end count)))
|
||||
|
||||
(provide 'kivy-mode)
|
||||
|
||||
;;; kivy-mode.el ends here
|
|
@ -0,0 +1,20 @@
|
|||
{ "name": "Kivy Language",
|
||||
"scopeName": "source.python.kivy",
|
||||
"fileTypes": ["kv"],
|
||||
"patterns": [
|
||||
{ "match": "#:.*?$",
|
||||
"name": "support.type.kivy" },
|
||||
{ "match": "#.*?$",
|
||||
"name": "comment.kivy" },
|
||||
{ "match": "\\<.+\\>",
|
||||
"name": "support.class.kivy" },
|
||||
{ "match": "[A-Za-z][A-Za-z0-9]+$",
|
||||
"name": "support.function.kivy" },
|
||||
{ "match": ".*?:$",
|
||||
"name": "support.function.kivy" },
|
||||
{ "name": "entity.name.section.kivy",
|
||||
"match": "(.*?):$" },
|
||||
{ "include": "source.python" }
|
||||
],
|
||||
"uuid": "49cecc44-5094-48ec-a876-91f597e8bf81"
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>fileTypes</key>
|
||||
<array>
|
||||
<string>kv</string>
|
||||
</array>
|
||||
<key>name</key>
|
||||
<string>Kivy Language</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>#:.*?$</string>
|
||||
<key>name</key>
|
||||
<string>support.type.kivy</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>#.*?$</string>
|
||||
<key>name</key>
|
||||
<string>comment.kivy</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\<.+\></string>
|
||||
<key>name</key>
|
||||
<string>support.class.kivy</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>[A-Za-z][A-Za-z0-9]+$</string>
|
||||
<key>name</key>
|
||||
<string>support.function.kivy</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>.*?:$</string>
|
||||
<key>name</key>
|
||||
<string>support.function.kivy</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(.*?):$</string>
|
||||
<key>name</key>
|
||||
<string>entity.name.section.kivy</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>source.python</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>scopeName</key>
|
||||
<string>source.python.kivy</string>
|
||||
<key>uuid</key>
|
||||
<string>49cecc44-5094-48ec-a876-91f597e8bf81</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,47 @@
|
|||
" ~/.vim/after/syntax/kivy.vim
|
||||
"
|
||||
" Vim syntax file
|
||||
" Language: Kivy
|
||||
" Maintainer: Gabriel Pettier <gabriel.pettier@gmail.com>
|
||||
" Last Change: 2020 June 23
|
||||
|
||||
syntax clear
|
||||
|
||||
syn include @pyth $VIMRUNTIME/syntax/python.vim
|
||||
|
||||
syn match kivyComment /#.*\n/ display contains=pythonTodo,Spell
|
||||
syn match kivyPreProc /^\s*#:.*/
|
||||
syn match kivyRule /<-*\I\i*\%([,@+]\I\i*\)*>:/
|
||||
syn match kivyRule /\[-*\I\i*\%([,@+]\I\i*\)*]:/
|
||||
syn match kivyRootRule /^\I\i*:\s*$/
|
||||
|
||||
syn region kivyAttrBlock matchgroup=kivyAttribute start=/^\z(\s\+\)\I\i*\s*:\s*$/ skip="^\s*$" end="^\%(\z1\s\{4}\)\@!" contains=@pyth
|
||||
syn region kivyAttrBlock matchgroup=kivyAttribute start=/^\s\+\I\i*\s*:\%(\s*\S\)\@=/ end="$" keepend oneline contains=@pyth
|
||||
|
||||
syn region kivyId matchgroup=kivyAttribute start=/^\s\+id\s*:\s*/ end="\w\+\zs" oneline
|
||||
|
||||
syn region kivyBindBlock matchgroup=kivyBind start=/^\z(\s\+\)on_\I\i*\s*:\s*$/ skip="^\s*$" end="^\%(\z1\s\{4}\)\@!" contains=@pyth
|
||||
syn region kivyBindBlock matchgroup=kivyBind start=/^\s\+on_\i\+\s*:\%(\s*\S\)\@=/ end="$" keepend oneline contains=@pyth
|
||||
|
||||
syn region kivyCanvasValue matchgroup=kivyCanvas start=/^\z(\s\+\)\I\i*\s*:\s*$/ skip="^\s*$" end="^\%(\z1\s\{4}\)\@!" contains=@pyth contained
|
||||
syn region kivyCanvasValue matchgroup=kivyCanvas start=/^\s\+\I\i*\s*:\%(\s*\S\)\@=/ end="$" keepend oneline contains=@pyth contained
|
||||
syn region kivyCanvas matchgroup=kivyCanvas start=/^\z(\s\+\)canvas.*:\s*$/ skip="^\s*$" end="^\%(\z1\s\{4}\)\@!"
|
||||
\ contains=kivyInstruction,kivyPreProc,kivyComment,kivyCanvasValue
|
||||
|
||||
syn match kivyInstruction /^\s\+\u\i*\s*:/ contained
|
||||
syn match kivyWidget /^\s\+\u\i*\s*:/
|
||||
|
||||
hi def link kivyPreproc PreProc
|
||||
hi def link kivyComment Comment
|
||||
hi def link kivyRule Type
|
||||
hi def link kivyRootRule Function
|
||||
hi def link kivyAttribute Label
|
||||
hi def link kivyBind Function
|
||||
hi def link kivyWidget Function
|
||||
hi def link kivyCanvas special
|
||||
hi def link kivyInstruction Statement
|
||||
|
||||
hi KivyId cterm=underline
|
||||
hi KivyPreproc cterm=bold
|
||||
|
||||
let b:current_syntax = "kivy"
|
|
@ -0,0 +1,148 @@
|
|||
Generating the image test suite
|
||||
-------------------------------
|
||||
|
||||
On Linux/unix systems, you can use the `imagemagick-testsuite.sh` script
|
||||
to create an image test suite using the `convert` command line utility. You
|
||||
must have ImageMagick installed ("apt install imagemagick" on debian
|
||||
derivatives). There is also a rule in the Makefile, `make image-testsuite`.
|
||||
|
||||
A more comprehensive test suite can be generated using Gimp (tested on
|
||||
version 2.8.18). To install the plugin, copy `gimp28-testsuite.py` to your
|
||||
gimp plugins directory, on linux/unix systems usually `~/.gimp-2.8/plug-ins`.
|
||||
You can find the plugin location via the Gimp menu `Edit` - `Preferences` -
|
||||
`Folders` - `Plug-Ins`. Once installed, the plugin should appear in "Tools"
|
||||
menu, named "Kivy image testsuite".
|
||||
|
||||
Test images must be saved in the `kivy/tests/image-testsuite` directory,
|
||||
after this you can run the test. It is (currently) preferable to run it
|
||||
directly as a script, instead of via `make test`, since the latter won't
|
||||
give you useful debug output.
|
||||
|
||||
cd kivy/tests
|
||||
python test_imageloader.py | less
|
||||
|
||||
or to get only the summary report:
|
||||
|
||||
python test_imageloader.py | grep REPORT | less
|
||||
|
||||
|
||||
Kivy ImageLoader testsuite
|
||||
--------------------------
|
||||
|
||||
These tools generate a wide range of images for testing Kivy's ImageLoaders.
|
||||
The pixel data is encoded in the file name, and reproduced "from the sideline"
|
||||
in order to verify the pixel data loaded from file. This is used to expose
|
||||
issues in the Kivy core and underlying provider libraries.
|
||||
|
||||
The filenames consist of sections separated by an underscore `_`:
|
||||
|
||||
v0_ <W> x <H> _ <pat> _ <alpha> _ <fmt> _ <testname> _ <encoder> . <ext>
|
||||
|
||||
Variables are enclosed in pointy brackets. The leading `v0_` indicates that
|
||||
it conforms to version 0 of the test protocol (described in this document)
|
||||
and must be present.
|
||||
|
||||
v0_5x1_rgb_FF_PNG24_OPAQUE_magick.png
|
||||
|
||||
This is a 5x1 image, pattern is "rgb", alpha is "FF". `PNG24` is the internal
|
||||
file format name (ImageMagick-specific), and `OPAQUE` is the test we are
|
||||
performing (drawing opaque pixels only), see test names below.
|
||||
|
||||
* <pattern> indicates the pixel colors (in order), as they are drawn in the
|
||||
image file.
|
||||
|
||||
* <alpha> is the global alpha from 00-FF (2 bytes, ascii) which is applied to
|
||||
all pixels except 't' (transparent) which have fixed alpha at 00
|
||||
|
||||
* <fmt> (aka fmtinfo) is an encoder-specific string with information about the
|
||||
format or process that generated the file. For example, if the same image
|
||||
is saved with and without interlacing, it will contain "I1" and "I0" to
|
||||
distinguish the files.
|
||||
* ImageMagick test suite generator uses magick format name, such as `PNG24`
|
||||
* The Gimp generator plugin adds information about the layer that was
|
||||
exported to form the image:
|
||||
* BPP1G = 1 byte per pixel, gray
|
||||
* BPP2GA = 2 bytes per pixel, gray + alpha
|
||||
* BPP3 = 3 bytes per pixel, rgb
|
||||
* BPP4 = 4 bytes per pixel, rgba
|
||||
* IX = indexed, IXA = indexed+alpha
|
||||
* Note: Indexed images are drawn in RGB or GRAY images (with alpha if
|
||||
needed), and converted to indexed before export. These values
|
||||
represent the layer type at time of export, it affects the parameters
|
||||
used for encoding the output data.
|
||||
|
||||
* <testname> is a special string that indicates what type of data is expected
|
||||
in the file. Options are OPAQUE, BINARY, ALPHA and repeated for grayscale,
|
||||
GRAY-OPAQUE, GRAY-BINARY, GRAY-ALPHA. We expect BINARY and ALPHA tests to
|
||||
result in an alpha channel (details below)
|
||||
|
||||
* <encoder> identifies the software that created the file, "magick", "gimp" ..
|
||||
|
||||
* <ext> is the extension, must be lowercase and match the extensions
|
||||
supported by Kivy image loaders (or they will be ignored)
|
||||
|
||||
|
||||
Test names
|
||||
----------
|
||||
|
||||
* `OPAQUE` tests opaque pixels (normal RGB) (lossless formats)
|
||||
* `BINARY` tests opaque + fully transparent pixels (GIF etc)
|
||||
* `ALPHA` tests semi-transparent pixels (normal RGBA) (PNG32 etc)
|
||||
* `GRAY-OPAQUE` tests opaque grayscale only (various PNG, tga, )
|
||||
* `GRAY-BINARY` tests opaque grayscale + fully transparent pixels (PNGs)
|
||||
* `GRAY-ALPHA` tests semi-transparent grayscale pixels (TGA, XCF)
|
||||
|
||||
Patterns must conform to the specific test. For example, the pattern "rgb" has
|
||||
undefined behavior for a grayscale test, since r/g/b can't be represented
|
||||
in grayscale. So all grayscale formats must use 0-9A-F only, and optionally
|
||||
't' for transparent pixels in GRAY-BINARY/GRAY-ALPHA.
|
||||
|
||||
|
||||
| Test name | Valid pattern characters |
|
||||
| -----------: | :---------------------------------------------------------- |
|
||||
| OPAQUE | `wxrgbcyp`, and full grayscale\*\* |
|
||||
| GRAY-OPAQUE | `0123456789ABCDEF` (full grayscale) |
|
||||
| BINARY | `t` REQUIRED + `wrgbcyp`, limited grayscale (no 0/x!!!) |
|
||||
| GRAY-BINARY | `t` REQUIRED + limited grayscale (no 0/x!!!) |
|
||||
| ALPHA | `t`, `wxrbgcyp` and full grayscale\*\* |
|
||||
| GRAY-ALPHA | `t`, `0123456789ABCDEF` (full grayscale) |
|
||||
|
||||
* `**`: While grayscale is supported here, it is generally better to use
|
||||
colors, since all the bytes in a grayscale pixel represented as rgb are
|
||||
identical. For example, 'A' or \xAA\xAA\xAA will pass despite a byte
|
||||
order problem.
|
||||
|
||||
* `!!!`: In some cases, black color is used for binary transparency. So
|
||||
if you use "0" (or "x"), test_imageloader will expect #000000FF in RGBA,
|
||||
but the pixel becomes transparent (a=00) and test fails. All BINARY tests
|
||||
**MUST** include at least one "t" pixel to ensure that the image is
|
||||
saved with an alpha channel.
|
||||
|
||||
|
||||
Pixel values
|
||||
------------
|
||||
|
||||
Each character in the pattern represents the color of a single pixel. It is
|
||||
important that you include only the correct type of pixel values for the
|
||||
different test types (see table above). Individual pixel values get their
|
||||
alpha from global setting (<alpha> in filename), but 't' pixels always have
|
||||
alpha = 0x00 regardless of the test's alpha setting.
|
||||
|
||||
|
||||
OPAQUE, BINARY, ALPHA (lowercase)
|
||||
-----------------------------------------
|
||||
"w" White (#fff) "x" Black (#000)!!!
|
||||
"r" Red (#f00) "g" Green (#0f0)
|
||||
"b" Blue (#00f) "y" Yellow (#ff0)
|
||||
"c" Cyan (#0ff) "p" Purple (#f0f)
|
||||
|
||||
|
||||
GRAY-OPAQUE, GRAY-BINARY, GRAY-ALPHA (uppercase)
|
||||
------------------------------------------------
|
||||
"0" #000!!! "1" #111 "2" #222 "3" #333
|
||||
"4" #444 "5" #555 "6" #666 "7" #777
|
||||
"8" #888 "9" #999 "A" #AAA "B" #BBB
|
||||
"C" #CCC "D" #DDD "E" #EEE "F" #FFF
|
||||
|
||||
!!! See warnings above regarding BINARY tests
|
||||
|
|
@ -0,0 +1,329 @@
|
|||
#!/usr/bin/env python
|
||||
# flake8: noqa
|
||||
import os
|
||||
import re
|
||||
import random
|
||||
from gimpfu import *
|
||||
|
||||
# Test suite configuration - key is test name, values are:
|
||||
#
|
||||
# alpha....: global alpha, used for all pixels except 't'
|
||||
# patterns.: allowed v0 pattern characters (+ force include and exclude)
|
||||
# *_IMAGE..: gimp layer types to export for this test, w/target extensions
|
||||
TESTSUITE_CONFIG = {
|
||||
'OPAQUE': {
|
||||
'alpha': [255],
|
||||
'patterns': ('wxrgbcyp', None, None),
|
||||
RGB_IMAGE: ['xcf', 'png', 'tga', 'tiff', 'ppm',
|
||||
'sgi', 'pcx', 'fits', 'ras'],
|
||||
INDEXED_IMAGE: ['xcf', 'png', 'tga', 'tiff', 'ppm', 'gif', 'ras'],
|
||||
},
|
||||
|
||||
'GRAY-OPAQUE': {
|
||||
'alpha': [255],
|
||||
'patterns': ('0123456789ABCDEF', None, None),
|
||||
GRAY_IMAGE: ['xcf', 'png', 'tga', 'tiff',
|
||||
'pgm', 'sgi', 'fits', 'ras'],
|
||||
INDEXED_IMAGE: ['xcf', 'png', 'tga', 'tiff', 'pgm', 'fits', 'ras'],
|
||||
},
|
||||
|
||||
'BINARY': {
|
||||
'alpha': [255],
|
||||
'patterns': ('twrgbcyp', 't', None),
|
||||
RGBA_IMAGE: ['xcf', 'png', 'tga', 'ico', 'sgi'],
|
||||
INDEXEDA_IMAGE: ['xcf', 'png', 'tga', 'gif'],
|
||||
},
|
||||
'GRAY-BINARY': {
|
||||
'alpha': [255],
|
||||
'patterns': ('t123456789ABCDEF', 't', None),
|
||||
GRAYA_IMAGE: ['xcf', 'tga', 'png', 'sgi'],
|
||||
INDEXEDA_IMAGE: ['xcf', 'tga', 'png'],
|
||||
},
|
||||
|
||||
"ALPHA": {
|
||||
'alpha': [0x7F, 0xF0],
|
||||
'patterns': ('twxrgbcyp', None, None),
|
||||
RGBA_IMAGE: ['xcf', 'png', 'tga', 'sgi'],
|
||||
},
|
||||
'GRAY-ALPHA': {
|
||||
'alpha': [0x7F, 0xF0],
|
||||
'patterns': ('t0123456789ABCDEF', None, None),
|
||||
GRAYA_IMAGE: ['xcf', 'png', 'tga', 'sgi'],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# kivy image test protocol v0 data: key is pattern char, value is pixel w/o a
|
||||
v0_PIXELS = {
|
||||
'w': [0xFF, 0xFF, 0xFF], 'x': [0x00, 0x00, 0x00], 'r': [0xFF, 0x00, 0x00],
|
||||
'g': [0x00, 0xFF, 0x00], 'b': [0x00, 0x00, 0xFF], 'y': [0xFF, 0xFF, 0x00],
|
||||
'c': [0x00, 0xFF, 0xFF], 'p': [0xFF, 0x00, 0xFF], '0': [0x00, 0x00, 0x00],
|
||||
'1': [0x11, 0x11, 0x11], '2': [0x22, 0x22, 0x22], '3': [0x33, 0x33, 0x33],
|
||||
'4': [0x44, 0x44, 0x44], '5': [0x55, 0x55, 0x55], '6': [0x66, 0x66, 0x66],
|
||||
'7': [0x77, 0x77, 0x77], '8': [0x88, 0x88, 0x88], '9': [0x99, 0x99, 0x99],
|
||||
'A': [0xAA, 0xAA, 0xAA], 'B': [0xBB, 0xBB, 0xBB], 'C': [0xCC, 0xCC, 0xCC],
|
||||
'D': [0xDD, 0xDD, 0xDD], 'E': [0xEE, 0xEE, 0xEE], 'F': [0xFF, 0xFF, 0xFF]}
|
||||
|
||||
|
||||
# kivy image test protocol v0: return pixel data for given pattern char
|
||||
def v0_pattern_pixel(char, alpha, fmt):
|
||||
if fmt == 'rgba':
|
||||
if char == 't':
|
||||
return [0, 0, 0, 0]
|
||||
return v0_PIXELS[char] + [alpha]
|
||||
if fmt == 'rgb':
|
||||
if char == 't':
|
||||
return [0, 0, 0]
|
||||
return v0_PIXELS[char]
|
||||
if fmt == 'gray':
|
||||
assert char in '0123456789ABCDEF'
|
||||
return [v0_PIXELS[char][0]]
|
||||
if fmt == 'graya':
|
||||
assert char in 't0123456789ABCDEF'
|
||||
if char == 't':
|
||||
return [0, 0]
|
||||
return [v0_PIXELS[char][0]] + [alpha]
|
||||
raise Exception('v0_pattern_pixel: unknown format {}'.format(fmt))
|
||||
|
||||
|
||||
# kivy image test protocol v0: filename
|
||||
def v0_filename(w, h, pat, alpha, fmtinfo, testname, ext):
|
||||
return 'v0_{}x{}_{}_{:02X}_{}_{}_gimp.{}'.format(
|
||||
w, h, pat, alpha, fmtinfo, testname, ext)
|
||||
|
||||
|
||||
# Saves an image to one or more files. We can't specify these details when
|
||||
# saving by extension. (This declaration is PEP8 compliant, 's all good)
|
||||
def save_image(dirname, img, lyr, w, h, pat, alpha, v0_fmtinfo, testname, ext):
|
||||
def filename(fmtinfo_in=None):
|
||||
fmtinfo = fmtinfo_in and v0_fmtinfo + '-' + fmtinfo_in or v0_fmtinfo
|
||||
return v0_filename(w, h, pat, alpha, fmtinfo, testname, ext)
|
||||
|
||||
def savepath(fn):
|
||||
return os.path.join(dirname, fn)
|
||||
|
||||
if ext in ('ppm', 'pgm', 'pbm', 'pnm', 'pam'):
|
||||
fn = filename('ASCII')
|
||||
pdb.file_pnm_save(img, lyr, savepath(fn), fn, 0)
|
||||
fn = filename('RAW')
|
||||
pdb.file_pnm_save(img, lyr, savepath(fn), fn, 1)
|
||||
|
||||
elif ext == 'tga':
|
||||
# FIXME: Last argument to file_tga_save is undocumented, not sure what
|
||||
fn = filename('RAW')
|
||||
pdb.file_tga_save(img, lyr, savepath(fn), fn, 0, 0)
|
||||
fn = filename('RLE')
|
||||
pdb.file_tga_save(img, lyr, savepath(fn), fn, 1, 0)
|
||||
|
||||
elif ext == 'gif':
|
||||
fn = filename('I0')
|
||||
pdb.file_gif_save(img, lyr, savepath(fn), fn, 0, 0, 0, 0)
|
||||
fn = filename('I1')
|
||||
pdb.file_gif_save(img, lyr, savepath(fn), fn, 1, 0, 0, 0)
|
||||
|
||||
elif ext == 'png':
|
||||
bits = [0, 1]
|
||||
# interlaced, bkgd block, gama block
|
||||
for i, b, g in [(i, b, g) for i in bits for b in bits for g in bits]:
|
||||
fn = filename('I{}B{}G{}'.format(i, b, g))
|
||||
pdb.file_png_save(img, lyr, savepath(fn), fn, i, 9, b, g, 1, 1, 1)
|
||||
|
||||
elif ext == 'sgi':
|
||||
fn = filename('RAW')
|
||||
pdb.file_sgi_save(img, lyr, savepath(fn), fn, 0)
|
||||
fn = filename('RLE')
|
||||
pdb.file_sgi_save(img, lyr, savepath(fn), fn, 1)
|
||||
fn = filename('ARLE')
|
||||
pdb.file_sgi_save(img, lyr, savepath(fn), fn, 2)
|
||||
|
||||
elif ext == 'tiff':
|
||||
fn = filename('RAW')
|
||||
pdb.file_tiff_save(img, lyr, savepath(fn), fn, 0)
|
||||
fn = filename('LZW')
|
||||
pdb.file_tiff_save(img, lyr, savepath(fn), fn, 1)
|
||||
fn = filename('PACKBITS')
|
||||
pdb.file_tiff_save(img, lyr, savepath(fn), fn, 2)
|
||||
fn = filename('DEFLATE')
|
||||
pdb.file_tiff_save(img, lyr, savepath(fn), fn, 3)
|
||||
|
||||
elif ext == 'ras':
|
||||
fn = filename('RAW')
|
||||
pdb.file_sunras_save(img, lyr, savepath(fn), fn, 0)
|
||||
fn = filename('RLE')
|
||||
pdb.file_sunras_save(img, lyr, savepath(fn), fn, 1)
|
||||
|
||||
else:
|
||||
fn = filename()
|
||||
pdb.gimp_file_save(img, lyr, savepath(fn), fn)
|
||||
|
||||
|
||||
# Draw pattern on layer, helper for make_images() below
|
||||
def draw_pattern(lyr, pat, alpha, direction, pixelgetter):
|
||||
assert 0 <= alpha <= 255
|
||||
assert re.match('[twxrgbycp0-9A-F]+$', pat)
|
||||
assert direction in ('x', 'y', 'width', 'height')
|
||||
dirx = direction in ('x', 'width')
|
||||
for i in range(0, len(pat)):
|
||||
pixel = pixelgetter(pat[i], alpha)
|
||||
if dirx:
|
||||
pdb.gimp_drawable_set_pixel(lyr, i, 0, len(pixel), pixel)
|
||||
else:
|
||||
pdb.gimp_drawable_set_pixel(lyr, 0, i, len(pixel), pixel)
|
||||
|
||||
|
||||
# Create an image from the given pattern, with the specified layertype_in*,
|
||||
# draw the pattern with given alpha, and save to the given extensions. Gimp
|
||||
# adjust the encoder accordingly.
|
||||
# * cheat for indexed formats: draw in RGB(A) and let gimp make palette
|
||||
def make_images(testname, pattern, alpha, layertype_in, extensions, dirname):
|
||||
assert testname.upper() == testname
|
||||
assert len(pattern) > 0
|
||||
assert len(extensions) > 0
|
||||
assert isinstance(extensions, (list, tuple))
|
||||
assert re.match('[wxtrgbcypA-F0-9]+$', pattern)
|
||||
|
||||
test_alpha = 'ALPHA' in testname or 'BINARY' in testname
|
||||
grayscale = 'GRAY' in testname
|
||||
|
||||
# Indexed layer types are drawn in RGB/RGBA, and converted later
|
||||
imgtype, v0_fmtinfo = {
|
||||
GRAY_IMAGE: (GRAY, 'BPP1G'),
|
||||
GRAYA_IMAGE: (GRAY, 'BPP2GA'),
|
||||
RGB_IMAGE: (RGB, 'BPP3'),
|
||||
RGBA_IMAGE: (RGB, 'BPP4'),
|
||||
INDEXED_IMAGE: (grayscale and GRAY or RGB, 'IX'),
|
||||
INDEXEDA_IMAGE: (grayscale and GRAY or RGB, 'IXA'),
|
||||
}[layertype_in]
|
||||
|
||||
# We need to supply pixels of the format of the layer
|
||||
PP = v0_pattern_pixel
|
||||
pixelgetter = {
|
||||
GRAY_IMAGE: lambda c, a: PP(c, a, 'gray'),
|
||||
GRAYA_IMAGE: lambda c, a: PP(c, a, 'graya'),
|
||||
RGB_IMAGE: lambda c, a: PP(c, a, 'rgb'),
|
||||
RGBA_IMAGE: lambda c, a: PP(c, a, 'rgba'),
|
||||
INDEXED_IMAGE: lambda c, a: PP(c, a, grayscale and 'gray' or 'rgb'),
|
||||
INDEXEDA_IMAGE: lambda c, a: PP(c, a, grayscale and 'graya' or 'rgba'),
|
||||
}[layertype_in]
|
||||
|
||||
# Pick the correct layer type for indexed formats
|
||||
layertype = {
|
||||
INDEXED_IMAGE: grayscale and GRAY_IMAGE or RGB_IMAGE,
|
||||
INDEXEDA_IMAGE: grayscale and GRAYA_IMAGE or RGBA_IMAGE,
|
||||
}.get(layertype_in, layertype_in)
|
||||
|
||||
# Draw pattern Nx1 and 1xN variations
|
||||
for direction in 'xy':
|
||||
# Create the gimp image, and the layer we will draw on
|
||||
w, h = (direction == 'x') and (len(pattern), 1) or (1, len(pattern))
|
||||
img = pdb.gimp_image_new(w, h, imgtype)
|
||||
lyr = pdb.gimp_layer_new(img, w, h, layertype, 'P', 100, NORMAL_MODE)
|
||||
|
||||
# Add alpha layer if we are planning on encoding alpha information
|
||||
if test_alpha:
|
||||
pdb.gimp_layer_add_alpha(lyr)
|
||||
pdb.gimp_drawable_fill(lyr, TRANSPARENT_FILL)
|
||||
pdb.gimp_image_add_layer(img, lyr, 0)
|
||||
|
||||
# Draw it
|
||||
draw_pattern(lyr, pattern, alpha, direction, pixelgetter)
|
||||
|
||||
# Convert to indexed before saving, if needed
|
||||
if layertype_in in (INDEXED_IMAGE, INDEXEDA_IMAGE):
|
||||
colors = len(set(pattern)) + (test_alpha and 1 or 0)
|
||||
pdb.gimp_convert_indexed(img, 0, 0, colors, 0, 0, "ignored")
|
||||
|
||||
# Save each individual extension
|
||||
for ext in extensions:
|
||||
save_image(dirname, img, lyr,
|
||||
w, h, pattern, alpha, v0_fmtinfo, testname, ext)
|
||||
# FIXME: this fails?
|
||||
# pdb.gimp_image_delete(img)
|
||||
|
||||
|
||||
# FIXME: pattern generation needs thought, this sucks..
|
||||
def makepatterns(allow, include=None, exclude=None):
|
||||
src = set()
|
||||
src.update([x for x in allow])
|
||||
src.update([allow[:i] for i in range(1, len(allow) + 1)])
|
||||
for i in range(len(allow)):
|
||||
pick1, pick2 = random.choice(allow), random.choice(allow)
|
||||
src.update([pick1 + pick2])
|
||||
for i in range(3, 11) + range(14, 18) + range(31, 34):
|
||||
src.update([''.join([random.choice(allow) for k in range(i)])])
|
||||
out = []
|
||||
for srcpat in src:
|
||||
if exclude and exclude in srcpat:
|
||||
continue
|
||||
if include and include not in srcpat:
|
||||
out.append(include + srcpat[1:])
|
||||
continue
|
||||
out.append(srcpat)
|
||||
return list(set(out))
|
||||
|
||||
|
||||
def plugin_main(dirname, do_opaque, do_binary, do_alpha):
|
||||
if not dirname:
|
||||
pdb.gimp_message("No output directory selected, aborting")
|
||||
return
|
||||
if not os.path.isdir(dirname) or not os.access(dirname, os.W_OK):
|
||||
pdb.gimp_message("Invalid / non-writeable output directory, aborting")
|
||||
return
|
||||
|
||||
tests = []
|
||||
tests.extend({
|
||||
0: ['OPAQUE', 'GRAY-OPAQUE'],
|
||||
2: ['OPAQUE'],
|
||||
3: ['GRAY-OPAQUE'],
|
||||
}.get(do_opaque, []))
|
||||
tests.extend({
|
||||
0: ['BINARY', 'GRAY-BINARY'],
|
||||
2: ['BINARY'],
|
||||
3: ['GRAY-BINARY'],
|
||||
}.get(do_binary, []))
|
||||
tests.extend({
|
||||
0: ['ALPHA', 'GRAY-ALPHA'],
|
||||
2: ['ALPHA'],
|
||||
3: ['GRAY-ALPHA'],
|
||||
}.get(do_alpha, []))
|
||||
|
||||
suite_cfg = dict(TESTSUITE_CONFIG)
|
||||
for testname, cfg in suite_cfg.items():
|
||||
if testname not in tests:
|
||||
continue
|
||||
pchars, inc, exc = cfg.pop('patterns')
|
||||
if not pchars:
|
||||
continue
|
||||
patterns = makepatterns(pchars, inc, exc)
|
||||
for alpha in cfg.pop('alpha', [255]):
|
||||
for layertype, exts in cfg.items():
|
||||
if not exts:
|
||||
continue
|
||||
for p in patterns:
|
||||
make_images(testname, p, alpha, layertype, exts, dirname)
|
||||
|
||||
|
||||
register(
|
||||
proc_name="kivy_image_testsuite",
|
||||
help="Creates image test suite for Kivy ImageLoader",
|
||||
blurb=("Creates image test suite for Kivy ImageLoader. "
|
||||
"Warning: This will create thousands of images"),
|
||||
author="For kivy.org, Terje Skjaeveland",
|
||||
copyright="Copyright 2017 kivy.org (MIT license)",
|
||||
date="2017",
|
||||
imagetypes="",
|
||||
params=[
|
||||
(PF_DIRNAME, "outputdir", "Output directory:", 0),
|
||||
(PF_OPTION, "opaque", "OPAQUE tests?", 0,
|
||||
["All", "None", "OPAQUE", "GRAY-OPAQUE"]),
|
||||
(PF_OPTION, "binary", "BINARY tests?", 0,
|
||||
["All", "None", "BINARY", "GRAY-BINARY"]),
|
||||
(PF_OPTION, "alpha", "ALPHA tests?", 0,
|
||||
["All", "None", "ALPHA", "GRAY-ALPHA"]),
|
||||
],
|
||||
results=[],
|
||||
function=plugin_main,
|
||||
menu="<Image>/Tools/_Kivy image testsuite...",
|
||||
label="Generate images...")
|
||||
|
||||
main()
|
|
@ -0,0 +1,238 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# ImageMagickFormat:extension
|
||||
FMT_OPAQUE="TIFF:tiff BMP:bmp BMP3:bmp PNG:png GIF87:gif CUR:cur \
|
||||
PPM:ppm FITS:fits RAS:ras"
|
||||
FMT_BINARY="BMP:bmp GIF:gif PNG8:png PNG24:png PNG48:png ICO:ico"
|
||||
FMT_ALPHA="PNG32:png PNG64:png TGA:tga SGI:sgi DPX:dpx"
|
||||
|
||||
# FIXME: Magick output is not completely predictable. Some images
|
||||
# become gray+alpha, some palette, some bitonal, and it's not obvious
|
||||
# how/if this can be controlled better
|
||||
#FMT_BITONAL=""
|
||||
FMT_GRAY_OPAQUE="PGM:pgm FITS:fits RAS:ras"
|
||||
FMT_GRAY_BINARY="PNG8:png"
|
||||
FMT_GRAY_ALPHA="PNG:png TGA:tga"
|
||||
|
||||
# Pixel values used for different tests
|
||||
PIX_alpha="twxrgbcyp48A"
|
||||
PIX_opaque="wxrgbcyp48A"
|
||||
PIX_binary="twrgbcyp48A"
|
||||
PIX_gray_opaque="0123456789ABCDEF"
|
||||
PIX_gray_binary="t123456789ABCDEF"
|
||||
PIX_gray_alpha="t0123456789ABCDEF"
|
||||
|
||||
|
||||
usage() { cat <<EOM
|
||||
Usage: $0 <target-directory>
|
||||
|
||||
Creates test images in many formats using ImageMagick 'convert'
|
||||
utility. The pixel values are encoded in the filename, so they
|
||||
can be reconstructed and verified independently. This system
|
||||
is referred to as the image test protocol (version 0).
|
||||
|
||||
More info: kivy/tools/image-testsuite/README.md
|
||||
EOM
|
||||
}
|
||||
|
||||
# Outputs command line arguments for convert to draw pixels from the
|
||||
# specified pattern in the specified direction. It is always 1 in w or h.
|
||||
draw_pattern() {
|
||||
pattern=$1
|
||||
direction="${2:-x}"
|
||||
pos=0
|
||||
for char in $(echo $pattern | fold -w1); do
|
||||
case $char in
|
||||
t) fill="#00000000" ;;
|
||||
w) fill="#FFFFFF${TESTALPHA}" ;;
|
||||
x) fill="#000000${TESTALPHA}" ;;
|
||||
r) fill="#FF0000${TESTALPHA}" ;;
|
||||
g) fill="#00FF00${TESTALPHA}" ;;
|
||||
b) fill="#0000FF${TESTALPHA}" ;;
|
||||
y) fill="#FFFF00${TESTALPHA}" ;;
|
||||
c) fill="#00FFFF${TESTALPHA}" ;;
|
||||
p) fill="#FF00FF${TESTALPHA}" ;;
|
||||
0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)
|
||||
fill="#${char}${char}${char}${char}${char}${char}${TESTALPHA}"
|
||||
;;
|
||||
*) (>&2 echo "Error: Invalid pattern char: $char"); exit 100 ;;
|
||||
esac
|
||||
case $direction in
|
||||
y|height) echo -n "-draw 'fill $fill color 0, $pos point' " ;;
|
||||
x|width) echo -n "-draw 'fill $fill color $pos, 0 point' " ;;
|
||||
esac
|
||||
pos=$((pos+1))
|
||||
done
|
||||
}
|
||||
|
||||
# Creates 1xN and Nx1 test images from the given pattern, in the given
|
||||
# format. Only use alpha != FF if you are actually testing alpha.
|
||||
make_images() {
|
||||
pattern=$1
|
||||
len=${#pattern}
|
||||
|
||||
if [ -z $pattern ] || [ -z $TESTFMT ] || [ -z $TESTEXT ]; then
|
||||
(>&2 echo "make_images() missing required arguments/environment")
|
||||
exit 101
|
||||
fi
|
||||
if [ ${#TESTALPHA} != 2 ]; then
|
||||
(>&2 echo "make_images() invalid TESTALPHA: $TESTALPHA")
|
||||
exit 102
|
||||
fi
|
||||
|
||||
# Nx1
|
||||
ending="${TESTALPHA}_${TESTFMT}_${TESTNAME}_magick.${TESTEXT}"
|
||||
outfile="v0_${len}x1_${pattern}_${ending}"
|
||||
eval convert -size ${len}x1 xc:none -quality 100% $TESTARGS \
|
||||
$(draw_pattern "$pattern" "x") \
|
||||
${convert_args} \
|
||||
"${TESTFMT}:$destdir/$outfile"
|
||||
|
||||
# 1xN - don't create duplicates for single pixel
|
||||
if [ $len -ne 1 ]; then
|
||||
outfile="v0_1x${len}_${pattern}_${ending}"
|
||||
eval convert -size 1x${len} xc:none -quality 100% $TESTARGS \
|
||||
$(draw_pattern "$pattern" "y") \
|
||||
"${TESTFMT}:$destdir/$outfile"
|
||||
fi
|
||||
}
|
||||
|
||||
# Make a random pattern from given characters $1 at length $2
|
||||
# FIXME: portability?
|
||||
mkpattern() {
|
||||
< /dev/urandom LC_ALL=C tr -dc "$1" | head -c $2
|
||||
}
|
||||
|
||||
# Makes simple permutations and random patterns, optionally with
|
||||
# prefix and postfix (args are pattern, prefix, postfix)
|
||||
permutepattern() {
|
||||
if [ -z "$1" ]; then
|
||||
(>&2 echo "permutepattern() missing required argument")
|
||||
exit 200
|
||||
fi
|
||||
|
||||
# Individual pixel values + poor permutation FIXME
|
||||
for char in $(echo $1 | fold -w1); do
|
||||
echo -n "$2${char}$3 "
|
||||
if [ ! -z $p1 ]; then echo -n "$2${char}${p1}$3 "; fi
|
||||
# Uncomment for more data
|
||||
# if [ ! -z $p2 ]; then echo -n "$2${char}${p1}${p2}$3 "; fi
|
||||
# if [ ! -z $p3 ]; then echo -n "$2${char}${p1}${p2}${p3}$3 "; fi
|
||||
# if [ ! -z $p4 ]; then echo -n "$2${char}${p1}${p2}${p3}${p4}$3 "; fi
|
||||
p4=$p3 ; p3=$p2 ; p2=$p1 ; p1=$char
|
||||
done
|
||||
|
||||
# Random
|
||||
for i in $(seq 3 9) $(seq 14 17) $(seq 31 33); do
|
||||
echo -n "$2$(mkpattern "$1" "$i")$3 "
|
||||
done
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Main
|
||||
# ------------------------------------------------------------
|
||||
if [ "$#" -ne 1 ] || [ -z "$1" ]; then
|
||||
echo "Usage: $0 <target-directory> (or -h for help)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case $1 in
|
||||
-h|--help) usage; exit 1 ;;
|
||||
esac
|
||||
|
||||
if [ ! -d "$1" ]; then
|
||||
(>&2 echo "Error: Destination directory '$1' does not exist")
|
||||
exit 2
|
||||
elif [ ! -w "$1" ]; then
|
||||
(>&2 echo "Error: Destination directory '$1' not writeable")
|
||||
exit 2
|
||||
fi
|
||||
destdir=$(cd "$1"; echo $(pwd))
|
||||
|
||||
if [ ! -x "$(command -v convert)" ]; then
|
||||
(2>&1 echo "Required ImageMagick 'convert' not found in path")
|
||||
exit 3
|
||||
fi
|
||||
|
||||
|
||||
# - Opaque patterns only include solid colors, alpha is fixed at FF
|
||||
# - Binary patterns MUST include 't' pixels and MUST NOT include 'x' or '0'
|
||||
# - Alpha can combine any pixel value and use alpha != FF
|
||||
PAT_opaque=$(permutepattern "$PIX_opaque")
|
||||
PAT_binary=$(permutepattern "$PIX_binary" "t")
|
||||
PAT_alpha="${PAT_binary} $(permutepattern "$PIX_alpha")"
|
||||
|
||||
# Grayscale patterns use only grayscale pixel values + 't' and alpha,
|
||||
# ie #000 #111 #222 .. #EEE #FFF (0 1 2 .. E F in patterns)
|
||||
PAT_gray_opaque=$(permutepattern "$PIX_gray_opaque")
|
||||
PAT_gray_binary=$(permutepattern "$PIX_gray_binary" "t")
|
||||
PAT_gray_alpha="${PAT_gray_binary} $(permutepattern "$PIX_gray_alpha")"
|
||||
|
||||
start() {
|
||||
TESTNAME="$1"
|
||||
TESTARGS="$2"
|
||||
TESTALPHA="FF"
|
||||
TESTFMT=""
|
||||
TESTEXT=""
|
||||
}
|
||||
|
||||
inform() {
|
||||
echo "[${TESTNAME}] Creating ${TESTFMT} (.${TESTEXT}) test images..."
|
||||
}
|
||||
|
||||
# OPAQUE / GRAY_OPAQUE
|
||||
start "OPAQUE" "-alpha off"
|
||||
for rawfmt in $FMT_OPAQUE $FMT_BINARY $FMT_ALPHA; do
|
||||
TESTFMT=${rawfmt%:*}; TESTEXT=${rawfmt#*:}; inform
|
||||
for pat in $PAT_opaque; do
|
||||
make_images "$pat"
|
||||
done
|
||||
done
|
||||
|
||||
start "GRAY-OPAQUE" "-alpha off -colorspace Gray"
|
||||
for rawfmt in $FMT_GRAY_OPAQUE $FMT_GRAY_BINARY $FMT_GRAY_ALPHA; do
|
||||
TESTFMT=${rawfmt%:*}; TESTEXT=${rawfmt#*:}; inform
|
||||
for pat in $PAT_gray_opaque; do
|
||||
make_images "$pat"
|
||||
done
|
||||
done
|
||||
|
||||
# BINARY / GRAY_BINARY
|
||||
start "BINARY" "-alpha on"
|
||||
for rawfmt in $FMT_BINARY $FMT_ALPHA; do
|
||||
TESTFMT=${rawfmt%:*}; TESTEXT=${rawfmt#*:}; inform
|
||||
for pat in $PAT_binary; do
|
||||
make_images "$pat"
|
||||
done
|
||||
done
|
||||
|
||||
start "GRAY-BINARY" "-alpha on -colorspace Gray"
|
||||
for rawfmt in $FMT_GRAY_BINARY $FMT_GRAY_ALPHA; do
|
||||
TESTFMT=${rawfmt%:*}; TESTEXT=${rawfmt#*:}; inform
|
||||
for pat in $PAT_gray_binary; do
|
||||
make_images "$pat"
|
||||
done
|
||||
done
|
||||
|
||||
# ALPHA / GRAY_ALPHA
|
||||
start "ALPHA" "-alpha on"
|
||||
for rawfmt in $FMT_ALPHA; do
|
||||
TESTFMT=${rawfmt%:*}; TESTEXT=${rawfmt#*:}; inform
|
||||
for alpha in 7F F0; do
|
||||
TESTALPHA=$alpha
|
||||
for pat in $PAT_alpha; do
|
||||
make_images "$pat"
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
start "GRAY-ALPHA" "-alpha on -colorspace Gray"
|
||||
for rawfmt in $FMT_GRAY_ALPHA; do
|
||||
TESTFMT=${rawfmt%:*}; TESTEXT=${rawfmt#*:}; inform
|
||||
for alpha in 7F F0; do
|
||||
TESTALPHA=$alpha
|
||||
for pat in $PAT_gray_alpha; do
|
||||
make_images "$pat"
|
||||
done
|
||||
done
|
||||
done
|
80
kivy_venv/lib/python3.11/site-packages/kivy/tools/kviewer.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env python
|
||||
'''
|
||||
KViewer
|
||||
=======
|
||||
|
||||
KViewer, for KV-Viewer, is a simple tool allowing you to dynamically display
|
||||
a KV file, taking its changes into account (thanks to watchdog). The
|
||||
idea is to facilitate design using the KV language. It's somewhat related to
|
||||
the KivyCatalog demo, except it uses an on-disc file, allowing the user to use
|
||||
any editor.
|
||||
|
||||
You can use the script as follows::
|
||||
|
||||
python kviewer.py ./test.kv
|
||||
|
||||
This will display the test.kv and automatically update the display when the
|
||||
file changes.
|
||||
|
||||
.. note: This scripts uses watchdog to listen for file changes. To install
|
||||
watchdog::
|
||||
|
||||
pip install watchdog
|
||||
|
||||
'''
|
||||
|
||||
from sys import argv
|
||||
from kivy.lang import Builder
|
||||
from kivy.app import App
|
||||
from kivy.core.window import Window
|
||||
from kivy.clock import Clock, mainthread
|
||||
from kivy.uix.label import Label
|
||||
|
||||
from watchdog.observers import Observer
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
from os.path import dirname, basename, join
|
||||
|
||||
|
||||
if len(argv) != 2:
|
||||
print('usage: %s filename.kv' % argv[0])
|
||||
exit(1)
|
||||
|
||||
|
||||
PATH = dirname(argv[1])
|
||||
TARGET = basename(argv[1])
|
||||
|
||||
|
||||
class KvHandler(FileSystemEventHandler):
|
||||
def __init__(self, callback, target, **kwargs):
|
||||
super(KvHandler, self).__init__(**kwargs)
|
||||
self.callback = callback
|
||||
self.target = target
|
||||
|
||||
def on_any_event(self, event):
|
||||
if basename(event.src_path) == self.target:
|
||||
self.callback()
|
||||
|
||||
|
||||
class KvViewerApp(App):
|
||||
def build(self):
|
||||
o = Observer()
|
||||
o.schedule(KvHandler(self.update, TARGET), PATH)
|
||||
o.start()
|
||||
Clock.schedule_once(self.update, 1)
|
||||
return super(KvViewerApp, self).build()
|
||||
|
||||
@mainthread
|
||||
def update(self, *args):
|
||||
Builder.unload_file(join(PATH, TARGET))
|
||||
for w in Window.children[:]:
|
||||
Window.remove_widget(w)
|
||||
try:
|
||||
Window.add_widget(Builder.load_file(join(PATH, TARGET)))
|
||||
except Exception as e:
|
||||
Window.add_widget(Label(text=(
|
||||
e.message if getattr(e, r'message', None) else str(e)
|
||||
)))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
KvViewerApp().run()
|
|
@ -0,0 +1,12 @@
|
|||
'''
|
||||
Packaging
|
||||
=========
|
||||
|
||||
This module contains `PyInstaller <http://www.pyinstaller.org/>`_ hooks in
|
||||
order to assist in the process of building binary packages. PyInstaller allows
|
||||
you to produce stand-alone, self-contained executables of your Kivy app for
|
||||
Windows, Linux and Mac.
|
||||
|
||||
For more information, please see the `PyInstaller website
|
||||
<http://www.pyinstaller.org/>`_
|
||||
'''
|
|
@ -0,0 +1,82 @@
|
|||
import configparser
|
||||
from os.path import join, dirname
|
||||
import textwrap
|
||||
|
||||
__all__ = ('get_cython_versions', 'get_cython_msg')
|
||||
|
||||
|
||||
def get_cython_versions(setup_cfg=''):
|
||||
_cython_config = configparser.ConfigParser()
|
||||
if setup_cfg:
|
||||
_cython_config.read(setup_cfg)
|
||||
else:
|
||||
_cython_config.read(
|
||||
join(dirname(__file__), '..', '..', '..', 'setup.cfg'))
|
||||
|
||||
cython_min = _cython_config['kivy']['cython_min']
|
||||
cython_max = _cython_config['kivy']['cython_max']
|
||||
cython_unsupported = _cython_config['kivy']['cython_exclude'].split(',')
|
||||
# ref https://github.com/cython/cython/issues/1968
|
||||
|
||||
cython_requires = (
|
||||
'cython>={min_version},<={max_version},{exclusion}'.format(
|
||||
min_version=cython_min,
|
||||
max_version=cython_max,
|
||||
exclusion=','.join('!=%s' % excl for excl in cython_unsupported),
|
||||
)
|
||||
)
|
||||
|
||||
return cython_requires, cython_min, cython_max, cython_unsupported
|
||||
|
||||
|
||||
def get_cython_msg():
|
||||
cython_requires, cython_min, cython_max, cython_unsupported = \
|
||||
get_cython_versions()
|
||||
cython_unsupported_append = '''
|
||||
|
||||
Please note that the following versions of Cython are not supported
|
||||
at all: {}'''.format(', '.join(map(str, cython_unsupported)))
|
||||
|
||||
cython_min_msg = textwrap.dedent('''
|
||||
This version of Cython is not compatible with Kivy. Please upgrade to
|
||||
at least version {0}, preferably the newest supported version {1}.
|
||||
|
||||
If your platform provides a Cython package, make sure you have upgraded
|
||||
to the newest version. If the newest version available is still too low,
|
||||
please remove it and install the newest supported Cython via pip:
|
||||
|
||||
pip install -I "{3}"{2}
|
||||
'''.format(cython_min, cython_max,
|
||||
cython_unsupported_append if cython_unsupported else '',
|
||||
cython_requires))
|
||||
|
||||
cython_max_msg = textwrap.dedent('''
|
||||
This version of Cython is untested with Kivy. While this version may
|
||||
work perfectly fine, it is possible that you may experience issues.
|
||||
Please downgrade to a supported version, or update cython_max in
|
||||
setup.cfg to your version of Cython. It is best to use the newest
|
||||
supported version, {1}, but the minimum supported version is {0}.
|
||||
|
||||
If your platform provides a Cython package, check if you can downgrade
|
||||
to a supported version. Otherwise, uninstall the platform package and
|
||||
install Cython via pip:
|
||||
|
||||
pip install -I "{3}"{2}
|
||||
'''.format(cython_min, cython_max,
|
||||
cython_unsupported_append if cython_unsupported else '',
|
||||
cython_requires))
|
||||
|
||||
cython_unsupported_msg = textwrap.dedent('''
|
||||
This version of Cython suffers from known bugs and is unsupported.
|
||||
Please install the newest supported version, {1}, if possible, but
|
||||
the minimum supported version is {0}.
|
||||
|
||||
If your platform provides a Cython package, check if you can install
|
||||
a supported version. Otherwise, uninstall the platform package and
|
||||
install Cython via pip:
|
||||
|
||||
pip install -I "{3}"{2}
|
||||
'''.format(cython_min, cython_max, cython_unsupported_append,
|
||||
cython_requires))
|
||||
|
||||
return cython_min_msg, cython_max_msg, cython_unsupported_msg
|
|
@ -0,0 +1,105 @@
|
|||
from __future__ import print_function
|
||||
|
||||
__all__ = ('FactoryBuild', )
|
||||
|
||||
import fnmatch
|
||||
import os
|
||||
|
||||
from setuptools import Command
|
||||
|
||||
import kivy
|
||||
|
||||
ignore_list = (
|
||||
'kivy.lib',
|
||||
'kivy.input.providers',
|
||||
'kivy.input.postproc',
|
||||
'kivy.modules',
|
||||
'kivy.tools',
|
||||
'kivy.parser',
|
||||
'kivy.tests',
|
||||
)
|
||||
|
||||
|
||||
class FactoryBuild(Command):
|
||||
description = 'Build the factory relation file (for factory.py)'
|
||||
user_options = []
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
print('--------------------------------------------')
|
||||
print('Building factory relation file')
|
||||
print('--------------------------------------------')
|
||||
|
||||
root_dir = os.path.dirname(kivy.__file__)
|
||||
filename = os.path.join(root_dir, 'factory_registers.py')
|
||||
with open(filename, 'w') as fd:
|
||||
fd.close()
|
||||
|
||||
# ensure we don't have any thing like doc running
|
||||
symbols = []
|
||||
for root, dirnames, filenames in os.walk(root_dir):
|
||||
if not root.startswith(root_dir):
|
||||
raise Exception('Directory should start with the kivy'
|
||||
'directory')
|
||||
root = 'kivy' + root[len(root_dir):].replace(os.path.sep, '.')
|
||||
for filename in fnmatch.filter(filenames, '*.[ps][yo]'):
|
||||
module = '%s.%s' % (root, filename[:-3])
|
||||
|
||||
# check ignore list first
|
||||
ignore = False
|
||||
for ignore in ignore_list:
|
||||
if module.startswith(ignore):
|
||||
ignore = True
|
||||
break
|
||||
if ignore:
|
||||
# print('<<< ignored (ignore list)')
|
||||
continue
|
||||
|
||||
# special case, core providers
|
||||
if root.startswith('kivy.core.'):
|
||||
if not root.endswith('__init__.py'):
|
||||
# print('<<< ignored (not a __init__.py)')
|
||||
continue
|
||||
|
||||
print('>>>', module, '::', end=' ')
|
||||
|
||||
try:
|
||||
m = __import__(name=module, fromlist='.')
|
||||
except Exception as e:
|
||||
print()
|
||||
print('ERROR:', e)
|
||||
continue
|
||||
if not hasattr(m, '__all__'):
|
||||
print()
|
||||
continue
|
||||
for symbol in getattr(m, '__all__'):
|
||||
if symbol.startswith('_'):
|
||||
continue
|
||||
attr = getattr(m, symbol)
|
||||
if type(attr) not in (type, type):
|
||||
continue
|
||||
symbols.append((symbol, module))
|
||||
print(symbol, end=' ')
|
||||
print()
|
||||
|
||||
print()
|
||||
print('--------------------------------------------')
|
||||
print('Found %d symbols, generating file' % len(symbols))
|
||||
print('--------------------------------------------')
|
||||
|
||||
filename = os.path.join(root_dir, 'factory_registers.py')
|
||||
with open(filename, 'w') as fd:
|
||||
fd.write('# Auto-generated file by setup.py build_factory\n')
|
||||
fd.write('\n')
|
||||
fd.write('from kivy.factory import Factory\n')
|
||||
fd.write('\n')
|
||||
fd.write('r = Factory.register\n')
|
||||
for x in symbols:
|
||||
fd.write("r('%s', module='%s')\n" % x)
|
||||
|
||||
print('File written at', filename)
|
|
@ -0,0 +1,376 @@
|
|||
'''
|
||||
Pyinstaller hooks
|
||||
=================
|
||||
|
||||
Module that exports pyinstaller related methods and parameters.
|
||||
|
||||
Hooks
|
||||
-----
|
||||
|
||||
PyInstaller comes with a default hook for kivy that lists the indirectly
|
||||
imported modules that pyinstaller would not find on its own using
|
||||
:func:`get_deps_all`. :func:`hookspath` returns the path to an alternate kivy
|
||||
hook, ``kivy/tools/packaging/pyinstaller_hooks/kivy-hook.py`` that does not
|
||||
add these dependencies to its list of hidden imports and they have to be
|
||||
explicitly included instead.
|
||||
|
||||
One can overwrite the default hook by providing on the command line the
|
||||
``--additional-hooks-dir=HOOKSPATH`` option. Because although the default
|
||||
hook will still run, the `important global variables
|
||||
<https://pythonhosted.org/PyInstaller/#hook-global-variables>`_, e.g.
|
||||
``excludedimports`` and ``hiddenimports`` will be overwritten by the
|
||||
new hook, if set there.
|
||||
|
||||
Additionally, one can add a hook to be run after the default hook by
|
||||
passing e.g. ``hookspath=[HOOKSPATH]`` to the ``Analysis`` class. In both
|
||||
cases, ``HOOKSPATH`` is the path to a directory containing a file named
|
||||
``hook-kivy.py`` that is the pyinstaller hook for kivy to be processed
|
||||
after the default hook.
|
||||
|
||||
hiddenimports
|
||||
-------------
|
||||
|
||||
When a module is imported indirectly, e.g. with ``__import__``, pyinstaller
|
||||
won't know about it and the module has to be added through ``hiddenimports``.
|
||||
|
||||
``hiddenimports`` and other hook variables can be specified within a hook as
|
||||
described above. Also, these variable can be passed to ``Analysis`` and their
|
||||
values are then appended to the hook's values for these variables.
|
||||
|
||||
Most of kivy's core modules, e.g. video are imported indirectly and therefore
|
||||
need to be added in hiddenimports. The default PyInstaller hook adds all the
|
||||
providers. To overwrite, a modified kivy-hook similar to the default hook, such
|
||||
as :func:`hookspath` that only imports the desired modules can be added. One
|
||||
then uses :func:`get_deps_minimal` or :func:`get_deps_all` to get the list of
|
||||
modules and adds them manually in a modified hook or passes them to
|
||||
``Analysis`` in the spec file.
|
||||
|
||||
Hook generator
|
||||
--------------
|
||||
|
||||
:mod:`pyinstaller_hooks` includes a tool to generate a hook which lists
|
||||
all the provider modules in a list so that one can manually comment out
|
||||
the providers not to be included. To use, do::
|
||||
|
||||
python -m kivy.tools.packaging.pyinstaller_hooks hook filename
|
||||
|
||||
``filename`` is the name and path of the hook file to create. If ``filename``
|
||||
is not provided the hook is printed to the terminal.
|
||||
'''
|
||||
|
||||
import os
|
||||
import sys
|
||||
import pkgutil
|
||||
import logging
|
||||
from os.path import dirname, join
|
||||
import importlib
|
||||
import subprocess
|
||||
import re
|
||||
import glob
|
||||
|
||||
import kivy
|
||||
try:
|
||||
from kivy import deps as old_deps
|
||||
except ImportError:
|
||||
old_deps = None
|
||||
try:
|
||||
import kivy_deps
|
||||
except ImportError:
|
||||
kivy_deps = None
|
||||
from kivy.factory import Factory
|
||||
from PyInstaller.depend import bindepend
|
||||
|
||||
from os import environ
|
||||
if 'KIVY_DOC' not in environ:
|
||||
from PyInstaller.utils.hooks import collect_submodules
|
||||
|
||||
curdir = dirname(__file__)
|
||||
|
||||
kivy_modules = [
|
||||
'xml.etree.cElementTree',
|
||||
'kivy.core.gl',
|
||||
'kivy.weakmethod',
|
||||
'kivy.core.window.window_info',
|
||||
] + collect_submodules('kivy.graphics')
|
||||
'''List of kivy modules that are always needed as hiddenimports of
|
||||
pyinstaller.
|
||||
'''
|
||||
|
||||
excludedimports = ['tkinter', '_tkinter', 'twisted']
|
||||
'''List of excludedimports that should always be excluded from
|
||||
pyinstaller.
|
||||
'''
|
||||
|
||||
datas = [
|
||||
(kivy.kivy_data_dir,
|
||||
os.path.join('kivy_install', os.path.basename(kivy.kivy_data_dir))),
|
||||
(kivy.kivy_modules_dir,
|
||||
os.path.join('kivy_install', os.path.basename(kivy.kivy_modules_dir)))
|
||||
]
|
||||
'''List of data to be included by pyinstaller.
|
||||
'''
|
||||
|
||||
|
||||
def runtime_hooks():
|
||||
'''Returns a list with the runtime hooks for kivy. It can be used with
|
||||
``runtime_hooks=runtime_hooks()`` in the spec file. Pyinstaller comes
|
||||
preinstalled with this hook.
|
||||
'''
|
||||
return [join(curdir, 'pyi_rth_kivy.py')]
|
||||
|
||||
|
||||
def hookspath():
|
||||
'''Returns a list with the directory that contains the alternate (not
|
||||
the default included with pyinstaller) pyinstaller hook for kivy,
|
||||
``kivy/tools/packaging/pyinstaller_hooks/kivy-hook.py``. It is
|
||||
typically used with ``hookspath=hookspath()`` in the spec
|
||||
file.
|
||||
|
||||
The default pyinstaller hook returns all the core providers used using
|
||||
:func:`get_deps_minimal` to add to its list of hidden imports. This
|
||||
alternate hook only included the essential modules and leaves the core
|
||||
providers to be included additionally with :func:`get_deps_minimal`
|
||||
or :func:`get_deps_all`.
|
||||
'''
|
||||
return [curdir]
|
||||
|
||||
|
||||
def get_hooks():
|
||||
'''Returns the dict for the spec ``hookspath`` and ``runtime_hooks``
|
||||
values.
|
||||
'''
|
||||
return {'hookspath': hookspath(), 'runtime_hooks': runtime_hooks()}
|
||||
|
||||
|
||||
def get_deps_minimal(exclude_ignored=True, **kwargs):
|
||||
'''Returns Kivy hidden modules as well as excluded modules to be used
|
||||
with ``Analysis``.
|
||||
|
||||
The function takes core modules as keyword arguments and their value
|
||||
indicates which of the providers to include/exclude from the compiled app.
|
||||
|
||||
The possible keyword names are ``audio, camera, clipboard, image, spelling,
|
||||
text, video, and window``. Their values can be:
|
||||
|
||||
``True``: Include current provider
|
||||
The providers imported when the core module is
|
||||
loaded on this system are added to hidden imports. This is the
|
||||
default if the keyword name is not specified.
|
||||
``None``: Exclude
|
||||
Don't return this core module at all.
|
||||
``A string or list of strings``: Providers to include
|
||||
Each string is the name of a provider for this module to be
|
||||
included.
|
||||
|
||||
For example, ``get_deps_minimal(video=None, window=True,
|
||||
audio=['gstplayer', 'ffpyplayer'], spelling='enchant')`` will exclude all
|
||||
the video providers, will include the gstreamer and ffpyplayer providers
|
||||
for audio, will include the enchant provider for spelling, and will use the
|
||||
current default provider for ``window``.
|
||||
|
||||
``exclude_ignored``, if ``True`` (the default), if the value for a core
|
||||
library is ``None``, then if ``exclude_ignored`` is True, not only will the
|
||||
library not be included in the hiddenimports but it'll also added to the
|
||||
excluded imports to prevent it being included accidentally by pyinstaller.
|
||||
|
||||
:returns:
|
||||
|
||||
A dict with three keys, ``hiddenimports``, ``excludes``, and
|
||||
``binaries``. Their values are a list of the corresponding modules to
|
||||
include/exclude. This can be passed directly to `Analysis`` with
|
||||
e.g. ::
|
||||
|
||||
a = Analysis(['..\\kivy\\examples\\demo\\touchtracer\\main.py'],
|
||||
...
|
||||
hookspath=hookspath(),
|
||||
runtime_hooks=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
**get_deps_minimal(video=None, audio=None))
|
||||
'''
|
||||
core_mods = ['audio', 'camera', 'clipboard', 'image', 'spelling', 'text',
|
||||
'video', 'window']
|
||||
mods = kivy_modules[:]
|
||||
excludes = excludedimports[:]
|
||||
|
||||
for mod_name, val in kwargs.items():
|
||||
if mod_name not in core_mods:
|
||||
raise KeyError('{} not found in {}'.format(mod_name, core_mods))
|
||||
|
||||
full_name = 'kivy.core.{}'.format(mod_name)
|
||||
if not val:
|
||||
core_mods.remove(mod_name)
|
||||
if exclude_ignored:
|
||||
excludes.extend(collect_submodules(full_name))
|
||||
continue
|
||||
if val is True:
|
||||
continue
|
||||
core_mods.remove(mod_name)
|
||||
|
||||
mods.append(full_name)
|
||||
single_mod = False
|
||||
if isinstance(val, (str, bytes)):
|
||||
single_mod = True
|
||||
mods.append('kivy.core.{0}.{0}_{1}'.format(mod_name, val))
|
||||
if not single_mod:
|
||||
for v in val:
|
||||
mods.append('kivy.core.{0}.{0}_{1}'.format(mod_name, v))
|
||||
|
||||
for mod_name in core_mods: # process remaining default modules
|
||||
full_name = 'kivy.core.{}'.format(mod_name)
|
||||
mods.append(full_name)
|
||||
m = importlib.import_module(full_name)
|
||||
|
||||
if mod_name == 'clipboard' and m.CutBuffer:
|
||||
mods.append(m.CutBuffer.__module__)
|
||||
if hasattr(m, mod_name.capitalize()): # e.g. video -> Video
|
||||
val = getattr(m, mod_name.capitalize())
|
||||
if val:
|
||||
mods.append(getattr(val, '__module__'))
|
||||
|
||||
if hasattr(m, 'libs_loaded') and m.libs_loaded:
|
||||
for name in m.libs_loaded:
|
||||
mods.append('kivy.core.{}.{}'.format(mod_name, name))
|
||||
|
||||
mods = sorted(set(mods))
|
||||
|
||||
binaries = []
|
||||
if any('gstplayer' in m for m in mods):
|
||||
binaries = _find_gst_binaries()
|
||||
elif exclude_ignored:
|
||||
excludes.append('kivy.lib.gstplayer')
|
||||
|
||||
return {
|
||||
'hiddenimports': mods,
|
||||
'excludes': excludes,
|
||||
'binaries': binaries,
|
||||
}
|
||||
|
||||
|
||||
def get_deps_all():
|
||||
'''Similar to :func:`get_deps_minimal`, but this returns all the
|
||||
kivy modules that can indirectly imported. Which includes all
|
||||
the possible kivy providers.
|
||||
|
||||
This can be used to get a list of all the possible providers
|
||||
which can then manually be included/excluded by commenting out elements
|
||||
in the list instead of passing on all the items. See module description.
|
||||
|
||||
:returns:
|
||||
|
||||
A dict with three keys, ``hiddenimports``, ``excludes``, and
|
||||
``binaries``. Their values are a list of the corresponding modules to
|
||||
include/exclude. This can be passed directly to `Analysis`` with
|
||||
e.g. ::
|
||||
|
||||
a = Analysis(['..\\kivy\\examples\\demo\\touchtracer\\main.py'],
|
||||
...
|
||||
**get_deps_all())
|
||||
'''
|
||||
return {
|
||||
'binaries': _find_gst_binaries(),
|
||||
'hiddenimports': sorted(set(kivy_modules +
|
||||
collect_submodules('kivy.core'))),
|
||||
'excludes': []}
|
||||
|
||||
|
||||
def get_factory_modules():
|
||||
'''Returns a list of all the modules registered in the kivy factory.
|
||||
'''
|
||||
mods = [x.get('module', None) for x in Factory.classes.values()]
|
||||
return [m for m in mods if m]
|
||||
|
||||
|
||||
def add_dep_paths():
|
||||
'''Should be called by the hook. It adds the paths with the binary
|
||||
dependencies to the system path so that pyinstaller can find the binaries
|
||||
during its crawling stage.
|
||||
'''
|
||||
paths = []
|
||||
if old_deps is not None:
|
||||
for importer, modname, ispkg in pkgutil.iter_modules(
|
||||
old_deps.__path__):
|
||||
if not ispkg:
|
||||
continue
|
||||
try:
|
||||
module_spec = importer.find_spec(modname)
|
||||
mod = importlib.util.module_from_spec(module_spec)
|
||||
module_spec.loader.exec_module(mod)
|
||||
except ImportError as e:
|
||||
logging.warning(f"deps: Error importing dependency: {e}")
|
||||
continue
|
||||
|
||||
if hasattr(mod, 'dep_bins'):
|
||||
paths.extend(mod.dep_bins)
|
||||
sys.path.extend(paths)
|
||||
|
||||
if kivy_deps is None:
|
||||
return
|
||||
|
||||
paths = []
|
||||
for importer, modname, ispkg in pkgutil.iter_modules(kivy_deps.__path__):
|
||||
if not ispkg:
|
||||
continue
|
||||
try:
|
||||
module_spec = importer.find_spec(modname)
|
||||
mod = importlib.util.module_from_spec(module_spec)
|
||||
module_spec.loader.exec_module(mod)
|
||||
except ImportError as e:
|
||||
logging.warning(f"deps: Error importing dependency: {e}")
|
||||
continue
|
||||
|
||||
if hasattr(mod, 'dep_bins'):
|
||||
paths.extend(mod.dep_bins)
|
||||
sys.path.extend(paths)
|
||||
|
||||
|
||||
def _find_gst_plugin_path():
|
||||
'''Returns a list of directories to search for GStreamer plugins.
|
||||
'''
|
||||
if 'GST_PLUGIN_PATH' in environ:
|
||||
return [
|
||||
os.path.abspath(os.path.expanduser(path))
|
||||
for path in environ['GST_PLUGIN_PATH'].split(os.pathsep)
|
||||
]
|
||||
|
||||
try:
|
||||
p = subprocess.Popen(
|
||||
['gst-inspect-1.0', 'coreelements'],
|
||||
stdout=subprocess.PIPE, universal_newlines=True)
|
||||
except:
|
||||
return []
|
||||
(stdoutdata, stderrdata) = p.communicate()
|
||||
|
||||
match = re.search(r'\s+(\S+libgstcoreelements\.\S+)', stdoutdata)
|
||||
|
||||
if not match:
|
||||
return []
|
||||
|
||||
return [os.path.dirname(match.group(1))]
|
||||
|
||||
|
||||
def _find_gst_binaries():
|
||||
'''Returns a list of GStreamer plugins and libraries to pass as the
|
||||
``binaries`` argument of ``Analysis``.
|
||||
'''
|
||||
gst_plugin_path = _find_gst_plugin_path()
|
||||
|
||||
plugin_filepaths = []
|
||||
for plugin_dir in gst_plugin_path:
|
||||
plugin_filepaths.extend(
|
||||
glob.glob(os.path.join(plugin_dir, 'libgst*')))
|
||||
if len(plugin_filepaths) == 0:
|
||||
logging.warning('Could not find GStreamer plugins. ' +
|
||||
'Possible solution: set GST_PLUGIN_PATH')
|
||||
return []
|
||||
|
||||
lib_filepaths = set()
|
||||
for plugin_filepath in plugin_filepaths:
|
||||
plugin_deps = bindepend.selectImports(plugin_filepath)
|
||||
lib_filepaths.update([path for _, path in plugin_deps])
|
||||
|
||||
plugin_binaries = [(f, 'gst-plugins') for f in plugin_filepaths]
|
||||
lib_binaries = [(f, '.') for f in lib_filepaths]
|
||||
|
||||
return plugin_binaries + lib_binaries
|
|
@ -0,0 +1,29 @@
|
|||
from kivy.tools.packaging.pyinstaller_hooks import get_deps_all
|
||||
import sys
|
||||
from os.path import dirname, join
|
||||
|
||||
args = sys.argv[1:]
|
||||
if args and args[0] == 'hook':
|
||||
with open(join(dirname(__file__), 'hook-kivy.py')) as fh:
|
||||
src = fh.read()
|
||||
|
||||
formatted_lines = []
|
||||
lines = get_deps_all()['hiddenimports']
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if i and line[:line.rfind('.')] != \
|
||||
lines[i - 1][:lines[i - 1].rfind('.')]:
|
||||
formatted_lines.append('\n')
|
||||
|
||||
if i == len(lines) - 1:
|
||||
formatted_lines.append(" '{}'".format(line))
|
||||
else:
|
||||
formatted_lines.append(" '{}',\n".format(line))
|
||||
lines = formatted_lines
|
||||
|
||||
lines = '{}\n\nhiddenimports += [\n{}\n]\n'.format(src, ''.join(lines))
|
||||
if len(args) > 1:
|
||||
with open(args[1], 'w') as fh:
|
||||
fh.write(lines)
|
||||
else:
|
||||
print(lines)
|
|
@ -0,0 +1,9 @@
|
|||
from kivy.tools.packaging.pyinstaller_hooks import (
|
||||
add_dep_paths, excludedimports, datas, get_deps_all,
|
||||
get_factory_modules, kivy_modules)
|
||||
|
||||
add_dep_paths()
|
||||
|
||||
hiddenimports = [] # get_deps_all()['hiddenimports']
|
||||
hiddenimports = list(set(
|
||||
get_factory_modules() + kivy_modules + hiddenimports))
|
|
@ -0,0 +1,17 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
root = os.path.join(sys._MEIPASS, 'kivy_install')
|
||||
|
||||
os.environ['KIVY_DATA_DIR'] = os.path.join(root, 'data')
|
||||
os.environ['KIVY_MODULES_DIR'] = os.path.join(root, 'modules')
|
||||
os.environ['GST_PLUGIN_PATH'] = '{}{}{}'.format(
|
||||
sys._MEIPASS, os.pathsep, os.path.join(sys._MEIPASS, 'gst-plugins'))
|
||||
os.environ['GST_REGISTRY'] = os.path.join(sys._MEIPASS, 'registry.bin')
|
||||
|
||||
sys.path += [os.path.join(root, '_libs')]
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
sitepackages = os.path.join(sys._MEIPASS, 'sitepackages')
|
||||
sys.path += [sitepackages, os.path.join(sitepackages, 'gst-0.10')]
|
||||
os.putenv('GST_REGISTRY_FORK', 'no')
|
|
@ -0,0 +1,109 @@
|
|||
import sys
|
||||
from os import walk
|
||||
from os.path import isdir, join, normpath
|
||||
|
||||
import pep8
|
||||
|
||||
|
||||
pep8_ignores = (
|
||||
'E125', # continuation line does not
|
||||
# distinguish itself from next logical line
|
||||
'E126', # continuation line over-indented for hanging indent
|
||||
'E127', # continuation line over-indented for visual indent
|
||||
'E128', # continuation line under-indented for visual indent
|
||||
'E402', # module level import not at top of file
|
||||
'E741', # ambiguous variable name
|
||||
'E731', # do not assign a lambda expression, use a def
|
||||
'W503', # allow putting binary operators after line split
|
||||
)
|
||||
|
||||
|
||||
class KivyStyleChecker(pep8.Checker):
|
||||
|
||||
def __init__(self, filename):
|
||||
pep8.Checker.__init__(self, filename, ignore=pep8_ignores)
|
||||
|
||||
def report_error(self, line_number, offset, text, check):
|
||||
return pep8.Checker.report_error(
|
||||
self, line_number, offset, text, check)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("DEPRECATED: Use pre-commit.com framework instead: ",
|
||||
"pip install pre-commit && make hook")
|
||||
|
||||
def usage():
|
||||
print('Usage: python pep8kivy.py <file_or_folder_to_check>*')
|
||||
print('Folders will be checked recursively.')
|
||||
sys.exit(1)
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
usage()
|
||||
elif sys.argv == 2:
|
||||
targets = sys.argv[-1]
|
||||
else:
|
||||
targets = sys.argv[-1].split()
|
||||
|
||||
def check(fn):
|
||||
try:
|
||||
checker = KivyStyleChecker(fn)
|
||||
except IOError:
|
||||
# File couldn't be opened, so was deleted apparently.
|
||||
# Don't check deleted files.
|
||||
return 0
|
||||
return checker.check_all()
|
||||
|
||||
errors = 0
|
||||
|
||||
exclude_dirs = [
|
||||
'kivy/lib',
|
||||
'kivy/deps',
|
||||
'kivy/tools/pep8checker',
|
||||
'coverage',
|
||||
'doc'
|
||||
]
|
||||
exclude_dirs = [normpath(i) for i in exclude_dirs]
|
||||
exclude_files = [
|
||||
'kivy/gesture.py',
|
||||
'kivy/tools/stub-gl-debug.py',
|
||||
'kivy/modules/webdebugger.py',
|
||||
'kivy/modules/_webdebugger.py'
|
||||
]
|
||||
exclude_files = [normpath(i) for i in exclude_files]
|
||||
|
||||
for target in targets:
|
||||
if isdir(target):
|
||||
for dirpath, dirnames, filenames in walk(target):
|
||||
cont = False
|
||||
dpath = normpath(dirpath)
|
||||
for pat in exclude_dirs:
|
||||
if dpath.startswith(pat):
|
||||
cont = True
|
||||
break
|
||||
if cont:
|
||||
continue
|
||||
for filename in filenames:
|
||||
if not filename.endswith('.py'):
|
||||
continue
|
||||
cont = False
|
||||
complete_filename = join(dirpath, filename)
|
||||
for pat in exclude_files:
|
||||
if complete_filename.endswith(pat):
|
||||
cont = True
|
||||
if cont:
|
||||
continue
|
||||
|
||||
errors += check(complete_filename)
|
||||
|
||||
else:
|
||||
# Got a single file to check
|
||||
for pat in exclude_dirs + exclude_files:
|
||||
if pat in target:
|
||||
break
|
||||
else:
|
||||
if target.endswith('.py'):
|
||||
errors += check(target)
|
||||
|
||||
if errors:
|
||||
print("Error: {} style guide violation(s) encountered.".format(errors))
|
||||
sys.exit(1)
|
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env python
|
||||
'''
|
||||
Kivy Git Pre-Commit Hook to Enforce Styleguide
|
||||
==============================================
|
||||
|
||||
DEPRECATED: Use pre-commit.com framework instead:
|
||||
`pip install pre-commit && make hook`
|
||||
|
||||
This script is not supposed to be run directly.
|
||||
Instead, copy it to your kivy/.git/hooks/ directory, call it 'pre-commit'
|
||||
and make it executable.
|
||||
|
||||
If you attempt to commit, git will run this script, which in turn will run
|
||||
the styleguide checker over your code and abort the commit if there are any
|
||||
errors. If that happens, please fix & retry.
|
||||
|
||||
To install::
|
||||
|
||||
cp kivy/tools/pep8checker/pre-commit.githook .git/hooks/pre-commit
|
||||
chmod +x .git/hooks/pre-commit
|
||||
'''
|
||||
|
||||
import os
|
||||
import sys
|
||||
from os.path import dirname, abspath, sep, join
|
||||
from subprocess import call, Popen, PIPE
|
||||
|
||||
curdir = dirname(abspath(__file__))
|
||||
kivydir = sep.join(curdir.split(sep)[:-2])
|
||||
srcdir = join(kivydir, 'kivy')
|
||||
script = join(srcdir, 'tools', 'pep8checker', 'pep8kivy.py')
|
||||
try:
|
||||
with open(script):
|
||||
pass
|
||||
except IOError:
|
||||
# if this not the kivy project, find the script file in the kivy project
|
||||
os.environ['KIVY_NO_CONSOLELOG'] = '1'
|
||||
import kivy
|
||||
script = join(dirname(kivy.__file__), 'tools', 'pep8checker', 'pep8kivy.py')
|
||||
srcdir = ''
|
||||
|
||||
# Only check the files that were staged
|
||||
# proc = Popen(['git', 'diff', '--cached', '--name-only', 'HEAD'], stdout=PIPE)
|
||||
# targets = [join(kivydir, target) for target in proc.stdout]
|
||||
|
||||
# Correction: only check the files that were staged, but do not include
|
||||
# deleted files.
|
||||
proc = Popen(['git', 'diff', '--cached', '--name-status', 'HEAD'], stdout=PIPE)
|
||||
proc.wait()
|
||||
|
||||
# This gives output like the following:
|
||||
#
|
||||
# A examples/widgets/lists/list_simple_in_kv.py
|
||||
# A examples/widgets/lists/list_simple_in_kv_2.py
|
||||
# D kivy/uix/observerview.py
|
||||
#
|
||||
# So check for D entries and remove them from targets.
|
||||
#
|
||||
targets = []
|
||||
for target in proc.stdout:
|
||||
parts = [p.strip() for p in target.split()]
|
||||
if parts[0] != 'D':
|
||||
targets.append(join(kivydir, target.decode(encoding='UTF-8')))
|
||||
|
||||
# Untested possibility: After making the changes above for removing deleted
|
||||
# files from targets, saw also where the git diff call could be:
|
||||
#
|
||||
# git diff --cached --name-only --diff-filter=ACM
|
||||
# (leaving off D)
|
||||
#
|
||||
# and we could then remove the special handling in python for targets above.
|
||||
|
||||
call(['git', 'stash', 'save', '--keep-index', '--quiet'])
|
||||
retval = call([sys.executable, script, srcdir] + targets)
|
||||
call(['git', 'stash', 'pop', '--quiet'])
|
||||
|
||||
if retval:
|
||||
# There are style guide violations
|
||||
print("Your commit has been aborted. Please fix the violations and retry.")
|
||||
sys.exit(1)
|
|
@ -0,0 +1,34 @@
|
|||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
default_language_version:
|
||||
python: python3
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.0.1
|
||||
hooks:
|
||||
- id: no-commit-to-branch
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-ast
|
||||
- id: check-merge-conflict
|
||||
- id: check-toml
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
- id: check-added-large-files
|
||||
- id: check-case-conflict
|
||||
- id: check-json
|
||||
- id: check-symlinks
|
||||
- id: pretty-format-json
|
||||
args:
|
||||
- --autofix
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 3.8.4
|
||||
hooks:
|
||||
- id: flake8
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: v1.1.7
|
||||
hooks:
|
||||
- id: forbid-crlf
|
||||
- id: remove-crlf
|
||||
- id: forbid-tabs
|
||||
- id: remove-tabs
|
223
kivy_venv/lib/python3.11/site-packages/kivy/tools/report.py
Normal file
|
@ -0,0 +1,223 @@
|
|||
'''
|
||||
Report tool
|
||||
===========
|
||||
|
||||
This tool is a helper for users. It can be used to dump information
|
||||
for help during the debugging process.
|
||||
|
||||
'''
|
||||
|
||||
import os
|
||||
import sys
|
||||
import platform as plf
|
||||
from time import ctime
|
||||
from configparser import ConfigParser
|
||||
from io import StringIO
|
||||
|
||||
import kivy
|
||||
|
||||
report = []
|
||||
report_dict = {} # One key value pair for each title.
|
||||
|
||||
|
||||
def title(t):
|
||||
report.append('')
|
||||
report.append('=' * 80)
|
||||
report.append(t)
|
||||
report.append('=' * 80)
|
||||
report.append('')
|
||||
|
||||
# This method sends report to gist(Different file in a single gist) and
|
||||
# returns the URL
|
||||
|
||||
|
||||
def send_report(dict_report):
|
||||
import requests
|
||||
import json
|
||||
|
||||
gist_report = {
|
||||
"description": "Report",
|
||||
"public": "true",
|
||||
"files": {
|
||||
"Global.txt": {
|
||||
"content": "\n".join(dict_report['Global']),
|
||||
"type": 'text'
|
||||
},
|
||||
"OpenGL.txt": {
|
||||
"content": "\n".join(dict_report['OpenGL']),
|
||||
"type": 'text'
|
||||
|
||||
},
|
||||
"Core selection.txt": {
|
||||
"content": "\n".join(dict_report['Core']),
|
||||
"type": 'text'
|
||||
},
|
||||
"Libraries.txt": {
|
||||
"content": "\n".join(dict_report['Libraries']),
|
||||
"type": 'text'
|
||||
},
|
||||
"Configuration.txt": {
|
||||
"content": "\n".join(dict_report['Configuration']),
|
||||
"type": 'text'
|
||||
},
|
||||
"Input Availability.txt": {
|
||||
"content": "\n".join(dict_report['InputAvailability']),
|
||||
"type": 'text'
|
||||
},
|
||||
"Environ.txt": {
|
||||
"content": "\n".join(dict_report['Environ']),
|
||||
"type": 'text'
|
||||
},
|
||||
"Options.txt": {
|
||||
"content": "\n".join(dict_report['Options']),
|
||||
"type": 'text'
|
||||
},
|
||||
}
|
||||
}
|
||||
report_json = json.dumps(gist_report)
|
||||
response = requests.post("https://api.github.com/gists", report_json)
|
||||
return json.loads(response.text)['html_url']
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Start output debugging
|
||||
# ----------------------------------------------------------
|
||||
|
||||
|
||||
title('Global')
|
||||
report.append('OS platform : %s | %s' % (plf.platform(), plf.machine()))
|
||||
report.append('Python EXE : %s' % sys.executable)
|
||||
report.append('Python Version : %s' % sys.version)
|
||||
report.append('Python API : %s' % sys.api_version)
|
||||
report.append('Kivy Version : %s' % kivy.__version__)
|
||||
report.append('Install path : %s' % os.path.dirname(kivy.__file__))
|
||||
report.append('Install date : %s' % ctime(os.path.getctime(kivy.__file__)))
|
||||
report_dict['Global'] = report
|
||||
report = []
|
||||
|
||||
title('OpenGL')
|
||||
from kivy.core import gl
|
||||
from kivy.core.window import Window
|
||||
report.append('GL Vendor: %s' % gl.glGetString(gl.GL_VENDOR))
|
||||
report.append('GL Renderer: %s' % gl.glGetString(gl.GL_RENDERER))
|
||||
report.append('GL Version: %s' % gl.glGetString(gl.GL_VERSION))
|
||||
ext = None
|
||||
try:
|
||||
gl.glGetString(gl.GL_EXTENSIONS)
|
||||
except AttributeError:
|
||||
pass
|
||||
if ext is None:
|
||||
report.append('GL Extensions: %s' % ext)
|
||||
else:
|
||||
report.append('GL Extensions:')
|
||||
for x in ext.split():
|
||||
report.append('\t%s' % x)
|
||||
Window.close()
|
||||
report_dict['OpenGL'] = report
|
||||
report = []
|
||||
|
||||
title('Core selection')
|
||||
from kivy.core.audio import SoundLoader
|
||||
report.append('Audio = %s' % SoundLoader._classes)
|
||||
from kivy.core.camera import Camera
|
||||
report.append('Camera = %s' % Camera)
|
||||
from kivy.core.image import ImageLoader
|
||||
report.append('Image = %s' % ImageLoader.loaders)
|
||||
from kivy.core.text import Label
|
||||
report.append('Text = %s' % Label)
|
||||
from kivy.core.video import Video
|
||||
report.append('Video = %s' % Video)
|
||||
report.append('Window = %s' % Window)
|
||||
report_dict['Core'] = report
|
||||
report = []
|
||||
|
||||
title('Libraries')
|
||||
|
||||
|
||||
def testimport(libname):
|
||||
try:
|
||||
lib = __import__(libname)
|
||||
report.append('%-20s exist at %s' % (libname, lib.__file__))
|
||||
except ImportError:
|
||||
report.append('%-20s is missing' % libname)
|
||||
|
||||
|
||||
for x in ('gst',
|
||||
'pygame',
|
||||
'pygame.midi',
|
||||
'squirtle',
|
||||
'PIL',
|
||||
'sdl2',
|
||||
'glew',
|
||||
'opencv',
|
||||
'opencv.cv',
|
||||
'opencv.highgui',
|
||||
'cython'):
|
||||
testimport(x)
|
||||
report_dict['Libraries'] = report
|
||||
report = []
|
||||
|
||||
title('Configuration')
|
||||
s = StringIO()
|
||||
from kivy.config import Config
|
||||
ConfigParser.write(Config, s)
|
||||
report.extend(s.getvalue().split('\n'))
|
||||
report_dict['Configuration'] = report
|
||||
report = []
|
||||
|
||||
title('Input availability')
|
||||
from kivy.input.factory import MotionEventFactory
|
||||
for x in MotionEventFactory.list():
|
||||
report.append(x)
|
||||
report_dict['InputAvailability'] = report
|
||||
report = []
|
||||
|
||||
'''
|
||||
title('Log')
|
||||
for x in pymt_logger_history.history:
|
||||
report.append(x.message)
|
||||
'''
|
||||
|
||||
title('Environ')
|
||||
for k, v in os.environ.items():
|
||||
report.append('%s = %s' % (k, v))
|
||||
report_dict['Environ'] = report
|
||||
report = []
|
||||
|
||||
title('Options')
|
||||
for k, v in kivy.kivy_options.items():
|
||||
report.append('%s = %s' % (k, v))
|
||||
report_dict['Options'] = report
|
||||
report = []
|
||||
|
||||
# Prints the entire Output
|
||||
print('\n'.join(report_dict['Global'] + report_dict['OpenGL'] +
|
||||
report_dict['Core'] + report_dict['Libraries'] +
|
||||
report_dict['Configuration'] +
|
||||
report_dict['InputAvailability'] +
|
||||
report_dict['Environ'] + report_dict['Options']))
|
||||
print('\n')
|
||||
print('\n')
|
||||
|
||||
try:
|
||||
print('The report will be sent as an anonymous gist.')
|
||||
reply = input(
|
||||
'Do you accept to send report to https://gist.github.com/ (Y/n) : ')
|
||||
except EOFError:
|
||||
sys.exit(0)
|
||||
|
||||
if reply.lower().strip() in ('', 'y'):
|
||||
print('Please wait while sending the report...')
|
||||
|
||||
paste_url = send_report(report_dict)
|
||||
|
||||
print('\n')
|
||||
print('\n')
|
||||
print('REPORT posted at %s' % paste_url)
|
||||
print('\n')
|
||||
print('\n')
|
||||
else:
|
||||
print('No report posted.')
|
||||
|
||||
# On windows system, the console leave directly after the end
|
||||
# of the dump. That's not cool if we want get report url
|
||||
input('Enter any key to leave.')
|
|
@ -0,0 +1,201 @@
|
|||
# flake8: noqa
|
||||
from __future__ import print_function
|
||||
|
||||
a = '''cdef void glActiveTexture (cgl.GLenum texture)
|
||||
cdef void glAttachShader (cgl.GLuint program, cgl.GLuint shader)
|
||||
cdef void glBindAttribLocation (cgl.GLuint program, cgl.GLuint index, cgl.GLchar* name)
|
||||
cdef void glBindBuffer (cgl.GLenum target, cgl.GLuint buffer)
|
||||
cdef void glBindFramebuffer (cgl.GLenum target, cgl.GLuint framebuffer)
|
||||
cdef void glBindRenderbuffer (cgl.GLenum target, cgl.GLuint renderbuffer)
|
||||
cdef void glBindTexture (cgl.GLenum target, cgl.GLuint texture)
|
||||
cdef void glBlendColor (cgl.GLclampf red, cgl.GLclampf green, cgl.GLclampf blue, cgl.GLclampf alpha)
|
||||
cdef void glBlendEquation (cgl.GLenum mode)
|
||||
cdef void glBlendEquationSeparate (cgl.GLenum modeRGB, cgl.GLenum modeAlpha)
|
||||
cdef void glBlendFunc (cgl.GLenum sfactor, cgl.GLenum dfactor)
|
||||
cdef void glBlendFuncSeparate (cgl.GLenum srcRGB, cgl.GLenum dstRGB, cgl.GLenum srcAlpha, cgl.GLenum dstAlpha)
|
||||
cdef void glBufferData (cgl.GLenum target, cgl.GLsizeiptr size, cgl.GLvoid* data, cgl.GLenum usage)
|
||||
cdef void glBufferSubData (cgl.GLenum target, cgl.GLintptr offset, cgl.GLsizeiptr size, cgl.GLvoid* data)
|
||||
cdef cgl.GLenum glCheckFramebufferStatus (cgl.GLenum target)
|
||||
cdef void glClear (cgl.GLbitfield mask)
|
||||
cdef void glClearColor (cgl.GLclampf red, cgl.GLclampf green, cgl.GLclampf blue, cgl.GLclampf alpha)
|
||||
cdef void glClearDepthf (cgl.GLclampf depth)
|
||||
cdef void glClearStencil (cgl.GLint s)
|
||||
cdef void glColorMask (cgl.GLboolean red, cgl.GLboolean green, cgl.GLboolean blue, cgl.GLboolean alpha)
|
||||
cdef void glCompileShader (cgl.GLuint shader)
|
||||
cdef void glCompressedTexImage2D (cgl.GLenum target, cgl.GLint level, cgl.GLenum internalformat, cgl.GLsizei width, cgl.GLsizei height, cgl.GLint border, cgl.GLsizei imageSize, cgl.GLvoid* data)
|
||||
cdef void glCompressedTexSubImage2D (cgl.GLenum target, cgl.GLint level, cgl.GLint xoffset, cgl.GLint yoffset, cgl.GLsizei width, cgl.GLsizei height, cgl.GLenum format, cgl.GLsizei imageSize, cgl.GLvoid* data)
|
||||
cdef void glCopyTexImage2D (cgl.GLenum target, cgl.GLint level, cgl.GLenum internalformat, cgl.GLint x, cgl.GLint y, cgl.GLsizei width, cgl.GLsizei height, cgl.GLint border)
|
||||
cdef void glCopyTexSubImage2D (cgl.GLenum target, cgl.GLint level, cgl.GLint xoffset, cgl.GLint yoffset, cgl.GLint x, cgl.GLint y, cgl.GLsizei width, cgl.GLsizei height)
|
||||
cdef cgl.GLuint glCreateProgram ()
|
||||
cdef cgl.GLuint glCreateShader (cgl.GLenum type)
|
||||
cdef void glCullFace (cgl.GLenum mode)
|
||||
cdef void glDeleteBuffers (cgl.GLsizei n, cgl.GLuint* buffers)
|
||||
cdef void glDeleteFramebuffers (cgl.GLsizei n, cgl.GLuint* framebuffers)
|
||||
cdef void glDeleteProgram (cgl.GLuint program)
|
||||
cdef void glDeleteRenderbuffers (cgl.GLsizei n, cgl.GLuint* renderbuffers)
|
||||
cdef void glDeleteShader (cgl.GLuint shader)
|
||||
cdef void glDeleteTextures (cgl.GLsizei n, cgl.GLuint* textures)
|
||||
cdef void glDepthFunc (cgl.GLenum func)
|
||||
cdef void glDepthMask (cgl.GLboolean flag)
|
||||
cdef void glDepthRangef (cgl.GLclampf zNear, cgl.GLclampf zFar)
|
||||
cdef void glDetachShader (cgl.GLuint program, cgl.GLuint shader)
|
||||
cdef void glDisable (cgl.GLenum cap)
|
||||
cdef void glDisableVertexAttribArray (cgl.GLuint index)
|
||||
cdef void glDrawArrays (cgl.GLenum mode, cgl.GLint first, cgl.GLsizei count)
|
||||
cdef void glDrawElements (cgl.GLenum mode, cgl.GLsizei count, cgl.GLenum type, cgl.GLvoid* indices)
|
||||
cdef void glEnable (cgl.GLenum cap)
|
||||
cdef void glEnableVertexAttribArray (cgl.GLuint index)
|
||||
cdef void glFinish ()
|
||||
cdef void glFlush ()
|
||||
cdef void glFramebufferRenderbuffer (cgl.GLenum target, cgl.GLenum attachment, cgl.GLenum renderbuffertarget, cgl.GLuint renderbuffer)
|
||||
cdef void glFramebufferTexture2D (cgl.GLenum target, cgl.GLenum attachment, cgl.GLenum textarget, cgl.GLuint texture, cgl.GLint level)
|
||||
cdef void glFrontFace (cgl.GLenum mode)
|
||||
cdef void glGenBuffers (cgl.GLsizei n, cgl.GLuint* buffers)
|
||||
cdef void glGenerateMipmap (cgl.GLenum target)
|
||||
cdef void glGenFramebuffers (cgl.GLsizei n, cgl.GLuint* framebuffers)
|
||||
cdef void glGenRenderbuffers (cgl.GLsizei n, cgl.GLuint* renderbuffers)
|
||||
cdef void glGenTextures (cgl.GLsizei n, cgl.GLuint* textures)
|
||||
cdef void glGetActiveAttrib (cgl.GLuint program, cgl.GLuint index, cgl.GLsizei bufsize, cgl.GLsizei* length, cgl.GLint* size, cgl.GLenum* type, cgl.GLchar* name)
|
||||
cdef void glGetActiveUniform (cgl.GLuint program, cgl.GLuint index, cgl.GLsizei bufsize, cgl.GLsizei* length, cgl.GLint* size, cgl.GLenum* type, cgl.GLchar* name)
|
||||
cdef void glGetAttachedShaders (cgl.GLuint program, cgl.GLsizei maxcount, cgl.GLsizei* count, cgl.GLuint* shaders)
|
||||
cdef int glGetAttribLocation (cgl.GLuint program, cgl.GLchar* name)
|
||||
cdef void glGetBooleanv (cgl.GLenum pname, cgl.GLboolean* params)
|
||||
cdef void glGetBufferParameteriv (cgl.GLenum target, cgl.GLenum pname, cgl.GLint* params)
|
||||
cdef cgl.GLenum glGetError ()
|
||||
cdef void glGetFloatv (cgl.GLenum pname, cgl.GLfloat* params)
|
||||
cdef void glGetFramebufferAttachmentParameteriv (cgl.GLenum target, cgl.GLenum attachment, cgl.GLenum pname, cgl.GLint* params)
|
||||
cdef void glGetIntegerv (cgl.GLenum pname, cgl.GLint* params)
|
||||
cdef void glGetProgramiv (cgl.GLuint program, cgl.GLenum pname, cgl.GLint* params)
|
||||
cdef void glGetProgramInfoLog (cgl.GLuint program, cgl.GLsizei bufsize, cgl.GLsizei* length, cgl.GLchar* infolog)
|
||||
cdef void glGetRenderbufferParameteriv (cgl.GLenum target, cgl.GLenum pname, cgl.GLint* params)
|
||||
cdef void glGetShaderiv (cgl.GLuint shader, cgl.GLenum pname, cgl.GLint* params)
|
||||
cdef void glGetShaderInfoLog (cgl.GLuint shader, cgl.GLsizei bufsize, cgl.GLsizei* length, cgl.GLchar* infolog)
|
||||
#cdef void glGetShaderPrecisionFormat (cgl.GLenum shadertype, cgl.GLenum precisiontype, cgl.GLint* range, cgl.GLint* precision)
|
||||
cdef void glGetShaderSource (cgl.GLuint shader, cgl.GLsizei bufsize, cgl.GLsizei* length, cgl.GLchar* source)
|
||||
cdef cgl.GLubyte* glGetString (cgl.GLenum name)
|
||||
cdef void glGetTexParameterfv (cgl.GLenum target, cgl.GLenum pname, cgl.GLfloat* params)
|
||||
cdef void glGetTexParameteriv (cgl.GLenum target, cgl.GLenum pname, cgl.GLint* params)
|
||||
cdef void glGetUniformfv (cgl.GLuint program, cgl.GLint location, cgl.GLfloat* params)
|
||||
cdef void glGetUniformiv (cgl.GLuint program, cgl.GLint location, cgl.GLint* params)
|
||||
cdef int glGetUniformLocation (cgl.GLuint program, cgl.GLchar* name)
|
||||
cdef void glGetVertexAttribfv (cgl.GLuint index, cgl.GLenum pname, cgl.GLfloat* params)
|
||||
cdef void glGetVertexAttribiv (cgl.GLuint index, cgl.GLenum pname, cgl.GLint* params)
|
||||
cdef void glGetVertexAttribPointerv (cgl.GLuint index, cgl.GLenum pname, cgl.GLvoid** pointer)
|
||||
cdef void glHint (cgl.GLenum target, cgl.GLenum mode)
|
||||
cdef cgl.GLboolean glIsBuffer (cgl.GLuint buffer)
|
||||
cdef cgl.GLboolean glIsEnabled (cgl.GLenum cap)
|
||||
cdef cgl.GLboolean glIsFramebuffer (cgl.GLuint framebuffer)
|
||||
cdef cgl.GLboolean glIsProgram (cgl.GLuint program)
|
||||
cdef cgl.GLboolean glIsRenderbuffer (cgl.GLuint renderbuffer)
|
||||
cdef cgl.GLboolean glIsShader (cgl.GLuint shader)
|
||||
cdef cgl.GLboolean glIsTexture (cgl.GLuint texture)
|
||||
cdef void glLineWidth (cgl.GLfloat width)
|
||||
cdef void glLinkProgram (cgl.GLuint program)
|
||||
cdef void glPixelStorei (cgl.GLenum pname, cgl.GLint param)
|
||||
cdef void glPolygonOffset (cgl.GLfloat factor, cgl.GLfloat units)
|
||||
cdef void glReadPixels (cgl.GLint x, cgl.GLint y, cgl.GLsizei width, cgl.GLsizei height, cgl.GLenum format, cgl.GLenum type, cgl.GLvoid* pixels)
|
||||
#cdef void glReleaseShaderCompiler ()
|
||||
cdef void glRenderbufferStorage (cgl.GLenum target, cgl.GLenum internalformat, cgl.GLsizei width, cgl.GLsizei height)
|
||||
cdef void glSampleCoverage (cgl.GLclampf value, cgl.GLboolean invert)
|
||||
cdef void glScissor (cgl.GLint x, cgl.GLint y, cgl.GLsizei width, cgl.GLsizei height)
|
||||
#cdef void glShaderBinary (cgl.GLsizei n, cgl.GLuint* shaders, cgl.GLenum binaryformat, cgl.GLvoid* binary, cgl.GLsizei length)
|
||||
cdef void glShaderSource (cgl.GLuint shader, cgl.GLsizei count, cgl.GLchar** string, cgl.GLint* length)
|
||||
cdef void glStencilFunc (cgl.GLenum func, cgl.GLint ref, cgl.GLuint mask)
|
||||
cdef void glStencilFuncSeparate (cgl.GLenum face, cgl.GLenum func, cgl.GLint ref, cgl.GLuint mask)
|
||||
cdef void glStencilMask (cgl.GLuint mask)
|
||||
cdef void glStencilMaskSeparate (cgl.GLenum face, cgl.GLuint mask)
|
||||
cdef void glStencilOp (cgl.GLenum fail, cgl.GLenum zfail, cgl.GLenum zpass)
|
||||
cdef void glStencilOpSeparate (cgl.GLenum face, cgl.GLenum fail, cgl.GLenum zfail, cgl.GLenum zpass)
|
||||
cdef void glTexImage2D (cgl.GLenum target, cgl.GLint level, cgl.GLint internalformat, cgl.GLsizei width, cgl.GLsizei height, cgl.GLint border, cgl.GLenum format, cgl.GLenum type, cgl.GLvoid* pixels)
|
||||
cdef void glTexParameterf (cgl.GLenum target, cgl.GLenum pname, cgl.GLfloat param)
|
||||
cdef void glTexParameterfv (cgl.GLenum target, cgl.GLenum pname, cgl.GLfloat* params)
|
||||
cdef void glTexParameteri (cgl.GLenum target, cgl.GLenum pname, cgl.GLint param)
|
||||
cdef void glTexParameteriv (cgl.GLenum target, cgl.GLenum pname, cgl.GLint* params)
|
||||
cdef void glTexSubImage2D (cgl.GLenum target, cgl.GLint level, cgl.GLint xoffset, cgl.GLint yoffset, cgl.GLsizei width, cgl.GLsizei height, cgl.GLenum format, cgl.GLenum type, cgl.GLvoid* pixels)
|
||||
cdef void glUniform1f (cgl.GLint location, cgl.GLfloat x)
|
||||
cdef void glUniform1fv (cgl.GLint location, cgl.GLsizei count, cgl.GLfloat* v)
|
||||
cdef void glUniform1i (cgl.GLint location, cgl.GLint x)
|
||||
cdef void glUniform1iv (cgl.GLint location, cgl.GLsizei count, cgl.GLint* v)
|
||||
cdef void glUniform2f (cgl.GLint location, cgl.GLfloat x, cgl.GLfloat y)
|
||||
cdef void glUniform2fv (cgl.GLint location, cgl.GLsizei count, cgl.GLfloat* v)
|
||||
cdef void glUniform2i (cgl.GLint location, cgl.GLint x, cgl.GLint y)
|
||||
cdef void glUniform2iv (cgl.GLint location, cgl.GLsizei count, cgl.GLint* v)
|
||||
cdef void glUniform3f (cgl.GLint location, cgl.GLfloat x, cgl.GLfloat y, cgl.GLfloat z)
|
||||
cdef void glUniform3fv (cgl.GLint location, cgl.GLsizei count, cgl.GLfloat* v)
|
||||
cdef void glUniform3i (cgl.GLint location, cgl.GLint x, cgl.GLint y, cgl.GLint z)
|
||||
cdef void glUniform3iv (cgl.GLint location, cgl.GLsizei count, cgl.GLint* v)
|
||||
cdef void glUniform4f (cgl.GLint location, cgl.GLfloat x, cgl.GLfloat y, cgl.GLfloat z, cgl.GLfloat w)
|
||||
cdef void glUniform4fv (cgl.GLint location, cgl.GLsizei count, cgl.GLfloat* v)
|
||||
cdef void glUniform4i (cgl.GLint location, cgl.GLint x, cgl.GLint y, cgl.GLint z, cgl.GLint w)
|
||||
cdef void glUniform4iv (cgl.GLint location, cgl.GLsizei count, cgl.GLint* v)
|
||||
cdef void glUniformMatrix2fv (cgl.GLint location, cgl.GLsizei count, cgl.GLboolean transpose, cgl.GLfloat* value)
|
||||
cdef void glUniformMatrix3fv (cgl.GLint location, cgl.GLsizei count, cgl.GLboolean transpose, cgl.GLfloat* value)
|
||||
cdef void glUniformMatrix4fv (cgl.GLint location, cgl.GLsizei count, cgl.GLboolean transpose, cgl.GLfloat* value)
|
||||
cdef void glUseProgram (cgl.GLuint program)
|
||||
cdef void glValidateProgram (cgl.GLuint program)
|
||||
cdef void glVertexAttrib1f (cgl.GLuint indx, cgl.GLfloat x)
|
||||
cdef void glVertexAttrib1fv (cgl.GLuint indx, cgl.GLfloat* values)
|
||||
cdef void glVertexAttrib2f (cgl.GLuint indx, cgl.GLfloat x, cgl.GLfloat y)
|
||||
cdef void glVertexAttrib2fv (cgl.GLuint indx, cgl.GLfloat* values)
|
||||
cdef void glVertexAttrib3f (cgl.GLuint indx, cgl.GLfloat x, cgl.GLfloat y, cgl.GLfloat z)
|
||||
cdef void glVertexAttrib3fv (cgl.GLuint indx, cgl.GLfloat* values)
|
||||
cdef void glVertexAttrib4f (cgl.GLuint indx, cgl.GLfloat x, cgl.GLfloat y, cgl.GLfloat z, cgl.GLfloat w)
|
||||
cdef void glVertexAttrib4fv (cgl.GLuint indx, cgl.GLfloat* values)
|
||||
cdef void glVertexAttribPointer (cgl.GLuint indx, cgl.GLint size, cgl.GLenum type, cgl.GLboolean normalized, cgl.GLsizei stride, cgl.GLvoid* ptr)
|
||||
cdef void glViewport (cgl.GLint x, cgl.GLint y, cgl.GLsizei width, cgl.GLsizei height)'''
|
||||
|
||||
def replace(s):
|
||||
item = s.split(' ')
|
||||
rettype = item[1]
|
||||
item = item[2:]
|
||||
for x in item:
|
||||
x = x.strip()
|
||||
if not x or x.startswith('GL'):
|
||||
continue
|
||||
if x.startswith('(GL'):
|
||||
yield '('
|
||||
continue
|
||||
if x.startswith('gl'):
|
||||
prefix = ''
|
||||
if rettype != 'void':
|
||||
prefix = 'return '
|
||||
yield '%scgl.%s' % (prefix, x)
|
||||
continue
|
||||
yield x
|
||||
|
||||
print('''
|
||||
# This file was automatically generated with kivy/tools/stub-gl-debug.py
|
||||
cimport c_opengl as cgl
|
||||
|
||||
''')
|
||||
|
||||
lines = a.splitlines()
|
||||
for x in lines:
|
||||
if x.startswith('#'):
|
||||
# There are some functions that either do not exist or break on OSX.
|
||||
# Just skip those.
|
||||
print('# Skipping generation of: "%s"' % x)
|
||||
continue
|
||||
x = x.replace('cgl.', '')
|
||||
y = ' '.join(replace(x))
|
||||
|
||||
print('%s with gil:' % x)
|
||||
s = x.split()
|
||||
print(' print("GL %s(' % s[2], end=' ')
|
||||
pointer = 0
|
||||
for arg in s[3:]:
|
||||
arg = arg.strip()
|
||||
arg = arg.replace(',', '').replace(')', '')
|
||||
if 'GL' in arg or arg == '(':
|
||||
pointer = arg.count('*')
|
||||
continue
|
||||
pointer = '*' * pointer
|
||||
if pointer:
|
||||
print('%s%s=", repr(hex(<long> %s)), ",' % (arg, pointer, arg), end=' ')
|
||||
else:
|
||||
print('%s = ", %s, ",' % (arg, arg), end=' ')
|
||||
pointer = 0
|
||||
print(')")')
|
||||
print(' %s' % y)
|
||||
print(' ret = glGetError()')
|
||||
print(' if ret: print("ERR {} / {}".format(ret, ret))')
|
|
@ -0,0 +1,233 @@
|
|||
'''
|
||||
Texture compression tool
|
||||
========================
|
||||
|
||||
This tool is designed to compress images into:
|
||||
|
||||
- PVRTC (PowerVR Texture Compression), mostly iOS devices
|
||||
- ETC1 (Ericson compression), working on all GLES2/Android devices
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
In order to compress a texture::
|
||||
|
||||
texturecompress.py [--dir <directory>] <format> <image.png>
|
||||
|
||||
This will create a `image.tex` file with a json header that contains all the
|
||||
image information and the compressed data.
|
||||
|
||||
TODO
|
||||
----
|
||||
|
||||
Support more format, such as:
|
||||
|
||||
- S3TC (already supported in Kivy)
|
||||
- DXT1 (already supported in Kivy)
|
||||
'''
|
||||
|
||||
import json
|
||||
from struct import pack
|
||||
from pprint import pprint
|
||||
from subprocess import Popen
|
||||
from PIL import Image
|
||||
from argparse import ArgumentParser
|
||||
from sys import exit
|
||||
from os.path import join, exists, dirname, basename
|
||||
from os import environ, unlink
|
||||
|
||||
|
||||
class Tool(object):
|
||||
def __init__(self, options):
|
||||
super(Tool, self).__init__()
|
||||
self.options = options
|
||||
self.source_fn = options.image
|
||||
self.dest_dir = options.dir or dirname(options.image)
|
||||
|
||||
@property
|
||||
def tex_fn(self):
|
||||
fn = basename(self.source_fn).rsplit('.', 1)[0] + '.tex'
|
||||
return join(self.dest_dir, fn)
|
||||
|
||||
def compress(self):
|
||||
pass
|
||||
|
||||
def nearest_pow2(self, v):
|
||||
# Credits: Sean Anderson
|
||||
v -= 1
|
||||
v |= v >> 1
|
||||
v |= v >> 2
|
||||
v |= v >> 4
|
||||
v |= v >> 8
|
||||
v |= v >> 16
|
||||
return v + 1
|
||||
|
||||
def runcmd(self, cmd):
|
||||
print('Run: {}'.format(' '.join(cmd)))
|
||||
Popen(cmd).communicate()
|
||||
|
||||
def write_tex(self, data, fmt, image_size, texture_size, mipmap=False,
|
||||
formatinfo=None):
|
||||
infos = {
|
||||
'datalen': len(data),
|
||||
'image_size': image_size,
|
||||
'texture_size': texture_size,
|
||||
'mipmap': mipmap,
|
||||
'format': fmt}
|
||||
if formatinfo:
|
||||
infos['formatinfo'] = formatinfo
|
||||
header = json.dumps(infos, indent=0, separators=(',', ':'))
|
||||
header = header.replace('\n', '')
|
||||
with open(self.tex_fn, 'wb') as fd:
|
||||
fd.write('KTEX')
|
||||
fd.write(pack('I', len(header)))
|
||||
fd.write(header)
|
||||
fd.write(data)
|
||||
|
||||
print('Done! Compressed texture written at {}'.format(self.tex_fn))
|
||||
pprint(infos)
|
||||
|
||||
@staticmethod
|
||||
def run():
|
||||
parser = ArgumentParser(
|
||||
description='Convert images to compressed texture')
|
||||
parser.add_argument('--mipmap', type=bool, default=False,
|
||||
help='Auto generate mipmaps')
|
||||
parser.add_argument('--dir', type=str, default=None,
|
||||
help='Output directory to generate the compressed texture')
|
||||
parser.add_argument('format', type=str, choices=['pvrtc', 'etc1'],
|
||||
help='Format of the final texture')
|
||||
parser.add_argument('image', type=str,
|
||||
help='Image filename')
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.format == 'pvrtc':
|
||||
PvrtcTool(args).compress()
|
||||
elif args.format == 'etc1':
|
||||
Etc1Tool(args).compress()
|
||||
else:
|
||||
print('Unknown compression format')
|
||||
exit(1)
|
||||
|
||||
|
||||
class Etc1Tool(Tool):
|
||||
def __init__(self, options):
|
||||
super(Etc1Tool, self).__init__(options)
|
||||
self.etc1tool = None
|
||||
self.locate_etc1tool()
|
||||
|
||||
def locate_etc1tool(self):
|
||||
search_directories = [environ.get('ANDROIDSDK', '/')]
|
||||
search_directories += environ.get('PATH', '').split(':')
|
||||
for directory in search_directories:
|
||||
fn = join(directory, 'etc1tool')
|
||||
if not exists(fn):
|
||||
fn = join(directory, 'tools', 'etc1tool')
|
||||
if not exists(fn):
|
||||
continue
|
||||
print('Found texturetool at {}'.format(directory))
|
||||
self.etc1tool = fn
|
||||
return
|
||||
|
||||
if self.etc1tool is None:
|
||||
print('Error: Unable to locate "etc1tool".\n'
|
||||
'Make sure that "etc1tool" is available in your PATH.\n'
|
||||
'Or export the path of your Android SDK to ANDROIDSDK')
|
||||
exit(1)
|
||||
|
||||
def compress(self):
|
||||
# 1. open the source image, and get the dimensions
|
||||
image = Image.open(self.source_fn)
|
||||
w, h = image.size
|
||||
print('Image size is {}x{}'.format(*image.size))
|
||||
|
||||
# 2. search the nearest 2^
|
||||
w2 = self.nearest_pow2(w)
|
||||
h2 = self.nearest_pow2(h)
|
||||
print('Nearest power-of-2 size is {}x{}'.format(w2, h2))
|
||||
|
||||
# 3. invoke etc1tool
|
||||
raw_tex_fn = self.tex_fn + '.raw'
|
||||
cmd = [self.etc1tool, self.source_fn, '--encodeNoHeader', '-o',
|
||||
raw_tex_fn]
|
||||
try:
|
||||
self.runcmd(cmd)
|
||||
with open(raw_tex_fn, 'rb') as fd:
|
||||
data = fd.read()
|
||||
finally:
|
||||
if exists(raw_tex_fn):
|
||||
unlink(raw_tex_fn)
|
||||
|
||||
# 5. write texture info
|
||||
self.write_tex(data, 'etc1_rgb8', (w, h), (w2, h2),
|
||||
self.options.mipmap)
|
||||
|
||||
|
||||
class PvrtcTool(Tool):
|
||||
def __init__(self, options):
|
||||
super(PvrtcTool, self).__init__(options)
|
||||
self.texturetool = None
|
||||
self.locate_texturetool()
|
||||
|
||||
def locate_texturetool(self):
|
||||
search_directories = [
|
||||
('/Applications/Xcode.app/Contents/Developer/Platforms/'
|
||||
'iPhoneOS.platform/Developer/usr/bin/'),
|
||||
'/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/']
|
||||
search_directories += environ.get('PATH', '').split(':')
|
||||
|
||||
for directory in search_directories:
|
||||
fn = join(directory, 'texturetool')
|
||||
if not exists(fn):
|
||||
continue
|
||||
print('Found texturetool at {}'.format(directory))
|
||||
self.texturetool = fn
|
||||
return
|
||||
|
||||
print('Error: Unable to locate "texturetool".\n'
|
||||
'Please install the iPhone SDK, or the PowerVR SDK.\n'
|
||||
'Then make sure that "texturetool" is available in your PATH.')
|
||||
exit(1)
|
||||
|
||||
def compress(self):
|
||||
# 1. open the source image, and get the dimensions
|
||||
image = Image.open(self.source_fn)
|
||||
w, h = image.size
|
||||
print('Image size is {}x{}'.format(*image.size))
|
||||
|
||||
# 2. search the nearest 2^
|
||||
w2 = self.nearest_pow2(w)
|
||||
h2 = self.nearest_pow2(h)
|
||||
print('Nearest power-of-2 size is {}x{}'.format(w2, h2))
|
||||
|
||||
# 3. for PVR, the image MUST be a square. use the bigger size then
|
||||
s2 = max(w2, h2)
|
||||
print('PVR need a square image, the texture will be {0}x{0}'
|
||||
.format(s2))
|
||||
|
||||
ext = self.source_fn.rsplit('.', 1)[-1]
|
||||
tmpfile = '/tmp/ktexturecompress.{}'.format(ext)
|
||||
image = image.resize((s2, s2))
|
||||
image.save(tmpfile)
|
||||
|
||||
# 4. invoke texture tool
|
||||
raw_tex_fn = self.tex_fn + '.raw'
|
||||
cmd = [self.texturetool]
|
||||
if self.options.mipmap:
|
||||
cmd += ['-m']
|
||||
cmd += ['-e', 'PVRTC', '-o', raw_tex_fn, '-f', 'RAW', tmpfile]
|
||||
try:
|
||||
self.runcmd(cmd)
|
||||
with open(raw_tex_fn, 'rb') as fd:
|
||||
data = fd.read()
|
||||
finally:
|
||||
if exists(raw_tex_fn):
|
||||
unlink(raw_tex_fn)
|
||||
|
||||
# 5. write texture info
|
||||
self.write_tex(data, 'pvrtc_rgba4', (w, h), (s2, s2),
|
||||
self.options.mipmap)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
Tool.run()
|
After Width: | Height: | Size: 86 B |
After Width: | Height: | Size: 181 B |
After Width: | Height: | Size: 168 B |
After Width: | Height: | Size: 330 B |
After Width: | Height: | Size: 82 B |
After Width: | Height: | Size: 96 B |
After Width: | Height: | Size: 82 B |
After Width: | Height: | Size: 528 B |
After Width: | Height: | Size: 425 B |
After Width: | Height: | Size: 478 B |
After Width: | Height: | Size: 477 B |
After Width: | Height: | Size: 332 B |
After Width: | Height: | Size: 179 B |
After Width: | Height: | Size: 96 B |
After Width: | Height: | Size: 178 B |
After Width: | Height: | Size: 190 B |
After Width: | Height: | Size: 182 B |
After Width: | Height: | Size: 222 B |
After Width: | Height: | Size: 223 B |
After Width: | Height: | Size: 158 B |
After Width: | Height: | Size: 296 B |
After Width: | Height: | Size: 121 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 213 B |
After Width: | Height: | Size: 429 B |
After Width: | Height: | Size: 225 B |
After Width: | Height: | Size: 693 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 434 B |
After Width: | Height: | Size: 134 B |
After Width: | Height: | Size: 279 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 700 B |
After Width: | Height: | Size: 99 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 204 B |
After Width: | Height: | Size: 692 B |
After Width: | Height: | Size: 123 B |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 72 B |