Compare commits

..

43 Commits

Author SHA1 Message Date
Tom Rothamel 7422fe43b8 Fix a bug building mac distributions on windows.
Ready 6.8.0d.
2008-10-17 10:06:57 -04:00
Tom Rothamel 879c45a5b3 Releasing 6.8.0c 2008-10-15 15:43:29 -04:00
Tom Rothamel db0d205374 Added BMFont support. 2008-10-15 15:36:05 -04:00
Tom Rothamel f20594a2b5 Add build_launchertrans to version control.
Remove obsolete files.
2008-10-15 12:40:26 -04:00
Tom Rothamel ee017f4bc6 The launcher now deals better with long project names.
The launcher now warns if java is missing.
2008-10-14 21:20:14 -04:00
Tom Rothamel 4d089f9a0e Fixed various editor bugs. 2008-10-14 19:35:02 -04:00
Tom Rothamel e7f9c5c2ac Making ready for 6.8.0b 2008-10-14 17:43:31 -04:00
Tom Rothamel 2df8d38c2f Add config.missing_background. 2008-10-14 17:36:51 -04:00
Tom Rothamel 17ac44d610 Ren'Py now supports the MudgeFont image-based file format. The new
renpy.register_mudgefont function is used to register a
MudgeFont.
2008-10-14 17:30:56 -04:00
Tom Rothamel 3c52c2ae3f Fixed positioning of 640x480 preferences. 2008-10-14 16:29:45 -04:00
Tom Rothamel 5a5115e29f Fixed a problem with outlines and bold/italic text. 2008-10-14 16:07:29 -04:00
Tom Rothamel 5c7ff1c97b Fixed a bug that prevented styles from being rebuilt. 2008-10-13 23:19:04 -04:00
Tom Rothamel cc820a3595 Fix bugs pointed out by delta at:
http://lemmasoft.renai.us/forums/viewtopic.php?p=58835#p58835
2008-10-13 22:49:23 -04:00
Tom Rothamel 48fff48d28 Updated tag script. 2008-10-13 17:59:53 -04:00
Tom Rothamel 1684243e57 Finalizing 6.8.0 2008-10-13 17:56:13 -04:00
Tom Rothamel 45e14781eb Custom mouse cursors should now be properly hidden when the mouse
leaves the window. Previously, this failed to work on the Mac OS X
platform.
2008-10-13 16:02:53 -04:00
Tom Rothamel 5ceea7b4a5 The new unscrollable style property allows one to choose how
unscrollbable scrollbars are displays. None keeps the current
behavior, which shows the bar normally. If set to "insensitive", the
bar becomes insensitive, while if set to "hide", the bar is not 
drawn at all.
2008-10-13 13:32:27 -04:00
Tom Rothamel 17e716b4c3 The presplash code now looks for presplash.jpg in the game directory
if presplash.png is not found.
2008-10-13 10:53:04 -04:00
Tom Rothamel adfdbf3246 Added icons to The Question. 2008-10-13 02:17:15 -04:00
Tom Rothamel 03b757d60e Added more files into bzr.
Fixed problem with pefile.py not being able to resize the resource segment... now it can.
2008-10-13 01:43:30 -04:00
Tom Rothamel 12c6d77990 Moved to bazaar. Added file to ignore temporaries and generated code. 2008-10-12 22:57:21 -04:00
Tom Rothamel 8a7373f412 Adding some files to subversion. 2008-10-13 00:08:29 +00:00
Tom Rothamel df28ff5bdc Updated distribute.py to respect new launcher directory. 2008-10-12 22:15:28 +00:00
Tom Rothamel 2afc2beb5d Refactored font code out into its own file.
Replaced asfont with a new font.

Updated the demo, generally got things ready for release.
2008-10-12 17:31:00 +00:00
Tom Rothamel 3896bf3aad Newly-created games will have a Help option on the main and game
menus. This is controlled by the config.help variable. By default 
the help system shows the README.html file in the game's base directory.

The new RENPY_SCREENSHOT_PATTERN environment variable lets you
configure the name of screenshot files. Ren'Py can now write out
screenshots as JPGs, as well as PNGs.
2008-10-11 18:52:37 +00:00
Tom Rothamel 744ace5ab6 Alt-f4 and Alt-q now trigger the quit event, as if you pressed the
quit button on the top of the window. The first press brings up the 
quit prompt, and a second press forcibly terminates the game. Alt
is mapped to Command on the Mac, so Command-q now works on Macintosh.

Alt/Command-h hides (iconifies) the window.
2008-10-10 19:51:53 +00:00
Tom Rothamel 4bf0b74b6c update changelog 2008-10-10 15:15:42 +00:00
Tom Rothamel 5c6e624ff7 If the file icon.ico is present in the base directory, it will be used
as the icon of the windows exe when building the windows
distribution. Similarly, the file icon.icns will be used as the icon
of the Macintosh application. (Note that .icns is a different file format 
from .ico.)

The Macintosh application will now show the name of the game in the 
menu bar, rather than "Ren'Py Launcher".
2008-10-10 15:09:44 +00:00
Tom Rothamel 6c0d5a7a10 Move launcher directory. 2008-10-10 13:52:45 +00:00
Tom Rothamel b34cb21f0c The newly-documented Style.set_parent method lets you change the
parent of a style. The new style.rebuild function allows styles to be
rebuilt even after the game has begun running, with some
caveats. (Changes are not persisted, for one thing.)


The new renpy.easy_displayable method can be used by user-defined
displayables to convert strings into Solid or Image displayables.
2008-10-10 13:51:55 +00:00
Tom Rothamel b77eb7ed0b When config.developer is set and an undefined image is used in a show
or scene statement, a list of undefined images will appear centered at
the top of the screen. A black screen will be show instead of any missing
background. This makes it easier to write a script before all images are
present.
2008-10-10 12:59:27 +00:00
Tom Rothamel 34193c510e Fixed problem with bytecode.rpyb being opened in ascii mode. Once again, I hate windows. 2008-10-08 16:05:07 +00:00
Tom Rothamel 55f1eaf5da There is now a new justify style property, that causes lines of text
to have additional whitespace inserted between words so that the left
and right margins are even, except on the last line of a paragraph.
2008-10-05 21:31:00 +00:00
Tom Rothamel 9b74b5a367 * Outlined text is now possible. The new outlines style property
allows you to specify one or more outlines, including offset
ones. This allows for several fairly complicated text effects, similar
to what you'd see in modern subtitles. [demo]

