first commit

This commit is contained in:
Yura 2024-09-15 15:12:16 +03:00
commit 417e54da96
5696 changed files with 900003 additions and 0 deletions

View file

@ -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.
"""

View 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.')

View file

@ -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:])

View 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())

View 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()

View file

@ -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()

View file

@ -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_ */

View file

@ -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')

View file

@ -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.
'''

View file

@ -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

View file

@ -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"
}

View file

@ -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>\&lt;.+\&gt;</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>

View file

@ -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"

View file

@ -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

View file

@ -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()

View file

@ -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

View 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()

View file

@ -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/>`_
'''

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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))

View file

@ -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')

File diff suppressed because it is too large Load diff

View file

@ -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)

View file

@ -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)

View file

@ -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

View 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.')

View file

@ -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))')

View file

@ -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()

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 B

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