* We believe the bug preventing fonts from being archived has been
fixed. It should now be possible to include a font in an archive, and
have that work. The archiver has been modified to allow this.
2008-10-04 16:09:13 +00:00
Tom Rothamel 008922edc6 Added support for one or more outlines around text. This allows the
sort of text effects one sees in modern subtitles.
2008-10-04 02:00:42 +00:00
Tom Rothamel 82edca785f Added _renpy_font module. 2008-10-04 00:52:04 +00:00
Tom Rothamel b271baecd5 2008-10-03 21:20:12 +00:00
Tom Rothamel 9b48cd2a35 Adding font stuff. 2008-10-03 19:42:16 +00:00
Tom Rothamel 183f6ace88 2008-10-01 20:23:40 +00:00
Tom Rothamel b5987cd6ea Minor editing fixes. 2008-10-01 20:21:55 +00:00
Tom Rothamel 6e153a5070 ready for 6.7.1c 2008-09-28 15:12:31 +00:00
Tom Rothamel 56e59d91dd The Question art refresh 2008-09-28 14:45:00 +00:00
Tom Rothamel fd91c6811f The new renpy.copy_images function copies images with one prefix to a
second prefix.
2008-09-27 03:06:04 +00:00
74 changed files with 4682 additions and 9340 deletions
+30
View File
@@ -0,0 +1,30 @@
build
dist
dists
renpy.app
**/*.rpyc
**/*.rpyb
**/*.rpymc
_renpy.c
nativemidi.c
sound.c
winmixer.c
jedit
lint.txt
renpy.code
traceback.txt
doc/common.css
doc/images
doc/index.html
doc/monobook.css
doc/monobook2.css
doc/reference
doc/shared.css
doc/tutorials
doc/www.renpy.org
testing
translations.rpy
launchertrans.rpy
jcc
scite/scite.zip
screenshot*
BIN
View File
Binary file not shown.
+122
View File
@@ -1,3 +1,116 @@
New in Ren'Py 6.8.0
-------------------
Ren'Py now includes its own font-handling library, derived from
pygame.font/SDL_ttf, which it uses in place of them when
possible. This gives two advantages:
* Outlined text is now possible. The new outlines style property
allows you to specify one or more outlines, including offset
ones. This allows for several fairly complicated text effects, similar
to what you'd see in modern subtitles.
* The bug preventing fonts from being archived has probably been
fixed. It should now be possible to include a font in an archive, and
have that work. The archiver has been modified to allow ttf files to
be archived again. Please report any bugs/crashes that occur.
There is now a new justify style property, that causes lines of text
to have additional whitespace inserted between words so that the left
and right margins are even, except on the last line of a paragraph.
Ren'Py now supports the MudgeFont and BMFont image-based font file
formats. The new renpy.register_mudgefont function is used to register
a MudgeFont, and the renpy.register_bmfon function is used to register
a BMFont.
Newly-created games will have a Help option on the main and game
menus. This is controlled by the config.help variable. By default
the help system shows the README.html file in the game's base directory.
If the file icon.ico is present in the base directory, it will be used
as the icon of the windows exe when building the windows
distribution. Similarly, the file icon.icns will be used as the icon
of the Macintosh application. (Note that .icns is a different file format
from .ico.)
On Mac OS X, Ren'Py will not change the application icon unless
config.window_icon is set. More specifically, it will default to the
launcher icon rather than a generic pygame icon.
The Macintosh application will now show the name of the game in the
menu bar, rather than "Ren'Py Launcher".
The "Continue Game" option on the main menu has been renamed "Load
Game", for consistency with the game menu.
When config.developer is set and an undefined image is used in a show
or scene statement, a list of undefined images will appear centered at
the top of the screen. A black screen (configurable with
config.missing_background) will be shown instead of any missing
background. This makes it easier to write a script before all images
are present.
The newly-documented Style.set_parent method lets you change the
parent of a style. The new style.rebuild function allows styles to be
rebuilt even after the game has begun running, with some
caveats. (Changes are not persisted, for one thing.)
The new unscrollable style property allows one to choose how
unscrollbable scrollbars are displays. None keeps the current
behavior, which shows the bar normally. If set to "insensitive", the
bar becomes insensitive, while if set to "hide", the bar is not
drawn at all.
The new renpy.easy_displayable method can be used by user-defined
displayables to convert strings into Solid or Image displayables.
Alt-F4 and Command-Q now trigger the quit event, as if you pressed the
quit button on the top of the window. The first press brings up the
quit prompt, and a second press forcibly terminates the game.
Alt-M and Command-M iconify the window.
The new RENPY_SCREENSHOT_PATTERN environment variable lets you
configure the name of screenshot files. Ren'Py can now write out
screenshots as JPGs, as well as PNGs.
Several of the libraries underlying Ren'Py have been updated. Pygame
has been updated to version 1.8.1, while Freetype is now at version
2.3.7.
The presplash code now looks for presplash.jpg in the game directory
if presplash.png is not found.
On Windows, config.window_icon will be scaled to 32x32 if it is wider
than 32 pixels. This allows the same icon to be used across platforms.
Custom mouse cursors should now be properly hidden when the mouse
leaves the window. Previously, this failed to work on the Mac OS X
platform.
The launcher has been moved into the launcher/ directory. This really
shouldn't matter much, but may affect packaging and translation.
New in Ren'Py 6.7.1
-------------------
@@ -48,11 +161,20 @@ what to archive. This makes it easier to break the files up into
multiple archives, in a single game.
The new renpy.copy_images function copies images with one prefix to a
second prefix.
The launcher will no longer include directories beginning with a dot
(like .svn and .bzr) when copying the template directory to create a
new project.
This version includes a refresh of the character art included with
"The Question". The new art is by Deji, and the full-color version of
the art is available from http://wiki.renai.us/.
New in Ren'Py 6.7.0
-------------------
-55
View File
@@ -1,55 +0,0 @@
This file contains boilerplate information about running Ren'Py that
can be included into the README for your game. It may be necessary to
change some of the filenames in this document, to make it specific to
your game.
Feel free to use this in your projects.
Running the Game
================
(Windows)
If this game was installed on Windows using an installer, then you can
run it by choosing the shortcut left by the installer. If this game
was installed on Windows using the cross-platform zip file, then it
can be run by executing the run_game.exe file.
(Macintosh)
For information about running Ren'Py games on Mac OS 10.3 or higher,
please go to http://www.bishoujo.us/renpy/mac.html .
(Linux/Unix)
For information about running Ren'Py games under Linux and Unix,
please go to http://www.bishoujo.us/renpy/linux.html . At the very
least, you will need to compile the _renpy module. Read
the file module/README.txt for details.
Playing the Game
================
By default, the game starts running in full screen mode. On some
computers, especially some virtual machines, this can lead to mouse
problems. To fix this, press 'f'.
Some of the more interesting game actions can be performed as follows:
- The left mouse button is used to advance to the next line of
dialogue, or to pick menu options.
- The right mouse button brings you into a menu screen where you can
save the game, load the game, change preferences, return to the main
menu, or quit entirely.
- Scrolling the mouse wheel up or pushing page up returns you to the
previous screen.
- Holding down the CTRL key skips dialogue. By default, it only
skips read dialogue, but this can be changed by a preference. Tab
toggles skip mode.
-21
View File
@@ -1,21 +0,0 @@
A version of dissolve that only draws the pixels that are being
dissolved, while doing a straight-blit on pixels that remain the same
between the two images.
Figure out some way of having variables updated in a new context saved
permanently, even if we return to the outer context because of a
rollback or something. Need to be very careful here.
Dynamic variables, parameterized labels, etc.
Implement an extension mechanism of some sort, so that users can drop
packages of Ren'Py code into the Ren'Py directory, and get stuff like
speech support.
Implement speech control support.
BPP conversion (perhaps as a package).
Automatically scale to a fixed size.
Hide picture-mouse when leaving window, restore it when entering window.
+2 -1
View File
@@ -18,7 +18,8 @@ def main():
setup(name="RenPy",
windows=[ dict(script="renpy.py",
dest_base="renpy",
icon_resources=[ (1, "newicon.ico") ] ) ],
icon_resources=[ (1, "newicon.ico") ] ),
],
console=[ dict(script="renpy.py", dest_base="console") ],
+51
View File
@@ -0,0 +1,51 @@
1#!/usr/bin/env python
import glob
import re
from sets import Set as set
import sys
seen_files = set()
seen_strings = set()
def tl(fn, s):
s = eval(s)
if len(s) < 3:
return
if s in seen_strings:
return
if fn not in seen_files:
print >>out
print >>out, " # Translatable strings found in", fn
print >>out
seen_files.add(fn)
print >>out, " config.translations[%r] = %r" % (s, s)
seen_strings.add(s)
def process(fn):
data = file(fn).read()
for m in re.finditer(r'\bu\"(\\"|[^"])+\"', data):
tl(fn, m.group(0))
for m in re.finditer(r"\bu\'(\\'|[^'])+\'", data):
tl(fn, m.group(0))
if __name__ == "__main__":
# out = file("extras/translations.rpy", "w")
out = sys.stdout
print >>out, "# This file contains a list of all of the phrases you can translate"
print >>out, "# from the Ren'Py launcher."
print >>out, ""
print >>out, "init python:"
for fn in glob.glob("launcher/*.rpy"):
process(fn)
+73 -1
View File
@@ -196,6 +196,9 @@ label _style_hierarchy:
jump _developer_screen
init -1050 python:
config.missing_background = "black"
init 1050 python:
if renpy.game.options.remote:
@@ -214,4 +217,73 @@ init 1050 python:
config.underlay.append(Remote())
del Remote
if config.developer:
# This is used to indicate that a scene has just occured,
# and so if the next thing is a missing_show, we should
# blank the screen.
__missing_scene = False
# This returns the __missing dictionary from the current
# context object.
def __missing():
try:
return renpy.context().__missing
except AttributeError:
rv = dict()
renpy.context().__missing = rv
return rv
def __missing_show_callback(name, what, layer):
if layer != 'master':
return False
global __missing_scene
if __missing_scene:
renpy.show(name, what=config.missing_background)
__missing_scene = False
what = " ".join(what).replace("{", "{{")
__missing()[name[0]] = what
return True
def __missing_hide_callback(name, layer):
if layer != 'master':
return False
global __missing_scene
__missing_scene = False
__missing().pop(name[0], None)
return True
def __missing_scene_callback(layer):
if layer != 'master':
return False
global __missing_scene
__missing_scene = True
__missing().clear()
return True
def __missing_overlay():
missing = __missing()
if not missing:
return
ui.vbox(xalign=0.5, yalign=0.0)
ui.text(_("Undefined Images"), xalign=0.5)
for what in sorted(missing.values()):
ui.text(what, xalign=0.5)
ui.close()
config.missing_scene = __missing_scene_callback
config.missing_show = __missing_show_callback
config.missing_hide = __missing_hide_callback
config.overlay_functions.append(__missing_overlay)
+26 -4
View File
@@ -111,16 +111,35 @@ init -1180 python:
renpy.jump("_noisy_return")
else:
renpy.restart_interaction()
config.help = None
def _help():
if not config.help:
return
if renpy.has_label(config.help):
renpy.call_in_new_context(config.help)
return
_preferences.fullscreen = False
import webbrowser
webbrowser.open_new("file:///" + config.basedir + "/" + config.help)
init -1180 python hide:
# Called to make a screenshot happen.
def screenshot():
import os.path
import os
pattern = os.environ.get("RENPY_SCREENSHOT_PATTERN", "screenshot%04d.png")
i = 1
while True:
fn = "screenshot%04d.png" % i
fn = pattern % i
if not os.path.exists(fn):
break
i += 1
@@ -143,7 +162,6 @@ init -1180 python hide:
toggle_skipping()
def fast_skip():
if config.fast_skipping or config.developer:
config.skipping = "fast"
@@ -163,8 +181,9 @@ init -1180 python hide:
filename, line = renpy.get_filename_line()
renpy.launch_editor([ filename ], line)
# The default keymap.
# The default keymap. We might also want to put some of this into
# the launcher.
km = renpy.Keymap(
rollback = renpy.rollback,
screenshot = screenshot,
@@ -178,6 +197,9 @@ init -1180 python hide:
dump_styles = dump_styles,
reload_game = reload_game,
developer = renpy.curried_call_in_new_context("_developer"),
quit = renpy.quit_event,
iconify = renpy.iconify,
help = _help,
)
config.underlay = [ km ]
+4 -2
View File
@@ -12,9 +12,10 @@ init -1150 python:
config.main_menu = [
(u"Start Game", "start", "True"),
(u"Continue Game", _intra_jumps("load_screen", "main_game_transition"), "True"),
(u"Load Game", _intra_jumps("load_screen", "main_game_transition"), "True"),
(u"Preferences", _intra_jumps("preferences_screen", "main_game_transition"), "True"),
(u"Quit", ui.jumps("_quit"), "True")
(u"Help", _help, "True", "config.help"),
(u"Quit", ui.jumps("_quit"), "True"),
]
config.game_menu = [
@@ -23,6 +24,7 @@ init -1150 python:
( "save", u"Save Game", _intra_jumps("save_screen", "intra_transition"), 'not main_menu' ),
( "load", u"Load Game", _intra_jumps("load_screen", "intra_transition"), 'True'),
( None, u"Main Menu", ui.callsinnewcontext("_main_menu_prompt"), 'not main_menu' ),
( "help", u"Help", _help, "True", "config.help"),
( None, u"Quit", ui.callsinnewcontext("_quit_prompt"), 'True' ),
]
+4 -1
View File
@@ -132,8 +132,10 @@ init -1090 python:
style.default.strikethrough = False
style.default.drop_shadow = None
style.default.drop_shadow_color = (0, 0, 0, 255)
style.default.outlines = [ ]
style.default.minwidth = 0
style.default.textalign = 0
style.default.text_align = 0
style.default.justify = False
style.default.text_y_fudge = 0
style.default.first_indent = 0
style.default.rest_indent = 0
@@ -185,6 +187,7 @@ init -1090 python:
style.default.left_gutter = 0
style.default.right_gutter = 0
style.default.thumb_offset = 0
style.default.unscrollable = None
# Misc.
style.default.activate_sound = None
+13 -26
View File
@@ -480,14 +480,6 @@ init -1110 python hide:
style.gm_root.background = "#e9d8bc"
theme.outline_drop_shadow = [
(0, -2),
(-1, -1), (0, -1), (1, -1),
(-2, 0), (-1, 0), (1, 0), (2, 0),
(-1, 1), (0, 1), (1, 1),
(0, 2)
]
@theme
def outline_frames():
theme.clear_frames()
@@ -507,12 +499,11 @@ init -1110 python hide:
style.button_text.size = text_size
style.button_text.color = inside
style.button_text.drop_shadow = theme.outline_drop_shadow
style.button_text.drop_shadow_color = idle
style.button_text.hover_drop_shadow_color = hover
style.button_text.selected_drop_shadow_color = selected
style.button_text.selected_hover_drop_shadow_color = hover
style.button_text.insensitive_drop_shadow_color = insensitive
style.button_text.outlines = [ (2, idle) ]
style.button_text.hover_outlines = [ (2, hover) ]
style.button_text.selected_outlines = [ (2, selected) ]
style.button_text.selected_hover_outlines = [ (2, hover) ]
style.button_text.insensitive_outlines = [ (2, insensitive) ]
@theme
@@ -534,12 +525,12 @@ init -1110 python hide:
style.large_button_text.size = text_size
style.large_button_text.color = inside
style.large_button_text.drop_shadow = theme.outline_drop_shadow
style.large_button_text.drop_shadow_color = idle
style.large_button_text.hover_drop_shadow_color = hover
style.large_button_text.selected_drop_shadow_color = selected
style.large_button_text.selected_hover_drop_shadow_color = hover
style.large_button_text.insensitive_drop_shadow_color = insensitive
style.large_button_text.outlines = [ (2, idle) ]
style.large_button_text.hover_outlines = [ (2, hover) ]
style.large_button_text.selected_outlines = [ (2, selected) ]
style.large_button_text.selected_hover_outlines = [ (2, hover) ]
style.large_button_text.insensitive_outlines = [ (2, insensitive) ]
@theme
def outline_prompts(
@@ -550,8 +541,7 @@ init -1110 python hide:
theme.clear_prompts()
style.prompt_text.color = inside
style.prompt_text.drop_shadow = theme.outline_drop_shadow
style.prompt_text.drop_shadow_color = prompt
style.prompt_text.outlines = [ (2, prompt) ]
style.prompt_text.size = text_size
@theme
@@ -563,8 +553,7 @@ init -1110 python hide:
theme.clear_labels()
style.label_text.color = inside
style.label_text.drop_shadow = theme.outline_drop_shadow
style.label_text.drop_shadow_color = label
style.label_text.outlines = [ (2, label) ]
style.label_text.size = text_size
@theme
@@ -622,8 +611,6 @@ init -1110 python hide:
style.vscrollbar.hover_bottom_bar = Frame(color("vbar", hover), 0, 0)
style.vscrollbar.hover_thumb = Frame(color("circle", hover), 0, 7)
@theme
def outline(
inside="#fff",
+1 -1
View File
@@ -22,7 +22,7 @@ init python:
style.prefs_column.box_spacing = 5
style.prefs_frame.top_margin = 5
style.prefs_left.xpos = 100
style.prefs_left.xpos = 110
style.prefs_center.xpos = 320
style.prefs_right.xpos = 530
+1
View File
@@ -0,0 +1 @@
dist/console.exe
-3
View File
@@ -1,3 +0,0 @@
init -50:
$ config.script_version = (6, 7, 1)
+1
View File
@@ -0,0 +1 @@
../help.html
Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because it is too large Load Diff
+38 -28
View File
@@ -2,41 +2,41 @@
# capabilities of Ren'Py.
init:
python:
# Register an sfont.
$ renpy.register_sfont('new_sfont', 22,
filename="new_sfont.png",
spacewidth=6)
# This imports in the asfont22 module, which contains a list of
# kerning pairs.
import asfont22
# Register the sfont contained in asfont22 as "subfont".
renpy.register_sfont('subfont', 22,
filename="asfont22.png",
kerns=asfont22.kerns,
spacewidth=4)
# Declare some characters that speak in the subfont.
# Just use the subfont.
$ esub = Character("Eileen",
color="#c8ffc8",
what_font="subfont",
what_black_color="#282")
# Declare a character that uses the sfont.
$ esfont = Character("Eileen",
color="#c8ffc8",
what_font="new_sfont")
# Slow text.
$ eslow = Character("Eileen",
color="#c8ffc8",
what_slow_cps=20)
# Outlined text.
$ eoutline = Character("Eileen",
color="#c8ffc8",
what_outlines=[ (1, "#282") ])
# Use it in subtitle mode.
$ esubtitle = Character(None,
what_font="subfont",
what_black_color="#282",
what_size=28,
what_outlines=[(3, "#0008", 2, 2), (3, "#282", 0, 0)],
what_layout="subtitle",
what_xalign=0.5,
what_text_align=0.5,
window_background=None,
window_yminimum=0,
show_say_vbox_properties=dict(xalign=0.5))
window_xfill=False,
window_xalign=0.5)
# This is used to show the defintion text, by the hyperlink demostration
# code.
$ definition = Character(None,
window_yfill=True,
window_xmargin=20,
@@ -48,7 +48,7 @@ init:
$ style.pink.color = "#ffc0c0"
label demo_text:
e "Ren'Py gives you quite a bit of control over how text appears."
e "Text tags let us control the appearance of text that is shown to the user."
@@ -86,13 +86,23 @@ label demo_text:
e "And we want to give you all the power you need."
esub "For even more control, Ren'Py supports SFonts, image files containing font information."
e "There are a couple of text adjustements that don't corrrespond to text tags."
eoutline "The outlines setting lets you put outlines around the text."
eoutline "You can have more than one outline, and each has its own color and offset."
esubtitle "Here, we have two outlines around the white text."
esubtitle "The bottom one is a translucent black that's offset a little, while the top one is green."
esub "SFonts let you use fonts you otherwise couldn't, and apply special effects to fonts... like I'm doing now, applying an outline to the font."
esubtitle "By hiding the window and adjusting the layout method, we are able to create reasonable subtitles."
esubtitle "Finally, you can adjust the line breaking algorithm. The subtitle line-breaking algorithm tries to make lines even in length."
esubtitle "Along with sfonts and the ability to change the text window, this lets us render reasonable subtitles."
esubtitle "This might be an interesting look for a game."
esfont "For even more control, Ren'Py supports SFonts, image files containing font information."
esfont "SFonts let you use fonts you otherwise couldn't, and apply special effects to fonts using your favorite image editor."
e "Well, that's it for fonts and text tags."
+1 -1
View File
@@ -13,7 +13,7 @@ init:
("demo_multimedia", "Music and Sound", "5.6.3"),
("demo_imageops", "Image Operations", "6.5.0"),
("demo_ui", "User Interaction", "6.5.0"),
("demo_text", "Fonts and Text Tags", "6.6.2"),
("demo_text", "Fonts and Text Tags", "6.8.0"),
("demo_character", "Character Objects", "6.2.0"),
("demo_advanced", "Advanced Features", "6.7.0"),
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

+13
View File
@@ -194,7 +194,20 @@ init -1 python hide:
# config.main_menu_music = "main_menu_theme.ogg"
#########################################
## Help.
## This lets you configure the help option on the Ren'Py menus.
## It may be:
## - A label in the script, in which case that label is called to
## show help to the user.
## - A file name relative to the base directory, which is opened in a
## web browser.
## - None, to disable help.
config.help = "README.html"
#########################################
## Transitions.
+5 -2
View File
@@ -125,7 +125,7 @@ def main():
os.chmod("./renpy.app/Contents/MacOS/Ren'Py Launcher", 0755)
# Compile the various games
for i in [ 'demo/game', 'data', 'template/game', 'the_question/game' ]:
for i in [ 'demo/game', 'launcher', 'template/game', 'the_question/game' ]:
os.system("./renpy.sh --compile --game " + i)
@@ -136,7 +136,7 @@ def main():
files.append("LICENSE.txt")
files.extend(tree("common"))
more_files.append("console.exe")
files.extend(tree("data"))
files.extend(tree("launcher"))
files.extend(tree("demo"))
# files.extend(tree("dse"))
files.extend(tree("the_question"))
@@ -177,6 +177,9 @@ def main():
"winmixer.pyx",
"IMG_savepng.c",
"IMG_savepng.h",
"renpy_font.c",
"renpy_ttf.c",
"renpy_ttf.h",
]
for i in module_files:
+109
View File
@@ -0,0 +1,109 @@
<html>
<head>
<title>README</title>
<style>
HTML {
background: #eed;
}
BODY {
background: #fff;
margin: 0px 10% 0px 10%;
border-left: 1px solid #888;
border-right: 1px solid #888;
padding-left: 4em;
padding-top: 1em;
padding-bottom: 1em;
padding-right: 1em;
}
DT {
font-weight: bold;
margin-top: .33em;
}
H3 {
color: #600;
margin-left: -2.5em;
}
</style>
</head>
<body>
<div id="renpy_help"></div>
<p><a name="Basic_Help" id="Basic_Help"></a></p>
<h3><span class="mw-headline">Basic Help</span></h3>
<p>To advance through the game, <tt>left-click</tt> or press the <tt>space</tt> or <tt>enter</tt> keys. When at a menu, <tt>left-click</tt> to make a choice, or use the arrow keys to select a choice and <tt>enter</tt> to activate it.</p>
<p><a name="Game_Menu" id="Game_Menu"></a></p>
<h3><span class="mw-headline">Game Menu</span></h3>
<p>When playing a game, <tt>right-click</tt> or press the <tt>escape</tt> key to enter the game menu. The game menu gives the following choices:</p>
<dl>
<dt>Return</dt>
<dd>Returns to the game.</dd>
<dt>Save Game</dt>
<dd>Allows you to save a game by clicking on a save slot.</dd>
<dt>Load Game</dt>
<dd>Allows you to load a game by clicking on a save slot. Clicking on "Auto" accesses the automatic save slots.</dd>
<dt>Preferences</dt>
<dd>Changes the game preferences (options/configuration):
<dl>
<dt>Display</dt>
<dd>Switches between fullscreen and windowed mode.</dd>
<dt>Transitions</dt>
<dd>Controls the display of transitions between game screens.</dd>
<dt>Text Speed</dt>
<dd>Controls the rate at which text displays. The further to the right this slider is, the faster the text will display. All the way to the right causes text to be shown instantly.</dd>
<dt>Joystick</dt>
<dd>Lets you control the game using a joystick.</dd>
<dt>Skip</dt>
<dd>Chooses between skipping messages that have been already seen (in any play through the game), and skipping all messages.</dd>
<dt>Begin Skipping</dt>
<dd>Returns to the game, while skipping.</dd>
<dt>After Choices</dt>
<dd>Controls if skipping stops upon reaching a menu.</dd>
<dt>Auto-Forward Time</dt>
<dd>Controls automatic advance. The further to the left this slider is, the shorter the amount of time before the game advances. All the way to the right means text will never auto-forward.</dd>
<dt>Music, Sound, and Voice Volume</dt>
<dd>Controls the volume of the Music, Sound effect, and Voice channels, respectively. The further to the right these are, the louder the volume.</dd>
</dl>
</dd>
</dl>
<dl>
<dt>Main Menu</dt>
<dd>Returns to the main menu, ending the current game.</dd>
<dt>Help</dt>
<dd>Shows this help screen.</dd>
<dt>Quit</dt>
<dd>Exits the game; the game will be closed and ended.</dd>
</dl>
<p><a name="Key_and_Mouse_Bindings" id="Key_and_Mouse_Bindings"></a></p>
<h3><span class="mw-headline">Key and Mouse Bindings</span></h3>
<dl>
<dt>Left-click, Enter</dt>
<dd>Advances through the game, activates menu choices, buttons, and sliders.</dd>
<dt>Space</dt>
<dd>Advances through the game, but does not activate choices.</dd>
<dt>Arrow Keys</dt>
<dd>Selects menu choices, buttons, and sliders.</dd>
<dt>Ctrl</dt>
<dd>Causes skipping to occur while the ctrl key is held down.</dd>
<dt>Tab</dt>
<dd>Toggles skipping, causing it to occur until tab is pressed again.</dd>
<dt>Mousewheel-Up, PageUp</dt>
<dd>Causes rollback to occur. Rollback reverses the game back in time, showing prior text and even allowing menu choices to be changed.</dd>
<dt>Mousewheel-Down, PageDown</dt>
<dd>Causes rollforward to occur, cancelling out a previous rollback.</dd>
<dt>Right-click, Escape</dt>
<dd>Enters the game menu. When in the game menu, returns to the game.</dd>
<dt>Middle-click, H</dt>
<dd>Hides the text window and other transient displays.</dd>
<dt>F</dt>
<dd>Toggles fullscreen mode</dd>
<dt>S</dt>
<dd>Takes a screenshot, saving it in a file named screenshotxxxx.png, where xxxx is a serial number.</dd>
<dt>Alt-H, Command-H</dt>
<dd>Hides (iconifies) the window.</dd>
<dt>Alt-F4, Command-Q</dt>
<dd>Quits the game.</dd>
</dl>
</body>
</html>
@@ -9,6 +9,8 @@ init python:
import sys
import zlib
import pefile
# Returns true if a file or directory should not be included in
# the distribution
@@ -16,7 +18,8 @@ init python:
"launcherinfo.py",
"traceback.txt",
"errors.txt",
"completion.lua",)
"icon.ico",
"icon.icns")
def ignored(fn):
if fn[0] == ".":
@@ -95,6 +98,8 @@ init python:
dfn = destdir + "/" + fn
else:
dfn = fn
dfn = dfn.replace("\\", "/")
rv.append((sfn, dfn))
@@ -173,7 +178,7 @@ label distribute:
spacer()
if windows:
text(u"Windows 98+", style='launcher_input')
text(u"Windows 2000+", style='launcher_input')
if linux:
text(u"Linux x86", style='launcher_input')
@@ -275,6 +280,13 @@ label distribute:
( config.renpy_base + "/msvcr71.dll", "msvcr71.dll" ),
]
win_data = { }
if os.path.exists(project.path + "/icon.ico"):
win_data[project.name + ".exe"] = pefile.change_icons(
config.renpy_base + "/renpy.exe",
project.path + "/icon.ico",
)
zf = zipfile.ZipFile(name + ".zip", "w", zipfile.ZIP_DEFLATED)
progress_len = len(multi) + len(win_files)
@@ -296,6 +308,8 @@ label distribute:
zi.external_attr = long(0100666) << 16
data = file(fn, "rb").read()
data = win_data.get(an, data)
zf.writestr(zi, data)
@@ -360,6 +374,19 @@ label distribute:
mac_files = tree(config.renpy_base + "/renpy.app",
project.name + ".app")
mac_files = [ (fn, an.replace("Ren'Py Launcher", project.name)) for (fn, an) in mac_files ]
# Data replacement for macintosh.
mac_data = { }
quoted_name = project.name.replace("&", "&amp;").replace("<", "&lt;")
info_plist = file(config.renpy_base + "/renpy.app/Contents/Info.plist", "rb").read().replace("Ren'Py Launcher", quoted_name)
mac_data[project.name + ".app/Contents/Info.plist"] = info_plist
if os.path.exists(project.path + "/icon.icns"):
icon_data = file(project.path + "/icon.icns", "rb").read()
mac_data[project.name + ".app/Contents/Resources/launcher.icns"] = icon_data
zf = zipfile.ZipFile(name + "-mac.zip", "w", zipfile.ZIP_DEFLATED)
progress_len = len(multi) + len(mac_files)
@@ -371,7 +398,6 @@ label distribute:
if os.path.isdir(fn):
continue
zi = zipfile.ZipInfo(name + "-mac/" + an)
@@ -387,6 +413,7 @@ label distribute:
zi.external_attr = long(0100666) << 16
data = file(fn, "rb").read()
data = mac_data.get(an, data)
zf.writestr(zi, data)
zf.close()
+2 -1
View File
@@ -4,11 +4,12 @@
init:
python hide:
import os
import os.path
import sys
if not config.editor:
editor = config.renpy_base + "/jedit/jedit.jar"
editor = os.path.normpath(config.renpy_base + "/jedit/jedit.jar")
editor = renpy.shell_escape(editor)
if sys.platform == 'win32':

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

+17 -3
View File
@@ -36,6 +36,13 @@ init:
style.hyperlink_text.color = "#0ff"
config.underlay = [
renpy.Keymap(
quit = renpy.quit_event,
iconify = renpy.iconify,
)
]
def quote(c):
n = ord(c)
if 0x20 <= n <= 0x7f:
@@ -58,13 +65,14 @@ init:
ui.add(DynamicDisplayable("Text(_(store.message), size=14, color='#fff', xpos=100, ypos=375, xmaximum=240)"))
ui.text(renpy.version(), xalign=0, yalign=1.0, size=12, color='#000')
return ui.interact(suppress_underlay=True)
return ui.interact()
def title(name):
ui.window(style='mm_root')
ui.null()
ui.frame(xminimum=350, yminimum=370)
ui.viewport(child_size=(2000, None), draggable=True, ymaximum=34)
_label_factory(name, "launcher_title", size=28)
# ui.text(name, xpos=4, ypos=4, size=30, color="#559")
@@ -93,7 +101,7 @@ init:
# ui.button(clicked=clicked, hovered=hovered)
# ui.text(text, style="button_text")
_button_factory(text, 'launcher', clicked=clicked, hovered=hovered, selected=selected)
_button_factory(text, 'launcher', clicked=clicked, hovered=hovered, selected=selected, xmaximum=200)
def prompt(name, message, cancel, default='', hint=''):
@@ -151,6 +159,8 @@ init:
mid(focus="paged_menu")
for name, desc, ret, hovered, selected in choices[page * per_page:(page + 1) * per_page]:
if len(name) > 19:
name = name[:18] + u"\u2026"
button(name, desc, clicked=ui.returns(("return", ret)), hovered=hovered, selected=selected)
ui.close()
@@ -273,6 +283,7 @@ init:
contents.sort()
for dd in contents:
dir = d + "/" + dd
if os.path.isdir(dir):
@@ -482,7 +493,8 @@ label edit:
files.remove(i)
files.insert(0, i)
renpy.launch_editor(files)
if not renpy.launch_editor(files):
error(u"Error", u"Launching the editor failed. You may need Java, which can be downloaded for free from {a=http://www.java.com}java.com{/a}.", "start")
store.message = _(u"Launched editor with %d script files.") % len(files)
@@ -625,6 +637,8 @@ label archive_files:
if fn == "presplash.png":
return False
if fn == "presplash.jpg":
return False
for e in extensions:
if fnmatch.fnmatch(fn, e):
View File
+291
View File
@@ -0,0 +1,291 @@
# http://www.csn.ul.ie/~caolan/publink/winresdump/winresdump/doc/pefile.html
# Contains a reasonable description of the format.
import struct
import sys
import array
# The starting point of the resource segment in the file.
RESOURCE_BASE=0x3400
# The virtual memory location the resource segment is loaded
# to.
RESOURCE_VIRTUAL=0x6000
# The offset of the field that tells us with the alignment need be.
ALIGNMENT_FIELD = 0x138
# Locations in the file where we need to patch in the resource
# segment length.
RESOURCE_LENGTH_PATCHES = [ 0x018c, 0x278 ]
# Locations in the file where we need to patch in the padded
# resource segment length.
RESOURCE_PADDED_PATCHES = [ 0x280 ]
# Locations in the file where we need to patch in the change in the
# size of the resource segement (and hence the change in the file's
# total size.)
SIZE_DELTA_PATCHES = [ 0x150 ]
# A location in the file that will be checked to be sure it matches
# RESOURCE_BASE.
CHECK_ADDRESS = 0x284
# This class performs various operations on memory-loaded binary files,
# including modifications.
class BinFile(object):
def set_u32(self, addr, value):
self.a[addr+0] = (value >> 0) & 0xff
self.a[addr+1] = (value >> 8) & 0xff
self.a[addr+2] = (value >> 16) & 0xff
self.a[addr+3] = (value >> 24) & 0xff
def u32(self):
addr = self.addr
rv = self.a[addr]
rv |= self.a[addr+1] << 8
rv |= self.a[addr+2] << 16
rv |= self.a[addr+3] << 24
self.addr += 4
return rv
def u16(self):
addr = self.addr
rv = self.a[addr]
rv |= self.a[addr+1] << 8
self.addr += 2
return rv
def u8(self):
rv = self.a[self.addr]
self.addr += 1
return rv
def name(self):
c = self.u16()
rv = u""
for i in range(c):
rv += unichr(self.u16())
return rv
def seek(self, addr):
self.addr = addr
def tostring(self):
return self.a.tostring()
def substring(self, start, len):
return self.a[start:start+len].tostring()
def __init__(self, fn):
data = open(fn, "rb").read()
self.a = array.array('B')
self.a.fromstring(data)
##############################################################################
# These functions parse data out of the file. In these functions, offset is
# relative to the start of the file.
# This parses a data block out of the resources.
def parse_data(offset):
pe.seek(RESOURCE_BASE + offset)
data_offset = pe.u32()
data_len = pe.u32()
code_page = pe.u32()
pe.u32()
l = [ ]
pe.seek(data_offset + RESOURCE_BASE - RESOURCE_VIRTUAL)
for i in range(data_len):
l.append(chr(pe.u8()))
return (code_page, "".join(l))
# This parses a resource directory.
def parse_directory(offset):
pe.seek(RESOURCE_BASE + offset)
char = pe.u32()
timedate = pe.u32()
major = pe.u16()
minor = pe.u16()
n_named = pe.u16()
n_id = pe.u16()
entries = [ ]
for i in range(n_named + n_id):
entries.append((pe.u32(), pe.u32()))
rv = { }
for name, value in entries:
if name & 0x80000000:
pe.seek((name & 0x7fffffff) + RESOURCE_BASE)
name = pe.name()
if value & 0x80000000:
value = parse_directory(value & 0x7fffffff)
else:
value = parse_data(value)
rv[name] = value
return rv
##############################################################################
# This utility function displays the tree of resources that have been loaded.
def show_resources(d, prefix):
if not isinstance(d, dict):
print prefix, "Codepage", d[0], "length", len(d[1])
return
for k in d:
print prefix, k
show_resources(d[k], prefix + " ")
##############################################################################
# These functions repack the resources into a new resource segment. Here,
# the offset is relative to the start of the resource segment.
def repack_name(s):
l = len(s)
s = s.encode("utf-16le")
return struct.pack("<H", l) + s + "\0\0"
def repack_tuple(o, offset):
codepage, data = o
# print "REPACK OFFSET IS", offset
return struct.pack("<IIII", offset + 16 + RESOURCE_VIRTUAL, len(data), codepage, 0) + data
def repack_dict(o, offset):
name_entries = sorted((a, b) for a, b in o.iteritems() if isinstance(a, unicode))
id_entries = sorted((a, b) for a, b in o.iteritems() if isinstance(a, int))
rv = struct.pack("<IIHHHH", 0, 0, 4, 0, len(name_entries), len(id_entries))
offset += len(rv) + (len(name_entries) + len(id_entries)) * 8
rest = ""
for (name, value) in name_entries + id_entries:
if isinstance(name, unicode):
packed = repack_name(name)
name = 0x80000000 | offset
offset += len(packed)
rest += packed
pad = 8 - (offset % 8)
offset += pad
rest += "RENPYVNE"[:pad]
addr = offset
if isinstance(value, dict):
addr = addr | 0x80000000
rv += struct.pack("<II", name, addr)
if isinstance(value, dict):
packed = repack_dict(value, offset)
elif isinstance(value, tuple):
packed = repack_tuple(value, offset)
offset += len(packed)
rest += packed
if offset % 8:
pad = 8 - (offset % 8)
offset += pad
rest += "RENPYVNE"[:pad]
return rv + rest
##############################################################################
# This loads in an icon file, and returns a dictionary that is suitable for
# use in the resources of an exe file.
def load_icon(fn):
f = BinFile(fn)
f.seek(0)
f.u16()
f.u16()
count = f.u16()
rv = { }
for i in range(count):
width = f.u8()
height = f.u8()
colors = f.u8()
reserved = f.u8()
planes = f.u16()
bpp = f.u16()
size = f.u32()
offset = f.u32()
rv[i + 1] = { 0 : (1252, f.substring(offset, size)) }
return rv
##############################################################################
# This is the main function that should be called externally, that copies over
# the icons.
def change_icons(oldexe, icofn):
global pe
pe = BinFile(oldexe)
# Check that RESOURCE_BASE is still valid.
pe.seek(CHECK_ADDRESS)
if pe.u32() != RESOURCE_BASE:
raise Exception("RESOURCE_BASE is no longer correct. Please check all relocations.")
resources = parse_directory(0)
# show_resources(resources, "")
resources[3] = load_icon(icofn)
# show_resources(resources, "")
rsrc = repack_dict(resources, 0)
rsrc_len = len(rsrc)
pe.seek(ALIGNMENT_FIELD)
alignment = pe.u32()
if len(rsrc) % alignment:
pad = alignment - (len(rsrc) % alignment)
padding = "RENPYVNE" * (pad / 8 + 1)
padding = padding[:pad]
rsrc += padding
padded_len = len(rsrc)
for addr in RESOURCE_LENGTH_PATCHES:
pe.set_u32(addr, rsrc_len)
for addr in RESOURCE_PADDED_PATCHES:
pe.seek(addr)
size_delta = padded_len - pe.u32()
pe.set_u32(addr, padded_len)
for addr in SIZE_DELTA_PATCHES:
pe.seek(addr)
pe.set_u32(addr, pe.u32() + size_delta)
return pe.tostring()[:RESOURCE_BASE] + rsrc
if __name__ == "__main__":
f = file(sys.argv[3], "wb")
f.write(change_icons(sys.argv[1], sys.argv[2]))
f.close()
+3
View File
@@ -0,0 +1,3 @@
init -999:
$ config.script_version = (6, 8, 0)
+858
View File
@@ -0,0 +1,858 @@
/*
pygame - Python Game Library
Copyright (C) 2000-2001 Pete Shinners
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Pete Shinners
pete@shinners.org
*/
/*
* font module for pygame
*/
#include <Python.h>
#include <stdio.h>
#include <string.h>
#include "pygame.h"
#include "structmember.h"
#include "renpy_ttf.h"
typedef struct {
PyObject_HEAD
RENPY_TTF_Font* font;
PyObject* weakreflist;
} PyFontObject;
#define PyFont_AsFont(x) (((PyFontObject*)x)->font)
static int font_initialized = 0;
static char* font_defaultname = "freesansbold.ttf";
static PyObject* self_module = NULL;
static char* pkgdatamodule_name = "pygame.pkgdata";
static char* resourcefunc_name = "getResource";
static PyObject *font_resource(char *filename) {
PyObject* load_basicfunc = NULL;
PyObject* pkgdatamodule = NULL;
PyObject* resourcefunc = NULL;
PyObject* result = NULL;
pkgdatamodule = PyImport_ImportModule(pkgdatamodule_name);
if (!pkgdatamodule) goto font_resource_end;
resourcefunc = PyObject_GetAttrString(pkgdatamodule, resourcefunc_name);
if (!resourcefunc) goto font_resource_end;
result = PyObject_CallFunction(resourcefunc, "s", filename);
if (!result) goto font_resource_end;
if (PyFile_Check(result)) {
PyObject *tmp = PyFile_Name(result);
Py_INCREF(tmp);
Py_DECREF(result);
result = tmp;
}
font_resource_end:
Py_XDECREF(pkgdatamodule);
Py_XDECREF(resourcefunc);
Py_XDECREF(load_basicfunc);
return result;
}
static void font_autoquit(void)
{
if(font_initialized)
{
font_initialized = 0;
RENPY_TTF_Quit();
}
}
static PyObject* font_autoinit(PyObject* self, PyObject* arg)
{
if(!PyArg_ParseTuple(arg, ""))
return NULL;
if(!font_initialized)
{
PyGame_RegisterQuit(font_autoquit);
if(RENPY_TTF_Init())
return PyInt_FromLong(0);
font_initialized = 1;
}
return PyInt_FromLong(font_initialized);
}
/*DOC*/ static char doc_quit[] =
/*DOC*/ "pygame.font.quit() -> none\n"
/*DOC*/ "uninitialize the font module\n"
/*DOC*/ "\n"
/*DOC*/ "Manually uninitialize SDL_ttf's font system. It is safe to call\n"
/*DOC*/ "this if font is currently not initialized.\n"
/*DOC*/ ;
static PyObject* fontmodule_quit(PyObject* self, PyObject* arg)
{
if(!PyArg_ParseTuple(arg, ""))
return NULL;
font_autoquit();
Py_RETURN_NONE;
}
/*DOC*/ static char doc_init[] =
/*DOC*/ "pygame.font.init() -> None\n"
/*DOC*/ "initialize the display module\n"
/*DOC*/ "\n"
/*DOC*/ "Manually initialize the font module. Will raise an exception if\n"
/*DOC*/ "it cannot be initialized. It is safe to call this function if\n"
/*DOC*/ "font is currently initialized.\n"
/*DOC*/ ;
static PyObject* fontmodule_init(PyObject* self, PyObject* arg)
{
PyObject* result;
int istrue;
if(!PyArg_ParseTuple(arg, ""))
return NULL;
result = font_autoinit(self, arg);
istrue = PyObject_IsTrue(result);
Py_DECREF(result);
if(!istrue)
return RAISE(PyExc_SDLError, SDL_GetError());
Py_RETURN_NONE;
}
/*DOC*/ static char doc_get_init[] =
/*DOC*/ "pygame.font.get_init() -> bool\n"
/*DOC*/ "get status of font module initialization\n"
/*DOC*/ "\n"
/*DOC*/ "Returns true if the font module is currently intialized.\n"
/*DOC*/ ;
static PyObject* get_init(PyObject* self, PyObject* arg)
{
if(!PyArg_ParseTuple(arg, ""))
return NULL;
return PyInt_FromLong(font_initialized);
}
/* font object methods */
/*DOC*/ static char doc_font_get_height[] =
/*DOC*/ "Font.get_height() -> int\n"
/*DOC*/ "average height of font glyph\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the average size of each glyph in the font.\n"
/*DOC*/ ;
static PyObject* font_get_height(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
if(!PyArg_ParseTuple(args, ""))
return NULL;
return PyInt_FromLong(RENPY_TTF_FontHeight(font));
}
/*DOC*/ static char doc_font_get_descent[] =
/*DOC*/ "Font.get_descent() -> int\n"
/*DOC*/ "gets the font descent\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the descent for the font. The descent is the number of\n"
/*DOC*/ "pixels from the font baseline to the bottom of the font.\n"
/*DOC*/ "With most fonts this is a negative number.\n"
/*DOC*/ ;
static PyObject* font_get_descent(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
if(!PyArg_ParseTuple(args, ""))
return NULL;
return PyInt_FromLong(RENPY_TTF_FontDescent(font));
}
/*DOC*/ static char doc_font_get_ascent[] =
/*DOC*/ "Font.get_ascent() -> int\n"
/*DOC*/ "gets the font ascent\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the ascent for the font. The ascent is the number of\n"
/*DOC*/ "pixels from the font baseline to the top of the font.\n"
/*DOC*/ ;
static PyObject* font_get_ascent(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
if(!PyArg_ParseTuple(args, ""))
return NULL;
return PyInt_FromLong(RENPY_TTF_FontAscent(font));
}
/*DOC*/ static char doc_font_get_linesize[] =
/*DOC*/ "Font.get_linesize() -> int\n"
/*DOC*/ "gets the font recommended linesize\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the linesize for the font. Each font comes with it's own\n"
/*DOC*/ "recommendation for the spacing number of pixels between each line\n"
/*DOC*/ "of the font.\n"
/*DOC*/ ;
static PyObject* font_get_linesize(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
if(!PyArg_ParseTuple(args, ""))
return NULL;
return PyInt_FromLong(RENPY_TTF_FontLineSkip(font));
}
/*DOC*/ static char doc_font_get_bold[] =
/*DOC*/ "Font.get_bold() -> bool\n"
/*DOC*/ "status of the bold attribute\n"
/*DOC*/ "\n"
/*DOC*/ "Get the current status of the font's bold attribute\n"
/*DOC*/ ;
static PyObject* font_get_bold(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
if(!PyArg_ParseTuple(args, ""))
return NULL;
return PyInt_FromLong((RENPY_TTF_GetFontStyle(font)&RENPY_TTF_STYLE_BOLD) != 0);
}
/*DOC*/ static char doc_font_set_bold[] =
/*DOC*/ "Font.set_bold(bool) -> None\n"
/*DOC*/ "assign the bold attribute\n"
/*DOC*/ "\n"
/*DOC*/ "Enables or disables the bold attribute for the font. Making the\n"
/*DOC*/ "font bold does not work as well as you expect.\n"
/*DOC*/ ;
static PyObject* font_set_bold(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
int style, val;
if(!PyArg_ParseTuple(args, "i", &val))
return NULL;
style = RENPY_TTF_GetFontStyle(font);
if(val)
style |= RENPY_TTF_STYLE_BOLD;
else
style &= ~RENPY_TTF_STYLE_BOLD;
RENPY_TTF_SetFontStyle(font, style);
Py_RETURN_NONE;
}
/*DOC*/ static char doc_font_get_italic[] =
/*DOC*/ "Font.get_italic() -> bool\n"
/*DOC*/ "status of the italic attribute\n"
/*DOC*/ "\n"
/*DOC*/ "Get the current status of the font's italic attribute\n"
/*DOC*/ ;
static PyObject* font_get_italic(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
if(!PyArg_ParseTuple(args, ""))
return NULL;
return PyInt_FromLong((RENPY_TTF_GetFontStyle(font)&RENPY_TTF_STYLE_ITALIC) != 0);
}
/*DOC*/ static char doc_font_set_italic[] =
/*DOC*/ "Font.set_italic(bool) -> None\n"
/*DOC*/ "assign the italic attribute\n"
/*DOC*/ "\n"
/*DOC*/ "Enables or disables the italic attribute for the font.\n"
/*DOC*/ ;
static PyObject* font_set_italic(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
int style, val;
if(!PyArg_ParseTuple(args, "i", &val))
return NULL;
style = RENPY_TTF_GetFontStyle(font);
if(val)
style |= RENPY_TTF_STYLE_ITALIC;
else
style &= ~RENPY_TTF_STYLE_ITALIC;
RENPY_TTF_SetFontStyle(font, style);
Py_RETURN_NONE;
}
/*DOC*/ static char doc_font_get_underline[] =
/*DOC*/ "Font.get_underline() -> bool\n"
/*DOC*/ "status of the underline attribute\n"
/*DOC*/ "\n"
/*DOC*/ "Get the current status of the font's underline attribute\n"
/*DOC*/ ;
static PyObject* font_get_underline(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
if(!PyArg_ParseTuple(args, ""))
return NULL;
return PyInt_FromLong((RENPY_TTF_GetFontStyle(font)&RENPY_TTF_STYLE_UNDERLINE) != 0);
}
/*DOC*/ static char doc_font_set_underline[] =
/*DOC*/ "Font.set_underline(bool) -> None\n"
/*DOC*/ "assign the underline attribute\n"
/*DOC*/ "\n"
/*DOC*/ "Enables or disables the underline attribute for the font.\n"
/*DOC*/ ;
static PyObject* font_set_underline(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
int style, val;
if(!PyArg_ParseTuple(args, "i", &val))
return NULL;
style = RENPY_TTF_GetFontStyle(font);
if(val)
style |= RENPY_TTF_STYLE_UNDERLINE;
else
style &= ~RENPY_TTF_STYLE_UNDERLINE;
RENPY_TTF_SetFontStyle(font, style);
Py_RETURN_NONE;
}
/*DOC*/ static char doc_font_render[] =
/*DOC*/ "Font.render(text, antialias, fore_RGBA, [back_RGBA]) -> Surface\n"
/*DOC*/ "render text to a new image\n"
/*DOC*/ "\n"
/*DOC*/ "Render the given text onto a new image surface. The given text\n"
/*DOC*/ "can be standard python text or unicode. Antialiasing will smooth\n"
/*DOC*/ "the edges of the font for a much cleaner look. The foreground\n"
/*DOC*/ "and background color are both RGBA, the alpha component is ignored\n"
/*DOC*/ "if given. If the background color is omitted, the text will have a\n"
/*DOC*/ "transparent background.\n"
/*DOC*/ "\n"
/*DOC*/ "Note that font rendering is not thread safe, therefore only one\n"
/*DOC*/ "thread can render text at any given time.\n"
/*DOC*/ "\n"
/*DOC*/ "Also, rendering smooth text with underlines will crash with SDL_ttf\n"
/*DOC*/ "less that version 2.0, be careful.\n"
/*DOC*/ "\n"
/*DOC*/ "If you pass an empty string, render() will return a blank surface\n"
/*DOC*/ "1 pixel wide and the same height as the font.\n"
/*DOC*/ ;
static PyObject* font_render(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
int aa;
PyObject* text, *final;
PyObject* fg_rgba_obj, *bg_rgba_obj = NULL;
Uint8 rgba[4];
SDL_Surface* surf;
SDL_Color foreg, backg;
if(!PyArg_ParseTuple(args, "OiO|O", &text, &aa, &fg_rgba_obj, &bg_rgba_obj))
return NULL;
if(!RGBAFromObj(fg_rgba_obj, rgba))
return RAISE(PyExc_TypeError, "Invalid foreground RGBA argument");
foreg.r = rgba[0]; foreg.g = rgba[1]; foreg.b = rgba[2];
if(bg_rgba_obj)
{
if(!RGBAFromObj(bg_rgba_obj, rgba))
return RAISE(PyExc_TypeError, "Invalid background RGBA argument");
backg.r = rgba[0];
backg.g = rgba[1];
backg.b = rgba[2];
backg.unused = 0;
} else {
backg.r = 0;
backg.g = 0;
backg.b = 0;
backg.unused = 0;
}
if(!PyObject_IsTrue(text))
{
int height = RENPY_TTF_FontHeight(font);
surf = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, height, 32, 0xff<<16, 0xff<<8, 0xff, 0);
if(bg_rgba_obj)
{
Uint32 c = SDL_MapRGB(surf->format, backg.r, backg.g, backg.b);
SDL_FillRect(surf, NULL, c);
}
else
SDL_SetColorKey(surf, SDL_SRCCOLORKEY, 0);
}
else if(PyUnicode_Check(text))
{
PyObject* strob = PyEval_CallMethod(text, "encode", "(s)", "utf-8");
char *string = PyString_AsString(strob);
if(aa)
{
if(!bg_rgba_obj)
surf = RENPY_TTF_RenderUTF8_Blended(font, string, foreg);
else
surf = RENPY_TTF_RenderUTF8_Shaded(font, string, foreg, backg);
}
else
surf = RENPY_TTF_RenderUTF8_Solid(font, string, foreg);
Py_DECREF(strob);
}
else if(PyString_Check(text))
{
char* string = PyString_AsString(text);
if(aa)
{
if(!bg_rgba_obj)
surf = RENPY_TTF_RenderText_Blended(font, string, foreg);
else
surf = RENPY_TTF_RenderText_Shaded(font, string, foreg, backg);
}
else
surf = RENPY_TTF_RenderText_Solid(font, string, foreg);
}
else
return RAISE(PyExc_TypeError, "text must be a string or unicode");
if(!surf)
return RAISE(PyExc_SDLError, "SDL_ttf render failed");
if(!aa && bg_rgba_obj) /*turn off transparancy*/
{
SDL_SetColorKey(surf, 0, 0);
surf->format->palette->colors[0].r = backg.r;
surf->format->palette->colors[0].g = backg.g;
surf->format->palette->colors[0].b = backg.b;
}
final = PySurface_New(surf);
if(!final)
SDL_FreeSurface(surf);
return final;
}
/*DOC*/ static char doc_font_size[] =
/*DOC*/ "Font.size(text) -> width, height\n"
/*DOC*/ "size of rendered text\n"
/*DOC*/ "\n"
/*DOC*/ "Computes the rendered size of the given text. The text can be\n"
/*DOC*/ "standard python text or unicode. Changing the bold and italic\n"
/*DOC*/ "attributes can change the size of the rendered text.\n"
/*DOC*/ ;
static PyObject* font_size(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
int w, h;
PyObject* text;
if(!PyArg_ParseTuple(args, "O", &text))
return NULL;
if(PyUnicode_Check(text))
{
PyObject* strob = PyEval_CallMethod(text, "encode", "(s)", "utf-8");
char *string = PyString_AsString(strob);
RENPY_TTF_SizeUTF8(font, string, &w, &h);
Py_DECREF(strob);
}
else if(PyString_Check(text))
{
char* string = PyString_AsString(text);
RENPY_TTF_SizeText(font, string, &w, &h);
}
else
return RAISE(PyExc_TypeError, "text must be a string or unicode");
return Py_BuildValue("(ii)", w, h);
}
static PyObject* font_set_expand(PyObject* self, PyObject* args)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
float expand;
if(!PyArg_ParseTuple(args, "f", &expand))
return NULL;
RENPY_TTF_SetExpand(font, expand);
Py_RETURN_NONE;
}
static PyMethodDef font_methods[] =
{
{ "get_height", font_get_height, 1, doc_font_get_height },
{ "get_descent", font_get_descent, 1, doc_font_get_descent },
{ "get_ascent", font_get_ascent, 1, doc_font_get_ascent },
{ "get_linesize", font_get_linesize, 1, doc_font_get_linesize },
{ "get_bold", font_get_bold, 1, doc_font_get_bold },
{ "set_bold", font_set_bold, 1, doc_font_set_bold },
{ "get_italic", font_get_italic, 1, doc_font_get_italic },
{ "set_italic", font_set_italic, 1, doc_font_set_italic },
{ "get_underline", font_get_underline, 1, doc_font_get_underline },
{ "set_underline", font_set_underline, 1, doc_font_set_underline },
{ "render", font_render, 1, doc_font_render },
{ "size", font_size, 1, doc_font_size },
{ "set_expand", font_set_expand, 1, ""},
{ NULL, NULL }
};
/*font object internals*/
static void font_dealloc(PyFontObject* self)
{
RENPY_TTF_Font* font = PyFont_AsFont(self);
if(font && font_initialized)
RENPY_TTF_CloseFont(font);
if(self->weakreflist)
PyObject_ClearWeakRefs((PyObject*)self);
self->ob_type->tp_free((PyObject*)self);
}
static int font_init(PyFontObject *self, PyObject *args, PyObject *kwds)
{
int fontsize;
RENPY_TTF_Font* font = NULL;
PyObject* fileobj;
self->font = NULL;
if(!PyArg_ParseTuple(args, "Oi|iff", &fileobj, &fontsize))
return -1;
if(!font_initialized)
{
RAISE(PyExc_SDLError, "font not initialized");
return -1;
}
Py_INCREF(fileobj);
if(fontsize <= 1)
fontsize = 1;
if(fileobj == Py_None) {
Py_DECREF(fileobj);
fileobj = font_resource(font_defaultname);
if(!fileobj)
{
RAISE(PyExc_RuntimeError, "default font not found");
return -1;
}
fontsize = (int)(fontsize * .6875);
if(fontsize <= 1)
fontsize = 1;
}
if(PyString_Check(fileobj) || PyUnicode_Check(fileobj))
{
FILE* test;
char* filename = PyString_AsString(fileobj);
Py_DECREF(fileobj);
fileobj = NULL;
if(!filename)
return -1;
/*check if it is a valid file, else SDL_ttf segfaults*/
test = fopen(filename, "rb");
if(!test)
{
if (!strcmp(filename, font_defaultname))
{
fileobj = font_resource(font_defaultname);
}
if (!fileobj) {
PyErr_SetString(PyExc_IOError, "unable to read font filename");
return -1;
}
}
else
{
fclose(test);
// Py_BEGIN_ALLOW_THREADS
font = RENPY_TTF_OpenFont(filename, fontsize);
// Py_END_ALLOW_THREADS
}
}
if (!font)
{
#ifdef RENPY_TTF_MAJOR_VERSION
SDL_RWops *rw;
rw = RWopsFromPython(fileobj);
if (!rw) {
Py_DECREF(fileobj);
return -1;
}
// Py_BEGIN_ALLOW_THREADS
font = RENPY_TTF_OpenFontIndexRW(rw, 1, fontsize, 0);
// Py_END_ALLOW_THREADS
#else
Py_DECREF(fileobj);
RAISE(PyExc_NotImplementedError, "nonstring fonts require SDL_ttf-2.0.6");
return -1;
#endif
}
if(!font)
{
RAISE(PyExc_RuntimeError, SDL_GetError());
return -1;
}
self->font = font;
return 0;
}
/*DOC*/ static char doc_Font_MODULE[] =
/*DOC*/ "The font object is created only from pygame.font.Font(). Once a\n"
/*DOC*/ "font is created it's size and TTF file cannot be changed. The\n"
/*DOC*/ "Font objects are mainly used to render() text into a new Surface.\n"
/*DOC*/ "The Font objects also have a few states that can be set with\n"
/*DOC*/ "set_underline(bool), set_bold(bool), set_italic(bool). Each of\n"
/*DOC*/ "these functions contains an equivalent get_XXX() routine to find\n"
/*DOC*/ "the current state. There are also many routines to query the\n"
/*DOC*/ "dimensions of the text. The rendering functions work with both\n"
/*DOC*/ "normal python strings, as well as with unicode strings.\n"
/*DOC*/ ;
static PyTypeObject PyFont_Type =
{
PyObject_HEAD_INIT(NULL)
0,
"pygame.font.Font",
sizeof(PyFontObject),
0,
(destructor)font_dealloc,
0,
0, /*getattr*/
0,
0,
0,
0,
NULL,
0,
(hashfunc)NULL,
(ternaryfunc)NULL,
(reprfunc)NULL,
0L,0L,0L,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
doc_Font_MODULE, /* Documentation string */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(PyFontObject, weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
font_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)font_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
//PyType_GenericNew, /* tp_new */
/*font module methods*/
/*DOC*/ static char doc_get_default_font[] =
/*DOC*/ "pygame.font.get_default_font() -> string\n"
/*DOC*/ "get the name of the default font\n"
/*DOC*/ "\n"
/*DOC*/ "returns the filename for the default truetype font.\n"
/*DOC*/ ;
static PyObject* get_default_font(PyObject* self, PyObject* args)
{
if(!PyArg_ParseTuple(args, ""))
return NULL;
return PyString_FromString(font_defaultname);
}
/*font module methods*/
#if 0
/*DOC*/ static char doc_Font[] =
/*DOC*/ "pygame.font.Font(file, size) -> Font\n"
/*DOC*/ "create a new font object\n"
/*DOC*/ "\n"
/*DOC*/ "This will create a new font object. The given file can\n"
/*DOC*/ "be a filename or any python file-like object.\n"
/*DOC*/ "The size represents the height of the font in\n"
/*DOC*/ "pixels. The file argument can be 'None', which will\n"
/*DOC*/ "use a plain default font.\n"
/*DOC*/ "\n"
/*DOC*/ "You must have at least SDL_ttf-2.0.6 for file object\n"
/*DOC*/ "support. You can load TTF and FON fonts.\n"
/*DOC*/ ;
#endif
static PyMethodDef font_builtins[] =
{
{ "__PYGAMEinit__", font_autoinit, 1, doc_init },
{ "init", fontmodule_init, 1, doc_init },
{ "quit", fontmodule_quit, 1, doc_quit },
{ "get_init", get_init, 1, doc_get_init },
{ "get_default_font", get_default_font, 1, doc_get_default_font },
{ NULL, NULL }
};
static PyObject* PyFont_New(RENPY_TTF_Font* font)
{
PyFontObject* fontobj;
if(!font)
return RAISE(PyExc_RuntimeError, "unable to load font.");
fontobj = (PyFontObject *)PyFont_Type.tp_new(&PyFont_Type, NULL, NULL);
if(fontobj)
fontobj->font = font;
return (PyObject*)fontobj;
}
/*DOC*/ static char doc_pygame_font_MODULE[] =
/*DOC*/ "The font module allows for rendering TrueType fonts into a new\n"
/*DOC*/ "Surface object. This module is optional and requires SDL_ttf as a\n"
/*DOC*/ "dependency. You may want to check for pygame.font to import and\n"
/*DOC*/ "initialize before attempting to use the module.\n"
/*DOC*/ "\n"
/*DOC*/ "Most of the work done with fonts are done by using the actual\n"
/*DOC*/ "Font objects. The module by itself only has routines to\n"
/*DOC*/ "initialize the module and create Font objects with\n"
/*DOC*/ "pygame.font.Font().\n"
/*DOC*/ "\n"
/*DOC*/ "You can load fonts from the standard system fonts by using the\n"
/*DOC*/ "pygame.font.SysFont() method. There are also other functions to\n"
/*DOC*/ "help you work with system fonts.\n"
/*DOC*/ "\n"
/*DOC*/ ;
PYGAME_EXPORT
void init_renpy_font(void)
{
PyObject *module;
if (PyType_Ready(&PyFont_Type) < 0)
return;
/* create the module */
PyFont_Type.ob_type = &PyType_Type;
PyFont_Type.tp_new = &PyType_GenericNew;
module = Py_InitModule3("_renpy_font", font_builtins, doc_pygame_font_MODULE);
self_module = module;
Py_INCREF((PyObject*)&PyFont_Type);
PyModule_AddObject(module, "FontType", (PyObject *)&PyFont_Type);
Py_INCREF((PyObject*)&PyFont_Type);
PyModule_AddObject(module, "Font", (PyObject *)&PyFont_Type);
import_pygame_base();
import_pygame_surface();
import_pygame_rwobject();
}
+1796
View File
File diff suppressed because it is too large Load Diff
+236
View File
@@ -0,0 +1,236 @@
/*
SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts
Copyright (C) 1997-2004 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/* $Id: SDL_ttf.h 2387 2006-05-11 09:03:37Z slouken $ */
/* This library is a wrapper around the excellent FreeType 2.0 library,
available at:
http://www.freetype.org/
*/
#ifndef _RENPY_TTF_H
#define _RENPY_TTF_H
#include "SDL.h"
#include "begin_code.h"
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
*/
#define RENPY_RENPY_TTF_MAJOR_VERSION 2
#define RENPY_RENPY_TTF_MINOR_VERSION 0
#define RENPY_RENPY_TTF_PATCHLEVEL 8
/* This macro can be used to fill a version structure with the compile-time
* version of the SDL_ttf library.
*/
#define RENPY_RENPY_TTF_VERSION(X) \
{ \
(X)->major = RENPY_RENPY_TTF_MAJOR_VERSION; \
(X)->minor = RENPY_RENPY_TTF_MINOR_VERSION; \
(X)->patch = RENPY_RENPY_TTF_PATCHLEVEL; \
}
/* Backwards compatibility */
#define RENPY_TTF_MAJOR_VERSION RENPY_RENPY_TTF_MAJOR_VERSION
#define RENPY_TTF_MINOR_VERSION RENPY_RENPY_TTF_MINOR_VERSION
#define RENPY_TTF_PATCHLEVEL RENPY_RENPY_TTF_PATCHLEVEL
#define RENPY_TTF_VERSION(X) RENPY_RENPY_TTF_VERSION(X)
/* This function gets the version of the dynamically linked SDL_ttf library.
it should NOT be used to fill a version structure, instead you should
use the RENPY_RENPY_TTF_VERSION() macro.
*/
extern DECLSPEC const SDL_version * SDLCALL RENPY_TTF_Linked_Version(void);
/* ZERO WIDTH NO-BREAKSPACE (Unicode byte order mark) */
#define UNICODE_BOM_NATIVE 0xFEFF
#define UNICODE_BOM_SWAPPED 0xFFFE
/* This function tells the library whether UNICODE text is generally
byteswapped. A UNICODE BOM character in a string will override
this setting for the remainder of that string.
*/
extern DECLSPEC void SDLCALL RENPY_TTF_ByteSwappedUNICODE(int swapped);
/* The internal structure containing font information */
typedef struct _RENPY_TTF_Font RENPY_TTF_Font;
/* Initialize the TTF engine - returns 0 if successful, -1 on error */
extern DECLSPEC int SDLCALL RENPY_TTF_Init(void);
/* Open a font file and create a font of the specified point size.
* Some .fon fonts will have several sizes embedded in the file, so the
* point size becomes the index of choosing which size. If the value
* is too high, the last indexed size will be the default. */
extern DECLSPEC RENPY_TTF_Font * SDLCALL RENPY_TTF_OpenFont(const char *file, int ptsize);
extern DECLSPEC RENPY_TTF_Font * SDLCALL RENPY_TTF_OpenFontIndex(const char *file, int ptsize, long index);
extern DECLSPEC RENPY_TTF_Font * SDLCALL RENPY_TTF_OpenFontRW(SDL_RWops *src, int freesrc, int ptsize);
extern DECLSPEC RENPY_TTF_Font * SDLCALL RENPY_TTF_OpenFontIndexRW(SDL_RWops *src, int freesrc, int ptsize, long index);
/* Set and retrieve the font style
This font style is implemented by modifying the font glyphs, and
doesn't reflect any inherent properties of the truetype font file.
*/
#define RENPY_TTF_STYLE_NORMAL 0x00
#define RENPY_TTF_STYLE_BOLD 0x01
#define RENPY_TTF_STYLE_ITALIC 0x02
#define RENPY_TTF_STYLE_UNDERLINE 0x04
extern DECLSPEC int SDLCALL RENPY_TTF_GetFontStyle(RENPY_TTF_Font *font);
extern DECLSPEC void SDLCALL RENPY_TTF_SetFontStyle(RENPY_TTF_Font *font, int style);
/* Get the total height of the font - usually equal to point size */
extern DECLSPEC int SDLCALL RENPY_TTF_FontHeight(RENPY_TTF_Font *font);
/* Get the offset from the baseline to the top of the font
This is a positive value, relative to the baseline.
*/
extern DECLSPEC int SDLCALL RENPY_TTF_FontAscent(RENPY_TTF_Font *font);
/* Get the offset from the baseline to the bottom of the font
This is a negative value, relative to the baseline.
*/
extern DECLSPEC int SDLCALL RENPY_TTF_FontDescent(RENPY_TTF_Font *font);
/* Get the recommended spacing between lines of text for this font */
extern DECLSPEC int SDLCALL RENPY_TTF_FontLineSkip(RENPY_TTF_Font *font);
/* Get the number of faces of the font */
extern DECLSPEC long SDLCALL RENPY_TTF_FontFaces(RENPY_TTF_Font *font);
/* Get the font face attributes, if any */
extern DECLSPEC int SDLCALL RENPY_TTF_FontFaceIsFixedWidth(RENPY_TTF_Font *font);
extern DECLSPEC char * SDLCALL RENPY_TTF_FontFaceFamilyName(RENPY_TTF_Font *font);
extern DECLSPEC char * SDLCALL RENPY_TTF_FontFaceStyleName(RENPY_TTF_Font *font);
/* Get the metrics (dimensions) of a glyph
To understand what these metrics mean, here is a useful link:
http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
*/
extern DECLSPEC int SDLCALL RENPY_TTF_GlyphMetrics(RENPY_TTF_Font *font, Uint16 ch,
int *minx, int *maxx,
int *miny, int *maxy, int *advance);
/* Get the dimensions of a rendered string of text */
extern DECLSPEC int SDLCALL RENPY_TTF_SizeText(RENPY_TTF_Font *font, const char *text, int *w, int *h);
extern DECLSPEC int SDLCALL RENPY_TTF_SizeUTF8(RENPY_TTF_Font *font, const char *text, int *w, int *h);
extern DECLSPEC int SDLCALL RENPY_TTF_SizeUNICODE(RENPY_TTF_Font *font, const Uint16 *text, int *w, int *h);
/* Create an 8-bit palettized surface and render the given text at
fast quality with the given font and color. The 0 pixel is the
colorkey, giving a transparent background, and the 1 pixel is set
to the text color.
This function returns the new surface, or NULL if there was an error.
*/
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderText_Solid(RENPY_TTF_Font *font,
const char *text, SDL_Color fg);
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderUTF8_Solid(RENPY_TTF_Font *font,
const char *text, SDL_Color fg);
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderUNICODE_Solid(RENPY_TTF_Font *font,
const Uint16 *text, SDL_Color fg);
/* Create an 8-bit palettized surface and render the given glyph at
fast quality with the given font and color. The 0 pixel is the
colorkey, giving a transparent background, and the 1 pixel is set
to the text color. The glyph is rendered without any padding or
centering in the X direction, and aligned normally in the Y direction.
This function returns the new surface, or NULL if there was an error.
*/
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderGlyph_Solid(RENPY_TTF_Font *font,
Uint16 ch, SDL_Color fg);
/* Create an 8-bit palettized surface and render the given text at
high quality with the given font and colors. The 0 pixel is background,
while other pixels have varying degrees of the foreground color.
This function returns the new surface, or NULL if there was an error.
*/
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderText_Shaded(RENPY_TTF_Font *font,
const char *text, SDL_Color fg, SDL_Color bg);
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderUTF8_Shaded(RENPY_TTF_Font *font,
const char *text, SDL_Color fg, SDL_Color bg);
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderUNICODE_Shaded(RENPY_TTF_Font *font,
const Uint16 *text, SDL_Color fg, SDL_Color bg);
/* Create an 8-bit palettized surface and render the given glyph at
high quality with the given font and colors. The 0 pixel is background,
while other pixels have varying degrees of the foreground color.
The glyph is rendered without any padding or centering in the X
direction, and aligned normally in the Y direction.
This function returns the new surface, or NULL if there was an error.
*/
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderGlyph_Shaded(RENPY_TTF_Font *font,
Uint16 ch, SDL_Color fg, SDL_Color bg);
/* Create a 32-bit ARGB surface and render the given text at high quality,
using alpha blending to dither the font with the given color.
This function returns the new surface, or NULL if there was an error.
*/
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderText_Blended(RENPY_TTF_Font *font,
const char *text, SDL_Color fg);
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderUTF8_Blended(RENPY_TTF_Font *font,
const char *text, SDL_Color fg);
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderUNICODE_Blended(RENPY_TTF_Font *font,
const Uint16 *text, SDL_Color fg);
/* Create a 32-bit ARGB surface and render the given glyph at high quality,
using alpha blending to dither the font with the given color.
The glyph is rendered without any padding or centering in the X
direction, and aligned normally in the Y direction.
This function returns the new surface, or NULL if there was an error.
*/
extern DECLSPEC SDL_Surface * SDLCALL RENPY_TTF_RenderGlyph_Blended(RENPY_TTF_Font *font,
Uint16 ch, SDL_Color fg);
/* For compatibility with previous versions, here are the old functions */
#define RENPY_TTF_RenderText(font, text, fg, bg) \
RENPY_TTF_RenderText_Shaded(font, text, fg, bg)
#define RENPY_TTF_RenderUTF8(font, text, fg, bg) \
RENPY_TTF_RenderUTF8_Shaded(font, text, fg, bg)
#define RENPY_TTF_RenderUNICODE(font, text, fg, bg) \
RENPY_TTF_RenderUNICODE_Shaded(font, text, fg, bg)
/* Close an opened font file */
extern DECLSPEC void SDLCALL RENPY_TTF_CloseFont(RENPY_TTF_Font *font);
/* De-initialize the TTF engine */
extern DECLSPEC void SDLCALL RENPY_TTF_Quit(void);
/* Check if the TTF engine is initialized */
extern DECLSPEC int SDLCALL RENPY_TTF_WasInit(void);
extern DECLSPEC void SDLCALL RENPY_TTF_SetExpand(RENPY_TTF_Font *, float);
/* We'll use SDL for reporting errors */
#define RENPY_TTF_SetError SDL_SetError
#define RENPY_TTF_GetError SDL_GetError
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
#include "close_code.h"
#endif /* _RENPY_TTF_H */
+13 -1
View File
@@ -28,7 +28,7 @@ if not os.path.isdir(install):
sys.exit(-1)
# Default compile arguements for everybody.
include_dirs = [ install + "/include", install + "/include/SDL" ]
include_dirs = [ install + "/include", install + "/include/SDL", install + "/include/freetype2", install + "/include/pygame"]
library_dirs = [ install + "/lib" ]
extra_compile_args = [ "-O3", "-funroll-loops", "-ffast-math" ]
extra_link_args = [ ]
@@ -75,6 +75,18 @@ rpe = distutils.core.Extension(
extensions.append(rpe)
renpy_font = distutils.core.Extension(
"_renpy_font",
[ "renpy_ttf.c", "renpy_font.c"],
include_dirs=include_dirs,
library_dirs=library_dirs,
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args,
libraries=sdl_libraries + ['freetype'],
)
extensions.append(renpy_font)
psse = distutils.core.Extension(
"pysdlsound.sound",
[ "pss.c", "rwobject.c", "sound.c" ],
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
rm -Rf cardgame/*~
rm -Rf cardgame/game/*~
rm -Rf cardgame/game/*.rpyc
rm -Rf cardgame/game/*.rpyb
rm -Rf cardgame/game/saves
rm cardgame-$1.zip
zip -9r cardgame-$1.zip cardgame -x \*.svn\*
+1
View File
@@ -0,0 +1 @@
zip -r renpygame-$1.zip renpygame-demo -x \*.svn\* -x \*saves\* -x \*.pyc -x \*.pyo -x \*~
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
rm -Rf spline_editor/*~
rm -Rf spline_editor/game/*~
rm -Rf spline_editor/game/*.rpyc
rm -Rf spline_editor/game/*.rpyb
rm -Rf spline_editor/game/saves
rm spline_editor.zip
zip -9r spline_editor.zip spline_editor -x \*.svn\*
Symlink
+1
View File
@@ -0,0 +1 @@
dist/renpy.exe
+2 -2
View File
@@ -68,8 +68,8 @@ def path_to_renpy_base():
##############################################################################
# The version of the Mac Launcher and py4renpy that we use.
macos_version = (6, 7, 1)
linux_version = (6, 7, 1)
macos_version = (6, 8, 0)
linux_version = (6, 8, 0)
if __name__ == "__main__":
+4 -3
View File
@@ -25,9 +25,9 @@
# Some version numbers and things.
# ***** ***** ***** ***** ***** ***** **** ***** ***** ***** *****
# Be sure to change script_version in data/script_version.rpy, too!
# Be sure to change script_version in launcher/script_version.rpy, too!
# Also check to see if we have to update renpy.py.
version = "Ren'Py 6.7.1b"
version = "Ren'Py 6.8.0d"
script_version = 5003000
savegame_suffix = "-LT1.save"
@@ -59,7 +59,8 @@ def import_all():
import renpy.display.module
import renpy.display.render # Most display stuff depends on this.
import renpy.display.core # object
import renpy.display.text # core
import renpy.display.font
import renpy.display.text # core, font
import renpy.display.layout # core
import renpy.display.behavior # layout
import renpy.display.transition # core, layout
+2
View File
@@ -34,6 +34,8 @@ def extra_imports():
import encodings.string_escape
import encodings.raw_unicode_escape
import encodings.mbcs
import encodings.utf_16_be
import encodings.utf_16_le
import math
import glob
import pickle
+8
View File
@@ -174,6 +174,9 @@ keymap = dict(
reload_game = [ 'R' ],
inspector = [ 'I' ],
developer = [ 'D' ],
quit = [ 'meta_q', 'alt_K_F4' ],
iconify = [ 'meta_m', 'alt_m' ],
help = [ 'K_F1', 'meta_shift_/' ],
# Say.
rollforward = [ 'mousedown_5', 'K_PAGEDOWN' ],
@@ -369,6 +372,11 @@ auto_save_extra_info = None
# game-specific data is saved.
save_directory = None
# These are used to deal with the case where a picture is missing.
missing_scene = None
missing_show = None
missing_hide = None
del renpy
del sets
+20 -2
View File
@@ -84,6 +84,12 @@ def compile_event(key, keydown):
else:
rv += " and not (ev.mod & %d)" % pygame.KMOD_ALT
if part[0] == "meta":
part.pop(0)
rv += " and (ev.mod & %d)" % pygame.KMOD_META
else:
rv += " and not (ev.mod & %d)" % pygame.KMOD_META
if part[0] == "shift":
part.pop(0)
rv += " and (ev.mod & %d)" % pygame.KMOD_SHIFT
@@ -618,6 +624,15 @@ class Bar(renpy.display.core.Displayable):
value = self.adjustment.value
page = self.adjustment.page
if range <= 0:
if self.style.unscrollable == "hide":
self.hidden = True
return renpy.display.render.Render(width, height)
elif self.style.unscrollable == "insensitive":
self.set_style_prefix("insensitive_")
self.hidden = False
if self.style.bar_invert ^ self.style.bar_vertical:
value = range - value
@@ -712,11 +727,14 @@ class Bar(renpy.display.core.Displayable):
def event(self, ev, x, y, st):
if not self.focusable:
return
return None
if not self.is_focused():
return
return None
if self.hidden:
return None
range = self.adjustment.range
old_value = self.adjustment.value
value = old_value
+40 -20
View File
@@ -32,12 +32,17 @@ import time
import cStringIO
import threading
on_windows = (sys.platform == 'win32')
try:
import pygame.macosx
except:
pass
# Is the cpu idle enough to do other things?
cpu_idle = threading.Event()
cpu_idle.clear()
TIMEEVENT = USEREVENT + 1
PERIODIC = USEREVENT + 2
JOYEVENT = USEREVENT + 3
@@ -658,6 +663,9 @@ class Display(object):
# Ensure that we kill off the movie when changing screen res.
renpy.display.video.movie_stop(clear=False)
if pygame.version.vernum < (1, 8, 1):
raise Exception("Ren'Py requires pygame 1.8.1 to run.")
try:
pygame.macosx.init()
except:
@@ -710,10 +718,16 @@ class Display(object):
# Window icon.
if renpy.config.window_icon:
pygame.display.set_icon(
renpy.display.scale.image_load_unscaled(
renpy.loader.load(renpy.config.window_icon),
renpy.config.window_icon))
im = renpy.display.scale.image_load_unscaled(
renpy.loader.load(renpy.config.window_icon),
renpy.config.window_icon)
if on_windows and im.get_width() > 32:
im = renpy.display.scale.real_bilinear(im, (32, 32))
pygame.display.set_icon(im)
# If a window exists of the right size and flags, use it. Otherwise,
# make our own window.
@@ -774,6 +788,9 @@ class Display(object):
self.window_caption = caption
pygame.display.set_caption(caption.encode("utf-8"))
def iconify(self):
pygame.display.iconify()
def can_redraw(self, first_pass):
"""
Uses the framerate to determine if we can and should redraw.
@@ -976,12 +993,7 @@ class Display(object):
Saves a full-size screenshot in the given filename.
"""
if filename.endswith(".png"):
f = file(filename, "wb")
renpy.display.module.save_png(self.window, f)
f.close()
else:
pygame.image.save(self.window, filename)
pygame.image.save(self.window, filename)
def screenshot(self, scale):
"""
@@ -1272,7 +1284,19 @@ class Interface(object):
rv[None] = root
return rv
def quit_event(self):
"""
This is called to handle the user invoking a quit.
"""
if renpy.game.script.has_label("_confirm_quit") and not self.quick_quit:
self.quick_quit = True
renpy.game.call_in_new_context("_confirm_quit")
self.quick_quit = False
else:
raise renpy.game.QuitException()
def interact(self, clear=True, **kwargs):
"""
@@ -1741,12 +1765,7 @@ class Interface(object):
# Handle quit specially for now.
if ev.type == QUIT:
if renpy.game.script.has_label("_confirm_quit") and not self.quick_quit:
self.quick_quit = True
renpy.game.call_in_new_context("_confirm_quit")
self.quick_quit = False
else:
raise renpy.game.QuitException()
self.quit_event()
# Merge mousemotion events.
if ev.type == MOUSEMOTION:
@@ -1754,7 +1773,8 @@ class Interface(object):
if len(evs):
ev = evs[-1]
self.focused = True
if on_windows:
self.focused = True
# Handle focus notifications.
if ev.type == ACTIVEEVENT:
+444
View File
@@ -0,0 +1,444 @@
# Copyright 2004-2008 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import pygame
from pygame.constants import *
import xml.etree.ElementTree as etree
try:
import _renpy_font
pygame.font = _renpy_font
except:
pass
import renpy
# This contains a map from (fn, size, bold, italics, underline) to the
# unloaded font object corresponding to that specification.
fonts = { }
# This contains a map from (fn, size, bold, italics, underline) to the
# loaded font object corresponding to that specification.
font_cache = { }
class ImageFont(object):
# ImageFonts are expected to have the following fields defined by
# a subclass:
# Font global:
# height - The line height, the height of each character cell.
# kerns - The kern between wach pair of characters.
# default_kern - The default kern.
# baseline - The y offset of the font baseline.
# Per-character:
# width - The width of each character.
# advance - The advance of each character.
# offsets - The x and y offsets of each character.
# chars - A map from a character to the surface containing that character.
def size(self, text):
w = 0
if not text:
return (0, self.height)
for a, b in zip(text, text[1:]):
try:
w += self.advance[a] + self.kerns.get(a + b, self.default_kern)
except KeyError:
raise Exception("Character %r not found in %s." % (a, type(self).__name__))
w += self.width[text[-1]]
return (w, self.height)
def render(self, text, antialias, color, black_color=(0, 0, 0, 255), background=None):
surf = pygame.Surface(self.size(text), 0,
renpy.game.interface.display.sample_surface)
if not text:
return surf
x = 0
y = 0
for a, b in zip(text, text[1:]):
xoff, yoff = self.offsets[a]
surf.blit(self.chars[a], (x + xoff, y + yoff))
x += self.advance[a] + self.kerns.get(a + b, self.default_kern)
xoff, yoff = self.offsets[text[-1]]
surf.blit(self.chars[text[-1]], (x + xoff, y + yoff))
if renpy.config.recolor_sfonts and \
(color != (255, 255, 255, 255) or black_color != (0, 0, 0, 255) ) and \
renpy.display.module.can_twomap:
newsurf = pygame.Surface(surf.get_size(), surf.get_flags(), surf)
renpy.display.module.twomap(surf, newsurf, color, black_color)
renpy.display.render.mutated_surface(newsurf)
surf = newsurf
return surf
def get_linesize(self):
return self.height + 10
def get_height(self):
return self.height
def get_ascent(self):
return self.baseline
def get_descent(self):
return -(self.height - self.baseline)
class SFont(ImageFont):
def __init__(self,
filename,
spacewidth,
default_kern,
kerns,
charset):
self.filename = filename
self.spacewidth = spacewidth
self.default_kern = default_kern
self.kerns = kerns
self.charset = charset
def load(self):
self.chars = { }
self.width = { }
self.advance = { }
self.offsets = { }
# Load in the image.
surf = renpy.display.im.Image(self.filename).load(unscaled=True)
sw, sh = surf.get_size()
height = sh
self.height = height
self.baseline = height
# Create space characters.
self.chars[u' '] = pygame.Surface((self.spacewidth, height), 0, surf)
self.width[u' '] = self.spacewidth
self.advance[u' '] = self.spacewidth
self.offsets[u' '] = (0, 0)
self.chars[u'\u00a0'] = self.chars[u' ']
self.width[u'\u00a0'] = self.width[u' ']
self.advance[u'\u00a0'] = self.advance[u' ']
self.offsets[u'\u00a0'] = self.offsets[u' ']
# The color key used to separate characters.
i = 0
while True:
key = surf.get_at((i, 0))
if key[3] != 0:
break
i += 1
ci = 0
# Find real characters, create them.
while i < sw and ci < len(self.charset):
if surf.get_at((i, 0)) != key:
start = i
i += 1
while i < sw:
if surf.get_at((i, 0)) == key:
break
i += 1
c = self.charset[ci]
ci += 1
ss = surf.subsurface((start, 0, i - start, height))
ss = renpy.display.scale.surface_scale(ss)
self.chars[c] = ss
self.width[c] = i - start
self.advance[c] = i - start
self.offsets[c] = (0, 0)
i += 1
class MudgeFont(ImageFont):
def __init__(self,
filename,
xml,
spacewidth,
default_kern,
kerns):
self.filename = filename
self.xml = xml
self.spacewidth = spacewidth
self.default_kern = default_kern
self.kerns = kerns
def load(self):
self.chars = { }
self.width = { }
self.advance = { }
self.offsets = { }
# Load in the image.
surf = renpy.display.im.Image(self.filename).load(unscaled=True)
# Parse the xml file.
tree = etree.fromstring(renpy.loader.load(self.xml).read())
height = 0
# Find each character.
for e in tree.findall("char"):
char = int(e.attrib["id"])
if char < 0:
continue
c = unichr(char)
x = int(e.attrib["x"])
y = int(e.attrib["y"])
w = int(e.attrib["width"])
h = int(e.attrib["height"])
ss = surf.subsurface((x, y, w, h))
ss = renpy.display.scale.surface_scale(ss)
self.chars[c] = ss
self.width[c] = w
self.advance[c] = w
self.offsets[c] = (0, 0)
height = max(height, h)
self.height = height
self.baseline = height
# Create space characters.
if u' ' not in self.chars:
self.chars[u' '] = pygame.Surface((self.spacewidth, height), 0, surf)
self.width[u' '] = self.spacewidth
self.advance[u' '] = self.spacewidth
self.offsets[u' '] = (0, 0)
if u'\u00a0' not in self.chars:
self.chars[u'\u00a0'] = self.chars[u' ']
self.width[u'\u00a0'] = self.width[u' ']
self.advance[u'\u00a0'] = self.advance[u' ']
self.offsets[u'\u00a0'] = self.offsets[u' ']
def parse_bmfont_line(l):
w = ""
line = [ ]
quote = False
for c in l:
if c == "\r" or c == "\n":
continue
if c == " " and not quote:
if w:
line.append(w)
w = ""
continue
if c == "\"":
quote = not quote
continue
w += c
if w:
line.append(w)
map = dict(i.split("=", 1) for i in line[1:])
return line[0], map
class BMFont(ImageFont):
def __init__(self, filename):
self.filename = filename
def load(self):
self.chars = { }
self.width = { }
self.advance = { }
self.offsets = { }
self.kerns = { }
self.default_kern = 0
pages = { }
f = renpy.loader.load(self.filename)
for l in f:
kind, args = parse_bmfont_line(l)
if kind == "common":
self.height = int(args["lineHeight"])
self.baseline = int(args["base"])
elif kind == "page":
pages[int(args["id"])] = renpy.display.im.Image(args["file"]).load(unscaled=True)
elif kind == "char":
c = unichr(int(args["id"]))
x = int(args["x"])
y = int(args["y"])
w = int(args["width"])
h = int(args["height"])
xo = int(args["xoffset"])
yo = int(args["yoffset"])
xadvance = int(args["xadvance"])
page = int(args["page"])
ss = pages[page].subsurface((x, y, w, h))
ss = renpy.display.scale.surface_scale(ss)
self.chars[c] = ss
self.width[c] = w + xo
self.advance[c] = xadvance
self.offsets[c] = (xo, yo)
f.close()
if u'\u00a0' not in self.chars:
self.chars[u'\u00a0'] = self.chars[u' ']
self.width[u'\u00a0'] = self.width[u' ']
self.advance[u'\u00a0'] = self.advance[u' ']
self.offsets[u'\u00a0'] = self.offsets[u' ']
def register_sfont(name=None, size=None, bold=False, italics=False, underline=False,
filename=None, spacewidth=10, default_kern=0, kerns={},
charset=u"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"):
if name is None or size is None or filename is None:
raise Exception("When registering an SFont, the font name, font size, and filename are required.")
sf = SFont(filename, spacewidth, default_kern, kerns, charset)
fonts[(name, size, bold, italics, underline)] = sf
def register_mudgefont(name=None, size=None, bold=False, italics=False, underline=False,
filename=None, xml=None, spacewidth=10, default_kern=0, kerns={}):
if name is None or size is None or filename is None or xml is None:
raise Exception("When registering a Mudge Font, the font name, font size, filename, and xml filename are required.")
mf = MudgeFont(filename, xml, spacewidth, default_kern, kerns)
fonts[(name, size, bold, italics, underline)] = mf
def register_bmfont(name=None, size=None, bold=False, italics=False, underline=False,
filename=None):
bmf = BMFont(filename)
fonts[(name, size, bold, italics, underline)] = bmf
def load_ttf(fn, size, bold, italics, underline, expand):
try:
rv = pygame.font.Font(renpy.loader.load(fn), size)
rv.set_bold(bold)
rv.set_italic(italics)
except:
# Let's try to find the font on our own.
fonts = [ i.strip().lower() for i in fn.split(",") ]
pygame.sysfont.initsysfonts()
rv = None
for k, v in pygame.sysfont.Sysfonts.iteritems():
for flags, ffn in v.iteritems():
for i in fonts:
if ffn.lower().endswith(i):
rv = pygame.font.Font(ffn, size)
rv.set_bold(bold)
rv.set_italic(italics)
break
if rv:
break
if rv:
break
else:
# Let pygame try to find the font for us.
rv = pygame.font.SysFont(fn, size, bold, italics)
rv.set_underline(underline)
try:
rv.set_expand(expand)
except AttributeError:
pass
return rv
def get_font(origfn, size, origbold=False, origitalics=False, underline=False, expand=0):
rv = font_cache.get((origfn, size, origbold, origitalics, underline, expand), None)
if rv is not None:
return rv
t = (origfn, origbold, origitalics)
fn, bold, italics = renpy.config.font_replacement_map.get(t, t)
rv = fonts.get((fn, size, bold, italics, underline), None)
if rv is not None:
rv.load()
else:
try:
rv = load_ttf(fn, size, bold, italics, underline, expand)
except:
if renpy.config.debug:
raise
raise Exception("Could not find font: %r" % ((fn, size, bold, italics, underline), ))
font_cache[(origfn, size, origbold, origitalics, underline, expand)] = rv
return rv
def free_memory():
"""
Clears the font cache.
"""
font_cache.clear()
+4 -4
View File
@@ -65,7 +65,6 @@ class UncachedImage(renpy.display.core.Displayable):
return rv
class ImageReference(renpy.display.core.Displayable):
"""
ImageReference objects are used to reference images by their name,
@@ -93,7 +92,7 @@ class ImageReference(renpy.display.core.Displayable):
if isinstance(name, renpy.display.core.Displayable):
self.target = name
return
return True
if not isinstance(name, tuple):
name = tuple(name.split())
@@ -121,15 +120,16 @@ class ImageReference(renpy.display.core.Displayable):
error(str(e))
return
return True
else:
parameters.insert(0, name[-1])
name = name[:-1]
error("Image '%s' not found." % ' '.join(self.name))
return False
def event(self, ev, x, y, st):
if not self.target:
self.find_target()
+8 -5
View File
@@ -34,12 +34,15 @@ def start(gamedir):
import os.path
global proc
fn = gamedir + "/presplash.png"
if not os.path.exists(fn):
filenames = [ "/presplash.png", "/presplash.jpg" ]
for fn in filenames:
fn = gamedir + fn
if os.path.exists(fn):
break
else:
return
import subprocess
import sys
+7 -2
View File
@@ -26,6 +26,11 @@ import math
import pygame
import renpy
try:
import _renpy_font as font_module
except ImportError:
import pygame.font as font_module
# This needs to be done before we mess too hard with pygame.
try:
import _renpy
@@ -314,7 +319,7 @@ else:
# Ignoring scale2x and chop. The former due to a pending api change,
# the latter due to general uselessness.
PygameFont = pygame.font.Font
PygameFont = font_module.Font
class Font(object):
@@ -364,7 +369,7 @@ else:
# Anything involving the parents of subsurfaces.
# get_pitch, get_shifts, get_losses
pygame.font.Font = Font
font_module.Font = Font
old_image_save = pygame.image.save
+114 -274
View File
@@ -26,6 +26,9 @@ import re
import renpy
import sys
get_font = renpy.display.font.get_font
ImageFont = renpy.display.font.ImageFont
# A list of text tags, mapping from the text tag prefix to if it
# requires a closing tag.
text_tags = dict(
@@ -48,236 +51,6 @@ text_tags = dict(
text_tags[""] = True
# This contains a map from (fn, size, bold, italics, underline) to the
# unloaded font object corresponding to that specification.
fonts = { }
# This contains a map from (fn, size, bold, italics, underline) to the
# loaded font object corresponding to that specification.
font_cache = { }
class SFont(object):
def __init__(self,
filename,
spacewidth,
default_kern,
kerns,
charset):
self.filename = filename
self.spacewidth = spacewidth
self.default_kern = default_kern
self.kerns = kerns
self.charset = charset
def load(self):
# Map from character to subsurface.
self.chars = { }
# Map from character to width, height.
self.sizes = { }
# Load in the image.
surf = renpy.display.im.Image(self.filename).load(unscaled=True)
self.surf = surf
sw, sh = surf.get_size()
height = sh - 1
self.height = height
# Create space characters.
self.chars[u' '] = pygame.Surface((self.spacewidth, height), 0, surf)
self.sizes[u' '] = self.spacewidth
self.chars[u'\u00a0'] = self.chars[u' ']
self.sizes[u'\u00a0'] = self.sizes[u' ']
# The color key used to separate characters.
i = 0
while True:
key = surf.get_at((i, 0))
if key[3] != 0:
break
i += 1
ci = 0
# Find real characters, create them.
while i < sw and ci < len(self.charset):
if surf.get_at((i, 0)) != key:
start = i
i += 1
while i < sw:
if surf.get_at((i, 0)) == key:
break
i += 1
c = self.charset[ci]
ci += 1
ss = surf.subsurface((start, 1, i - start, height))
ss = renpy.display.scale.surface_scale(ss)
self.chars[c] = ss
self.sizes[c] = i - start
i += 1
def size(self, text):
w = 0
if not text:
return (0, self.height)
for a, b in zip(text, text[1:]):
w += self.sizes[a] + self.kerns.get(a + b, self.default_kern)
w += self.sizes[text[-1]]
return (w, self.height)
def render(self, text, antialias, color, black_color=(0, 0, 0, 255), background=None):
surf = pygame.Surface(self.size(text), 0,
renpy.game.interface.display.sample_surface)
if not text:
return surf
x = 0
y = 0
for a, b in zip(text, text[1:]):
surf.blit(self.chars[a], (x, y))
x += self.sizes[a] + self.kerns.get(a + b, self.default_kern)
surf.blit(self.chars[text[-1]], (x, y))
if renpy.config.recolor_sfonts and \
(color != (255, 255, 255, 255) or black_color != (0, 0, 0, 255) ) and \
renpy.display.module.can_twomap:
newsurf = pygame.Surface(surf.get_size(), surf.get_flags(), surf)
renpy.display.module.twomap(surf, newsurf, color, black_color)
renpy.display.render.mutated_surface(newsurf)
surf = newsurf
return surf
def get_linesize(self):
return self.height
def get_height(self):
return self.height
def get_ascent(self):
return self.height
def get_descent(self):
return 0
def register_sfont(name=None, size=None, bold=False, italics=False, underline=False,
filename=None, spacewidth=10, default_kern=0, kerns={},
charset=u"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"):
"""
This registers an SFont with the given details. Please note that
size, bold, italic, and underline are all advisory (used for matching), and
do not change the appearance of the font.
@param name: The name of the font being registered.
@param size: The size of the font being registered.
@param bold: The boldness of the font being registered.
@param italics: The italicness of the font being registered.
@param underline: The underline of the font being registered.
@param filename: The file containing the sfont image.
@param spacewidth: The width of a space character.
@param default_kern: The default kern spacing between characters.
@param kerns: A map from two-character strings to the kern that should
be used between those characters.
@param charset: The character set of the font. A string containing characters
in the order in which they are found in the image.
"""
if name is None or size is None or filename is None:
raise Exception("When registering an SFont, the font name, font size, and filename are required.")
sf = SFont(filename, spacewidth, default_kern, kerns, charset)
fonts[(name, size, bold, italics, underline)] = sf
def load_ttf(fn, size, bold, italics, underline):
try:
rv = pygame.font.Font(renpy.loader.load(fn), size)
rv.set_bold(bold)
rv.set_italic(italics)
except:
# Let's try to find the font on our own.
fonts = [ i.strip().lower() for i in fn.split(",") ]
pygame.sysfont.initsysfonts()
rv = None
for k, v in pygame.sysfont.Sysfonts.iteritems():
for flags, ffn in v.iteritems():
for i in fonts:
if ffn.lower().endswith(i):
rv = pygame.font.Font(ffn, size)
rv.set_bold(bold)
rv.set_italic(italics)
break
if rv:
break
if rv:
break
else:
# Let pygame try to find the font for us.
rv = pygame.font.SysFont(fn, size, bold, italics)
rv.set_underline(underline)
return rv
# TODO: Something sane if the font file can't be found.
def get_font(fn, size, bold=False, italics=False, underline=False):
from renpy.loader import transfn
if (fn, bold, italics) in renpy.config.font_replacement_map:
fn, bold, italics = renpy.config.font_replacement_map[fn, bold, italics]
if (fn, size, bold, italics, underline) in font_cache:
return font_cache[(fn, size, bold, italics, underline)]
rv = fonts.get((fn, size, bold, italics, underline), None)
if rv is not None:
rv.load()
else:
try:
rv = load_ttf(fn, size, bold, italics, underline)
except:
if renpy.config.debug:
raise
raise Exception("Could not find font: %r" % ((fn, size, bold, italics, underline), ))
font_cache[(fn, size, bold, italics, underline)] = rv
return rv
def free_memory():
"""
Clears the font cache.
"""
font_cache.clear()
def color(s):
"""
This function converts a hexcode into a color/alpha tuple. Leading
@@ -332,7 +105,7 @@ class TextStyle(object):
self.wcache = { }
def update(self):
self.f = get_font(self.font, self.size, self.bold, self.italic, self.underline)
self.f = get_font(self.font, self.size, self.bold, self.italic, self.underline, 0)
def get_font(self):
return self.f
@@ -351,16 +124,18 @@ class TextStyle(object):
def sizes(self, text):
return self.get_width(text), self.f.get_ascent() - self.f.get_descent()
def render(self, text, antialias, color, black_color, use_colors, time, at):
def render(self, text, antialias, color, black_color, use_colors, time, at, expand):
if use_colors:
color = self.color or color
black_color = self.black_color or black_color
if expand:
font = get_font(self.font, self.size, self.bold, self.italic, self.underline, expand)
else:
font = self.f
font = self.f
if isinstance(font, SFont):
if isinstance(font, ImageFont):
rv = font.render(text, antialias, color, black_color)
if self.strikethrough:
@@ -428,7 +203,7 @@ class WidgetStyle(object):
def sizes(self, widget):
return self.width, self.height
def render(self, widget, antialias, color, black_color, foreground, st, at):
def render(self, widget, antialias, color, black_color, foreground, st, at, expand):
# If in the foreground
if foreground:
@@ -439,7 +214,23 @@ class WidgetStyle(object):
def length(self, text):
return 1
class SpacerStyle(object):
def update(self):
pass
# The actual size is computed at render time.
def sizes(self, ignored):
return (0, 0)
def get_ascent(self):
return 0
def get_width(self, text):
return 0
def length(self, text):
return 0
# The line breaking algorithm for western languages.
western_text_regexp = re.compile(ur"""(?x)
@@ -591,6 +382,9 @@ def greedy_text_layout(triples, width, style):
lines = [ ]
line = [ ]
# Is this the last line in a paragraph?
lines_last = [ ]
target = width - style.first_indent
@@ -600,7 +394,8 @@ def greedy_text_layout(triples, width, style):
if type == "newline":
lines.append(line)
line = [ triple ]
lines_last.append(True)
line = [ ]
target = width - style.rest_indent
continue
@@ -614,20 +409,22 @@ def greedy_text_layout(triples, width, style):
else:
if layout_width(line + [ triple ]) > target:
lines.append(line)
lines_last.append(False)
line = [ triple ]
target = width - style.rest_indent
else:
line.append(triple)
lines.append(line)
lines_last.append(True)
# Remove trailing whitespace, except on the last line, where it
# might be intentional.
for l in lines[:-1]:
if l and l[-1][0] == "space":
l.pop()
return lines
return lines, lines_last
def subtitle_text_layout_core(triples, width, style, soft, n):
@@ -636,7 +433,7 @@ def subtitle_text_layout_core(triples, width, style, soft, n):
lines = [ ]
line = [ ]
target = width
total = soft * n
@@ -725,7 +522,8 @@ def subtitle_text_layout(triples, width, style):
# Deal with each paragraph separately.
rrv = [ ] # Real return value.
lines = [ ]
lines_last = [ ]
for triples in pars:
@@ -740,10 +538,13 @@ def subtitle_text_layout(triples, width, style):
if len(rv) == i:
break
i += 1
rrv.extend(rv)
return rrv
lines.extend(rv)
for i in range(len(lines) - 1):
lines_last.append(False)
lines_last.append(True)
return lines, lines_last
def text_layout(triples, width, style):
@@ -760,8 +561,8 @@ class Text(renpy.display.core.Displayable):
nosave = [ 'laidout', 'laidout_lineheights', 'laidout_linewidths',
'laidout_width', 'laidout_height', 'laidout_start',
'laidout_length', 'laidout_hyperlinks', 'width', 'tokens', 'children',
'child_pos']
'laidout_length', 'laidout_hyperlinks', 'laidout_lines_last',
'width', 'tokens', 'children', 'child_pos']
__version__ = 2
@@ -1257,7 +1058,6 @@ class Text(renpy.display.core.Displayable):
raise Exception("Unknown text token kind %s." % kind)
if kind == "widget":
wstyle = WidgetStyle(tsl[-1], i, width, time)
triples.append(("word", wstyle, i))
@@ -1269,9 +1069,8 @@ class Text(renpy.display.core.Displayable):
# Give text_layout a list of triples, get back a list of lists of
# triples, one per line.
linetriples = renpy.config.text_layout(triples, width, self.style)
linetriples, lines_last = renpy.config.text_layout(triples, width, self.style)
# Now, we need to go through these lines, to generate the data
# we need to render text.
@@ -1282,12 +1081,16 @@ class Text(renpy.display.core.Displayable):
self.laidout_start = 0
self.laidout_width = self.style.min_width
self.laidout_height = 0
self.laidout_lines_last = lines_last
# Add something to empty lines.
for l in linetriples:
if not l:
l.append(('word', tsl[-1], ' '))
justify = self.style.justify
for l in linetriples:
line = [ ]
@@ -1304,7 +1107,7 @@ class Text(renpy.display.core.Displayable):
self.laidout_length += len(i)
except:
self.laidout_length += ts.length(i)
if ts is not oldts:
if oldts is not None:
line.append((oldts, cur))
@@ -1314,6 +1117,12 @@ class Text(renpy.display.core.Displayable):
else:
cur += i
if justify and kind == "space":
if cur:
line.append((oldts, cur))
cur = ""
line.append((SpacerStyle(), ""))
if oldts:
line.append((oldts, cur))
@@ -1383,7 +1192,7 @@ class Text(renpy.display.core.Displayable):
def render_pass(self, r, offsets, color, black_color, user_colors, length, time, at, child_pos, add_focus):
def render_pass(self, r, xo, yo, color, black_color, user_colors, length, time, at, child_pos, add_focus, expand):
"""
Renders the text to r at the offsets. Color is the base color,
and user_colors controls if the user can override those colors.
@@ -1397,18 +1206,39 @@ class Text(renpy.display.core.Displayable):
rest_indent = self.style.rest_indent
antialias = self.style.antialias
line_spacing = self.style.line_spacing
for line, line_height, line_width in zip(self.laidout, self.laidout_lineheights, self.laidout_linewidths):
x = indent + self.style.text_align * (self.laidout_width - line_width)
text_align = self.style.text_align
justify = self.style.justify
lines = len(self.laidout)
for line, line_height, line_width, last in zip(self.laidout, self.laidout_lineheights, self.laidout_linewidths, self.laidout_lines_last):
if justify and not last:
empty_space = (self.laidout_width - line_width - indent)
x = indent
else:
empty_space = 0
x = indent + text_align * (self.laidout_width - line_width)
indent = rest_indent
max_ascent = 0
spacers = 0
for ts, text in line:
max_ascent = max(ts.get_ascent(), max_ascent)
for ts, text in line:
if isinstance(ts, SpacerStyle):
spacers += 1
for ts, text in line:
if isinstance(ts, SpacerStyle):
space = empty_space / spacers
x += space
empty_space -= space
spacers -= 1
continue
length -= ts.length(text)
if length < 0:
@@ -1417,20 +1247,21 @@ class Text(renpy.display.core.Displayable):
else:
return False
surf, (sw, sh) = ts.render(text, antialias, color, black_color, user_colors, time, at)
surf, (sw, sh) = ts.render(text, antialias, color, black_color, user_colors, time, at, expand)
if expand:
(sw, sh) = ts.sizes(text)
actual_y = y + max_ascent - ts.get_ascent()
for xo, yo in offsets:
if surf:
r.blit(surf, (x + xo, actual_y + yo))
if surf:
r.blit(surf, (x + xo, actual_y + yo))
if add_focus and ts.hyperlink is not None:
r.add_focus(self, ts.hyperlink, x + xo, y + yo, sw, sh)
if add_focus and ts.hyperlink is not None:
r.add_focus(self, ts.hyperlink, x + xo, y + yo, sw, sh)
if not isinstance(text, (str, unicode)):
child_pos.append((text, x + xo, actual_y + yo))
if not isinstance(text, (str, unicode)):
child_pos.append((text, x + xo, actual_y + yo))
x = x + sw
@@ -1480,7 +1311,8 @@ class Text(renpy.display.core.Displayable):
dslist = self.style.drop_shadow
outlines = self.style.outlines
if dslist is None:
dslist = [ ]
elif not isinstance(dslist, list):
@@ -1497,6 +1329,12 @@ class Text(renpy.display.core.Displayable):
maxdsx = max(maxdsx, dsx)
maxdsy = max(maxdsy, dsy)
for expand, color, dsx, dsy in outlines:
mindsx = min(mindsx, dsx - expand)
mindsy = min(mindsy, dsy - expand)
maxdsx = max(maxdsx, dsx + expand)
maxdsy = max(maxdsy, dsy + expand)
# minds{x,y} are negative (or 0), maxds{x,y} are positive (or 0).
self.layout(width + mindsx - maxdsx, st)
@@ -1510,13 +1348,15 @@ class Text(renpy.display.core.Displayable):
rv = renpy.display.render.Render(self.laidout_width - mindsx + maxdsx, self.laidout_height - mindsy + maxdsy)
if dslist:
dsoffsets = [ (dsxo - mindsx, dsyo - mindsy) for dsxo, dsyo in dslist ]
self.render_pass(rv, dsoffsets, self.style.drop_shadow_color, self.style.drop_shadow_color, False, length, st, at, [ ], False)
for dsxo, dsyo in dslist:
self.render_pass(rv, dsxo - mindsx, dsyo - mindsy, self.style.drop_shadow_color, self.style.drop_shadow_color, False, length, st, at, [ ], False, 0)
for expand, color, dsxo, dsyo in outlines:
self.render_pass(rv, dsxo - mindsx - expand, dsyo - mindsy - expand, color, color, False, length, st, at, [ ], False, expand)
self.child_pos = [ ]
if self.render_pass(rv, [ (-mindsx, -mindsy) ], self.style.color, self.style.black_color, True, length, st, at, self.child_pos, True):
if self.render_pass(rv, -mindsx, -mindsy, self.style.color, self.style.black_color, True, length, st, at, self.child_pos, True, 0):
if self.slow:
self.call_slow_done(st)
+83 -23
View File
@@ -28,16 +28,12 @@
_file = file
import renpy
# Many of these shouldn't be used directly.
# from renpy.display.layout import *
from renpy.display.text import ParameterizedText, register_sfont
from renpy.display.text import ParameterizedText
from renpy.display.font import register_sfont, register_mudgefont, register_bmfont
from renpy.display.behavior import Keymap
from renpy.display.minigame import Minigame
# from renpy.display.image import *
from renpy.curry import curry
# from renpy.display.audio import music_start, music_stop
from renpy.audio.sound import play
from renpy.display.video import movie_start_fullscreen, movie_start_displayable, movie_stop
from renpy.loadsave import load, save, list_saved_games, can_load, rename_save, unlink_save, scan_saved_game
@@ -135,6 +131,22 @@ def image(name, img):
img = renpy.easy.displayable(img)
images[name] = img
def copy_images(old, new):
if not isinstance(old, tuple):
old = tuple(old.split())
if not isinstance(new, tuple):
new = tuple(new.split())
lenold = len(old)
for k in list(images.keys()):
if len(k) < lenold:
continue
if k[:lenold] == old:
images[new + k[lenold:]] = images[k]
def showing(name, layer='master'):
"""
@@ -169,8 +181,11 @@ def show(name, at_list=[ ], layer='master', what=None, zorder=0, tag=None, behin
if what is None:
what = name
elif isinstance(what, basestring):
what = tuple(what.split())
base = img = renpy.display.image.ImageReference(what, style='image_placement')
img = renpy.display.image.ImageReference(what, style='image_placement')
for i in at_list:
img = i(img)
@@ -180,6 +195,13 @@ def show(name, at_list=[ ], layer='master', what=None, zorder=0, tag=None, behin
if tag:
name = (tag,) + name[1:]
if not base.find_target() and renpy.config.missing_show:
if renpy.config.missing_show(name, what, layer):
return
if renpy.config.missing_hide:
renpy.config.missing_hide(name, layer)
sls.add(layer, img, key, zorder, behind, at_list=at_list, name=name)
@@ -204,6 +226,9 @@ def hide(name, layer='master'):
sls = scene_lists()
key = name[0]
sls.remove(layer, key)
if renpy.config.missing_hide:
renpy.config.missing_hide(name, layer)
def scene(layer='master'):
@@ -215,7 +240,9 @@ def scene(layer='master'):
sls = scene_lists()
sls.clear(layer)
if renpy.config.missing_scene:
renpy.config.missing_scene(layer)
def watch(expression, style='default', **properties):
"""
@@ -890,13 +917,41 @@ def get_filename_line():
def shell_escape(s):
s = s.replace("\\", "\\\\")
s = s.replace("\'", "\\\'")
s = s.replace("\"", "\\\"")
s = s.replace("\$", "\\\$")
s = s.replace("\%", "\\\%")
s = s.replace("\`", "\\\`")
return s
def split_args(s):
rv = [ ]
word = ""
quoted = False
i = 0
while i < len(s):
c = s[i]
i += 1
if not quoted and c == ' ' and word:
if word:
rv.append(word)
word = ""
continue
if c == '"':
quoted = not quoted
continue
if c == '\\':
c = s[i]
i += 1
word += c
if word:
rv.append(word)
return rv
def launch_editor(filenames, line=1, transient=0):
"""
This causes an editor to be launched at the location of the current
@@ -913,16 +968,8 @@ def launch_editor(filenames, line=1, transient=0):
if not len(filenames):
return
# join = '" "'
shell = True
# if hasattr(sys, "winver"):
# shell = False
# # join = '" "'
# else:
# shell = True
# # join = "' '"
filenames = [ shell_escape(os.path.normpath(i)) for i in filenames ]
filename = filenames[0]
@@ -938,11 +985,12 @@ def launch_editor(filenames, line=1, transient=0):
cmd = cmd.replace('""', '')
try:
return subprocess.Popen(cmd, shell=shell)
subprocess.Popen(split_args(cmd))
return True
except:
if renpy.config.debug:
raise
return None
return False
# A file that log logs to.
logfile = None
@@ -1050,9 +1098,21 @@ def layer_at_list(at_list, layer='master'):
def free_memory():
force_full_redraw()
renpy.display.im.free_memory()
renpy.display.text.free_memory()
renpy.display.font.free_memory()
renpy.display.render.free_memory()
def easy_displayable(d, none=False):
if none:
return renpy.easy.displayable(d)
else:
return renpy.easy.displayable_or_none(d)
def quit_event():
renpy.game.interface.quit_event()
def iconify():
renpy.game.interface.display.iconify()
# New context stuff.
call_in_new_context = renpy.game.call_in_new_context
curried_call_in_new_context = renpy.curry.curry(renpy.game.call_in_new_context)
+1 -1
View File
@@ -443,7 +443,7 @@ class Script(object):
if self.bytecode_dirty:
try:
data = (BYTECODE_VERSION, self.bytecode_newcache)
f = file(os.path.join(renpy.config.searchpath[0], "bytecode.rpyb"), "w")
f = file(os.path.join(renpy.config.searchpath[0], "bytecode.rpyb"), "wb")
f.write(dumps(data, 2).encode("zlib"))
f.close()
except:
+21 -1
View File
@@ -72,6 +72,18 @@ def none_is_null(d):
else:
return renpy.easy.displayable(d)
# This expands the outlines list.
def expand_outlines(l):
rv = [ ]
for i in l:
if len(i) == 2:
rv.append((i[0], renpy.easy.color(i[1]), 0, 0))
else:
rv.append((i[0], renpy.easy.color(i[1]), i[2], i[3]))
return rv
# A map of properties that we know about. The properties may take a
# function that is called to convert the argument to something more
# useful.
@@ -82,6 +94,7 @@ style_properties = dict(
background = renpy.easy.displayable_or_none,
bar_invert = None,
bar_resizing = None,
unscrollable = None,
bar_vertical = None,
black_color = renpy.easy.color,
bold = None,
@@ -103,6 +116,7 @@ style_properties = dict(
foreground = renpy.easy.displayable_or_none,
sound = None,
italic = None,
justify = None,
language = None,
layout = None,
left_margin = None,
@@ -110,6 +124,7 @@ style_properties = dict(
line_spacing = None,
mouse = None,
min_width = None,
outlines = expand_outlines,
rest_indent = None,
right_margin = None,
right_padding = None,
@@ -292,6 +307,9 @@ class StyleManager(object):
s = Style(parent, { }, heavy=True, help=description)
setattr(self, name, s)
def rebuild(self):
renpy.style.rebuild()
def exists(self, name):
"""
@@ -472,10 +490,12 @@ def build_styles():
styles_built = True
def rebuild():
global style_pending
global styles_built
if renpy.game.init_phase:
return
styles_pending = [ j for i in style_parts.values() for j in i.values() ]
styles_built = False
+2 -2
View File
@@ -71,8 +71,8 @@ def archive(prefix, files):
for fullfn, shortfn in files:
if shortfn.lower().endswith(".ttf"):
continue
# if shortfn.lower().endswith(".ttf"):
# continue
shortfn = shortfn.replace("\\", "/")
Executable
+116
View File
@@ -0,0 +1,116 @@
#!/usr/bin/env python
# Copyright 2004-2007 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import os
import os.path
import sys
import lsprofcalltree
# Functions to be customized by distributors. ################################
# Given the Ren'Py base directory (usually the directory containing
# this file), this is expected to return the path to the common directory.
def path_to_common(renpy_base):
return renpy_base + "/common"
# Given a directory holding a Ren'Py game, this is expected to return
# the path to a directory that will hold save files.
def path_to_saves(gamedir):
return gamedir + "/saves"
# Returns the path to the Ren'Py base directory (containing common and
# the launcher, usually.)
def path_to_renpy_base():
renpy_base = os.path.dirname(sys.argv[0])
renpy_base = os.environ.get('RENPY_BASE', renpy_base)
renpy_base = os.path.abspath(renpy_base)
return renpy_base
##############################################################################
# The version of the Mac Launcher and py4renpy that we use.
macos_version = (6, 1, 0)
linux_version = (6, 1, 0)
if __name__ == "__main__":
if not 'RENPY_NO_VERSION_CHECK' in os.environ:
# Check for mac compatibility.
if "mac_version" in globals():
mac_version(macos_version)
# Check py4renpy compatibility.
try:
import py4renpy
if py4renpy.version < linux_version:
print "The version of py4renpy that you are using is too old. Please go to"
print "http://www.bishoujo.us/renpy/linux.html, and download the latest"
print "version."
sys.exit(-1)
except ImportError:
pass
renpy_base = path_to_renpy_base()
# Add paths.
if os.path.exists(renpy_base + "/module"):
sys.path.append(renpy_base + "/module")
sys.path.append(renpy_base)
# This is looked for by the mac launcher.
if os.path.exists(renpy_base + "/renpy.zip"):
sys.path.append(renpy_base + "/renpy.zip")
# Start Ren'Py proper.
try:
import renpy.bootstrap
except ImportError:
print >>sys.stderr, "Could not import renpy.bootstrap. Please ensure you decompressed Ren'Py"
print >>sys.stderr, "correctly, preserving the directory structure."
raise
import cProfile
prof = cProfile.Profile()
try:
prof = prof.run('renpy.bootstrap.bootstrap(renpy_base)')
except SystemExit:
pass
prof.dump_stats('renpy.stats')
import pstats
stats = pstats.Stats('renpy.stats')
stats.sort_stats('time')
stats.print_stats(20)
kg = lsprofcalltree.KCacheGrind(prof)
kg.output(file("renpy.kcg", "w"))
@@ -13,18 +13,18 @@ init:
if platform.mac_ver()[0]:
config.editor = "open -t '%(allfiles)s'"
else:
if sys.platform == 'win32':
editor = config.renpy_base + "/editor/scite.exe"
else:
editor = config.renpy_base + "/editor/scite"
editor = os.path.normpath(editor)
editor = renpy.shell_escape(editor)
if os.path.exists(editor):
editor = renpy.shell_escape(editor)
config.editor = '"' + editor + '" "%(allfiles)s" "-open:%(filename)s" -goto:%(line)d'
config.editor_transient = config.editor+' -revert:'
config.editor = '"' + editor + '" "%(allfiles)s" -goto:%(line)d'
config.editor_transient = config.editor+' -revert:'
if config.editor:
os.environ['RENPY_EDITOR'] = config.editor
+4 -2
View File
@@ -6,6 +6,8 @@ version = renpy.version[7:]
import sys
if "retag" in sys.argv[1:]:
renpy.subprocess.call([ "svn", "rm", 'http://www.bishoujo.us/svn/renpy/tags/' + version, "-m", "Tagging " + version ])
renpy.subprocess.call([ "bzr", "tag", "--delete", version ])
renpy.subprocess.call([ "svn", "copy", ".", 'http://www.bishoujo.us/svn/renpy/tags/' + version, "-m", "Tagging " + version ])
renpy.subprocess.call([ "bzr", "tag", version ])
+1
View File
@@ -0,0 +1 @@
../help.html
+13
View File
@@ -192,6 +192,19 @@ init -1 python hide:
# config.main_menu_music = "main_menu_theme.ogg"
#########################################
## Help.
## This lets you configure the help option on the Ren'Py menus.
## It may be:
## - A label in the script, in which case that label is called to
## show help to the user.
## - A file name relative to the base directory, which is opened in a
## web browser.
## - None, to disable help.
config.help = "README.html"
#########################################
## Transitions.
+1
View File
@@ -0,0 +1 @@
../help.html
Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 125 KiB

+13
View File
@@ -195,6 +195,19 @@ init -1 python hide:
# config.main_menu_music = "main_menu_theme.ogg"
#########################################
## Help.
## This lets you configure the help option on the Ren'Py menus.
## It may be:
## - A label in the script, in which case that label is called to
## show help to the user.
## - A file name relative to the base directory, which is opened in a
## web browser.
## - None, to disable help.
config.help = "README.html"
#########################################
## Miscellaneous customizations
Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

+1 -2
View File
@@ -1,3 +1,2 @@
description="A simple and complete Ren'Py game."
ro=True
special=True