Re-ran indent on all .c & .h source code files

Like so --
  find . -name "*.c" -or -name "*.h" -exec  indent -nbfda -npcs -npsl -bli0 --no-tabs {} \;

The `indent` invocation differs from the last one noted in
CHANGES.txt (from 2006!?), in that I've added "--no-tabs",
to ensure indents are all space-based.
This commit is contained in:
Bill Kendrick 2022-09-15 00:11:16 -07:00
parent 09f332367f
commit cc05925d9e
99 changed files with 31659 additions and 27102 deletions

View file

@ -19,25 +19,26 @@
#include <android/asset_manager_jni.h>
#include "android_assets.h"
AAssetManager * asset_manager = NULL;
char* nativelibdir = NULL;
AAssetManager *asset_manager = NULL;
char *nativelibdir = NULL;
AAssetDir * open_asset_dir(char * dirname)
AAssetDir *open_asset_dir(char *dirname)
{
return AAssetManager_openDir(asset_manager, dirname);
}
char* get_nativelibdir()
char *get_nativelibdir()
{
return nativelibdir;
return nativelibdir;
}
void load_assets_dir(char * dirname, tp_ftw_str ** ffilenames, unsigned * num_file_names)
void load_assets_dir(char *dirname, tp_ftw_str ** ffilenames,
unsigned *num_file_names)
{
AAssetDir* assetDir = AAssetManager_openDir(asset_manager, dirname);
const char* filename = (const char*)NULL;
tp_ftw_str * filenames = NULL;
AAssetDir *assetDir = AAssetManager_openDir(asset_manager, dirname);
const char *filename = (const char *) NULL;
tp_ftw_str *filenames = NULL;
unsigned max_file_names = 0;
int fulllen = 0;
*num_file_names = 0;
@ -46,7 +47,7 @@ void load_assets_dir(char * dirname, tp_ftw_str ** ffilenames, unsigned * num_f
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL)
{
char *cp;
fulllen = strlen(filename) + 1;
if (*num_file_names == max_file_names)
@ -66,7 +67,12 @@ void load_assets_dir(char * dirname, tp_ftw_str ** ffilenames, unsigned * num_f
*ffilenames = filenames;
}
JNIEXPORT jboolean Java_org_tuxpaint_tuxpaintActivity_managertojni(JNIEnv * env, jclass clazz, jobject mgr)
JNIEXPORT jboolean Java_org_tuxpaint_tuxpaintActivity_managertojni(JNIEnv *
env,
jclass
clazz,
jobject
mgr)
{
asset_manager = AAssetManager_fromJava(env, mgr);
@ -76,7 +82,12 @@ JNIEXPORT jboolean Java_org_tuxpaint_tuxpaintActivity_managertojni(JNIEnv * env,
return 1;
}
JNIEXPORT void Java_org_tuxpaint_tuxpaintActivity_setnativelibdir(JNIEnv * env, jclass clazz, jstring path)
JNIEXPORT void Java_org_tuxpaint_tuxpaintActivity_setnativelibdir(JNIEnv *
env,
jclass
clazz,
jstring
path)
{
const char *cpath = (*env)->GetStringUTFChars(env, path, NULL);
nativelibdir = strdup(cpath);
@ -84,21 +95,24 @@ JNIEXPORT void Java_org_tuxpaint_tuxpaintActivity_setnativelibdir(JNIEnv * env,
}
void load_brushes_from_assets(SDL_Surface * screen, SDL_Texture *texture, SDL_Renderer *renderer, const char * dirname, void (*fn) (SDL_Surface * screen,
SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const dir,
unsigned dirlen, tp_ftw_str * files,
unsigned count, const char *restrict const locale))
void load_brushes_from_assets(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer, const char *dirname,
void (*fn)(SDL_Surface * screen,
SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const dir,
unsigned dirlen, tp_ftw_str * files,
unsigned count,
const char *restrict const locale))
{
unsigned num_file_names = 0;
char * dir = "data/brushes";
char *dir = "data/brushes";
char buf[TP_FTW_PATHSIZE];
unsigned dirlen = strlen(dirname);
memcpy(buf, dir, dirlen);
tp_ftw_str * filenames = NULL;
tp_ftw_str *filenames = NULL;
load_assets_dir(dirname, &filenames, &num_file_names);
fn(screen, texture, renderer, dir, dirlen, filenames, num_file_names, NULL);
@ -107,12 +121,14 @@ void load_brushes_from_assets(SDL_Surface * screen, SDL_Texture *texture, SDL_Re
void load_from_assets(SDL_Surface * screen, SDL_Texture *texture, SDL_Renderer *renderer, const char * dirname, void (*fn) (SDL_Surface * screen,
SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const dir,
unsigned dirlen, tp_ftw_str * files,
unsigned count, const char *restrict const locale))
void load_from_assets(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer, const char *dirname,
void (*fn)(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const dir,
unsigned dirlen, tp_ftw_str * files,
unsigned count,
const char *restrict const locale))
{
unsigned num_file_names = 0;
// char * dir = "data/stamps/cartoon/tux";
@ -121,8 +137,9 @@ void load_from_assets(SDL_Surface * screen, SDL_Texture *texture, SDL_Renderer *
memcpy(buf, dirname, dirlen);
tp_ftw_str * filenames = NULL;
tp_ftw_str *filenames = NULL;
load_assets_dir(dirname, &filenames, &num_file_names);
fn(screen, texture, renderer, dirname, dirlen, filenames, num_file_names, NULL);
fn(screen, texture, renderer, dirname, dirlen, filenames, num_file_names,
NULL);
}

View file

@ -18,7 +18,7 @@
#define TP_ANDROID_ASSETS
#include <jni.h>
#include "debug.h"
#include "debug.h"
#include "dirwalk.h"
#include "progressbar.h"
#include <android/asset_manager.h>
@ -28,27 +28,43 @@
#define ASSETS_BRUSHES_DIR "data/brushes"
#define ASSETS_STAMPS_DIR "stamps/cartoon/tux"
AAssetDir * open_asset_dir(char * dirname);
char* get_nativelibdir();
AAssetDir *open_asset_dir(char *dirname);
char *get_nativelibdir();
void load_brushes_from_assets(SDL_Surface * screen, SDL_Texture *texture, SDL_Renderer *renderer, const char * dirname, void (*fn) (SDL_Surface * screen,
SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const dir,
unsigned dirlen, tp_ftw_str * files,
unsigned count, const char *restrict const locale) );
void load_brushes_from_assets(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer, const char *dirname,
void (*fn)(SDL_Surface * screen,
SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const dir,
unsigned dirlen, tp_ftw_str * files,
unsigned count,
const char *restrict const locale));
void load_from_assets(SDL_Surface * screen, SDL_Texture *texture, SDL_Renderer *renderer, const char * dirname, void (*fn) (SDL_Surface * screen,
SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const dir,
unsigned dirlen, tp_ftw_str * files,
unsigned count, const char *restrict const locale) );
void load_from_assets(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer, const char *dirname,
void (*fn)(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const dir,
unsigned dirlen, tp_ftw_str * files,
unsigned count,
const char *restrict const locale));
void load_assets_dir(char * dirname, tp_ftw_str ** ffilenames, unsigned * num_file_names);
void load_assets_dir(char *dirname, tp_ftw_str ** ffilenames,
unsigned *num_file_names);
JNIEXPORT jboolean Java_org_tuxpaint_tuxpaintActivity_managertojni(JNIEnv * env, jclass clazz, jobject mgr);
JNIEXPORT jboolean Java_org_tuxpaint_tuxpaintActivity_managertojni(JNIEnv *
env,
jclass
clazz,
jobject
mgr);
JNIEXPORT void Java_org_tuxpaint_tuxpaintActivity_setnativelibdir(JNIEnv * env, jclass clazz, jstring path);
JNIEXPORT void Java_org_tuxpaint_tuxpaintActivity_setnativelibdir(JNIEnv *
env,
jclass
clazz,
jstring
path);
#endif

View file

@ -30,58 +30,67 @@
#include <string.h>
// This implementation may be simple, but can work fine for all of Android devices
size_t mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n){
int length = strnlen (s, n);
// w is the index of pwcs, s is the index of s
int w = 0, c = 0;
size_t mbstowcs(wchar_t *__restrict pwcs, const char *__restrict s, size_t n)
{
int length = strnlen(s, n);
// w is the index of pwcs, s is the index of s
int w = 0, c = 0;
while (1) {
pwcs[w] = '\0';
char first = s[c];
int len = 0;
if ((first & 0x80) == 0) {
pwcs[w] = (wchar_t)s[c];
len = 1;
}
else if ((first & 0xe0) == 0xc0) {
pwcs[w] |= first & 0x1f;
pwcs[w] <<= 6;
pwcs[w] |= s[c+1] & 0x3f;
len = 2;
}
else if ((first & 0xf0) == 0xe0) {
pwcs[w] |= first & 0x0f;
pwcs[w] <<= 6;
pwcs[w] |= s[c+1] & 0x3f;
pwcs[w] <<= 6;
pwcs[w] |= s[c+2] & 0x3f;
len = 3;
}
else if ((first & 0xf8) == 0xf0) {
pwcs[w] |= first & 0x07;
pwcs[w] <<= 6;
pwcs[w] |= s[c+1] & 0x3f;
pwcs[w] <<= 6;
pwcs[w] |= s[c+2] & 0x3f;
pwcs[w] <<= 6;
pwcs[w] |= s[c+3] & 0x3f;
len = 4;
}
else {
return -1;
}
while (1)
{
pwcs[w] = '\0';
char first = s[c];
int len = 0;
if ((first & 0x80) == 0)
{
pwcs[w] = (wchar_t) s[c];
len = 1;
}
else if ((first & 0xe0) == 0xc0)
{
pwcs[w] |= first & 0x1f;
pwcs[w] <<= 6;
pwcs[w] |= s[c + 1] & 0x3f;
len = 2;
}
else if ((first & 0xf0) == 0xe0)
{
pwcs[w] |= first & 0x0f;
pwcs[w] <<= 6;
pwcs[w] |= s[c + 1] & 0x3f;
pwcs[w] <<= 6;
pwcs[w] |= s[c + 2] & 0x3f;
len = 3;
}
else if ((first & 0xf8) == 0xf0)
{
pwcs[w] |= first & 0x07;
pwcs[w] <<= 6;
pwcs[w] |= s[c + 1] & 0x3f;
pwcs[w] <<= 6;
pwcs[w] |= s[c + 2] & 0x3f;
pwcs[w] <<= 6;
pwcs[w] |= s[c + 3] & 0x3f;
len = 4;
}
else
{
return -1;
}
c += len;
w++;
c += len;
w++;
if (c > length){
pwcs[w] = '\0';
return -1;
}
if (c == length){
pwcs[w] = '\0';
return w;
}
}
if (c > length)
{
pwcs[w] = '\0';
return -1;
}
if (c == length)
{
pwcs[w] = '\0';
return w;
}
}
}

View file

@ -31,6 +31,6 @@ Anyway, using our own implementation of "mbstowcs" can fix this problem.
#undef mbsrtowcs
// redefine mbstowcs function
size_t mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n);
size_t mbstowcs(wchar_t *__restrict pwcs, const char *__restrict s, size_t n);
#endif

View file

@ -19,7 +19,7 @@
(See COPYING.txt)
*/
// Based on JNI and PrintHelper class
// https://developer.android.com/reference/android/support/v4/print/PrintHelper.html
// https://developer.android.com/training/printing/photos.html
@ -31,58 +31,80 @@
/* FIXME: Is this check still needed after the change from android/support/v4 to AndroidX
and being Android 5 the minimum version we support? */
// Since Print work is based on Java PrintHelper class, which may not be supported on some old versions
int IsPrinterAvailable( void )
int IsPrinterAvailable(void)
{
JNIEnv *mEnv = Android_JNI_GetEnv();
jclass mPrintHelperClass = (*mEnv)->FindClass(mEnv, "androidx/print/PrintHelper");
JNIEnv *mEnv = Android_JNI_GetEnv();
jclass mPrintHelperClass =
(*mEnv)->FindClass(mEnv, "androidx/print/PrintHelper");
if (mPrintHelperClass == NULL)
return 0;
if (mPrintHelperClass == NULL)
return 0;
jmethodID mSupportMethod = (*mEnv)->GetStaticMethodID(mEnv, mPrintHelperClass, "systemSupportsPrint", "()Z");
jboolean support = (*mEnv)->CallStaticBooleanMethod(mEnv, mPrintHelperClass, mSupportMethod);
jmethodID mSupportMethod =
(*mEnv)->GetStaticMethodID(mEnv, mPrintHelperClass, "systemSupportsPrint",
"()Z");
jboolean support =
(*mEnv)->CallStaticBooleanMethod(mEnv, mPrintHelperClass, mSupportMethod);
return support ? 1 : 0;
return support ? 1 : 0;
}
// This function is based on
// (1) convert surface to Java BitMap object
// (2) call Java PrintHelper to do print job.
const char *SurfacePrint(SDL_Surface *surface)
const char *SurfacePrint(SDL_Surface * surface)
{
JNIEnv *mEnv = Android_JNI_GetEnv();
jclass mBitmapClass = (*mEnv)->FindClass(mEnv, "android/graphics/Bitmap");
jmethodID mCreateMethod = (*mEnv)->GetStaticMethodID(mEnv, mBitmapClass, "createBitmap", "([IIILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
jintArray mSurfaceArray = (*mEnv)->NewIntArray(mEnv, surface->w * surface->h);
(*mEnv)->SetIntArrayRegion(mEnv,mSurfaceArray, 0, surface->w * surface->h, surface->pixels);
jclass mConfigClass = (*mEnv)->FindClass(mEnv, "android/graphics/Bitmap$Config");
jfieldID mConfigField = (*mEnv)->GetStaticFieldID(mEnv, mConfigClass , "ARGB_8888", "Landroid/graphics/Bitmap$Config;");
jobject mConfig = (*mEnv)->GetStaticObjectField(mEnv, mConfigClass, mConfigField);
jobject mBitMap = (*mEnv)->CallStaticObjectMethod(mEnv, mBitmapClass, mCreateMethod, mSurfaceArray, surface->w, surface->h, mConfig);
JNIEnv *mEnv = Android_JNI_GetEnv();
jclass mBitmapClass = (*mEnv)->FindClass(mEnv, "android/graphics/Bitmap");
jmethodID mCreateMethod =
(*mEnv)->GetStaticMethodID(mEnv, mBitmapClass, "createBitmap",
"([IIILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
jintArray mSurfaceArray =
(*mEnv)->NewIntArray(mEnv, surface->w * surface->h);
(*mEnv)->SetIntArrayRegion(mEnv, mSurfaceArray, 0, surface->w * surface->h,
surface->pixels);
jclass mConfigClass =
(*mEnv)->FindClass(mEnv, "android/graphics/Bitmap$Config");
jfieldID mConfigField =
(*mEnv)->GetStaticFieldID(mEnv, mConfigClass, "ARGB_8888",
"Landroid/graphics/Bitmap$Config;");
jobject mConfig =
(*mEnv)->GetStaticObjectField(mEnv, mConfigClass, mConfigField);
jobject mBitMap =
(*mEnv)->CallStaticObjectMethod(mEnv, mBitmapClass, mCreateMethod,
mSurfaceArray, surface->w, surface->h,
mConfig);
jobject mContext = (jobject)SDL_AndroidGetActivity();
jclass mPrintClass = (*mEnv)->FindClass(mEnv, "androidx/print/PrintHelper");
// sometimes android v4 support library may be not ready
if (mPrintClass == NULL)
return "There is no androidX support library.";
jmethodID mInitMethod = (*mEnv)->GetMethodID(mEnv, mPrintClass, "<init>", "(Landroid/content/Context;)V");
jobject mPrint = (*mEnv)->NewObject(mEnv, mPrintClass, mInitMethod, mContext);
jmethodID mPrintMethod = (*mEnv)->GetMethodID(mEnv, mPrintClass, "printBitmap", "(Ljava/lang/String;Landroid/graphics/Bitmap;)V");
jobject mContext = (jobject) SDL_AndroidGetActivity();
jclass mPrintClass = (*mEnv)->FindClass(mEnv, "androidx/print/PrintHelper");
// sometimes android v4 support library may be not ready
if (mPrintClass == NULL)
return "There is no androidX support library.";
jmethodID mInitMethod = (*mEnv)->GetMethodID(mEnv, mPrintClass, "<init>",
"(Landroid/content/Context;)V");
jobject mPrint =
(*mEnv)->NewObject(mEnv, mPrintClass, mInitMethod, mContext);
jmethodID mPrintMethod =
(*mEnv)->GetMethodID(mEnv, mPrintClass, "printBitmap",
"(Ljava/lang/String;Landroid/graphics/Bitmap;)V");
/* Thanks to n.collins for the explaination on the int signature
on https://stackoverflow.com/questions/13468041/android-how-to-call-java-method-from-jni-with-int-and-int-parameters --Pere */
jmethodID msetScaleMode = (*mEnv)->GetMethodID(mEnv, mPrintClass, "setScaleMode", "(I)V");
jfieldID mScaleModeField = (*mEnv)->GetStaticFieldID(mEnv, mPrintClass, "SCALE_MODE_FIT", "I");
jint mScaleModeInt = (*mEnv)->GetStaticIntField(mEnv, mPrintClass, mScaleModeField);
(*mEnv)->CallVoidMethod(mEnv, mPrint, msetScaleMode, mScaleModeInt);
/* Thanks to n.collins for the explaination on the int signature
on https://stackoverflow.com/questions/13468041/android-how-to-call-java-method-from-jni-with-int-and-int-parameters --Pere */
jmethodID msetScaleMode =
(*mEnv)->GetMethodID(mEnv, mPrintClass, "setScaleMode", "(I)V");
jfieldID mScaleModeField =
(*mEnv)->GetStaticFieldID(mEnv, mPrintClass, "SCALE_MODE_FIT", "I");
jint mScaleModeInt =
(*mEnv)->GetStaticIntField(mEnv, mPrintClass, mScaleModeField);
(*mEnv)->CallVoidMethod(mEnv, mPrint, msetScaleMode, mScaleModeInt);
jstring mString = (*mEnv)->NewStringUTF(mEnv, "TuxPaint");
(*mEnv)->CallVoidMethod(mEnv, mPrint, mPrintMethod, mString, mBitMap);
jstring mString = (*mEnv)->NewStringUTF(mEnv, "TuxPaint");
(*mEnv)->CallVoidMethod(mEnv, mPrint, mPrintMethod, mString, mBitMap);
// clean up
(*mEnv)->DeleteLocalRef(mEnv, mSurfaceArray);
(*mEnv)->DeleteLocalRef(mEnv, mConfig);
(*mEnv)->DeleteLocalRef(mEnv, mPrint);
(*mEnv)->DeleteLocalRef(mEnv, mString);
return NULL;
// clean up
(*mEnv)->DeleteLocalRef(mEnv, mSurfaceArray);
(*mEnv)->DeleteLocalRef(mEnv, mConfig);
(*mEnv)->DeleteLocalRef(mEnv, mPrint);
(*mEnv)->DeleteLocalRef(mEnv, mString);
return NULL;
}

View file

@ -1,7 +1,7 @@
/* android_print.h */
/* printing support for Tux Paint */
/* android_print.h */
/* printing support for Tux Paint */
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,15 +17,15 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt)
*/
*/
#ifndef __ANDROID_PRINT_H__
#define __ANDROID_PRINT_H__
#include "SDL.h"
extern const char *SurfacePrint(SDL_Surface *surface);
extern const char *SurfacePrint(SDL_Surface * surface);
extern int IsPrinterAvailable(void);
#endif /* __ANDROID_PRINT__ */
#endif /* __ANDROID_PRINT__ */

View file

@ -129,9 +129,8 @@
/* h/t https://tutel.me/c/programming/questions/45349079/how+to+use+__attribute__fallthrough+correctly+in+gcc */
#ifndef FALLTHROUGH
#if defined(__GNUC__) && __GNUC__ >= 7
#define FALL_THROUGH __attribute__ ((fallthrough))
#define FALL_THROUGH __attribute__ ((fallthrough))
#else
#define FALL_THROUGH ((void)0)
#define FALL_THROUGH ((void)0)
#endif /* __GNUC__ >= 7 */
#endif

View file

@ -97,8 +97,8 @@ void do_setcursor(SDL_Cursor * c)
void free_cursor(SDL_Cursor ** cursor)
{
if (*cursor)
{
SDL_FreeCursor(*cursor);
*cursor = NULL;
}
{
SDL_FreeCursor(*cursor);
*cursor = NULL;
}
}

View file

@ -79,8 +79,10 @@ extern char *strcasestr(const char *haystack, const char *needle);
* @param screen Screen surface, for animating progress bar.
* FIXME
*/
void loadfont_callback(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer,
const char *restrict const dir, unsigned dirlen, tp_ftw_str * files, unsigned i,
void loadfont_callback(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const dir, unsigned dirlen,
tp_ftw_str * files, unsigned i,
const char *restrict const locale)
{
dirlen = dirlen;
@ -90,188 +92,209 @@ void loadfont_callback(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer
#else
while (i--)
#endif
{
int loadable = 0;
const char *restrict const cp = strchr(files[i].str, '.');
show_progress_bar_(screen, texture, renderer);
if (cp)
{
int loadable = 0;
const char *restrict const cp = strchr(files[i].str, '.');
// need gcc 3.4 for the restrict in this location
const char * /*restrict */ const suffixes[] =
{ "ttc", "dfont", "pfa", "pfb", "otf", "ttf", };
int j = sizeof suffixes / sizeof suffixes[0];
show_progress_bar_(screen, texture, renderer);
if (cp)
while (j--)
{
// only check part, because of potential .gz or .bz2 suffix
if (!strncasecmp(cp + 1, suffixes[j], strlen(suffixes[j])))
{
// need gcc 3.4 for the restrict in this location
const char * /*restrict */ const suffixes[] =
{ "ttc", "dfont", "pfa", "pfb", "otf", "ttf", };
int j = sizeof suffixes / sizeof suffixes[0];
while (j--)
{
// only check part, because of potential .gz or .bz2 suffix
if (!strncasecmp(cp + 1, suffixes[j], strlen(suffixes[j])))
{
loadable = 1;
break;
}
}
loadable = 1;
break;
}
if (!loadable)
}
}
if (!loadable)
{
if (strcasestr(files[i].str, "/rsrc"))
loadable = 1;
}
// Loadable: TrueType (.ttf), OpenType (.otf), Type1 (.pfa and .pfb),
// and various useless bitmap fonts. Compressed files (with .gz or .bz2)
// should also work. A *.dfont is pretty much a Mac resource fork in a normal
// file, and may load with some library versions.
if (loadable)
{
char fname[512];
TuxPaint_Font *font;
snprintf(fname, sizeof fname, "%s/%s", dir, files[i].str);
#ifdef DEBUG
printf("%s:%d - Loading font: %s (locale is: %s)\n", __FILE__, __LINE__, fname, (locale ? locale : "NULL")); //EP
fflush(stdout);
#endif
if (locale && strstr(fname, "locale") && !all_locale_fonts)
{
char fname_check[512];
/* We're (probably) loading from our locale fonts folder; ONLY load our locale's font */
snprintf(fname_check, sizeof fname_check, "%s/%s.ttf", dir, locale);
#ifdef DEBUG
printf("%s:%d - checking \"%s\" vs \"%s\"\n", __FILE__, __LINE__, fname_check, fname); //EP
#endif
if (strcmp(fname, fname_check) == 0)
font = TuxPaint_Font_OpenFont("", fname, text_sizes[text_size]);
else
font = NULL;
}
else
{
font = TuxPaint_Font_OpenFont("", fname, text_sizes[text_size]);
}
if (font)
{
const char *restrict const family =
TuxPaint_Font_FontFaceFamilyName(font);
const char *restrict const style =
TuxPaint_Font_FontFaceStyleName(font);
#ifdef DEBUG
if (font->typ == FONT_TYPE_TTF)
{
if (strcasestr(files[i].str, "/rsrc"))
loadable = 1;
int numfaces = TTF_FontFaces(font->ttf_font);
if (numfaces != 1)
printf("%s:%d - Found %d faces in %s, %s, %s\n", __FILE__,
__LINE__, numfaces, files[i].str, family, style);
printf("%s:%d - success: tpf: 0x%x tpf->ttf_font: 0x%x\n", __FILE__, __LINE__, (unsigned int) (intptr_t) font, (unsigned int) (intptr_t) font->ttf_font); //EP added (intptr_t) to avoid warning on x64
}
// Loadable: TrueType (.ttf), OpenType (.otf), Type1 (.pfa and .pfb),
// and various useless bitmap fonts. Compressed files (with .gz or .bz2)
// should also work. A *.dfont is pretty much a Mac resource fork in a normal
// file, and may load with some library versions.
if (loadable)
{
char fname[512];
TuxPaint_Font *font;
snprintf(fname, sizeof fname, "%s/%s", dir, files[i].str);
#ifdef DEBUG
printf("%s:%d - Loading font: %s (locale is: %s)\n", __FILE__, __LINE__, fname, (locale ? locale : "NULL")); //EP
fflush(stdout);
#endif
if (locale && strstr(fname, "locale") && !all_locale_fonts)
{
char fname_check[512];
/* We're (probably) loading from our locale fonts folder; ONLY load our locale's font */
snprintf(fname_check, sizeof fname_check, "%s/%s.ttf", dir, locale);
#ifdef DEBUG
printf("%s:%d - checking \"%s\" vs \"%s\"\n", __FILE__, __LINE__, fname_check, fname); //EP
#endif
if (strcmp(fname, fname_check) == 0)
font = TuxPaint_Font_OpenFont("", fname, text_sizes[text_size]);
else
font = NULL;
}
else
{
font = TuxPaint_Font_OpenFont("", fname, text_sizes[text_size]);
}
if (font)
{
const char *restrict const family = TuxPaint_Font_FontFaceFamilyName(font);
const char *restrict const style = TuxPaint_Font_FontFaceStyleName(font);
#ifdef DEBUG
if (font->typ == FONT_TYPE_TTF)
{
int numfaces = TTF_FontFaces(font->ttf_font);
if (numfaces != 1)
printf("%s:%d - Found %d faces in %s, %s, %s\n", __FILE__, __LINE__, numfaces, files[i].str, family, style);
printf("%s:%d - success: tpf: 0x%x tpf->ttf_font: 0x%x\n", __FILE__, __LINE__, (unsigned int)(intptr_t) font, (unsigned int)(intptr_t) font->ttf_font); //EP added (intptr_t) to avoid warning on x64
}
#ifndef NO_SDLPANGO
else
printf("%s:%d - success: tpf: 0x%x tpf->pango_context: 0x%x\n", __FILE__, __LINE__, (unsigned int)(intptr_t) font, (unsigned int)(intptr_t) font->pango_context);
else
printf("%s:%d - success: tpf: 0x%x tpf->pango_context: 0x%x\n",
__FILE__, __LINE__, (unsigned int) (intptr_t) font,
(unsigned int) (intptr_t) font->pango_context);
#endif
#endif
// These fonts crash Tux Paint via a library bug.
int blacklisted = !strcmp("Zapfino", family) || !strcmp("Elvish Ring NFI", family);
// These fonts crash Tux Paint via a library bug.
int blacklisted = !strcmp("Zapfino", family)
|| !strcmp("Elvish Ring NFI", family);
// First, the blacklist. We list font families that can crash Tux Paint
// via bugs in the SDL_ttf library. We also test fonts to be sure that
// they have both uppercase and lowercase letters. Note that we do not
// test for "Aa", because it is OK if uppercase and lowercase are the
// same (but not nice -- such fonts get a low score later).
//
// Most locales leave the blacklist strings alone: "QX" and "qx"
// (it is less destructive to use the scoring strings instead)
//
// Locales that absolutely require all fonts to have some
// extra characters should use "QX..." and "qx...", where "..."
// are some characters you absolutely require in all fonts.
//
// Locales with absolutely NO use for ASCII may use "..." and "...",
// where "..." are some characters you absolutely require in
// all fonts. This would be the case for a locale in which it is
// impossible for a user to type ASCII letters.
//
// Most translators should use scoring instead.
if (!charset_works(font, gettext("qx")) || !charset_works(font, gettext("QX")))
blacklisted = 1;
// First, the blacklist. We list font families that can crash Tux Paint
// via bugs in the SDL_ttf library. We also test fonts to be sure that
// they have both uppercase and lowercase letters. Note that we do not
// test for "Aa", because it is OK if uppercase and lowercase are the
// same (but not nice -- such fonts get a low score later).
//
// Most locales leave the blacklist strings alone: "QX" and "qx"
// (it is less destructive to use the scoring strings instead)
//
// Locales that absolutely require all fonts to have some
// extra characters should use "QX..." and "qx...", where "..."
// are some characters you absolutely require in all fonts.
//
// Locales with absolutely NO use for ASCII may use "..." and "...",
// where "..." are some characters you absolutely require in
// all fonts. This would be the case for a locale in which it is
// impossible for a user to type ASCII letters.
//
// Most translators should use scoring instead.
if (!charset_works(font, gettext("qx"))
|| !charset_works(font, gettext("QX")))
blacklisted = 1;
if (!blacklisted)
{
if (num_font_styles == num_font_styles_max)
{
num_font_styles_max = num_font_styles_max * 5 / 4 + 30;
user_font_styles = realloc(user_font_styles, num_font_styles_max * sizeof *user_font_styles);
}
user_font_styles[num_font_styles] = malloc(sizeof *user_font_styles[num_font_styles]);
user_font_styles[num_font_styles]->directory = strdup(dir);
user_font_styles[num_font_styles]->filename = files[i].str; // steal it (mark NULL below)
user_font_styles[num_font_styles]->family = strdup(family);
user_font_styles[num_font_styles]->style = strdup(style);
user_font_styles[num_font_styles]->score = 0;
if (!blacklisted)
{
if (num_font_styles == num_font_styles_max)
{
num_font_styles_max = num_font_styles_max * 5 / 4 + 30;
user_font_styles =
realloc(user_font_styles,
num_font_styles_max * sizeof *user_font_styles);
}
user_font_styles[num_font_styles] =
malloc(sizeof *user_font_styles[num_font_styles]);
user_font_styles[num_font_styles]->directory = strdup(dir);
user_font_styles[num_font_styles]->filename = files[i].str; // steal it (mark NULL below)
user_font_styles[num_font_styles]->family = strdup(family);
user_font_styles[num_font_styles]->style = strdup(style);
user_font_styles[num_font_styles]->score = 0;
// TODO: weight specification
// TODO: weight specification
// Now we score fonts to ensure that the best ones will be placed at
// the top of the list. The user will see them first. This sorting is
// especially important for users who have scroll buttons disabled.
// Translators should do whatever is needed to put crummy fonts last.
// Now we score fonts to ensure that the best ones will be placed at
// the top of the list. The user will see them first. This sorting is
// especially important for users who have scroll buttons disabled.
// Translators should do whatever is needed to put crummy fonts last.
// distinct uppercase and lowercase (e.g., 'o' vs. 'O')
user_font_styles[num_font_styles]->score += charset_works(font, gettext("oO"));
// distinct uppercase and lowercase (e.g., 'o' vs. 'O')
user_font_styles[num_font_styles]->score +=
charset_works(font, gettext("oO"));
// common punctuation (e.g., '?', '!', '.', ',', etc.)
user_font_styles[num_font_styles]->score += charset_works(font, gettext(",.?!"));
// common punctuation (e.g., '?', '!', '.', ',', etc.)
user_font_styles[num_font_styles]->score +=
charset_works(font, gettext(",.?!"));
// uncommon punctuation (e.g., '@', '#', '*', etc.)
user_font_styles[num_font_styles]->score += charset_works(font, gettext("`\%_@$~#{<(^&*"));
// uncommon punctuation (e.g., '@', '#', '*', etc.)
user_font_styles[num_font_styles]->score +=
charset_works(font, gettext("`\%_@$~#{<(^&*"));
// digits (e.g., '0', '1' and '7')
user_font_styles[num_font_styles]->score += charset_works(font, gettext("017"));
// digits (e.g., '0', '1' and '7')
user_font_styles[num_font_styles]->score +=
charset_works(font, gettext("017"));
// distinct circle-like characters (e.g., 'O' (capital oh) vs. '0' (zero))
user_font_styles[num_font_styles]->score += charset_works(font, gettext("O0"));
// distinct circle-like characters (e.g., 'O' (capital oh) vs. '0' (zero))
user_font_styles[num_font_styles]->score +=
charset_works(font, gettext("O0"));
// distinct line-like characters (e.g., 'l' (lowercase elle) vs. '1' (one) vs. 'I' (capital aye))
user_font_styles[num_font_styles]->score += charset_works(font, gettext("1Il|"));
// distinct line-like characters (e.g., 'l' (lowercase elle) vs. '1' (one) vs. 'I' (capital aye))
user_font_styles[num_font_styles]->score +=
charset_works(font, gettext("1Il|"));
// translation spares -- design not finalized
// translation spares -- design not finalized
#if 0
user_font_styles[num_font_styles]->score += charset_works(font, gettext("<1>spare-1a"));
user_font_styles[num_font_styles]->score += charset_works(font, gettext("<1>spare-1b"));
user_font_styles[num_font_styles]->score += charset_works(font, gettext("<9>spare-9a")) * 9;
user_font_styles[num_font_styles]->score += charset_works(font, gettext("<9>spare-9b")) * 9;
user_font_styles[num_font_styles]->score +=
charset_works(font, gettext("<1>spare-1a"));
user_font_styles[num_font_styles]->score +=
charset_works(font, gettext("<1>spare-1b"));
user_font_styles[num_font_styles]->score +=
charset_works(font, gettext("<9>spare-9a")) * 9;
user_font_styles[num_font_styles]->score +=
charset_works(font, gettext("<9>spare-9b")) * 9;
#endif
// this really should be dynamic, avoiding the need for a special build
#ifdef OLPC_XO
// Maybe German adds a "\xc2\xb7" (middle dot) and colon here? The key wouldn't change though.
user_font_styles[num_font_styles]->score += charset_works(font, "\xc3\x97\xc3\xb7"); // multiply and divide
// Maybe German adds a "\xc2\xb7" (middle dot) and colon here? The key wouldn't change though.
user_font_styles[num_font_styles]->score += charset_works(font, "\xc3\x97\xc3\xb7"); // multiply and divide
#endif
// FIXME: add topology tests ('A' has one hole, 'B' has two holes, etc.)
// FIXME: add topology tests ('A' has one hole, 'B' has two holes, etc.)
num_font_styles++;
num_font_styles++;
//printf("Accepted: %s, %s, %s, score(%d)\n", files[i].str, family, style, user_font_styles[num_font_styles]->score);
files[i].str = NULL; // so free() won't crash -- we stole the memory
}
else
{
#ifdef DEBUG
fprintf(stderr, "Font is too defective: %s, %s, %s\n", files[i].str, family, style);
#endif
}
TuxPaint_Font_CloseFont(font);
}
else
{
#ifdef DEBUG
fprintf(stderr, "could not open %s\n", files[i].str);
#endif
}
files[i].str = NULL; // so free() won't crash -- we stole the memory
}
free(files[i].str);
else
{
#ifdef DEBUG
fprintf(stderr, "Font is too defective: %s, %s, %s\n", files[i].str,
family, style);
#endif
}
TuxPaint_Font_CloseFont(font);
}
else
{
#ifdef DEBUG
fprintf(stderr, "could not open %s\n", files[i].str);
#endif
}
}
free(files[i].str);
}
free(files);
}
@ -305,10 +328,17 @@ int compare_ftw_str(const void *v1, const void *v2)
* @param fn Callback function to invoke
* @param locale Locale, to pass to callback function when applicable (i.e., for fonts), else NULL
*/
void tp_ftw(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer, char *restrict const dir,
unsigned dirlen, int rsrc, void (*fn) (SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer,
const char *restrict const dir, unsigned dirlen, tp_ftw_str * files,
unsigned count, const char *restrict const locale),
void tp_ftw(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer, char *restrict const dir,
unsigned dirlen, int rsrc, void (*fn)(SDL_Surface * screen,
SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const
dir, unsigned dirlen,
tp_ftw_str * files,
unsigned count,
const char *restrict const
locale),
const char *restrict const locale)
{
DIR *d;
@ -335,173 +365,177 @@ void tp_ftw(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer
AAssetDir *adir;
if (!d) /* Fallback into assets */
{
/* Remove the trailing '/' */
dlen = strlen(dir) - 1;
di = strndup(dir, dlen);
adir = open_asset_dir(di);
if (!adir)
return;
}
{
/* Remove the trailing '/' */
dlen = strlen(dir) - 1;
di = strndup(dir, dlen);
adir = open_asset_dir(di);
if (!adir)
return;
}
#else
if (!d)
return;
#endif
for (;;)
{
struct dirent *f;
{
struct dirent *f;
if (d)
f = readdir(d);
int filetype = TP_FTW_UNKNOWN;
if (d)
f = readdir(d);
int filetype = TP_FTW_UNKNOWN;
#ifdef __ANDROID__
char *afilename;
char *afilename;
if (!d)
{
afilename = AAssetDir_getNextFileName(adir);
if (afilename)
{
f = malloc(sizeof(struct dirent));
strncpy(f->d_name, afilename, sizeof(f->d_name));
f->d_type = DT_REG;
if (!d)
{
afilename = AAssetDir_getNextFileName(adir);
if (afilename)
{
f = malloc(sizeof(struct dirent));
strncpy(f->d_name, afilename, sizeof(f->d_name));
f->d_type = DT_REG;
/* There is not _DIRENT_HAVE_D_NAMLEN currently on Android 4.3, but who knows in the future... */
/* There is not _DIRENT_HAVE_D_NAMLEN currently on Android 4.3, but who knows in the future... */
#if defined(_DIRENT_HAVE_D_NAMLEN)
f->d_namlen = strlen(f->d_name);
f->d_namlen = strlen(f->d_name);
#endif
/* AAssetDir_getNextFileName() only lists files, not (sub)dirs,
and we don't put any device or special file inside assets,
so it is a regular file */
filetype = TP_FTW_NORMAL;
}
else
break;
}
#endif
if (!f)
/* AAssetDir_getNextFileName() only lists files, not (sub)dirs,
and we don't put any device or special file inside assets,
so it is a regular file */
filetype = TP_FTW_NORMAL;
}
else
break;
if (f->d_name[0] == '.')
continue;
}
#endif
if (!f)
break;
if (f->d_name[0] == '.')
continue;
// Linux and BSD can often provide file type info w/o the stat() call
#ifdef DT_UNKNOWN
switch (f->d_type)
{
default:
continue;
case DT_REG:
if (!rsrc) // if maybe opening resource files, need st_size
filetype = TP_FTW_NORMAL;
break;
case DT_DIR:
filetype = TP_FTW_DIRECTORY;
break;
case DT_UNKNOWN:
case DT_LNK:
;
}
switch (f->d_type)
{
default:
continue;
case DT_REG:
if (!rsrc) // if maybe opening resource files, need st_size
filetype = TP_FTW_NORMAL;
break;
case DT_DIR:
filetype = TP_FTW_DIRECTORY;
break;
case DT_UNKNOWN:
case DT_LNK:
;
}
#else
#warning Failed to see DT_UNKNOWN
#endif
#if defined(_DIRENT_HAVE_D_NAMLEN) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
d_namlen = f->d_namlen;
d_namlen = f->d_namlen;
#else
d_namlen = strlen(f->d_name);
d_namlen = strlen(f->d_name);
#endif
add_rsrc = 0;
add_rsrc = 0;
if (filetype == TP_FTW_UNKNOWN)
{
struct stat sbuf;
if (filetype == TP_FTW_UNKNOWN)
{
struct stat sbuf;
memcpy(dir + dirlen, f->d_name, d_namlen + 1);
if (stat(dir, &sbuf))
continue; // oh well... try the next one
if (S_ISDIR(sbuf.st_mode))
filetype = TP_FTW_DIRECTORY;
else if (S_ISREG(sbuf.st_mode))
{
filetype = TP_FTW_NORMAL;
if (rsrc && !sbuf.st_size)
add_rsrc = 5; // 5 is length of "/rsrc"
}
else
continue; // was a device file or somesuch
}
if (filetype == TP_FTW_NORMAL)
{
char *cp;
if (num_file_names == max_file_names)
{
max_file_names = max_file_names * 5 / 4 + 30;
file_names = realloc(file_names, max_file_names * sizeof *file_names);
}
cp = malloc(d_namlen + add_rsrc + 1);
memcpy(cp, f->d_name, d_namlen);
if (add_rsrc)
memcpy(cp + d_namlen, "/rsrc", 6);
else
cp[d_namlen] = '\0';
file_names[num_file_names].str = cp;
file_names[num_file_names].len = d_namlen;
num_file_names++;
}
if (filetype == TP_FTW_DIRECTORY)
{
char *cp;
if (num_dir_names == max_dir_names)
{
max_dir_names = max_dir_names * 5 / 4 + 3;
dir_names = realloc(dir_names, max_dir_names * sizeof *dir_names);
}
cp = malloc(d_namlen + 1);
memcpy(cp, f->d_name, d_namlen + 1);
dir_names[num_dir_names].str = cp;
dir_names[num_dir_names].len = d_namlen;
num_dir_names++;
}
memcpy(dir + dirlen, f->d_name, d_namlen + 1);
if (stat(dir, &sbuf))
continue; // oh well... try the next one
if (S_ISDIR(sbuf.st_mode))
filetype = TP_FTW_DIRECTORY;
else if (S_ISREG(sbuf.st_mode))
{
filetype = TP_FTW_NORMAL;
if (rsrc && !sbuf.st_size)
add_rsrc = 5; // 5 is length of "/rsrc"
}
else
continue; // was a device file or somesuch
}
if (filetype == TP_FTW_NORMAL)
{
char *cp;
if (num_file_names == max_file_names)
{
max_file_names = max_file_names * 5 / 4 + 30;
file_names = realloc(file_names, max_file_names * sizeof *file_names);
}
cp = malloc(d_namlen + add_rsrc + 1);
memcpy(cp, f->d_name, d_namlen);
if (add_rsrc)
memcpy(cp + d_namlen, "/rsrc", 6);
else
cp[d_namlen] = '\0';
file_names[num_file_names].str = cp;
file_names[num_file_names].len = d_namlen;
num_file_names++;
}
if (filetype == TP_FTW_DIRECTORY)
{
char *cp;
if (num_dir_names == max_dir_names)
{
max_dir_names = max_dir_names * 5 / 4 + 3;
dir_names = realloc(dir_names, max_dir_names * sizeof *dir_names);
}
cp = malloc(d_namlen + 1);
memcpy(cp, f->d_name, d_namlen + 1);
dir_names[num_dir_names].str = cp;
dir_names[num_dir_names].len = d_namlen;
num_dir_names++;
}
}
closedir(d);
show_progress_bar_(screen, texture, renderer);
dir[dirlen] = '\0'; // repair it (clobbered for stat() call above)
if (1 || file_names) // Now ALWAYS calling callback function, so stamp loader can notice top-level directories (even if there are only subdirs, and no files, inside) -bjk 2007.05.16
{
{
// let callee sort and keep the string
#if 0
qsort(file_names, num_file_names, sizeof *file_names, compare_ftw_str);
while (num_file_names--)
{
free(file_names[num_file_names].str);
}
free(file_names);
qsort(file_names, num_file_names, sizeof *file_names, compare_ftw_str);
while (num_file_names--)
{
free(file_names[num_file_names].str);
}
free(file_names);
#else
#ifdef __ANDROID__
if (dlen != dirlen) /* First case only happens in Android files coming from assets */
fn(screen, texture, renderer, di, dlen, file_names, num_file_names, locale);
else
if (dlen != dirlen) /* First case only happens in Android files coming from assets */
fn(screen, texture, renderer, di, dlen, file_names, num_file_names,
locale);
else
#endif
fn(screen, texture, renderer, dir, dirlen, file_names, num_file_names, locale);
fn(screen, texture, renderer, dir, dirlen, file_names, num_file_names,
locale);
#endif
}
}
if (dir_names)
{
qsort(dir_names, num_dir_names, sizeof *dir_names, compare_ftw_str);
while (num_dir_names--)
{
qsort(dir_names, num_dir_names, sizeof *dir_names, compare_ftw_str);
while (num_dir_names--)
{
memcpy(dir + dirlen, dir_names[num_dir_names].str, dir_names[num_dir_names].len + 1);
tp_ftw(screen, texture, renderer, dir, dirlen + dir_names[num_dir_names].len, rsrc, fn, locale);
free(dir_names[num_dir_names].str);
}
free(dir_names);
memcpy(dir + dirlen, dir_names[num_dir_names].str,
dir_names[num_dir_names].len + 1);
tp_ftw(screen, texture, renderer, dir,
dirlen + dir_names[num_dir_names].len, rsrc, fn, locale);
free(dir_names[num_dir_names].str);
}
free(dir_names);
}
}

View file

@ -45,14 +45,23 @@ typedef struct tp_ftw_str
} tp_ftw_str;
void loadfont_callback(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer,
const char *restrict const dir, unsigned dirlen, tp_ftw_str * files, unsigned i,
void loadfont_callback(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const dir, unsigned dirlen,
tp_ftw_str * files, unsigned i,
const char *restrict const locale);
int compare_ftw_str(const void *v1, const void *v2);
void tp_ftw(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer, char *restrict const dir,
unsigned dirlen, int rsrc, void (*fn) (SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer,
const char *restrict const dir, unsigned dirlen, tp_ftw_str * files,
unsigned count, const char *restrict const locale),
void tp_ftw(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer, char *restrict const dir,
unsigned dirlen, int rsrc, void (*fn)(SDL_Surface * screen,
SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const
dir, unsigned dirlen,
tp_ftw_str * files,
unsigned count,
const char *restrict const
locale),
const char *restrict const locale);
#endif

View file

@ -64,63 +64,73 @@
#define QUEUE_SIZE_CHUNK 1024
typedef struct queue_s {
typedef struct queue_s
{
int x, y, y_outside;
} queue_t;
queue_t * queue;
queue_t *queue;
int queue_size = 0, queue_end = 0;
/* Local function prototypes: */
SDL_Surface * global_screen, * global_last, * global_canvas;
SDL_Surface *global_screen, *global_last, *global_canvas;
Uint32 global_old_colr, global_cur_colr;
Uint8 * global_touched;
Uint8 *global_touched;
int global_extent_x1, global_extent_y1, global_extent_x2, global_extent_y2;
int global_prog_anim;
double colors_close(SDL_Surface * canvas, Uint32 c1, Uint32 c2);
Uint32 blend(SDL_Surface * canvas, Uint32 draw_colr, Uint32 old_colr, double pct);
void simulate_flood_fill_outside_check(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer, int x, int y, int y_outside);
void draw_brush_fill_single(SDL_Surface * canvas, int x, int y, Uint32 draw_color, Uint8 * touched);
Uint32 blend(SDL_Surface * canvas, Uint32 draw_colr, Uint32 old_colr,
double pct);
void simulate_flood_fill_outside_check(SDL_Surface * screen,
SDL_Texture * texture,
SDL_Renderer * renderer, int x, int y,
int y_outside);
void draw_brush_fill_single(SDL_Surface * canvas, int x, int y,
Uint32 draw_color, Uint8 * touched);
void init_queue(void);
void add_to_queue(int x, int y, int y_outside);
int remove_from_queue(int * x, int * y, int * y_outside);
int remove_from_queue(int *x, int *y, int *y_outside);
void cleanup_queue(void);
void init_queue(void) {
void init_queue(void)
{
queue_size = 0;
queue_end = 0;
queue = (queue_t *) malloc(sizeof(queue_t) * QUEUE_SIZE_CHUNK);
if (queue == NULL)
{
fprintf(stderr, "Fill queue cannot be malloc()'d\n");
return;
}
{
fprintf(stderr, "Fill queue cannot be malloc()'d\n");
return;
}
queue_size = QUEUE_SIZE_CHUNK;
}
void add_to_queue(int x, int y, int y_outside) {
void add_to_queue(int x, int y, int y_outside)
{
/* Reallocate if we need more space */
if (queue_end + 1 > queue_size)
{
queue_t *tmp;
tmp =
(queue_t *) realloc(queue,
sizeof(queue_t) * (queue_size + QUEUE_SIZE_CHUNK));
if (tmp == NULL)
{
queue_t * tmp;
tmp = (queue_t *) realloc(queue, sizeof(queue_t) * (queue_size + QUEUE_SIZE_CHUNK));
if (tmp == NULL)
{
fprintf(stderr, "Fill queue cannot be realloc()'d\n");
return;
}
queue_size += QUEUE_SIZE_CHUNK;
#ifdef DEBUG
printf("queue_size = %d\n", queue_size);
fflush(stdout);
#endif
queue = tmp;
fprintf(stderr, "Fill queue cannot be realloc()'d\n");
return;
}
queue_size += QUEUE_SIZE_CHUNK;
#ifdef DEBUG
printf("queue_size = %d\n", queue_size);
fflush(stdout);
#endif
queue = tmp;
}
queue[queue_end].x = x;
queue[queue_end].y = y;
@ -130,14 +140,15 @@ void add_to_queue(int x, int y, int y_outside) {
#ifdef DEBUG
if (queue_end % 100 == 0)
{
printf("queue_end = %d\n", queue_end);
fflush(stdout);
}
{
printf("queue_end = %d\n", queue_end);
fflush(stdout);
}
#endif
}
int remove_from_queue(int * x, int * y, int * y_outside) {
int remove_from_queue(int *x, int *y, int *y_outside)
{
if (queue_end == 0)
return 0;
@ -149,16 +160,17 @@ int remove_from_queue(int * x, int * y, int * y_outside) {
#ifdef DEBUG
if (queue_end % 100 == 0)
{
printf("queue_end = %d\n", queue_end);
fflush(stdout);
}
{
printf("queue_end = %d\n", queue_end);
fflush(stdout);
}
#endif
return 1;
}
void cleanup_queue(void) {
void cleanup_queue(void)
{
if (queue != NULL)
free(queue);
@ -177,51 +189,60 @@ double colors_close(SDL_Surface * canvas, Uint32 c1, Uint32 c2)
Uint8 r1, g1, b1, r2, g2, b2;
if (c1 == c2)
{
/* Get it over with quick, if possible! */
{
/* Get it over with quick, if possible! */
return 0.0;
}
return 0.0;
}
else
{
double r, g, b;
{
double r, g, b;
SDL_GetRGB(c1, canvas->format, &r1, &g1, &b1);
SDL_GetRGB(c2, canvas->format, &r2, &g2, &b2);
SDL_GetRGB(c1, canvas->format, &r1, &g1, &b1);
SDL_GetRGB(c2, canvas->format, &r2, &g2, &b2);
// use distance in linear RGB space
r = sRGB_to_linear_table[r1] - sRGB_to_linear_table[r2];
r *= r;
g = sRGB_to_linear_table[g1] - sRGB_to_linear_table[g2];
g *= g;
b = sRGB_to_linear_table[b1] - sRGB_to_linear_table[b2];
b *= b;
// use distance in linear RGB space
r = sRGB_to_linear_table[r1] - sRGB_to_linear_table[r2];
r *= r;
g = sRGB_to_linear_table[g1] - sRGB_to_linear_table[g2];
g *= g;
b = sRGB_to_linear_table[b1] - sRGB_to_linear_table[b2];
b *= b;
// easy to confuse:
// dark grey, brown, purple
// light grey, tan
// red, orange
return (r + g + b);
}
// easy to confuse:
// dark grey, brown, purple
// light grey, tan
// red, orange
return (r + g + b);
}
}
int would_flood_fill(SDL_Surface * canvas, Uint32 cur_colr, Uint32 old_colr)
{
if (colors_close(canvas, cur_colr, old_colr) < COLOR_MATCH_NARROW)
{
return 0;
} else {
return 1;
}
{
return 0;
}
else
{
return 1;
}
}
void do_flood_fill(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer, SDL_Surface * last, SDL_Surface * canvas, int x, int y, Uint32 cur_colr, Uint32 old_colr, int * x1, int * y1, int * x2, int * y2, Uint8 * touched)
void do_flood_fill(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer, SDL_Surface * last,
SDL_Surface * canvas, int x, int y, Uint32 cur_colr,
Uint32 old_colr, int *x1, int *y1, int *x2, int *y2,
Uint8 * touched)
{
simulate_flood_fill(screen, texture, renderer, last, canvas, x, y, cur_colr, old_colr, x1, y1, x2, y2, touched);
simulate_flood_fill(screen, texture, renderer, last, canvas, x, y, cur_colr,
old_colr, x1, y1, x2, y2, touched);
}
Uint32 blend(SDL_Surface * canvas, Uint32 draw_colr, Uint32 old_colr, double pct) {
Uint32 blend(SDL_Surface * canvas, Uint32 draw_colr, Uint32 old_colr,
double pct)
{
Uint8 old_r, old_g, old_b, draw_r, draw_g, draw_b, new_r, new_g, new_b;
SDL_GetRGB(draw_colr, canvas->format, &draw_r, &draw_g, &draw_b);
@ -235,7 +256,12 @@ Uint32 blend(SDL_Surface * canvas, Uint32 draw_colr, Uint32 old_colr, double pct
return SDL_MapRGB(canvas->format, new_r, new_g, new_b);
}
void simulate_flood_fill(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer, SDL_Surface * last, SDL_Surface * canvas, int x, int y, Uint32 cur_colr, Uint32 old_colr, int * extent_x1, int * extent_y1, int * extent_x2, int * extent_y2, Uint8 * touched) {
void simulate_flood_fill(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer, SDL_Surface * last,
SDL_Surface * canvas, int x, int y, Uint32 cur_colr,
Uint32 old_colr, int *extent_x1, int *extent_y1,
int *extent_x2, int *extent_y2, Uint8 * touched)
{
int y_outside;
/* Get ready */
@ -257,9 +283,10 @@ void simulate_flood_fill(SDL_Surface * screen, SDL_Texture * texture, SDL_Render
/* Do the work (possibly queuing more, as we go) */
while (remove_from_queue(&x, &y, &y_outside))
{
simulate_flood_fill_outside_check(screen, texture, renderer, x, y, y_outside);
}
{
simulate_flood_fill_outside_check(screen, texture, renderer, x, y,
y_outside);
}
cleanup_queue();
*extent_x1 = global_extent_x1;
@ -268,7 +295,10 @@ void simulate_flood_fill(SDL_Surface * screen, SDL_Texture * texture, SDL_Render
*extent_y2 = global_extent_y2;
}
void simulate_flood_fill_outside_check(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer, int x, int y, int y_outside)
void simulate_flood_fill_outside_check(SDL_Surface * screen,
SDL_Texture * texture,
SDL_Renderer * renderer, int x, int y,
int y_outside)
{
int fillL, fillR, narrowFillL, narrowFillR, i, outside, just_queued;
double in_line, closeness;
@ -287,13 +317,13 @@ void simulate_flood_fill_outside_check(SDL_Surface * screen, SDL_Texture * textu
return;
if (y < global_extent_y1)
{
global_extent_y1 = y;
}
{
global_extent_y1 = y;
}
if (y > global_extent_y2)
{
global_extent_y2 = y;
}
{
global_extent_y2 = y;
}
fillL = x;
@ -303,139 +333,172 @@ void simulate_flood_fill_outside_check(SDL_Surface * screen, SDL_Texture * textu
global_prog_anim++;
if ((global_prog_anim % 8) == 0)
{
show_progress_bar_(screen, texture, renderer);
{
show_progress_bar_(screen, texture, renderer);
}
}
if ((global_prog_anim % 800) == 1) /* Always lay sound _once_ */
if ((global_prog_anim % 800) == 1) /* Always lay sound _once_ */
playsound(global_canvas, 1, SND_FILL, 1, x, SNDDIST_NEAR);
#ifdef DEBUG_WATCH
if (global_prog_anim % 100 == 0)
{
SDL_BlitSurface(global_canvas, NULL, global_screen, NULL);
SDL_Flip(global_screen);
}
{
SDL_BlitSurface(global_canvas, NULL, global_screen, NULL);
SDL_Flip(global_screen);
}
#endif
/* Find left side, filling along the way */
px_colr = getpixels[global_last->format->BytesPerPixel] (global_last, fillL /* - 1 */, y);
px_colr =
getpixels[global_last->format->BytesPerPixel] (global_last,
fillL /* - 1 */ , y);
in_line = colors_close(global_canvas, px_colr, global_old_colr);
outside = 0;
while (in_line < COLOR_MATCH_WIDE && outside < WIDE_MATCH_THRESHOLD)
{
if (in_line > COLOR_MATCH_NARROW)
{
if (in_line > COLOR_MATCH_NARROW) {
outside++;
} else {
narrowFillL = fillL;
}
if (global_touched != NULL) {
touch_byt = (255 - ((Uint8) (in_line * 85)));
if (touch_byt == 0)
touch_byt = 1;
global_touched[(y * global_canvas->w) + fillL] = touch_byt;
}
px_colr = getpixels[global_last->format->BytesPerPixel] (global_last, fillL, y);
putpixels[global_canvas->format->BytesPerPixel] (global_canvas, fillL, y, blend(global_canvas, global_cur_colr, px_colr, (1.0 - in_line)));
fillL--;
px_colr = getpixels[global_last->format->BytesPerPixel] (global_last, fillL, y);
if (fillL >= 0)
{
in_line = colors_close(global_canvas, px_colr, global_old_colr);
}
else
{
in_line = 3.0;
}
outside++;
}
else
{
narrowFillL = fillL;
}
if (global_touched != NULL)
{
touch_byt = (255 - ((Uint8) (in_line * 85)));
if (touch_byt == 0)
touch_byt = 1;
global_touched[(y * global_canvas->w) + fillL] = touch_byt;
}
px_colr =
getpixels[global_last->format->BytesPerPixel] (global_last, fillL, y);
putpixels[global_canvas->format->BytesPerPixel] (global_canvas, fillL, y,
blend(global_canvas,
global_cur_colr,
px_colr,
(1.0 - in_line)));
fillL--;
px_colr =
getpixels[global_last->format->BytesPerPixel] (global_last, fillL, y);
if (fillL >= 0)
{
in_line = colors_close(global_canvas, px_colr, global_old_colr);
}
else
{
in_line = 3.0;
}
}
if (fillL >= 0)
{
if (global_touched != NULL)
{
if (global_touched != NULL)
{
touch_byt = (255 - ((Uint8) (in_line * 85)));
if (touch_byt == 0)
touch_byt = 1;
touch_byt = (255 - ((Uint8) (in_line * 85)));
if (touch_byt == 0)
touch_byt = 1;
global_touched[(y * global_canvas->w) + fillL] = touch_byt;
}
px_colr = getpixels[global_last->format->BytesPerPixel] (global_last, fillL, y);
putpixels[global_canvas->format->BytesPerPixel] (global_canvas, fillL, y, blend(global_canvas, global_cur_colr, px_colr, (1.0 - in_line)));
global_touched[(y * global_canvas->w) + fillL] = touch_byt;
}
px_colr =
getpixels[global_last->format->BytesPerPixel] (global_last, fillL, y);
putpixels[global_canvas->format->BytesPerPixel] (global_canvas, fillL, y,
blend(global_canvas,
global_cur_colr,
px_colr,
(1.0 - in_line)));
}
if (fillL < global_extent_x1)
{
global_extent_x1 = fillL;
}
{
global_extent_x1 = fillL;
}
fillL++;
/* Find right side, filling along the way */
px_colr = getpixels[global_last->format->BytesPerPixel] (global_last, fillR + 1, y);
px_colr =
getpixels[global_last->format->BytesPerPixel] (global_last, fillR + 1, y);
in_line = colors_close(global_canvas, px_colr, global_old_colr);
outside = 0;
while (in_line < COLOR_MATCH_WIDE && outside < WIDE_MATCH_THRESHOLD)
{
if (in_line > COLOR_MATCH_NARROW)
{
if (in_line > COLOR_MATCH_NARROW) {
outside++;
} else {
narrowFillR = fillR;
}
if (global_touched != NULL) {
touch_byt = (255 - ((Uint8) (in_line * 85)));
if (touch_byt == 0)
touch_byt = 1;
global_touched[(y * global_canvas->w) + fillR] = touch_byt;
}
px_colr = getpixels[global_last->format->BytesPerPixel] (global_last, fillR, y);
putpixels[global_canvas->format->BytesPerPixel] (global_canvas, fillR, y, blend(global_canvas, global_cur_colr, px_colr, (1.0 - in_line)));
fillR++;
px_colr = getpixels[global_last->format->BytesPerPixel] (global_last, fillR, y);
if (fillR < global_canvas->w)
{
in_line = colors_close(global_canvas, px_colr, global_old_colr);
}
else
{
in_line = 3.0;
}
outside++;
}
else
{
narrowFillR = fillR;
}
if (global_touched != NULL)
{
touch_byt = (255 - ((Uint8) (in_line * 85)));
if (touch_byt == 0)
touch_byt = 1;
global_touched[(y * global_canvas->w) + fillR] = touch_byt;
}
px_colr =
getpixels[global_last->format->BytesPerPixel] (global_last, fillR, y);
putpixels[global_canvas->format->BytesPerPixel] (global_canvas, fillR, y,
blend(global_canvas,
global_cur_colr,
px_colr,
(1.0 - in_line)));
fillR++;
px_colr =
getpixels[global_last->format->BytesPerPixel] (global_last, fillR, y);
if (fillR < global_canvas->w)
{
in_line = colors_close(global_canvas, px_colr, global_old_colr);
}
else
{
in_line = 3.0;
}
}
if (fillR < global_canvas->w)
{
if (global_touched != NULL)
{
if (global_touched != NULL)
{
touch_byt = (255 - ((Uint8) (in_line * 85)));
if (touch_byt == 0)
touch_byt = 1;
touch_byt = (255 - ((Uint8) (in_line * 85)));
if (touch_byt == 0)
touch_byt = 1;
global_touched[(y * global_canvas->w) + fillR] = touch_byt;
}
px_colr = getpixels[global_last->format->BytesPerPixel] (global_last, fillR, y);
putpixels[global_canvas->format->BytesPerPixel] (global_canvas, fillR, y, blend(global_canvas, global_cur_colr, px_colr, (1.0 - in_line)));
global_touched[(y * global_canvas->w) + fillR] = touch_byt;
}
px_colr =
getpixels[global_last->format->BytesPerPixel] (global_last, fillR, y);
putpixels[global_canvas->format->BytesPerPixel] (global_canvas, fillR, y,
blend(global_canvas,
global_cur_colr,
px_colr,
(1.0 - in_line)));
}
if (fillR > global_extent_x2)
{
global_extent_x2 = fillR;
}
{
global_extent_x2 = fillR;
}
fillR--;
@ -444,69 +507,74 @@ void simulate_flood_fill_outside_check(SDL_Surface * screen, SDL_Texture * textu
just_queued = 0;
if (y > 0)
{
for (i = narrowFillL; i <= narrowFillR; i++)
{
for (i = narrowFillL; i <= narrowFillR; i++)
px_colr =
getpixels[global_last->format->BytesPerPixel] (global_last, i, y - 1);
closeness = colors_close(global_canvas, px_colr, global_old_colr);
if (closeness < COLOR_MATCH_NARROW ||
(closeness < COLOR_MATCH_WIDE && y_outside < WIDE_MATCH_THRESHOLD))
{
if (!just_queued
&& (global_touched == NULL
|| !global_touched[((y - 1) * global_canvas->w) + i]))
{
px_colr = getpixels[global_last->format->BytesPerPixel] (global_last, i, y - 1);
closeness = colors_close(global_canvas, px_colr, global_old_colr);
if (closeness < COLOR_MATCH_NARROW ||
(closeness < COLOR_MATCH_WIDE && y_outside < WIDE_MATCH_THRESHOLD)
)
{
if (!just_queued && (global_touched == NULL || !global_touched[((y - 1) * global_canvas->w) + i]))
{
add_to_queue(i, y - 1, y_outside + 1);
just_queued = 1;
}
else
{
just_queued = 0;
}
}
else
{
just_queued = 0;
}
add_to_queue(i, y - 1, y_outside + 1);
just_queued = 1;
}
else
{
just_queued = 0;
}
}
else
{
just_queued = 0;
}
}
}
/* Continue filling downwards from this scanline */
just_queued = 0;
if (y < global_canvas->h - 1)
{
for (i = narrowFillL; i <= narrowFillR; i++)
{
for (i = narrowFillL; i <= narrowFillR; i++)
px_colr =
getpixels[global_last->format->BytesPerPixel] (global_last, i, y + 1);
closeness = colors_close(global_canvas, px_colr, global_old_colr);
if (closeness < COLOR_MATCH_NARROW ||
(closeness < COLOR_MATCH_WIDE && y_outside < WIDE_MATCH_THRESHOLD))
{
if (!just_queued
&& (global_touched == NULL
|| !global_touched[((y + 1) * global_canvas->w) + i]))
{
px_colr = getpixels[global_last->format->BytesPerPixel] (global_last, i, y + 1);
closeness = colors_close(global_canvas, px_colr, global_old_colr);
if (closeness < COLOR_MATCH_NARROW ||
(closeness < COLOR_MATCH_WIDE && y_outside < WIDE_MATCH_THRESHOLD)
)
{
if (!just_queued && (global_touched == NULL || !global_touched[((y + 1) * global_canvas->w) + i]))
{
add_to_queue(i, y + 1, y_outside + 1);
just_queued = 1;
}
else
{
just_queued = 0;
}
}
else
{
just_queued = 0;
}
add_to_queue(i, y + 1, y_outside + 1);
just_queued = 1;
}
else
{
just_queued = 0;
}
}
else
{
just_queued = 0;
}
}
}
}
void draw_linear_gradient(SDL_Surface * canvas, SDL_Surface * last,
int x_left, int y_top, int x_right, int y_bottom,
int x1, int y1, int x2, int y2, Uint32 draw_color, Uint8 * touched
) {
int x_left, int y_top, int x_right, int y_bottom,
int x1, int y1, int x2, int y2, Uint32 draw_color,
Uint8 * touched)
{
Uint32 old_colr, new_colr;
int xx, yy;
Uint8 draw_r, draw_g, draw_b, old_r, old_g, old_b, new_r, new_g, new_b;
@ -521,9 +589,12 @@ void draw_linear_gradient(SDL_Surface * canvas, SDL_Surface * last,
C2 = (A * x2) + (B * y2);
/* FIXME: C2 should be larger than C1? */
for (yy = y_top; yy <= y_bottom; yy++) {
for (xx = x_left; xx <= x_right; xx++) {
if (touched[(yy * canvas->w) + xx]) {
for (yy = y_top; yy <= y_bottom; yy++)
{
for (xx = x_left; xx <= x_right; xx++)
{
if (touched[(yy * canvas->w) + xx])
{
/* Get the old color, and blend it (with a distance-based ratio) with the target color */
old_colr = getpixels[last->format->BytesPerPixel] (last, xx, yy);
SDL_GetRGB(old_colr, last->format, &old_r, &old_g, &old_b);
@ -532,13 +603,18 @@ void draw_linear_gradient(SDL_Surface * canvas, SDL_Surface * last,
https://stackoverflow.com/questions/521493/creating-a-linear-gradient-in-2d-array) */
C = (A * xx) + (B * yy);
if (C < C1) {
if (C < C1)
{
/* At/beyond the click spot (opposite direction of mouse); solid color */
ratio = 0.0;
} else if (C >= C2) {
}
else if (C >= C2)
{
/* At/beyond the mouse; completely faded out */
ratio = 1.0;
} else {
}
else
{
/* The actual gradient... */
ratio = (C - C1) / (C2 - C1);
}
@ -546,9 +622,15 @@ void draw_linear_gradient(SDL_Surface * canvas, SDL_Surface * last,
/* Apply fuzziness at any antialiased edges we detected */
ratio = (ratio * ((float) touched[yy * canvas->w + xx] / 255.0));
new_r = (Uint8) (((float) old_r) * ratio + ((float) draw_r * (1.0 - ratio)));
new_g = (Uint8) (((float) old_g) * ratio + ((float) draw_g * (1.0 - ratio)));
new_b = (Uint8) (((float) old_b) * ratio + ((float) draw_b * (1.0 - ratio)));
new_r =
(Uint8) (((float) old_r) * ratio +
((float) draw_r * (1.0 - ratio)));
new_g =
(Uint8) (((float) old_g) * ratio +
((float) draw_g * (1.0 - ratio)));
new_b =
(Uint8) (((float) old_b) * ratio +
((float) draw_b * (1.0 - ratio)));
new_colr = SDL_MapRGB(canvas->format, new_r, new_g, new_b);
putpixels[canvas->format->BytesPerPixel] (canvas, xx, yy, new_colr);
@ -557,27 +639,32 @@ void draw_linear_gradient(SDL_Surface * canvas, SDL_Surface * last,
}
}
void draw_brush_fill_single(SDL_Surface * canvas, int x, int y, Uint32 draw_color, Uint8 * touched) {
void draw_brush_fill_single(SDL_Surface * canvas, int x, int y,
Uint32 draw_color, Uint8 * touched)
{
int xx, yy;
for (yy = -16; yy < 16; yy++)
{
for (xx = -16; xx < 16; xx++)
{
for (xx = -16; xx < 16; xx++)
{
if ((xx * xx) + (yy * yy) < (16 * 16) &&
touched[((y + yy) * canvas->w) + (x + xx)])
{
putpixels[canvas->format->BytesPerPixel] (canvas, x + xx, y + yy, draw_color);
}
}
if ((xx * xx) + (yy * yy) < (16 * 16) &&
touched[((y + yy) * canvas->w) + (x + xx)])
{
putpixels[canvas->format->BytesPerPixel] (canvas, x + xx, y + yy,
draw_color);
}
}
}
}
void draw_brush_fill(SDL_Surface * canvas,
int x_left ATTRIBUTE_UNUSED, int y_top ATTRIBUTE_UNUSED, int x_right ATTRIBUTE_UNUSED, int y_bottom ATTRIBUTE_UNUSED,
int x1, int y1, int x2, int y2, Uint32 draw_color, Uint8 * touched,
int * up_x1, int * up_y1, int * up_x2, int * up_y2
) {
int x_left ATTRIBUTE_UNUSED, int y_top ATTRIBUTE_UNUSED,
int x_right ATTRIBUTE_UNUSED,
int y_bottom ATTRIBUTE_UNUSED, int x1, int y1, int x2,
int y2, Uint32 draw_color, Uint8 * touched, int *up_x1,
int *up_y1, int *up_x2, int *up_y2)
{
int dx, dy;
int y;
int orig_x1, orig_y1, orig_x2, orig_y2, tmp;
@ -593,60 +680,60 @@ void draw_brush_fill(SDL_Surface * canvas,
dy = y2 - y1;
if (dx != 0)
{
m = ((float) dy) / ((float) dx);
b = y1 - m * x1;
if (x2 >= x1)
dx = 1;
else
dx = -1;
while (x1 != x2)
{
m = ((float)dy) / ((float)dx);
b = y1 - m * x1;
y1 = m * x1 + b;
y2 = m * (x1 + dx) + b;
if (x2 >= x1)
dx = 1;
else
dx = -1;
while (x1 != x2)
{
y1 = m * x1 + b;
y2 = m * (x1 + dx) + b;
if (y1 > y2)
{
for (y = y1; y >= y2; y--)
draw_brush_fill_single(canvas, x1, y, draw_color, touched);
}
else
{
for (y = y1; y <= y2; y++)
draw_brush_fill_single(canvas, x1, y, draw_color, touched);
}
x1 = x1 + dx;
}
}
else
{
if (y1 > y2)
{
y = y1;
y1 = y2;
y2 = y;
}
{
for (y = y1; y >= y2; y--)
draw_brush_fill_single(canvas, x1, y, draw_color, touched);
}
else
{
for (y = y1; y <= y2; y++)
draw_brush_fill_single(canvas, x1, y, draw_color, touched);
}
for (y = y1; y <= y2; y++)
draw_brush_fill_single(canvas, x1, y, draw_color, touched);
x1 = x1 + dx;
}
}
else
{
if (y1 > y2)
{
y = y1;
y1 = y2;
y2 = y;
}
for (y = y1; y <= y2; y++)
draw_brush_fill_single(canvas, x1, y, draw_color, touched);
}
if (orig_x1 > orig_x2)
{
tmp = orig_x1;
orig_x1 = orig_x2;
orig_x2 = tmp;
}
{
tmp = orig_x1;
orig_x1 = orig_x2;
orig_x2 = tmp;
}
if (orig_y1 > orig_y2)
{
tmp = orig_y1;
orig_y1 = orig_y2;
orig_y2 = tmp;
}
{
tmp = orig_y1;
orig_y1 = orig_y2;
orig_y2 = tmp;
}
*up_x1 = orig_x1 - 16;
*up_y1 = orig_y1 - 16;
@ -654,9 +741,10 @@ void draw_brush_fill(SDL_Surface * canvas,
*up_y2 = orig_y2 + 16;
}
void draw_radial_gradient(SDL_Surface * canvas, int x_left, int y_top, int x_right, int y_bottom,
int x, int y, Uint32 draw_color, Uint8 * touched
) {
void draw_radial_gradient(SDL_Surface * canvas, int x_left, int y_top,
int x_right, int y_bottom, int x, int y,
Uint32 draw_color, Uint8 * touched)
{
Uint32 old_colr, new_colr;
int xx, yy;
float xd, yd, dist, rad, ratio;
@ -666,7 +754,8 @@ void draw_radial_gradient(SDL_Surface * canvas, int x_left, int y_top, int x_rig
xd = max(abs(x - x_right), abs(x - x_left));
yd = max(abs(y - y_bottom), abs(y - y_top));
rad = sqrt(xd * xd + yd * yd);
if (rad == 0) {
if (rad == 0)
{
return;
}
@ -674,27 +763,38 @@ void draw_radial_gradient(SDL_Surface * canvas, int x_left, int y_top, int x_rig
SDL_GetRGB(draw_color, canvas->format, &draw_r, &draw_g, &draw_b);
/* Traverse the flood-filled zone */
for (yy = y_top; yy <= y_bottom; yy++) {
for (xx = x_left; xx <= x_right; xx++) {
for (yy = y_top; yy <= y_bottom; yy++)
{
for (xx = x_left; xx <= x_right; xx++)
{
/* Only alter the pixels within the flood itself */
if (touched[(yy * canvas->w) + xx]) {
if (touched[(yy * canvas->w) + xx])
{
/* Determine the distance from the click point */
xd = fabs((float) (xx - x));
yd = fabs((float) (yy - y));
dist = sqrt(xd * xd + yd * yd);
if (dist < rad) {
if (dist < rad)
{
ratio = (dist / rad);
/* Get the old color, and blend it (with a distance-based ratio) with the target color */
old_colr = getpixels[canvas->format->BytesPerPixel] (canvas, xx, yy);
old_colr =
getpixels[canvas->format->BytesPerPixel] (canvas, xx, yy);
SDL_GetRGB(old_colr, canvas->format, &old_r, &old_g, &old_b);
/* Apply fuzziness at any antialiased edges we detected */
ratio = (ratio * ((float) touched[yy * canvas->w + xx] / 255.0));
new_r = (Uint8) (((float) old_r) * ratio + ((float) draw_r * (1.00 - ratio)));
new_g = (Uint8) (((float) old_g) * ratio + ((float) draw_g * (1.00 - ratio)));
new_b = (Uint8) (((float) old_b) * ratio + ((float) draw_b * (1.00 - ratio)));
new_r =
(Uint8) (((float) old_r) * ratio +
((float) draw_r * (1.00 - ratio)));
new_g =
(Uint8) (((float) old_g) * ratio +
((float) draw_g * (1.00 - ratio)));
new_b =
(Uint8) (((float) old_b) * ratio +
((float) draw_b * (1.00 - ratio)));
new_colr = SDL_MapRGB(canvas->format, new_r, new_g, new_b);
putpixels[canvas->format->BytesPerPixel] (canvas, xx, yy, new_colr);
@ -703,4 +803,3 @@ void draw_radial_gradient(SDL_Surface * canvas, int x_left, int y_top, int x_rig
}
}
}

View file

@ -37,17 +37,26 @@
#include "SDL.h"
int would_flood_fill(SDL_Surface * canvas, Uint32 cur_colr, Uint32 old_colr);
void do_flood_fill(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer, SDL_Surface * last, SDL_Surface * canvas, int x, int y, Uint32 cur_colr, Uint32 old_colr, int * x1, int * y1, int * x2, int * y2, Uint8 * touched);
void simulate_flood_fill(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer, SDL_Surface * last, SDL_Surface * canvas, int x, int y, Uint32 cur_colr, Uint32 old_colr, int * x1, int * y1, int * x2, int * y2, Uint8 * touched);
void do_flood_fill(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer, SDL_Surface * last,
SDL_Surface * canvas, int x, int y, Uint32 cur_colr,
Uint32 old_colr, int *x1, int *y1, int *x2, int *y2,
Uint8 * touched);
void simulate_flood_fill(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer, SDL_Surface * last,
SDL_Surface * canvas, int x, int y, Uint32 cur_colr,
Uint32 old_colr, int *x1, int *y1, int *x2, int *y2,
Uint8 * touched);
void draw_linear_gradient(SDL_Surface * canvas, SDL_Surface * last,
int x_left, int y_top, int x_right, int y_bottom,
int x1, int y1, int x2, int y2, Uint32 draw_color, Uint8 * touched);
void draw_radial_gradient(SDL_Surface * canvas, int x_left, int y_top, int x_right, int y_bottom,
int x, int y, Uint32 draw_color, Uint8 * touched);
void draw_brush_fill(SDL_Surface * canvas,
int x_left, int y_top, int x_right, int y_bottom,
int x1, int y1, int x2, int y2, Uint32 draw_color, Uint8 * touched,
int * up_x1, int * up_y1, int * up_x2, int * up_y2);
int x_left, int y_top, int x_right, int y_bottom,
int x1, int y1, int x2, int y2, Uint32 draw_color,
Uint8 * touched);
void draw_radial_gradient(SDL_Surface * canvas, int x_left, int y_top,
int x_right, int y_bottom, int x, int y,
Uint32 draw_color, Uint8 * touched);
void draw_brush_fill(SDL_Surface * canvas, int x_left, int y_top, int x_right,
int y_bottom, int x1, int y1, int x2, int y2,
Uint32 draw_color, Uint8 * touched, int *up_x1,
int *up_y1, int *up_x2, int *up_y2);
#endif

View file

@ -38,7 +38,8 @@
#define gettext_noop(String) String
#endif
enum {
enum
{
FILL_FLOOD,
FILL_BRUSH,
FILL_GRADIENT_LINEAR,
@ -56,8 +57,10 @@ const char *const fill_names[NUM_FILLS] = {
const char *const fill_tips[NUM_FILLS] = {
gettext_noop("Click to fill an area with a solid color."),
gettext_noop("Click and drag to fill an area by hand, using a brush."),
gettext_noop("Click and drag to fill an area with a linear gradient (from the chosen color to transparent)."),
gettext_noop("Click to fill an area with a radial gradient (from the chosen color to transparent).")
gettext_noop
("Click and drag to fill an area with a linear gradient (from the chosen color to transparent)."),
gettext_noop
("Click to fill an area with a radial gradient (from the chosen color to transparent).")
};
const char *const fill_img_fnames[NUM_FILLS] = {
@ -68,4 +71,3 @@ const char *const fill_img_fnames[NUM_FILLS] = {
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -121,9 +121,11 @@ int TuxPaint_Font_FontHeight(TuxPaint_Font * tpf);
#ifdef FORKED_FONTS
void reliable_write(int fd, const void *buf, size_t count);
void run_font_scanner(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer,
void run_font_scanner(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer,
const char *restrict const locale);
void receive_some_font_info(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer);
void receive_some_font_info(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer);
#endif
//////////////////////////////////////////////////////////////////////
@ -191,7 +193,8 @@ TuxPaint_Font *getfonthandle(int desire);
int charset_works(TuxPaint_Font * font, const char *s);
TuxPaint_Font *TuxPaint_Font_OpenFont(const char *pangodesc, const char *ttffilename, int size);
TuxPaint_Font *TuxPaint_Font_OpenFont(const char *pangodesc,
const char *ttffilename, int size);
void TuxPaint_Font_CloseFont(TuxPaint_Font * tpf);
const char *TuxPaint_Font_FontFaceFamilyName(TuxPaint_Font * tpf);
const char *TuxPaint_Font_FontFaceStyleName(TuxPaint_Font * tpf);
@ -199,10 +202,12 @@ const char *TuxPaint_Font_FontFaceStyleName(TuxPaint_Font * tpf);
#ifdef NO_SDLPANGO
TuxPaint_Font *load_locale_font(TuxPaint_Font * fallback, int size);
#else
void sdl_color_to_pango_color(SDL_Color sdl_color, SDLPango_Matrix * pango_color);
void sdl_color_to_pango_color(SDL_Color sdl_color,
SDLPango_Matrix * pango_color);
#endif
int load_user_fonts(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer, void *vp,
int load_user_fonts(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer, void *vp,
const char *restrict const locale);
#endif

View file

@ -87,35 +87,40 @@ char *get_fname(const char *const name, int kind)
{
char f[512];
// const char *restrict const dir;
const char * dir;
const char *dir;
if (kind == DIR_SAVE) {
if (kind == DIR_SAVE)
{
dir = savedir;
} else if (kind == DIR_DATA) {
}
else if (kind == DIR_DATA)
{
dir = datadir;
} else if (kind == DIR_EXPORT || kind == DIR_EXPORT_PARENT) {
}
else if (kind == DIR_EXPORT || kind == DIR_EXPORT_PARENT)
{
dir = exportdir;
}
snprintf(f, sizeof(f),
"%s%c%s",
dir, (*name) ? '/' : '\0', /* Some mkdir()'s don't like trailing slashes */
name);
snprintf(f, sizeof(f), "%s%c%s", dir, (*name) ? '/' : '\0', /* Some mkdir()'s don't like trailing slashes */
name);
if (kind == DIR_EXPORT_PARENT) {
if (kind == DIR_EXPORT_PARENT)
{
int len, i, stop;
stop = -1;
len = strlen(f);
for (i = len - 1; i >= 0 && stop == -1; i--) {
for (i = len - 1; i >= 0 && stop == -1; i--)
{
if (f[i] == '/')
stop = i;
}
if (stop != -1) {
if (stop != -1)
{
f[stop] = '\0';
}
}
return strdup(f);
}

View file

@ -16,52 +16,50 @@
#define write_num(fd, n) write((fd), (uint8_t []) {(n) & 0xFF, (n) >> 8}, 2)
static uint8_t vga[0x30] = {
0x00, 0x00, 0x00,
0xAA, 0x00, 0x00,
0x00, 0xAA, 0x00,
0xAA, 0x55, 0x00,
0x00, 0x00, 0xAA,
0xAA, 0x00, 0xAA,
0x00, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA,
0x55, 0x55, 0x55,
0xFF, 0x55, 0x55,
0x55, 0xFF, 0x55,
0xFF, 0xFF, 0x55,
0x55, 0x55, 0xFF,
0xFF, 0x55, 0xFF,
0x55, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00,
0xAA, 0x00, 0x00,
0x00, 0xAA, 0x00,
0xAA, 0x55, 0x00,
0x00, 0x00, 0xAA,
0xAA, 0x00, 0xAA,
0x00, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA,
0x55, 0x55, 0x55,
0xFF, 0x55, 0x55,
0x55, 0xFF, 0x55,
0xFF, 0xFF, 0x55,
0x55, 0x55, 0xFF,
0xFF, 0x55, 0xFF,
0x55, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF,
};
struct Node {
uint16_t key;
struct Node *children[];
struct Node
{
uint16_t key;
struct Node *children[];
};
typedef struct Node Node;
static Node *
new_node(uint16_t key, int degree)
static Node *new_node(uint16_t key, int degree)
{
Node *node = calloc(1, sizeof(*node) + degree * sizeof(Node *));
if (node)
node->key = key;
return node;
Node *node = calloc(1, sizeof(*node) + degree * sizeof(Node *));
if (node)
node->key = key;
return node;
}
static Node *
new_trie(int degree, int *nkeys)
static Node *new_trie(int degree, int *nkeys)
{
Node *root = new_node(0, degree);
/* Create nodes for single pixels. */
for (*nkeys = 0; *nkeys < degree; (*nkeys)++)
root->children[*nkeys] = new_node(*nkeys, degree);
*nkeys += 2; /* skip clear code and stop code */
return root;
Node *root = new_node(0, degree);
/* Create nodes for single pixels. */
for (*nkeys = 0; *nkeys < degree; (*nkeys)++)
root->children[*nkeys] = new_node(*nkeys, degree);
*nkeys += 2; /* skip clear code and stop code */
return root;
}
static void
del_trie(Node *root, int degree)
static void del_trie(Node * root, int degree)
{
int i;
@ -72,191 +70,261 @@ del_trie(Node *root, int degree)
free(root);
}
static void put_loop(ge_GIF *gif, uint16_t loop);
static void put_loop(ge_GIF * gif, uint16_t loop);
#define OR_ABORT if (res == -1) { fprintf(stderr, "Cannot write to GIF\n"); return(NULL); }
#define OR_ABORT2 if (res == -1) { fprintf(stderr, "Cannot write to GIF\n"); return; }
ge_GIF *
ge_new_gif(
const char *fname, uint16_t width, uint16_t height,
uint8_t *palette, int depth, int loop
)
ge_GIF *ge_new_gif(const char *fname, uint16_t width, uint16_t height,
uint8_t * palette, int depth, int loop)
{
int i, r, g, b, v;
ssize_t res;
ge_GIF *gif = calloc(1, sizeof(*gif) + 2*width*height);
if (!gif)
goto no_gif;
gif->w = width; gif->h = height;
gif->depth = depth > 1 ? depth : 2;
gif->frame = (uint8_t *) &gif[1];
gif->back = &gif->frame[width*height];
gif->fd = creat(fname, 0666);
if (gif->fd == -1)
goto no_fd;
int i, r, g, b, v;
ssize_t res;
ge_GIF *gif = calloc(1, sizeof(*gif) + 2 * width * height);
if (!gif)
goto no_gif;
gif->w = width;
gif->h = height;
gif->depth = depth > 1 ? depth : 2;
gif->frame = (uint8_t *) & gif[1];
gif->back = &gif->frame[width * height];
gif->fd = creat(fname, 0666);
if (gif->fd == -1)
goto no_fd;
#ifdef _WIN32
setmode(gif->fd, O_BINARY);
setmode(gif->fd, O_BINARY);
#endif
res = write(gif->fd, "GIF89a", 6); OR_ABORT;
res = write_num(gif->fd, width); OR_ABORT;
res = write_num(gif->fd, height); OR_ABORT;
res = write(gif->fd, (uint8_t []) {0xF0 | (depth-1), 0x00, 0x00}, 3); OR_ABORT;
if (palette) {
res = write(gif->fd, palette, 3 << depth); OR_ABORT;
} else if (depth <= 4) {
res = write(gif->fd, vga, 3 << depth); OR_ABORT;
} else {
res = write(gif->fd, vga, sizeof(vga)); OR_ABORT;
i = 0x10;
for (r = 0; r < 6; r++) {
for (g = 0; g < 6; g++) {
for (b = 0; b < 6; b++) {
res = write(gif->fd, (uint8_t []) {r*51, g*51, b*51}, 3); OR_ABORT;
if (++i == 1 << depth)
goto done_gct;
}
}
}
for (i = 1; i <= 24; i++) {
v = i * 0xFF / 25;
res = write(gif->fd, (uint8_t []) {v, v, v}, 3); OR_ABORT;
res = write(gif->fd, "GIF89a", 6);
OR_ABORT;
res = write_num(gif->fd, width);
OR_ABORT;
res = write_num(gif->fd, height);
OR_ABORT;
res = write(gif->fd, (uint8_t[])
{
0xF0 | (depth - 1), 0x00, 0x00}
, 3);
OR_ABORT;
if (palette)
{
res = write(gif->fd, palette, 3 << depth);
OR_ABORT;
}
else if (depth <= 4)
{
res = write(gif->fd, vga, 3 << depth);
OR_ABORT;
}
else
{
res = write(gif->fd, vga, sizeof(vga));
OR_ABORT;
i = 0x10;
for (r = 0; r < 6; r++)
{
for (g = 0; g < 6; g++)
{
for (b = 0; b < 6; b++)
{
res = write(gif->fd, (uint8_t[])
{
r * 51, g * 51, b * 51}
, 3);
OR_ABORT;
if (++i == 1 << depth)
goto done_gct;
}
}
}
for (i = 1; i <= 24; i++)
{
v = i * 0xFF / 25;
res = write(gif->fd, (uint8_t[])
{
v, v, v}
, 3);
OR_ABORT;
}
}
done_gct:
if (loop >= 0 && loop <= 0xFFFF)
put_loop(gif, (uint16_t) loop);
return gif;
if (loop >= 0 && loop <= 0xFFFF)
put_loop(gif, (uint16_t) loop);
return gif;
no_fd:
free(gif);
free(gif);
no_gif:
return NULL;
return NULL;
}
static void
put_loop(ge_GIF *gif, uint16_t loop)
static void put_loop(ge_GIF * gif, uint16_t loop)
{
ssize_t res;
ssize_t res;
res = write(gif->fd, (uint8_t []) {'!', 0xFF, 0x0B}, 3); OR_ABORT2;
res = write(gif->fd, "NETSCAPE2.0", 11); OR_ABORT2;
res = write(gif->fd, (uint8_t []) {0x03, 0x01}, 2); OR_ABORT2;
res = write_num(gif->fd, loop); OR_ABORT2;
res = write(gif->fd, "\0", 1); OR_ABORT2;
res = write(gif->fd, (uint8_t[])
{
'!', 0xFF, 0x0B}, 3);
OR_ABORT2;
res = write(gif->fd, "NETSCAPE2.0", 11);
OR_ABORT2;
res = write(gif->fd, (uint8_t[])
{
0x03, 0x01}, 2);
OR_ABORT2;
res = write_num(gif->fd, loop);
OR_ABORT2;
res = write(gif->fd, "\0", 1);
OR_ABORT2;
}
/* Add packed key to buffer, updating offset and partial.
* gif->offset holds position to put next *bit*
* gif->partial holds bits to include in next byte */
static void
put_key(ge_GIF *gif, uint16_t key, int key_size)
static void put_key(ge_GIF * gif, uint16_t key, int key_size)
{
int byte_offset, bit_offset, bits_to_write;
ssize_t res;
int byte_offset, bit_offset, bits_to_write;
ssize_t res;
byte_offset = gif->offset / 8;
bit_offset = gif->offset % 8;
gif->partial |= ((uint32_t) key) << bit_offset;
bits_to_write = bit_offset + key_size;
while (bits_to_write >= 8) {
gif->buffer[byte_offset++] = gif->partial & 0xFF;
if (byte_offset == 0xFF) {
res = write(gif->fd, "\xFF", 1); OR_ABORT2;
res = write(gif->fd, gif->buffer, 0xFF); OR_ABORT2;
byte_offset = 0;
}
gif->partial >>= 8;
bits_to_write -= 8;
byte_offset = gif->offset / 8;
bit_offset = gif->offset % 8;
gif->partial |= ((uint32_t) key) << bit_offset;
bits_to_write = bit_offset + key_size;
while (bits_to_write >= 8)
{
gif->buffer[byte_offset++] = gif->partial & 0xFF;
if (byte_offset == 0xFF)
{
res = write(gif->fd, "\xFF", 1);
OR_ABORT2;
res = write(gif->fd, gif->buffer, 0xFF);
OR_ABORT2;
byte_offset = 0;
}
gif->offset = (gif->offset + key_size) % (0xFF * 8);
gif->partial >>= 8;
bits_to_write -= 8;
}
gif->offset = (gif->offset + key_size) % (0xFF * 8);
}
static void end_key(ge_GIF * gif)
{
int byte_offset;
ssize_t res;
byte_offset = gif->offset / 8;
if (gif->offset % 8)
gif->buffer[byte_offset++] = gif->partial & 0xFF;
res = write(gif->fd, (uint8_t[])
{
byte_offset}
, 1);
OR_ABORT2;
res = write(gif->fd, gif->buffer, byte_offset);
OR_ABORT2;
res = write(gif->fd, "\0", 1);
OR_ABORT2;
gif->offset = gif->partial = 0;
}
static void
end_key(ge_GIF *gif)
put_image(ge_GIF * gif, uint16_t w, uint16_t h, uint16_t x, uint16_t y)
{
int byte_offset;
ssize_t res;
int nkeys, key_size, i, j;
Node *node, *child, *root;
ssize_t res;
int degree = 1 << gif->depth;
byte_offset = gif->offset / 8;
if (gif->offset % 8)
gif->buffer[byte_offset++] = gif->partial & 0xFF;
res = write(gif->fd, (uint8_t []) {byte_offset}, 1); OR_ABORT2;
res = write(gif->fd, gif->buffer, byte_offset); OR_ABORT2;
res = write(gif->fd, "\0", 1); OR_ABORT2;
gif->offset = gif->partial = 0;
}
static void
put_image(ge_GIF *gif, uint16_t w, uint16_t h, uint16_t x, uint16_t y)
{
int nkeys, key_size, i, j;
Node *node, *child, *root;
ssize_t res;
int degree = 1 << gif->depth;
res = write(gif->fd, ",", 1); OR_ABORT2;
res = write_num(gif->fd, x); OR_ABORT2;
res = write_num(gif->fd, y); OR_ABORT2;
res = write_num(gif->fd, w); OR_ABORT2;
res = write_num(gif->fd, h); OR_ABORT2;
res = write(gif->fd, (uint8_t []) {0x00, gif->depth}, 2); OR_ABORT2;
root = node = new_trie(degree, &nkeys);
key_size = gif->depth + 1;
put_key(gif, degree, key_size); /* clear code */
for (i = y; i < y+h; i++) {
for (j = x; j < x+w; j++) {
uint8_t pixel = gif->frame[i*gif->w+j] & (degree - 1);
child = node->children[pixel];
if (child) {
node = child;
} else {
put_key(gif, node->key, key_size);
if (nkeys < 0x1000) {
if (nkeys == (1 << key_size))
key_size++;
node->children[pixel] = new_node(nkeys++, degree);
} else {
put_key(gif, degree, key_size); /* clear code */
del_trie(root, degree);
root = node = new_trie(degree, &nkeys);
key_size = gif->depth + 1;
}
node = root->children[pixel];
}
res = write(gif->fd, ",", 1);
OR_ABORT2;
res = write_num(gif->fd, x);
OR_ABORT2;
res = write_num(gif->fd, y);
OR_ABORT2;
res = write_num(gif->fd, w);
OR_ABORT2;
res = write_num(gif->fd, h);
OR_ABORT2;
res = write(gif->fd, (uint8_t[])
{
0x00, gif->depth}, 2);
OR_ABORT2;
root = node = new_trie(degree, &nkeys);
key_size = gif->depth + 1;
put_key(gif, degree, key_size); /* clear code */
for (i = y; i < y + h; i++)
{
for (j = x; j < x + w; j++)
{
uint8_t pixel = gif->frame[i * gif->w + j] & (degree - 1);
child = node->children[pixel];
if (child)
{
node = child;
}
else
{
put_key(gif, node->key, key_size);
if (nkeys < 0x1000)
{
if (nkeys == (1 << key_size))
key_size++;
node->children[pixel] = new_node(nkeys++, degree);
}
else
{
put_key(gif, degree, key_size); /* clear code */
del_trie(root, degree);
root = node = new_trie(degree, &nkeys);
key_size = gif->depth + 1;
}
node = root->children[pixel];
}
}
put_key(gif, node->key, key_size);
put_key(gif, degree + 1, key_size); /* stop code */
end_key(gif);
del_trie(root, degree);
}
put_key(gif, node->key, key_size);
put_key(gif, degree + 1, key_size); /* stop code */
end_key(gif);
del_trie(root, degree);
}
static int
get_bbox(ge_GIF *gif, uint16_t *w, uint16_t *h, uint16_t *x, uint16_t *y)
get_bbox(ge_GIF * gif, uint16_t * w, uint16_t * h, uint16_t * x, uint16_t * y)
{
int i, j, k;
int left, right, top, bottom;
left = gif->w; right = 0;
top = gif->h; bottom = 0;
k = 0;
for (i = 0; i < gif->h; i++) {
for (j = 0; j < gif->w; j++, k++) {
if (gif->frame[k] != gif->back[k]) {
if (j < left) left = j;
if (j > right) right = j;
if (i < top) top = i;
if (i > bottom) bottom = i;
}
}
}
if (left != gif->w && top != gif->h) {
*x = left; *y = top;
*w = right - left + 1;
*h = bottom - top + 1;
return 1;
} else {
return 0;
int i, j, k;
int left, right, top, bottom;
left = gif->w;
right = 0;
top = gif->h;
bottom = 0;
k = 0;
for (i = 0; i < gif->h; i++)
{
for (j = 0; j < gif->w; j++, k++)
{
if (gif->frame[k] != gif->back[k])
{
if (j < left)
left = j;
if (j > right)
right = j;
if (i < top)
top = i;
if (i > bottom)
bottom = i;
}
}
}
if (left != gif->w && top != gif->h)
{
*x = left;
*y = top;
*w = right - left + 1;
*h = bottom - top + 1;
return 1;
}
else
{
return 0;
}
}
/* (From the docs)
@ -267,46 +335,52 @@ get_bbox(ge_GIF *gif, uint16_t *w, uint16_t *h, uint16_t *x, uint16_t *y)
* a minimum of `delay` == 6. If `delay` == 0, no delay information will be stored
* for the frame. This can be used when creating still (single-frame) GIF images.
*/
static void
set_delay(ge_GIF *gif, uint16_t d)
static void set_delay(ge_GIF * gif, uint16_t d)
{
ssize_t res;
ssize_t res;
res = write(gif->fd, (uint8_t []) {'!', 0xF9, 0x04, 0x04}, 4); OR_ABORT2;
res = write_num(gif->fd, d); OR_ABORT2;
res = write(gif->fd, "\0\0", 2); OR_ABORT2;
res = write(gif->fd, (uint8_t[])
{
'!', 0xF9, 0x04, 0x04}, 4);
OR_ABORT2;
res = write_num(gif->fd, d);
OR_ABORT2;
res = write(gif->fd, "\0\0", 2);
OR_ABORT2;
}
void
ge_add_frame(ge_GIF *gif, uint16_t delay)
void ge_add_frame(ge_GIF * gif, uint16_t delay)
{
uint16_t w, h, x, y;
uint8_t *tmp;
uint16_t w, h, x, y;
uint8_t *tmp;
if (delay)
set_delay(gif, delay);
if (gif->nframes == 0) {
w = gif->w;
h = gif->h;
x = y = 0;
} else if (!get_bbox(gif, &w, &h, &x, &y)) {
/* image's not changed; save one pixel just to add delay */
w = h = 1;
x = y = 0;
}
put_image(gif, w, h, x, y);
gif->nframes++;
tmp = gif->back;
gif->back = gif->frame;
gif->frame = tmp;
if (delay)
set_delay(gif, delay);
if (gif->nframes == 0)
{
w = gif->w;
h = gif->h;
x = y = 0;
}
else if (!get_bbox(gif, &w, &h, &x, &y))
{
/* image's not changed; save one pixel just to add delay */
w = h = 1;
x = y = 0;
}
put_image(gif, w, h, x, y);
gif->nframes++;
tmp = gif->back;
gif->back = gif->frame;
gif->frame = tmp;
}
void
ge_close_gif(ge_GIF* gif)
void ge_close_gif(ge_GIF * gif)
{
ssize_t res;
ssize_t res;
res = write(gif->fd, ";", 1); OR_ABORT2;
close(gif->fd);
free(gif);
res = write(gif->fd, ";", 1);
OR_ABORT2;
close(gif->fd);
free(gif);
}

View file

@ -3,22 +3,21 @@
#include <stdint.h>
typedef struct ge_GIF {
uint16_t w, h;
int depth;
int fd;
int offset;
int nframes;
uint8_t *frame, *back;
uint32_t partial;
uint8_t buffer[0xFF];
typedef struct ge_GIF
{
uint16_t w, h;
int depth;
int fd;
int offset;
int nframes;
uint8_t *frame, *back;
uint32_t partial;
uint8_t buffer[0xFF];
} ge_GIF;
ge_GIF *ge_new_gif(
const char *fname, uint16_t width, uint16_t height,
uint8_t *palette, int depth, int loop
);
void ge_add_frame(ge_GIF *gif, uint16_t delay);
void ge_close_gif(ge_GIF* gif);
ge_GIF *ge_new_gif(const char *fname, uint16_t width, uint16_t height,
uint8_t * palette, int depth, int loop);
void ge_add_frame(ge_GIF * gif, uint16_t delay);
void ge_close_gif(ge_GIF * gif);
#endif /* GIFENC_H */

View file

@ -60,10 +60,16 @@ static char *android_locale()
static char android_locale_buf[32];
JNIEnv *mEnv = Android_JNI_GetEnv();
jclass mLocaleClass = (*mEnv)->FindClass(mEnv, "java/util/Locale");
jmethodID mGetDefaultMethod = (*mEnv)->GetStaticMethodID(mEnv, mLocaleClass, "getDefault", "()Ljava/util/Locale;");
jobject mLocaleObject = (*mEnv)->CallStaticObjectMethod(mEnv, mLocaleClass, mGetDefaultMethod);
jmethodID mToStringMethod = (*mEnv)->GetMethodID(mEnv, mLocaleClass, "toString", "()Ljava/lang/String;");
jstring mLocaleString = (*mEnv)->CallObjectMethod(mEnv, mLocaleObject, mToStringMethod);
jmethodID mGetDefaultMethod =
(*mEnv)->GetStaticMethodID(mEnv, mLocaleClass, "getDefault",
"()Ljava/util/Locale;");
jobject mLocaleObject =
(*mEnv)->CallStaticObjectMethod(mEnv, mLocaleClass, mGetDefaultMethod);
jmethodID mToStringMethod =
(*mEnv)->GetMethodID(mEnv, mLocaleClass, "toString",
"()Ljava/lang/String;");
jstring mLocaleString =
(*mEnv)->CallObjectMethod(mEnv, mLocaleObject, mToStringMethod);
const char *locale = (*mEnv)->GetStringUTFChars(mEnv, mLocaleString, 0);
strcpy(android_locale_buf, locale);
@ -484,7 +490,9 @@ static void show_lang_usage(int exitcode)
const char *const prg = "tuxpaint";
/* FIXME: All this should REALLY be array-based!!! */
fprintf(f, "\n" "Usage: %s [--lang LANGUAGE]\n" "\n" "LANGUAGE may be one of:\n"
fprintf(f,
"\n" "Usage: %s [--lang LANGUAGE]\n" "\n"
"LANGUAGE may be one of:\n"
/* C */ " english american-english\n"
/* ach */ " acholi acoli\n"
/* af */ " afrikaans\n"
@ -505,7 +513,8 @@ static void show_lang_usage(int exitcode)
/* brx */ " bodo\n"
/* nb */ " bokmal\n"
/* bs */ " bosnian\n"
/* pt_BR */ " brazilian brazilian-portuguese portugues-brazilian\n"
/* pt_BR */
" brazilian brazilian-portuguese portugues-brazilian\n"
/* br */ " breton brezhoneg\n"
/* en_GB */ " british british-english\n"
/* bg_BG */ " bulgarian\n"
@ -562,7 +571,8 @@ static void show_lang_usage(int exitcode)
/* mni */ " manipuri-bengali\n"
/* mni@meiteimayek */ " manipuri-meitei-mayek\n"
/* nr */ " marathi\n"
/* es_MX */ " mexican mexican-spanish espanol-mejicano\n"
/* es_MX */
" mexican mexican-spanish espanol-mejicano\n"
/* mn */ " mongolian\n"
/* nr */ " ndebele\n"
/* ne */ " nepali\n"
@ -760,7 +770,8 @@ static void show_locale_usage(FILE * f, const char *const prg)
" wa_BE (Walloon)\n"
" wo_SN (Wolof)\n"
" cy_GB (Welsh Cymraeg)\n"
" xh_ZA (Xhosa)\n" " zam (Zapoteco-Miahuatlan)\n" " zu_ZA (Zulu)\n" "\n", prg);
" xh_ZA (Xhosa)\n" " zam (Zapoteco-Miahuatlan)\n"
" zu_ZA (Zulu)\n" "\n", prg);
}
/**
@ -785,10 +796,10 @@ static int search_int_array(int l, int *array)
int i;
for (i = 0; array[i] != -1; i++)
{
if (array[i] == l)
return 1;
}
{
if (array[i] == l)
return 1;
}
return 0;
}
@ -804,18 +815,19 @@ static void ctype_utf8(void)
#ifndef _WIN32
/* FIXME: should this iterate over more locales?
A zapotec speaker may have es_MX.UTF-8 available but not have en_US.UTF-8 for example */
const char *names[] = { "en_US.UTF8", "en_US.UTF-8", "UTF8", "UTF-8", "C.UTF-8" };
const char *names[] =
{ "en_US.UTF8", "en_US.UTF-8", "UTF8", "UTF-8", "C.UTF-8" };
int i = sizeof(names) / sizeof(names[0]);
for (;;)
{
if (iswprint((wchar_t) 0xf7)) // division symbol -- which is in Latin-1 :-/
return;
if (--i < 0)
break;
setlocale(LC_CTYPE, names[i]);
setlocale(LC_MESSAGES, names[i]);
}
{
if (iswprint((wchar_t) 0xf7)) // division symbol -- which is in Latin-1 :-/
return;
if (--i < 0)
break;
setlocale(LC_CTYPE, names[i]);
setlocale(LC_MESSAGES, names[i]);
}
fprintf(stderr, "Failed to find a locale with iswprint() working!\n");
#endif
}
@ -828,13 +840,14 @@ static void ctype_utf8(void)
*/
static const char *language_to_locale(const char *langstr)
{
int i = sizeof language_to_locale_array / sizeof language_to_locale_array[0];
int i =
sizeof language_to_locale_array / sizeof language_to_locale_array[0];
while (i--)
{
if (!strcmp(langstr, language_to_locale_array[i].language))
return language_to_locale_array[i].locale;
}
{
if (!strcmp(langstr, language_to_locale_array[i].language))
return language_to_locale_array[i].locale;
}
if (strcmp(langstr, "help") == 0 || strcmp(langstr, "list") == 0)
show_lang_usage(0);
fprintf(stderr, "%s is an invalid language\n", langstr);
@ -854,34 +867,37 @@ static const char *language_to_locale(const char *langstr)
*/
static const char *locale_to_closest_locale(const char *inlocale)
{
const int numlocale = sizeof(language_to_locale_array) / sizeof(language_to_locale_array[0]);
const char* outlocale = NULL;
const int numlocale =
sizeof(language_to_locale_array) / sizeof(language_to_locale_array[0]);
const char *outlocale = NULL;
int outlocale_score = 0;
int i = 0;
int j = 0;
/* find the locale with the longest string match */
for (i = 0; i < numlocale; i++)
{
const char *candidate = language_to_locale_array[i].locale;
for (j = 0; j < (int) strlen(inlocale) && j < (int) strlen(candidate);
j++)
{
const char* candidate = language_to_locale_array[i].locale;
for (j = 0; j < (int) strlen(inlocale) && j < (int) strlen(candidate); j++)
{
if(inlocale[j] != candidate[j]) break;
}
if (j > outlocale_score)
{
outlocale = candidate;
outlocale_score = j;
}
if (inlocale[j] != candidate[j])
break;
}
if (j > outlocale_score)
{
outlocale = candidate;
outlocale_score = j;
}
}
/* locale must match at least two characters */
if (outlocale_score < 2)
{
outlocale = "";
}
{
outlocale = "";
}
return outlocale;
}
@ -925,68 +941,70 @@ static void set_langint_from_locale_string(const char *restrict loc)
*dot = '\0';
if (cntrycode)
{
ccodeaux = strdup(cntrycode);
*cntrycode = '\0';
}
{
ccodeaux = strdup(cntrycode);
*cntrycode = '\0';
}
if (at)
{
ataux = strdup(at);
*at = '\0';
if (cntrycode)
{
ataux = strdup(at);
*at = '\0';
if (cntrycode)
{
/* ll_CC@variant */
//if (found == 0) printf("ll_CC@variant check\n");
snprintf(straux, 255, "%s%s%s", baseloc, ccodeaux, ataux);
len_baseloc = strlen(straux);
for (i = 0; i < NUM_LANGS && found == 0; i++)
{
// Case-insensitive (both "pt_BR" and "pt_br" work, etc.)
if (len_baseloc == strlen(lang_prefixes[i]) && !strncasecmp(straux, lang_prefixes[i], len_baseloc))
{
langint = i;
found = 1;
}
}
}
/* ll@variant */
//if (found == 0) printf("ll@variant check\n");
snprintf(straux, 255, "%s%s", baseloc, ataux);
/* ll_CC@variant */
//if (found == 0) printf("ll_CC@variant check\n");
snprintf(straux, 255, "%s%s%s", baseloc, ccodeaux, ataux);
len_baseloc = strlen(straux);
for (i = 0; i < NUM_LANGS && found == 0; i++)
{
// Case-insensitive (both "pt_BR" and "pt_br" work, etc.)
if (len_baseloc == strlen(lang_prefixes[i])
&& !strncasecmp(straux, lang_prefixes[i], len_baseloc))
{
// Case-insensitive (both "pt_BR" and "pt_br" work, etc.)
if (len_baseloc == strlen(lang_prefixes[i]) && !strncasecmp(straux, lang_prefixes[i], len_baseloc))
{
langint = i;
found = 1;
}
langint = i;
found = 1;
}
}
}
/* ll@variant */
//if (found == 0) printf("ll@variant check\n");
snprintf(straux, 255, "%s%s", baseloc, ataux);
len_baseloc = strlen(straux);
for (i = 0; i < NUM_LANGS && found == 0; i++)
{
// Case-insensitive (both "pt_BR" and "pt_br" work, etc.)
if (len_baseloc == strlen(lang_prefixes[i])
&& !strncasecmp(straux, lang_prefixes[i], len_baseloc))
{
langint = i;
found = 1;
}
}
}
if (cntrycode)
{
/* ll_CC */
//if (found == 0) printf("ll_CC check\n");
snprintf(straux, 255, "%s%s", baseloc, ccodeaux);
len_baseloc = strlen(straux);
/* Which, if any, of the locales is it? */
for (i = 0; i < NUM_LANGS && found == 0; i++)
{
/* ll_CC */
//if (found == 0) printf("ll_CC check\n");
snprintf(straux, 255, "%s%s", baseloc, ccodeaux);
len_baseloc = strlen(straux);
/* Which, if any, of the locales is it? */
for (i = 0; i < NUM_LANGS && found == 0; i++)
{
// Case-insensitive (both "pt_BR" and "pt_br" work, etc.)
if (len_baseloc == strlen(lang_prefixes[i]) &&
!strncasecmp(straux, lang_prefixes[i], strlen(lang_prefixes[i])))
{
langint = i;
found = 1;
}
}
// Case-insensitive (both "pt_BR" and "pt_br" work, etc.)
if (len_baseloc == strlen(lang_prefixes[i]) &&
!strncasecmp(straux, lang_prefixes[i], strlen(lang_prefixes[i])))
{
langint = i;
found = 1;
}
}
}
/* ll */
// if (found == 0) printf("ll check\n");
@ -994,14 +1012,15 @@ static void set_langint_from_locale_string(const char *restrict loc)
/* Which, if any, of the locales is it? */
for (i = 0; i < NUM_LANGS && found == 0; i++)
{
// Case-insensitive (both "pt_BR" and "pt_br" work, etc.)
if (len_baseloc == strlen(lang_prefixes[i])
&& !strncasecmp(baseloc, lang_prefixes[i], strlen(lang_prefixes[i])))
{
// Case-insensitive (both "pt_BR" and "pt_br" work, etc.)
if (len_baseloc == strlen(lang_prefixes[i]) && !strncasecmp(baseloc, lang_prefixes[i], strlen(lang_prefixes[i])))
{
langint = i;
found = 1;
}
langint = i;
found = 1;
}
}
/* Last resort, we should never arrive here, this check depends
on the right order in lang_prefixes[]
@ -1011,14 +1030,14 @@ static void set_langint_from_locale_string(const char *restrict loc)
// printf("Language still not found: loc= %s Trying reverse check as last resource...\n", loc);
for (i = 0; i < NUM_LANGS && found == 0; i++)
{
// Case-insensitive (both "pt_BR" and "pt_br" work, etc.)
if (!strncasecmp(loc, lang_prefixes[i], strlen(lang_prefixes[i])))
{
// Case-insensitive (both "pt_BR" and "pt_br" work, etc.)
if (!strncasecmp(loc, lang_prefixes[i], strlen(lang_prefixes[i])))
{
langint = i;
found = 1;
}
langint = i;
found = 1;
}
}
// printf("langint %i, lang_ext %s\n", langint, lang_prefixes[langint]);
free(baseloc);
@ -1048,7 +1067,8 @@ static void mysetenv(const char *name, const char *value)
char *str;
#endif
if (name != NULL && value != NULL) {
if (name != NULL && value != NULL)
{
#ifdef HAVE_SETENV
setenv(name, value, 1);
#else
@ -1058,11 +1078,12 @@ static void mysetenv(const char *name, const char *value)
sprintf(str, "%s=%s", name, value);
putenv(str);
#endif
} else {
fprintf(stderr, "WARNING: mysetenv() received a null pointer. name=%s, value=%s\n",
(name == NULL ? "NULL" : name),
(value == NULL ? "NULL" : value)
);
}
else
{
fprintf(stderr,
"WARNING: mysetenv() received a null pointer. name=%s, value=%s\n",
(name == NULL ? "NULL" : name), (value == NULL ? "NULL" : value));
}
}
@ -1074,7 +1095,8 @@ static void mysetenv(const char *name, const char *value)
* @return The Y-nudge value for font rendering in the language.
*/
static int set_current_language(const char *restrict loc, int * ptr_num_wished_langs)
static int set_current_language(const char *restrict loc,
int *ptr_num_wished_langs)
{
int i;
int j = 0;
@ -1087,66 +1109,67 @@ static int set_current_language(const char *restrict loc, int * ptr_num_wished_l
*ptr_num_wished_langs = 0;
if (strlen(loc) > 0)
{
/* Got command line or config file language */
DEBUG_PRINTF("Language via config: %s\n", loc);
mysetenv("LANGUAGE", loc);
}
{
/* Got command line or config file language */
DEBUG_PRINTF("Language via config: %s\n", loc);
mysetenv("LANGUAGE", loc);
}
else
{
DEBUG_PRINTF("Language NOT set via config\n");
{
DEBUG_PRINTF("Language NOT set via config\n");
/* Find what language to use from env vars */
env = getenv("LANGUAGE");
if (env == NULL || env[0] == '\0')
{
env = getenv("LC_ALL");
if (env != NULL && env[0] != '\0')
{
DEBUG_PRINTF("Language via LC_ALL: %s\n", getenv("LC_ALL"));
mysetenv("LANGUAGE", getenv("LC_ALL"));
}
else
{
env = getenv("LC_MESSAGES");
if (env != NULL && env[0] != '\0')
{
DEBUG_PRINTF("Language via LC_MESSAGES: %s\n", getenv("LC_MESSAGES"));
mysetenv("LANGUAGE", getenv("LC_MESSAGES"));
}
else
{
env = getenv("LANG");
if (env != NULL && env[0] != '\0')
{
DEBUG_PRINTF("Language via LANG: %s\n", getenv("LANG"));
mysetenv("LANGUAGE", getenv("LANG"));
}
else
{
DEBUG_PRINTF("No language set!\n");
}
}
}
}
/* Find what language to use from env vars */
env = getenv("LANGUAGE");
if (env == NULL || env[0] == '\0')
{
env = getenv("LC_ALL");
if (env != NULL && env[0] != '\0')
{
DEBUG_PRINTF("Language via LC_ALL: %s\n", getenv("LC_ALL"));
mysetenv("LANGUAGE", getenv("LC_ALL"));
}
else
{
env = getenv("LC_MESSAGES");
if (env != NULL && env[0] != '\0')
{
DEBUG_PRINTF("Language was set to '%s'\n", getenv("LANGUAGE"));
}
DEBUG_PRINTF("Language via LC_MESSAGES: %s\n",
getenv("LC_MESSAGES"));
mysetenv("LANGUAGE", getenv("LC_MESSAGES"));
}
else
{
env = getenv("LANG");
if (env != NULL && env[0] != '\0')
{
DEBUG_PRINTF("Language via LANG: %s\n", getenv("LANG"));
mysetenv("LANGUAGE", getenv("LANG"));
}
else
{
DEBUG_PRINTF("No language set!\n");
}
}
}
}
else
{
DEBUG_PRINTF("Language was set to '%s'\n", getenv("LANGUAGE"));
}
}
oldloc = strdup(loc);
/* First set the locale according to the environment, then try to overwrite with loc,
after that, ctype_utf8() call will test the compatibility with utf8 and try to load
a different locale if the resulting one is not compatible. */
DEBUG_PRINTF("Locale BEFORE is: %s\n", setlocale(LC_ALL, NULL)); //EP
DEBUG_PRINTF("Locale BEFORE is: %s\n", setlocale(LC_ALL, NULL)); //EP
setlocale(LC_ALL, "");
setlocale(LC_ALL, loc);
ctype_utf8();
DEBUG_PRINTF("Locale AFTER is: %s\n", setlocale(LC_ALL, NULL)); //EP
DEBUG_PRINTF("Locale AFTER is: %s\n", setlocale(LC_ALL, NULL)); //EP
#ifdef BDIST_WIN32
// FIXME: After the update of MinGW/MSYS2 in January 2022, gettext() no longer find
@ -1177,77 +1200,80 @@ static int set_current_language(const char *restrict loc, int * ptr_num_wished_l
loc = setlocale(LC_MESSAGES, NULL);
if (oldloc && loc && strcmp(oldloc, "") != 0 && strcmp(loc, oldloc) != 0)
{
/* System doesn't recognize that locale! Hack, per Albert C., is to set LC_ALL to a valid UTF-8 locale, then set LANGUAGE to the locale we want to force -bjk 2010.10.05 */
{
/* System doesn't recognize that locale! Hack, per Albert C., is to set LC_ALL to a valid UTF-8 locale, then set LANGUAGE to the locale we want to force -bjk 2010.10.05 */
/* Albert's comments from December 2009:
gettext() won't even bother to look up messages unless it
is totally satisfied that you are using one of the locales that
it ships with! Make gettext() unhappy, and it'll switch to the
lobotomized 7-bit Linux "C" locale just to spite you.
/* Albert's comments from December 2009:
gettext() won't even bother to look up messages unless it
is totally satisfied that you are using one of the locales that
it ships with! Make gettext() unhappy, and it'll switch to the
lobotomized 7-bit Linux "C" locale just to spite you.
http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/localedata/SUPPORTED?content-type=text/x-cvsweb-markup&cvsroot=glibc
http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/localedata/SUPPORTED?content-type=text/x-cvsweb-markup&cvsroot=glibc
You can confuse gettext() into mostly behaving. For example, a
user could pick a random UTF-8 locale and change the messages.
In that case, Tux Paint thinks it's in the other locale but the
messages come out right. Like so: LANGUAGE=zam LC_ALL=fr_FR.UTF-8
It doesn't work to leave LC_ALL unset, set it to "zam", set it to "C",
or set it to random nonsense. Yeah, Tux Paint will think it's in
a French locale, but the messages will be Zapotec nonetheless.
You can confuse gettext() into mostly behaving. For example, a
user could pick a random UTF-8 locale and change the messages.
In that case, Tux Paint thinks it's in the other locale but the
messages come out right. Like so: LANGUAGE=zam LC_ALL=fr_FR.UTF-8
It doesn't work to leave LC_ALL unset, set it to "zam", set it to "C",
or set it to random nonsense. Yeah, Tux Paint will think it's in
a French locale, but the messages will be Zapotec nonetheless.
Maybe it's time to give up on gettext().
Maybe it's time to give up on gettext().
[see also: https://sourceforge.net/mailarchive/message.php?msg_name=787b0d920912222352i5ab22834x92686283b565016b%40mail.gmail.com ]
*/
[see also: https://sourceforge.net/mailarchive/message.php?msg_name=787b0d920912222352i5ab22834x92686283b565016b%40mail.gmail.com ]
*/
/* Unneeded here, this has yet been done as part of ctype_utf8() call before, iterating over a list of locales */
// setlocale(LC_ALL, "en_US.UTF-8"); /* Is it dumb to assume "en_US" is pretty close to "C" locale? */
/* Unneeded here, this has yet been done as part of ctype_utf8() call before, iterating over a list of locales */
// setlocale(LC_ALL, "en_US.UTF-8"); /* Is it dumb to assume "en_US" is pretty close to "C" locale? */
mysetenv("LANGUAGE", oldloc);
set_langint_from_locale_string(oldloc);
}
mysetenv("LANGUAGE", oldloc);
set_langint_from_locale_string(oldloc);
}
else
{
{
#ifdef _WIN32
if (getenv("LANGUAGE") == NULL)
mysetenv("LANGUAGE", loc);
if (getenv("LANGUAGE") == NULL)
mysetenv("LANGUAGE", loc);
#endif
if (getenv("LANGUAGE") == NULL)
mysetenv("LANGUAGE", "C");
}
if (getenv("LANGUAGE") == NULL)
mysetenv("LANGUAGE", "C");
}
env_language = strdup(getenv("LANGUAGE"));
if (*env_language)
{
env_language_lang = strtok(env_language, ":");
while (env_language_lang != NULL)
{
env_language_lang = strtok(env_language, ":");
while (env_language_lang != NULL)
num_wished_langs++;
set_langint_from_locale_string(env_language_lang);
wished_langs[j].langint = langint;
wished_langs[j].lang_prefix = lang_prefixes[langint];
wished_langs[j].need_own_font =
search_int_array(langint, lang_use_own_font);
wished_langs[j].need_right_to_left =
search_int_array(langint, lang_use_right_to_left);
wished_langs[j].need_right_to_left_word =
search_int_array(langint, lang_use_right_to_left_word);
for (i = 0; lang_y_nudge[i][0] != -1; i++)
{
// printf("lang_y_nudge[%d][0] = %d\n", i, lang_y_nudge[i][0]);
if (lang_y_nudge[i][0] == langint)
{
num_wished_langs++;
set_langint_from_locale_string(env_language_lang);
wished_langs[j].langint = langint;
wished_langs[j].lang_prefix = lang_prefixes[langint];
wished_langs[j].need_own_font = search_int_array(langint, lang_use_own_font);
wished_langs[j].need_right_to_left = search_int_array(langint, lang_use_right_to_left);
wished_langs[j].need_right_to_left_word = search_int_array(langint, lang_use_right_to_left_word);
for (i = 0; lang_y_nudge[i][0] != -1; i++)
{
// printf("lang_y_nudge[%d][0] = %d\n", i, lang_y_nudge[i][0]);
if (lang_y_nudge[i][0] == langint)
{
wished_langs[j].lang_y_nudge = lang_y_nudge[i][1];
break;
}
}
j++;
env_language_lang = strtok(NULL, ":");
wished_langs[j].lang_y_nudge = lang_y_nudge[i][1];
break;
}
if (*env_language)
free(env_language);
}
j++;
env_language_lang = strtok(NULL, ":");
}
if (*env_language)
free(env_language);
}
// set_langint_from_locale_string(loc);
@ -1264,13 +1290,15 @@ static int set_current_language(const char *restrict loc, int * ptr_num_wished_l
#ifdef DEBUG
fprintf(stderr, "DEBUG: Language is %s (%d) %s/%s\n",
lang_prefix, langint, need_right_to_left ? "(RTL)" : "", need_right_to_left_word ? "(RTL words)" : "");
lang_prefix, langint, need_right_to_left ? "(RTL)" : "",
need_right_to_left_word ? "(RTL words)" : "");
fflush(stderr);
#endif
free(oldloc);
DEBUG_PRINTF("lang_prefixes[%d] is \"%s\"\n", get_current_language(), lang_prefixes[get_current_language()]);
DEBUG_PRINTF("lang_prefixes[%d] is \"%s\"\n", get_current_language(),
lang_prefixes[get_current_language()]);
*ptr_num_wished_langs = num_wished_langs;
@ -1289,27 +1317,28 @@ static int set_current_language(const char *restrict loc, int * ptr_num_wished_l
* @param int * a place to return the number of languages we want to use, when scanning stamp descriptions
* @return Y-nudge
*/
int setup_i18n(const char *restrict lang, const char *restrict locale, int * num_wished_langs)
int setup_i18n(const char *restrict lang, const char *restrict locale,
int *num_wished_langs)
{
DEBUG_PRINTF("lang %p, locale %p\n", lang, locale);
DEBUG_PRINTF("lang \"%s\", locale \"%s\"\n", lang, locale);
if (locale)
{
if (!strcmp(locale, "help"))
{
if (!strcmp(locale, "help"))
{
show_locale_usage(stdout, "tuxpaint");
exit(0);
}
show_locale_usage(stdout, "tuxpaint");
exit(0);
}
}
else
{
#if defined(__APPLE__)
locale = locale_to_closest_locale(apple_locale());
#else
locale = "";
#endif
}
{
#if defined(__APPLE__)
locale = locale_to_closest_locale(apple_locale());
#else
locale = "";
#endif
}
if (lang)
locale = language_to_locale(lang);

View file

@ -206,7 +206,8 @@ extern w_langs wished_langs[255];
/* Function prototypes: */
int get_current_language(void);
int setup_i18n(const char *restrict lang, const char *restrict locale, int * ptr_num_wished_languages) MUST_CHECK;
int setup_i18n(const char *restrict lang, const char *restrict locale,
int *ptr_num_wished_languages) MUST_CHECK;
#ifdef NO_SDLPANGO
int smash_i18n(void) MUST_CHECK;

1987
src/im.c

File diff suppressed because it is too large Load diff

View file

@ -25,8 +25,8 @@
#include "SDL.h"
int DisplayPageSetup(const SDL_Surface* surface);
const char* SurfacePrint(const SDL_Surface* surface, int showDialog);
int DisplayPageSetup(const SDL_Surface * surface);
const char *SurfacePrint(const SDL_Surface * surface, int showDialog);
#endif /* __IOS_PRINT_H__ */

File diff suppressed because it is too large Load diff

View file

@ -105,13 +105,13 @@ typedef struct osk_keyboard
char *name; /* The name of the keyboard */
char *keyboard_list; /* The names of the keyboards allowed from this one */
SDL_Surface *surface; /* The surface containing the current layout's keyboard */
/* The surfaces containing the current layout's button backgrounds*/
/* The surfaces containing the current layout's button backgrounds */
SDL_Surface *button_up;
SDL_Surface *button_down;
SDL_Surface *button_off;
SDL_Surface *button_nav;
SDL_Surface *button_hold;
/* The surfaces containing some symbols for the current layout's buttons */
/* The surfaces containing some symbols for the current layout's buttons */
SDL_Surface *oskdel; /* delete arrow */
SDL_Surface *osktab; /* Tab arrows */
SDL_Surface *oskenter; /* Return hook/arrow */
@ -133,7 +133,7 @@ typedef struct osk_keyboard
int composed_type; /* 1 if the value stored in composed is yet the unicode value */
osk_composenode *composing; /* The node in the middle of a compose sequence */
osk_key *last_key_pressed; /* The last key pressed */
SDL_Surface * canvas_ptr; /* Canvas drawing surface, for bpp and sizing needs when cycling through keyboard layouts */
SDL_Surface *canvas_ptr; /* Canvas drawing surface, for bpp and sizing needs when cycling through keyboard layouts */
/* Large and small buttons, to pass back to osk_create() when cycling through keyboard layouts */
SDL_Surface *BLANK_button_up;
SDL_Surface *BLANK_button_down;
@ -147,17 +147,23 @@ typedef struct osk_keyboard
SDL_Surface *BLANK_oskshift;
} on_screen_keyboard;
struct osk_keyboard *osk_create(char * layout_name, SDL_Surface * canvas,
SDL_Surface * BLANK_button_up, SDL_Surface * BLANK_button_down,
SDL_Surface * BLANK_button_off, SDL_Surface * BLANK_button_nav,
struct osk_keyboard *osk_create(char *layout_name, SDL_Surface * canvas,
SDL_Surface * BLANK_button_up,
SDL_Surface * BLANK_button_down,
SDL_Surface * BLANK_button_off,
SDL_Surface * BLANK_button_nav,
SDL_Surface * BLANK_button_hold,
SDL_Surface * BLANK_oskdel, SDL_Surface * BLANK_osktab, SDL_Surface * BLANK_oskenter,
SDL_Surface * BLANK_oskcapslock, SDL_Surface * BLANK_oskshift,
SDL_Surface * BLANK_oskdel,
SDL_Surface * BLANK_osktab,
SDL_Surface * BLANK_oskenter,
SDL_Surface * BLANK_oskcapslock,
SDL_Surface * BLANK_oskshift,
int disable_change);
struct osk_layout *osk_load_layout(char *layout_name);
void osk_get_layout_data(char *layout_name, int *layout_w, int *layout_h, char *layout_buttons, char *layout_labels,
void osk_get_layout_data(char *layout_name, int *layout_w, int *layout_h,
char *layout_buttons, char *layout_labels,
char *layout_keycodes);
void osk_reset(on_screen_keyboard * osk);
struct osk_keyboard *osk_clicked(on_screen_keyboard * keyboard, int x, int y);

View file

@ -95,5 +95,5 @@ struct cfginfo
#define CFGINFO_MAXOFFSET (sizeof(struct cfginfo))
extern void parse_one_option(struct cfginfo *restrict tmpcfg, const char *str, const char *opt,
const char *restrict src);
extern void parse_one_option(struct cfginfo *restrict tmpcfg, const char *str,
const char *opt, const char *restrict src);

View file

@ -37,19 +37,21 @@ static void putpixel8(SDL_Surface * surface, int x, int y, Uint32 pixel)
Uint8 *p;
/* Assuming the X/Y values are within the bounds of this surface... */
if (likely(likely((unsigned)x < (unsigned)surface->w) && likely((unsigned)y < (unsigned)surface->h)))
{
// Set a pointer to the exact location in memory of the pixel
p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
(y * surface->pitch) + /* Go down Y lines */
x); /* Go in X pixels */
if (likely
(likely((unsigned) x < (unsigned) surface->w)
&& likely((unsigned) y < (unsigned) surface->h)))
{
// Set a pointer to the exact location in memory of the pixel
p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
(y * surface->pitch) + /* Go down Y lines */
x); /* Go in X pixels */
/* Set the (correctly-sized) piece of data in the surface's RAM
* to the pixel value sent in: */
/* Set the (correctly-sized) piece of data in the surface's RAM
* to the pixel value sent in: */
*p = pixel;
}
*p = pixel;
}
}
/* Draw a single pixel into the surface: */
@ -58,19 +60,21 @@ static void putpixel16(SDL_Surface * surface, int x, int y, Uint32 pixel)
Uint8 *p;
/* Assuming the X/Y values are within the bounds of this surface... */
if (likely(likely((unsigned)x < (unsigned)surface->w) && likely((unsigned)y < (unsigned)surface->h)))
{
// Set a pointer to the exact location in memory of the pixel
p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
(y * surface->pitch) + /* Go down Y lines */
(x * 2)); /* Go in X pixels */
if (likely
(likely((unsigned) x < (unsigned) surface->w)
&& likely((unsigned) y < (unsigned) surface->h)))
{
// Set a pointer to the exact location in memory of the pixel
p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
(y * surface->pitch) + /* Go down Y lines */
(x * 2)); /* Go in X pixels */
/* Set the (correctly-sized) piece of data in the surface's RAM
* to the pixel value sent in: */
/* Set the (correctly-sized) piece of data in the surface's RAM
* to the pixel value sent in: */
*(Uint16 *) p = pixel;
}
*(Uint16 *) p = pixel;
}
}
/* Draw a single pixel into the surface: */
@ -79,31 +83,33 @@ static void putpixel24(SDL_Surface * surface, int x, int y, Uint32 pixel)
Uint8 *p;
/* Assuming the X/Y values are within the bounds of this surface... */
if (likely(likely((unsigned)x < (unsigned)surface->w) && likely((unsigned)y < (unsigned)surface->h)))
if (likely
(likely((unsigned) x < (unsigned) surface->w)
&& likely((unsigned) y < (unsigned) surface->h)))
{
// Set a pointer to the exact location in memory of the pixel
p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
(y * surface->pitch) + /* Go down Y lines */
(x * 3)); /* Go in X pixels */
/* Set the (correctly-sized) piece of data in the surface's RAM
* to the pixel value sent in: */
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
// Set a pointer to the exact location in memory of the pixel
p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
(y * surface->pitch) + /* Go down Y lines */
(x * 3)); /* Go in X pixels */
/* Set the (correctly-sized) piece of data in the surface's RAM
* to the pixel value sent in: */
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
else
{
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
else
{
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
}
}
/* Draw a single pixel into the surface: */
@ -112,19 +118,21 @@ static void putpixel32(SDL_Surface * surface, int x, int y, Uint32 pixel)
Uint8 *p;
/* Assuming the X/Y values are within the bounds of this surface... */
if (likely(likely((unsigned)x < (unsigned)surface->w) && likely((unsigned)y < (unsigned)surface->h)))
{
// Set a pointer to the exact location in memory of the pixel
p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
(y * surface->pitch) + /* Go down Y lines */
(x * 4)); /* Go in X pixels */
if (likely
(likely((unsigned) x < (unsigned) surface->w)
&& likely((unsigned) y < (unsigned) surface->h)))
{
// Set a pointer to the exact location in memory of the pixel
p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
(y * surface->pitch) + /* Go down Y lines */
(x * 4)); /* Go in X pixels */
/* Set the (correctly-sized) piece of data in the surface's RAM
* to the pixel value sent in: */
/* Set the (correctly-sized) piece of data in the surface's RAM
* to the pixel value sent in: */
*(Uint32 *) p = pixel; // 32-bit display
}
*(Uint32 *) p = pixel; // 32-bit display
}
}
/* Get a pixel: */
@ -133,9 +141,9 @@ static Uint32 getpixel8(SDL_Surface * surface, int x, int y)
Uint8 *p;
/* get the X/Y values within the bounds of this surface */
if (unlikely((unsigned)x > (unsigned)surface->w - 1u))
if (unlikely((unsigned) x > (unsigned) surface->w - 1u))
x = (x < 0) ? 0 : surface->w - 1;
if (unlikely((unsigned)y > (unsigned)surface->h - 1u))
if (unlikely((unsigned) y > (unsigned) surface->h - 1u))
y = (y < 0) ? 0 : surface->h - 1;
/* Set a pointer to the exact location in memory of the pixel
@ -159,9 +167,9 @@ static Uint32 getpixel16(SDL_Surface * surface, int x, int y)
Uint8 *p;
/* get the X/Y values within the bounds of this surface */
if (unlikely((unsigned)x > (unsigned)surface->w - 1u))
if (unlikely((unsigned) x > (unsigned) surface->w - 1u))
x = (x < 0) ? 0 : surface->w - 1;
if (unlikely((unsigned)y > (unsigned)surface->h - 1u))
if (unlikely((unsigned) y > (unsigned) surface->h - 1u))
y = (y < 0) ? 0 : surface->h - 1;
/* Set a pointer to the exact location in memory of the pixel
@ -186,9 +194,9 @@ static Uint32 getpixel24(SDL_Surface * surface, int x, int y)
Uint32 pixel;
/* get the X/Y values within the bounds of this surface */
if (unlikely((unsigned)x > (unsigned)surface->w - 1u))
if (unlikely((unsigned) x > (unsigned) surface->w - 1u))
x = (x < 0) ? 0 : surface->w - 1;
if (unlikely((unsigned)y > (unsigned)surface->h - 1u))
if (unlikely((unsigned) y > (unsigned) surface->h - 1u))
y = (y < 0) ? 0 : surface->h - 1;
/* Set a pointer to the exact location in memory of the pixel
@ -219,9 +227,9 @@ static Uint32 getpixel32(SDL_Surface * surface, int x, int y)
Uint8 *p;
/* get the X/Y values within the bounds of this surface */
if (unlikely((unsigned)x > (unsigned)surface->w - 1u))
if (unlikely((unsigned) x > (unsigned) surface->w - 1u))
x = (x < 0) ? 0 : surface->w - 1;
if (unlikely((unsigned)y > (unsigned)surface->h - 1u))
if (unlikely((unsigned) y > (unsigned) surface->h - 1u))
y = (y < 0) ? 0 : surface->h - 1;
/* Set a pointer to the exact location in memory of the pixel
@ -239,11 +247,11 @@ static Uint32 getpixel32(SDL_Surface * surface, int x, int y)
return *(Uint32 *) p; // 32-bit display
}
void (*putpixels[]) (SDL_Surface *, int, int, Uint32) =
{
putpixel8, putpixel8, putpixel16, putpixel24, putpixel32};
void (*putpixels[])(SDL_Surface *, int, int, Uint32) = {
putpixel8, putpixel8, putpixel16, putpixel24, putpixel32
};
Uint32(*getpixels[])(SDL_Surface *, int, int) =
{
getpixel8, getpixel8, getpixel16, getpixel24, getpixel32};
Uint32(*getpixels[])(SDL_Surface *, int, int) = {
getpixel8, getpixel8, getpixel16, getpixel24, getpixel32
};

View file

@ -32,7 +32,7 @@
#include "SDL.h"
extern void (*putpixels[]) (SDL_Surface *, int, int, Uint32);
extern void (*putpixels[])(SDL_Surface *, int, int, Uint32);
extern Uint32(*getpixels[]) (SDL_Surface *, int, int);
#endif

View file

@ -24,21 +24,21 @@
#if defined(__APPLE__)
#include <TargetConditionals.h>
#include <TargetConditionals.h>
/*
* MAC test must be last because it tests true even on iOS / tvOS / watchOS.
*/
* MAC test must be last because it tests true even on iOS / tvOS / watchOS.
*/
#if TARGET_OS_IOS || TARGET_OS_IPHONE || TARGET_OS_SIMULATOR || TARGET_IPHONE_SIMULATOR || TARGET_OS_EMBEDDED
#define __IOS__ 1
#elif TARGET_OS_OSX || TARGET_OS_MAC
#define __MACOS__ 1
#else
#define __OTHER_APPLE__ 1
#if TARGET_OS_IOS || TARGET_OS_IPHONE || TARGET_OS_SIMULATOR || TARGET_IPHONE_SIMULATOR || TARGET_OS_EMBEDDED
#define __IOS__ 1
#elif TARGET_OS_OSX || TARGET_OS_MAC
#define __MACOS__ 1
#else
#define __OTHER_APPLE__ 1
#warning "Unsupported Apple platform, will build on a best-effort basis"
#endif
#warning "Unsupported Apple platform, will build on a best-effort basis"
#endif
#endif /* __APPLE__ */

View file

@ -48,70 +48,72 @@ static int old_sound[4] = { -1, -1, -1, -1 };
* (low values, near the top of the window, are quieter), or
* SNDDIST_NEAR for full volume
*/
void playsound(SDL_Surface * screen, int chan, int s, int override, int x, int y)
void playsound(SDL_Surface * screen, int chan, int s, int override, int x,
int y)
{
#ifndef NOSOUND
int left, dist;
if (!mute && use_sound && s != SND_NONE)
{
{
#ifdef DEBUG
printf("playsound #%d in channel %d, pos (%d,%d), %soverride, ptr=%p\n", s, chan, x, y, override ? "" : "no ",
sounds[s]);
printf("playsound #%d in channel %d, pos (%d,%d), %soverride, ptr=%p\n",
s, chan, x, y, override ? "" : "no ", sounds[s]);
fflush(stdout);
#endif
if (override || !Mix_Playing(chan))
{
Mix_PlayChannel(chan, sounds[s], 0);
old_sound[chan] = s;
}
if (old_sound[chan] == s)
{
if (y == SNDDIST_NEAR)
dist = 0;
else
{
if (y < 0)
y = 0;
else if (y >= screen->h - 1)
y = screen->h - 1;
dist = (255 * ((screen->h - 1) - y)) / (screen->h - 1);
}
if (use_stereo)
{
if (x == SNDPOS_LEFT)
left = 255 - dist;
else if (x == SNDPOS_CENTER)
left = (255 - dist) / 2;
else if (x == SNDPOS_RIGHT)
left = 0;
else
{
if (x < 0)
x = 0;
else if (x >= screen->w)
x = screen->w - 1;
left = ((255 - dist) * ((screen->w - 1) - x)) / (screen->w - 1);
}
}
else
{
/* Stereo disabled; treat everything like a SNDPOS_CENTER
(equal amount in each of the left/right channels) */
left = (255 - dist) / 2;
}
#ifdef DEBUG
printf("Panning of sound #%d in channel %d, left=%d, right=%d\n", s,
chan, left, (255 - dist) - left);
fflush(stdout);
#endif
if (override || !Mix_Playing(chan))
{
Mix_PlayChannel(chan, sounds[s], 0);
old_sound[chan] = s;
}
if (old_sound[chan] == s)
{
if (y == SNDDIST_NEAR)
dist = 0;
else
{
if (y < 0)
y = 0;
else if (y >= screen->h - 1)
y = screen->h - 1;
dist = (255 * ((screen->h - 1) - y)) / (screen->h - 1);
}
if (use_stereo)
{
if (x == SNDPOS_LEFT)
left = 255 - dist;
else if (x == SNDPOS_CENTER)
left = (255 - dist) / 2;
else if (x == SNDPOS_RIGHT)
left = 0;
else
{
if (x < 0)
x = 0;
else if (x >= screen->w)
x = screen->w - 1;
left = ((255 - dist) * ((screen->w - 1) - x)) / (screen->w - 1);
}
}
else
{
/* Stereo disabled; treat everything like a SNDPOS_CENTER
(equal amount in each of the left/right channels) */
left = (255 - dist) / 2;
}
#ifdef DEBUG
printf("Panning of sound #%d in channel %d, left=%d, right=%d\n", s, chan, left, (255 - dist) - left);
fflush(stdout);
#endif
Mix_SetPanning(chan, left, (255 - dist) - left);
}
Mix_SetPanning(chan, left, (255 - dist) - left);
}
}
#endif
}

View file

@ -37,6 +37,7 @@
extern Mix_Chunk *sounds[NUM_SOUNDS];
extern int mute, use_sound, use_stereo;
void playsound(SDL_Surface * screen, int chan, int s, int override, int x, int y);
void playsound(SDL_Surface * screen, int chan, int s, int override, int x,
int y);
#endif

View file

@ -69,17 +69,18 @@
static int f2int(float f)
{
return ((int)f);
return ((int) f);
}
static int f2dec(float f)
{
return (int)((f - f2int(f)) * 100);
return (int) ((f - f2int(f)) * 100);
}
/* Actually save the PostScript data to the file stream: */
int do_ps_save(FILE * fi,
const char *restrict const fname, SDL_Surface * surf, const char *restrict pprsize, int is_pipe)
const char *restrict const fname, SDL_Surface * surf,
const char *restrict pprsize, int is_pipe)
{
const struct paper *ppr;
int img_w = surf->w;
@ -93,7 +94,8 @@ int do_ps_save(FILE * fi,
Uint8 r, g, b;
char buf[256];
Uint32(*getpixel) (SDL_Surface *, int, int) = getpixels[surf->format->BytesPerPixel];
Uint32(*getpixel) (SDL_Surface *, int, int) =
getpixels[surf->format->BytesPerPixel];
int printed_img_w, printed_img_h;
time_t t = time(NULL);
int rotate;
@ -103,35 +105,35 @@ int do_ps_save(FILE * fi,
/* Determine paper size: */
if (pprsize == NULL)
{
/* User did not request a specific paper size (on command-line or
in config file), ask the system. It will return either their
$PAPER env. var., the value from /etc/papersize, or NULL: */
pprsize = systempapername();
if (pprsize == NULL)
{
/* User did not request a specific paper size (on command-line or
in config file), ask the system. It will return either their
$PAPER env. var., the value from /etc/papersize, or NULL: */
/* No setting, env. var. or /etc/ file; use the default! */
pprsize = systempapername();
if (pprsize == NULL)
{
/* No setting, env. var. or /etc/ file; use the default! */
pprsize = defaultpapername();
pprsize = defaultpapername();
#ifdef DEBUG
printf("Using default paper\n");
#endif
}
#ifdef DEBUG
else
{
printf("Using system paper\n");
}
printf("Using default paper\n");
#endif
}
#ifdef DEBUG
else
{
printf("Using system paper\n");
}
#endif
}
#ifdef DEBUG
else
{
printf("Using user paper\n");
}
{
printf("Using user paper\n");
}
#endif
#ifdef DEBUG
@ -147,7 +149,8 @@ int do_ps_save(FILE * fi,
ppr_h = paperpsheight(ppr);
#ifdef DEBUG
printf("Paper is %d x %d (%.2f\" x %.2f\")\n", ppr_w, ppr_h, (float)ppr_w / 72.0, (float)ppr_h / 72.0);
printf("Paper is %d x %d (%.2f\" x %.2f\")\n", ppr_w, ppr_h,
(float) ppr_w / 72.0, (float) ppr_h / 72.0);
#endif
paperdone(); // FIXME: Should we do this at quit? -bjk 2007.06.25
@ -155,18 +158,19 @@ int do_ps_save(FILE * fi,
/* Determine whether it's best to rotate the image: */
if ((ppr_w >= ppr_h && img_w >= img_h) || (ppr_w <= ppr_h && img_w <= img_h))
{
rotate = 0;
r_img_w = img_w;
r_img_h = img_h;
}
if ((ppr_w >= ppr_h && img_w >= img_h)
|| (ppr_w <= ppr_h && img_w <= img_h))
{
rotate = 0;
r_img_w = img_w;
r_img_h = img_h;
}
else
{
rotate = 1;
r_img_w = img_h;
r_img_h = img_w;
}
{
rotate = 1;
r_img_w = img_h;
r_img_h = img_w;
}
#ifdef DEBUG
printf("Image is %d x %d\n", img_w, img_h);
@ -177,13 +181,16 @@ int do_ps_save(FILE * fi,
/* Determine scale: */
scale = my_min(((float)(ppr_w - (MARGIN * 2)) / (float)r_img_w), ((float)(ppr_h - (MARGIN * 2)) / (float)r_img_h));
scale =
my_min(((float) (ppr_w - (MARGIN * 2)) / (float) r_img_w),
((float) (ppr_h - (MARGIN * 2)) / (float) r_img_h));
printed_img_w = r_img_w * scale;
printed_img_h = r_img_h * scale;
#ifdef DEBUG
printf("Scaling image by %.2f (to %d x %d)\n", scale, printed_img_w, printed_img_h);
printf("Scaling image by %.2f (to %d x %d)\n", scale, printed_img_w,
printed_img_h);
#endif
@ -209,7 +216,8 @@ int do_ps_save(FILE * fi,
fprintf(fi, "%%%%Pages: 1\n");
fprintf(fi, "%%%%BoundingBox: 0 0 %d %d\n", (int)(ppr_w + 0.5), (int)(ppr_h + 0.5));
fprintf(fi, "%%%%BoundingBox: 0 0 %d %d\n", (int) (ppr_w + 0.5),
(int) (ppr_h + 0.5));
fprintf(fi, "%%%%EndComments\n");
@ -228,20 +236,23 @@ int do_ps_save(FILE * fi,
fprintf(fi, "%%%%Page: 1 1\n");
fprintf(fi, "<< /PageSize [ %d %d ] /ImagingBBox null >> setpagedevice\n", ppr_w, ppr_h);
fprintf(fi, "<< /PageSize [ %d %d ] /ImagingBBox null >> setpagedevice\n",
ppr_w, ppr_h);
fprintf(fi, "gsave\n");
/* 'translate' moves the user space origin to a new position with
respect to the current page, leaving the orientation of the axes and
the unit lengths unchanged. */
fprintf(fi, "%d.%02d %d.%02d translate\n", f2int(tlate_x), f2dec(tlate_x), f2int(tlate_y), f2dec(tlate_y));
fprintf(fi, "%d.%02d %d.%02d translate\n", f2int(tlate_x), f2dec(tlate_x),
f2int(tlate_y), f2dec(tlate_y));
/* 'scale' modifies the unit lengths independently along the current
x and y axes, leaving the origin location and the orientation of the
axes unchanged. */
fprintf(fi, "%d.%02d %d.%02d scale\n",
f2int(printed_img_w), f2dec(printed_img_w), f2int(printed_img_h), f2dec(printed_img_h));
f2int(printed_img_w), f2dec(printed_img_w), f2int(printed_img_h),
f2dec(printed_img_h));
/* Rotate the image */
if (rotate)
@ -261,23 +272,23 @@ int do_ps_save(FILE * fi,
cur_line_len = 0;
for (y = 0; y < img_h; y++)
{
for (plane = 0; plane < 3; plane++)
{
for (plane = 0; plane < 3; plane++)
{
for (x = 0; x < img_w; x++)
{
SDL_GetRGB(getpixel(surf, x, y), surf->format, &r, &g, &b);
fprintf(fi, "%02x", (plane == 0 ? r : (plane == 1 ? g : b)));
for (x = 0; x < img_w; x++)
{
SDL_GetRGB(getpixel(surf, x, y), surf->format, &r, &g, &b);
fprintf(fi, "%02x", (plane == 0 ? r : (plane == 1 ? g : b)));
cur_line_len++;
if (cur_line_len >= 30)
{
fprintf(fi, "\n");
cur_line_len = 0;
}
}
cur_line_len++;
if (cur_line_len >= 30)
{
fprintf(fi, "\n");
cur_line_len = 0;
}
}
}
}
fprintf(fi, "\n");
fprintf(fi, "grestore\n");
@ -286,74 +297,74 @@ int do_ps_save(FILE * fi,
fprintf(fi, "%%%%EOF\n");
if (!is_pipe)
{
fclose(fi);
return 1;
}
{
fclose(fi);
return 1;
}
else
{
pid_t child_pid, w;
int status;
{
pid_t child_pid, w;
int status;
#ifdef __APPLE__
/* macOS does not always reset errno so Tux Paint thinks print never
* succeeds - let's reset before calling pclose() on macOS */
errno = 0;
/* macOS does not always reset errno so Tux Paint thinks print never
* succeeds - let's reset before calling pclose() on macOS */
errno = 0;
#endif
child_pid = pclose(fi);
child_pid = pclose(fi);
#ifdef DEBUG
printf("pclose returned %d\n", child_pid);
fflush(stdout);
printf("errno = %d\n", errno);
fflush(stdout);
printf("pclose returned %d\n", child_pid);
fflush(stdout);
printf("errno = %d\n", errno);
fflush(stdout);
#endif
if (child_pid < 0 || (errno != 0 && errno != EAGAIN))
{ /* FIXME: This right? */
return 0;
}
else if (child_pid == 0)
{
return 1;
}
do
{
w = waitpid(child_pid, &status, 0);
#ifdef DEBUG
if (w == -1)
{
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status))
{
printf("exited, status=%d\n", WEXITSTATUS(status));
}
else if (WIFSIGNALED(status))
{
printf("killed by signal %d\n", WTERMSIG(status));
}
else if (WIFSTOPPED(status))
{
printf("stopped by signal %d\n", WSTOPSIG(status));
}
else if (WIFCONTINUED(status))
{
printf("continued\n");
}
#endif
}
while (w != -1 && !WIFEXITED(status) && !WIFSIGNALED(status));
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) /* Not happy exit */
return 0;
if (child_pid < 0 || (errno != 0 && errno != EAGAIN))
{ /* FIXME: This right? */
return 0;
}
else if (child_pid == 0)
{
return 1;
}
do
{
w = waitpid(child_pid, &status, 0);
#ifdef DEBUG
if (w == -1)
{
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status))
{
printf("exited, status=%d\n", WEXITSTATUS(status));
}
else if (WIFSIGNALED(status))
{
printf("killed by signal %d\n", WTERMSIG(status));
}
else if (WIFSTOPPED(status))
{
printf("stopped by signal %d\n", WSTOPSIG(status));
}
else if (WIFCONTINUED(status))
{
printf("continued\n");
}
#endif
}
while (w != -1 && !WIFEXITED(status) && !WIFSIGNALED(status));
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) /* Not happy exit */
return 0;
return 1;
}
}
#endif

View file

@ -79,7 +79,8 @@
#ifdef PRINTMETHOD_PS
int do_ps_save(FILE * fi,
const char *restrict const fname, SDL_Surface * surf, const char *restrict pprsize, int is_pipe);
const char *restrict const fname, SDL_Surface * surf,
const char *restrict pprsize, int is_pipe);
#endif

View file

@ -39,7 +39,8 @@ int progress_bar_disabled, prog_bar_ctr;
*
* @param screen Screen surface
*/
void show_progress_bar_(SDL_Surface * screen, SDL_Texture * texture, SDL_Renderer * renderer)
void show_progress_bar_(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer)
{
SDL_Rect dest, src, r;
int x;
@ -51,34 +52,36 @@ void show_progress_bar_(SDL_Surface * screen, SDL_Texture * texture, SDL_Rendere
newtime = SDL_GetTicks();
if (newtime > oldtime + 15) /* trying not to eat some serious CPU time! */
{
for (x = 0; x < screen->w; x = x + 65)
{
for (x = 0; x < screen->w; x = x + 65)
{
src.x = 65 - (prog_bar_ctr % 65);
src.y = 0;
src.w = 65;
src.h = 24;
src.x = 65 - (prog_bar_ctr % 65);
src.y = 0;
src.w = 65;
src.h = 24;
dest.x = x;
dest.y = screen->h - 24;
dest.x = x;
dest.y = screen->h - 24;
SDL_BlitSurface(img_progress, &src, screen, &dest);
}
prog_bar_ctr++;
r.x = 0;
r.y = screen->h - 24;
r.w = screen->w;
r.h = 24;
SDL_UpdateTexture(texture, &r, screen->pixels + ((screen->h - 24) * screen->pitch), screen->pitch);
/* Docs says one should clear the renderer, even if this means a refresh of the whole thing. */
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
SDL_BlitSurface(img_progress, &src, screen, &dest);
}
prog_bar_ctr++;
r.x = 0;
r.y = screen->h - 24;
r.w = screen->w;
r.h = 24;
SDL_UpdateTexture(texture, &r,
screen->pixels + ((screen->h - 24) * screen->pitch),
screen->pitch);
/* Docs says one should clear the renderer, even if this means a refresh of the whole thing. */
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
oldtime = newtime;

View file

@ -36,6 +36,7 @@
extern SDL_Surface *img_progress;
extern int progress_bar_disabled, prog_bar_ctr;
void show_progress_bar_(SDL_Surface * screen, SDL_Texture *texture, SDL_Renderer *renderer);
void show_progress_bar_(SDL_Surface * screen, SDL_Texture * texture,
SDL_Renderer * renderer);
#endif

View file

@ -43,11 +43,11 @@ unsigned char linear_to_sRGB(float linear)
slot = linear * 4096.0 + 0.5;
if (slot > 4095)
{
if (linear > 0.5)
slot = 4095;
else
slot = 0;
}
{
if (linear > 0.5)
slot = 4095;
else
slot = 0;
}
return linear_to_sRGB_table[slot];
}

View file

@ -305,7 +305,8 @@ static const unsigned char linear_to_sRGB_table[4096] =
"\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd"
"\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
"\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
"\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
"\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
unsigned char linear_to_sRGB(float linear) FUNCTION;

View file

@ -118,8 +118,8 @@ const int shape_locked[NUM_SHAPES] = {
0, /* Hexagon */
0, /* Heptagon */
0, /* Heptagon */
1, /* Octagon */ /* FIXME: Consider unlocking? -bjk 2022.01.21 */
1, /* Octagon */ /* FIXME: Consider unlocking? -bjk 2022.01.21 */
1, /* Octagon *//* FIXME: Consider unlocking? -bjk 2022.01.21 */
1, /* Octagon *//* FIXME: Consider unlocking? -bjk 2022.01.21 */
0, /* Rhombus */
0, /* Rhombus */
0, /* 3 points star */
@ -334,8 +334,10 @@ const char *const shape_tips[NUM_SHAPES] = {
gettext_noop("A rectangle has four sides and four right angles."),
// Description of a circle
gettext_noop("A circle is a curve where all points have the same distance from the center."),
gettext_noop("A circle is a curve where all points have the same distance from the center."),
gettext_noop
("A circle is a curve where all points have the same distance from the center."),
gettext_noop
("A circle is a curve where all points have the same distance from the center."),
// Description of an ellipse
gettext_noop("An ellipse is a stretched circle."),
@ -362,8 +364,10 @@ const char *const shape_tips[NUM_SHAPES] = {
gettext_noop("An octagon has eight equal sides."),
// Description of a rhombus
gettext_noop("A rhombus has four equal sides, and opposite sides are parallel."),
gettext_noop("A rhombus has four equal sides, and opposite sides are parallel."),
gettext_noop
("A rhombus has four equal sides, and opposite sides are parallel."),
gettext_noop
("A rhombus has four equal sides, and opposite sides are parallel."),
gettext_noop("A star with 3 points."),
gettext_noop("A star with 3 points."),
@ -423,15 +427,18 @@ const char *const shapemode_img_fnames[NUM_SHAPEMODES] = {
/* String shown when Shapes tool is selected;
one version for normal ("complex shapes"),
the other for simplified mode ("simple shapes") */
enum {
enum
{
SHAPE_COMPLEXITY_NORMAL,
SHAPE_COMPLEXITY_SIMPLE,
NUM_SHAPE_COMPLEXITIES
};
const char *const shape_tool_tips[NUM_SHAPE_COMPLEXITIES] = {
gettext_noop("Pick a shape. Click to start drawing, drag, and let go when it is the size and shape you want. Move around to rotate it, and click again to draw it."),
gettext_noop("Pick a shape. Click to start drawing, drag, and let go when it is the size and shape you want.")
gettext_noop
("Pick a shape. Click to start drawing, drag, and let go when it is the size and shape you want. Move around to rotate it, and click again to draw it."),
gettext_noop
("Pick a shape. Click to start drawing, drag, and let go when it is the size and shape you want.")
};
/* Strings shown when switching between "from center"

View file

@ -29,17 +29,19 @@
#include <unistd.h>
#include <png.h>
int main(int argc, char * argv[]) {
int main(int argc, char *argv[])
{
int i, w, h, y;
FILE * fi;
FILE *fi;
png_structp png;
png_infop info;
png_byte ctype, depth;
png_bytep * rows;
png_bytep *rows;
/* Usage output */
if (argc == 1 || strcmp(argv[1], "--help") == 0) {
if (argc == 1 || strcmp(argv[1], "--help") == 0)
{
fprintf(stderr, "Usage: %s file.png [file.png ...]\n", argv[0]);
exit(1);
}
@ -53,30 +55,39 @@ int main(int argc, char * argv[]) {
/* Open each PNG image!... */
for (i = 1; i < argc; i++) {
printf("%5d ------------------------------------------------------------------\n", i);
for (i = 1; i < argc; i++)
{
printf
("%5d ------------------------------------------------------------------\n",
i);
printf("%s\n", argv[i]);
fflush(stdout);
/* Open the file */
fi = fopen(argv[i], "rb");
if (fi == NULL) {
if (fi == NULL)
{
printf("Cannot open\n");
} else {
}
else
{
/* Prepare PNG library stuff... */
png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png) {
if (!png)
{
fprintf(stderr, "Cannot png_create_read_struct()!\n");
exit(1);
}
info = png_create_info_struct(png);
if (!info) {
if (!info)
{
fprintf(stderr, "Cannot png_create_info_struct()!\n");
exit(1);
}
if (setjmp(png_jmpbuf(png))) {
if (setjmp(png_jmpbuf(png)))
{
fprintf(stderr, "Cannot setjmp(png_jmpbuf(png)))!\n");
exit(1);
}
@ -95,39 +106,43 @@ int main(int argc, char * argv[]) {
depth = png_get_bit_depth(png, info);
/* If 16-bit, strip to 8-bit */
if (depth == 16) {
if (depth == 16)
{
printf("test-png warning: 16-bit\n");
png_set_strip_16(png);
}
/* Switch palette to RGB */
if (ctype == PNG_COLOR_TYPE_PALETTE) {
if (ctype == PNG_COLOR_TYPE_PALETTE)
{
printf("test-png warning: paletted\n");
png_set_palette_to_rgb(png);
}
/* Expand low-depth greyscale up to 8-bit */
if (ctype == PNG_COLOR_TYPE_GRAY && depth < 8) {
if (ctype == PNG_COLOR_TYPE_GRAY && depth < 8)
{
printf("test-png warning: greyscale with only %d-bit depth\n", depth);
png_set_expand_gray_1_2_4_to_8(png);
}
/* Expand tRNS chunks into alpha */
if (png_get_valid(png, info, PNG_INFO_tRNS)) {
if (png_get_valid(png, info, PNG_INFO_tRNS))
{
printf("test-png warning: contains tRNS chunk\n");
png_set_tRNS_to_alpha(png);
}
/* Fill alpha channel if there is none */
if (ctype == PNG_COLOR_TYPE_RGB ||
ctype == PNG_COLOR_TYPE_GRAY ||
ctype == PNG_COLOR_TYPE_PALETTE) {
ctype == PNG_COLOR_TYPE_GRAY || ctype == PNG_COLOR_TYPE_PALETTE)
{
png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
}
/* Expand grey to color */
if (ctype == PNG_COLOR_TYPE_GRAY ||
ctype == PNG_COLOR_TYPE_GRAY_ALPHA) {
if (ctype == PNG_COLOR_TYPE_GRAY || ctype == PNG_COLOR_TYPE_GRAY_ALPHA)
{
printf("test-png warning: greyscale\n");
png_set_gray_to_rgb(png);
}
@ -137,15 +152,19 @@ int main(int argc, char * argv[]) {
/* Allocate space */
rows = (png_bytep *) malloc(sizeof(png_bytep) * h);
if (!rows) {
if (!rows)
{
fprintf(stderr, "Failed to malloc() space for image data rows!\n");
exit(1);
}
for (y = 0; y < h; y++) {
for (y = 0; y < h; y++)
{
rows[y] = (png_byte *) malloc(png_get_rowbytes(png, info));
if (!rows[y]) {
fprintf(stderr, "Failed to malloc() space for image data row #%d!\n", y);
if (!rows[y])
{
fprintf(stderr,
"Failed to malloc() space for image data row #%d!\n", y);
exit(1);
}
}
@ -170,5 +189,5 @@ int main(int argc, char * argv[]) {
fflush(stdout);
}
return(0);
return (0);
}

File diff suppressed because it is too large Load diff

View file

@ -54,10 +54,10 @@ DIR *opendir(const char *pSpec)
strcat(pathname, "/*");
pDir->hFind = FindFirstFile(pathname, &pDir->wfd);
if (pDir->hFind == INVALID_HANDLE_VALUE)
{
free(pDir);
pDir = NULL;
}
{
free(pDir);
pDir = NULL;
}
return pDir;
}
@ -83,16 +83,16 @@ struct dirent *readdir(struct DIR *pDir)
assert(pDir != NULL);
if (pDir->hFind)
{
strcpy(pDir->de.d_name, (const char *)pDir->wfd.cFileName);
if (!FindNextFile(pDir->hFind, &pDir->wfd))
{
strcpy(pDir->de.d_name, (const char *) pDir->wfd.cFileName);
if (!FindNextFile(pDir->hFind, &pDir->wfd))
{
FindClose(pDir->hFind);
pDir->hFind = NULL;
}
return &pDir->de;
{
FindClose(pDir->hFind);
pDir->hFind = NULL;
}
return &pDir->de;
}
return NULL;
}
@ -107,7 +107,9 @@ struct dirent *readdir(struct DIR *pDir)
*/
int alphasort(const void *a, const void *b)
{
return (strcmp((*(const struct dirent **)a)->d_name, (*(const struct dirent **)b)->d_name));
return (strcmp
((*(const struct dirent **) a)->d_name,
(*(const struct dirent **) b)->d_name));
}
/**
@ -124,11 +126,15 @@ static int addToList(int i, struct dirent ***namelist, struct dirent *entry)
int size;
struct dirent *block;
*namelist = (struct dirent **)realloc((void *)(*namelist), (size_t) ((i + 1) * sizeof(struct dirent *)));
*namelist =
(struct dirent **) realloc((void *) (*namelist),
(size_t) ((i + 1) * sizeof(struct dirent *)));
if (*namelist == NULL)
return -1;
size = (((char *)&entry->d_name) - ((char *)entry)) + strlen(entry->d_name) + 1;
block = (struct dirent *)malloc(size);
size =
(((char *) &entry->d_name) - ((char *) entry)) + strlen(entry->d_name) +
1;
block = (struct dirent *) malloc(size);
if (block == NULL)
return -1;
(*namelist)[i] = block;
@ -145,7 +151,8 @@ static int addToList(int i, struct dirent ***namelist, struct dirent *entry)
* @param compar Callback for sorting items in the list (via qsort()).
* @return Count of items, or -1 on error.
*/
int scandir(const char *dir, struct dirent ***namelist, selectCB select, comparCB compar)
int scandir(const char *dir, struct dirent ***namelist, selectCB select,
comparCB compar)
{
DIR *pDir;
int count;
@ -157,15 +164,16 @@ int scandir(const char *dir, struct dirent ***namelist, selectCB select, comparC
return -1;
count = 0;
while ((entry = readdir(pDir)) != NULL)
{
if (select == NULL || (select != NULL && select(entry)))
if ((count = addToList(count, namelist, entry)) < 0)
break;
}
{
if (select == NULL || (select != NULL && select(entry)))
if ((count = addToList(count, namelist, entry)) < 0)
break;
}
closedir(pDir);
if (count <= 0)
return -1;
if (compar != NULL)
qsort((void *)(*namelist), (size_t) count, sizeof(struct dirent *), compar);
qsort((void *) (*namelist), (size_t) count, sizeof(struct dirent *),
compar);
return count;
}

View file

@ -68,7 +68,8 @@ typedef struct
extern DIR *opendir(const char *pSpec);
extern void closedir(DIR * pDir);
extern struct dirent *readdir(struct DIR *pDir);
typedef int (*selectCB) (const struct dirent *);
typedef int (*comparCB) (const void *, const void *);
typedef int (*selectCB)(const struct dirent *);
typedef int (*comparCB)(const void *, const void *);
extern int alphasort(const void *a, const void *b);
extern int scandir(const char *dir, struct dirent ***namelist, selectCB select, comparCB compar);
extern int scandir(const char *dir, struct dirent ***namelist,
selectCB select, comparCB compar);

View file

@ -68,17 +68,18 @@ static SDL_Surface *make24bitDIB(SDL_Surface * surf)
surf24 = SDL_ConvertSurface(surf, &pixfmt, SDL_SWSURFACE);
surfDIB = SDL_CreateRGBSurface(SDL_SWSURFACE, surf24->w, surf24->h, 24,
pixfmt.Rmask, pixfmt.Gmask, pixfmt.Bmask, pixfmt.Amask);
pixfmt.Rmask, pixfmt.Gmask, pixfmt.Bmask,
pixfmt.Amask);
linesize = surf24->w * 3; // Flip top2bottom
dst = surfDIB->pixels;
src = ((Uint8 *) surf24->pixels) + ((surf24->h - 1) * surf24->pitch);
for (i = 0; i < surf24->h; ++i)
{
memcpy(dst, src, linesize);
src -= surf24->pitch;
dst += surfDIB->pitch;
}
{
memcpy(dst, src, linesize);
src -= surf24->pitch;
dst += surfDIB->pitch;
}
SDL_FreeSurface(surf24); // Free temp surface
@ -104,16 +105,17 @@ static int GetDefaultPrinterStrings(char *device, char *driver, char *output)
return 0;
if (((dev = strtok(buff, ",")) != NULL) &&
((drv = strtok(NULL, ", ")) != NULL) && ((out = strtok(NULL, ", ")) != NULL))
{
if (device)
strcpy(device, dev);
if (driver)
strcpy(driver, drv);
if (output)
strcpy(output, out);
return 1;
}
((drv = strtok(NULL, ", ")) != NULL)
&& ((out = strtok(NULL, ", ")) != NULL))
{
if (device)
strcpy(device, dev);
if (driver)
strcpy(driver, drv);
if (output)
strcpy(output, out);
return 1;
}
return 0;
}
@ -143,7 +145,8 @@ static HANDLE LoadCustomPrinterHDEVMODE(HWND hWnd, const char *filepath)
if (!OpenPrinter(device, &hPrinter, NULL))
goto err_exit;
sizeof_devmode = (int)DocumentProperties(hWnd, hPrinter, device, NULL, NULL, 0);
sizeof_devmode =
(int) DocumentProperties(hWnd, hPrinter, device, NULL, NULL, 0);
if (!sizeof_devmode)
goto err_exit;
@ -156,7 +159,8 @@ static HANDLE LoadCustomPrinterHDEVMODE(HWND hWnd, const char *filepath)
if (!devmode)
goto err_exit;
res = DocumentProperties(hWnd, hPrinter, device, devmode, NULL, DM_OUT_BUFFER);
res =
DocumentProperties(hWnd, hPrinter, device, devmode, NULL, DM_OUT_BUFFER);
if (res != IDOK)
goto err_exit;
@ -166,7 +170,9 @@ static HANDLE LoadCustomPrinterHDEVMODE(HWND hWnd, const char *filepath)
goto err_exit;
fclose(fp);
res = DocumentProperties(hWnd, hPrinter, device, devmode, devmode, DM_IN_BUFFER | DM_OUT_BUFFER);
res =
DocumentProperties(hWnd, hPrinter, device, devmode, devmode,
DM_IN_BUFFER | DM_OUT_BUFFER);
if (res != IDOK)
goto err_exit;
@ -189,25 +195,26 @@ err_exit:
/**
* FIXME
*/
static int SaveCustomPrinterHDEVMODE(HWND hWnd, const char *filepath, HANDLE hDevMode)
static int SaveCustomPrinterHDEVMODE(HWND hWnd, const char *filepath,
HANDLE hDevMode)
{
FILE *fp = NULL;
NOREF(hWnd);
if ((fp = fopen(filepath, "wb")) != NULL)
{
DEVMODE *devmode = (DEVMODE *) GlobalLock(hDevMode);
int block_size = devmode->dmSize + devmode->dmDriverExtra;
int block_written;
char devname[dmDeviceNameSize];
{
DEVMODE *devmode = (DEVMODE *) GlobalLock(hDevMode);
int block_size = devmode->dmSize + devmode->dmDriverExtra;
int block_written;
char devname[dmDeviceNameSize];
strcpy(devname, (const char *)devmode->dmDeviceName);
fwrite(devname, 1, sizeof(devname), fp);
block_written = fwrite(devmode, 1, block_size, fp);
GlobalUnlock(hDevMode);
fclose(fp);
return block_size == block_written;
}
strcpy(devname, (const char *) devmode->dmDeviceName);
fwrite(devname, 1, sizeof(devname), fp);
block_written = fwrite(devmode, 1, block_size, fp);
GlobalUnlock(hDevMode);
fclose(fp);
return block_size == block_written;
}
return 0;
}
@ -222,10 +229,10 @@ static int FileExists(const char *filepath)
FILE *fp;
if ((fp = fopen(filepath, "rb")) != NULL)
{
fclose(fp);
return 1;
}
{
fclose(fp);
return 1;
}
return 0;
}
@ -250,22 +257,23 @@ static int GetCustomPrinterDC(HWND hWnd, const char *printcfg, int show)
pd.hDevMode = LoadCustomPrinterHDEVMODE(hWnd, printcfg);
if (show || !FileExists(printcfg))
{
if (PrintDlg(&pd))
{
if (PrintDlg(&pd))
{
hDCprinter = pd.hDC;
SaveCustomPrinterHDEVMODE(hWnd, printcfg, pd.hDevMode);
GlobalFree(pd.hDevMode);
return 1;
}
hDCprinter = pd.hDC;
SaveCustomPrinterHDEVMODE(hWnd, printcfg, pd.hDevMode);
GlobalFree(pd.hDevMode);
return 0;
return 1;
}
GlobalFree(pd.hDevMode);
return 0;
}
{
DEVMODE *devmode = (DEVMODE *) GlobalLock(pd.hDevMode);
hDCprinter = CreateDC(NULL, (const char *)devmode->dmDeviceName, NULL, devmode);
hDCprinter =
CreateDC(NULL, (const char *) devmode->dmDeviceName, NULL, devmode);
GlobalUnlock(pd.hDevMode);
GlobalFree(pd.hDevMode);
}
@ -295,9 +303,9 @@ static int GetPrinterDC(HWND hWnd, const char *printcfg, int show)
hDCprinter = NULL;
if (printcfg)
{
return GetCustomPrinterDC(hWnd, printcfg, show);
}
{
return GetCustomPrinterDC(hWnd, printcfg, show);
}
hDCprinter = GetDefaultPrinterDC();
return 1;
}
@ -318,7 +326,8 @@ int IsPrinterAvailable(void)
/**
* FIXME
*/
const char *SurfacePrint(SDL_Window * window, SDL_Surface * surf, const char *printcfg, int showdialog)
const char *SurfacePrint(SDL_Window * window, SDL_Surface * surf,
const char *printcfg, int showdialog)
{
const char *res = NULL;
HWND hWnd;
@ -342,10 +351,10 @@ const char *SurfacePrint(SDL_Window * window, SDL_Surface * surf, const char *pr
hWnd = wminfo.info.win.window;
if (!GetPrinterDC(hWnd, printcfg, showdialog))
{
ShowWindow(hWnd, SW_SHOWNORMAL);
return NULL;
}
{
ShowWindow(hWnd, SW_SHOWNORMAL);
return NULL;
}
if (!hDCprinter)
return "win32_print: GetPrinterDC() failed.";
@ -360,26 +369,26 @@ const char *SurfacePrint(SDL_Window * window, SDL_Surface * surf, const char *pr
nError = StartDoc(hDCprinter, &di);
if (nError == SP_ERROR)
{
res = "win32_print: StartDoc() failed.";
goto error;
}
{
res = "win32_print: StartDoc() failed.";
goto error;
}
nError = StartPage(hDCprinter);
if (nError <= 0)
{
res = "win32_print: StartPage() failed.";
goto error;
}
{
res = "win32_print: StartPage() failed.";
goto error;
}
//////////////////////////////////////////////////////////////////////////////////////
surf24 = make24bitDIB(surf);
if (!surf24)
{
res = "win32_print: make24bitDIB() failed.";
goto error;
}
{
res = "win32_print: make24bitDIB() failed.";
goto error;
}
memset(&bmih, 0, sizeof(bmih));
bmih.biSize = sizeof(bmih);
@ -395,100 +404,100 @@ const char *SurfacePrint(SDL_Window * window, SDL_Surface * surf, const char *pr
sY = GetDeviceCaps(hDCprinter, LOGPIXELSY);
switch (scaling)
{
case STRETCH_TO_FIT:
{
case STRETCH_TO_FIT:
{
/* stretches x and y dimensions independently to fit the page */
/* doesn't preserve image aspect-ratio */
rcDst.top = 0;
rcDst.left = 0;
rcDst.bottom = pageHeight;
rcDst.right = pageWidth;
break;
}
case SCALE_TO_FIT:
{
/* maximises image size on the page */
/* preserves aspect-ratio, alignment is top and center */
int width = bmih.biWidth;
int height = bmih.biHeight;
if (width < pageWidth && height < pageHeight)
{
float dW = (float)pageWidth / width;
float dH = (float)pageHeight / height;
if (dW < dH)
{
width = pageWidth;
height = (int)((height * dW * (sY / sX)) + 0.5f);
}
else
{
width = (int)((width * dH * (sX / sY)) + 0.5f);
height = pageHeight;
}
}
if (width > pageWidth)
{
height = height * width / pageWidth;
width = pageWidth;
}
if (height > pageHeight)
{
width = width * height / pageHeight;
height = pageHeight;
}
rcDst.top = 0;
rcDst.left = (pageWidth - width) / 2;
rcDst.bottom = rcDst.top + height;
rcDst.right = rcDst.left + width;
break;
}
default:
res = "win32_print: invalid scaling option.";
goto error;
/* stretches x and y dimensions independently to fit the page */
/* doesn't preserve image aspect-ratio */
rcDst.top = 0;
rcDst.left = 0;
rcDst.bottom = pageHeight;
rcDst.right = pageWidth;
break;
}
case SCALE_TO_FIT:
{
/* maximises image size on the page */
/* preserves aspect-ratio, alignment is top and center */
int width = bmih.biWidth;
int height = bmih.biHeight;
if (width < pageWidth && height < pageHeight)
{
float dW = (float) pageWidth / width;
float dH = (float) pageHeight / height;
if (dW < dH)
{
width = pageWidth;
height = (int) ((height * dW * (sY / sX)) + 0.5f);
}
else
{
width = (int) ((width * dH * (sX / sY)) + 0.5f);
height = pageHeight;
}
}
if (width > pageWidth)
{
height = height * width / pageWidth;
width = pageWidth;
}
if (height > pageHeight)
{
width = width * height / pageHeight;
height = pageHeight;
}
rcDst.top = 0;
rcDst.left = (pageWidth - width) / 2;
rcDst.bottom = rcDst.top + height;
rcDst.right = rcDst.left + width;
break;
}
default:
res = "win32_print: invalid scaling option.";
goto error;
}
hDCCaps = GetDeviceCaps(hDCprinter, RASTERCAPS);
if (hDCCaps & RC_PALETTE)
{
res = "win32_print: printer context requires palette.";
goto error;
}
{
res = "win32_print: printer context requires palette.";
goto error;
}
if (hDCCaps & RC_STRETCHDIB)
{
SetStretchBltMode(hDCprinter, COLORONCOLOR);
{
SetStretchBltMode(hDCprinter, COLORONCOLOR);
bmi.bmiHeader = bmih;
nError = StretchDIBits(hDCprinter, rcDst.left, rcDst.top,
rcDst.right - rcDst.left,
rcDst.bottom - rcDst.top,
0, 0, bmih.biWidth, bmih.biHeight,
surf24->pixels, &bmi, DIB_RGB_COLORS, SRCCOPY);
if (nError == (int) GDI_ERROR)
{
res = "win32_print: StretchDIBits() failed.";
goto error;
}
}
else
bmi.bmiHeader = bmih;
nError = StretchDIBits(hDCprinter, rcDst.left, rcDst.top,
rcDst.right - rcDst.left,
rcDst.bottom - rcDst.top,
0, 0, bmih.biWidth, bmih.biHeight,
surf24->pixels, &bmi, DIB_RGB_COLORS, SRCCOPY);
if (nError == (int) GDI_ERROR)
{
res = "win32_print: StretchDIBits() not available.";
res = "win32_print: StretchDIBits() failed.";
goto error;
}
}
else
{
res = "win32_print: StretchDIBits() not available.";
goto error;
}
//////////////////////////////////////////////////////////////////////////////////////
nError = EndPage(hDCprinter);
if (nError <= 0)
{
res = "win32_print: EndPage() failed.";
goto error;
}
{
res = "win32_print: EndPage() failed.";
goto error;
}
EndDoc(hDCprinter);
@ -514,7 +523,8 @@ error:
/*
Read access to Windows Registry
*/
static HRESULT ReadRegistry(const char *key, const char *option, char *value, int size)
static HRESULT ReadRegistry(const char *key, const char *option, char *value,
int size)
{
LONG res;
HKEY hKey = NULL;
@ -563,17 +573,18 @@ char *GetDefaultSaveDir(const char *suffix)
{
char prefix[MAX_PATH];
char path[2 * MAX_PATH];
const char *key = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
const char *key =
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
const char *option = "AppData";
HRESULT hr = S_OK;
if (SUCCEEDED(hr = ReadRegistry(key, option, prefix, sizeof(prefix))))
{
remove_slash(prefix);
snprintf(path, sizeof(path), "%s/%s", prefix, suffix);
_mkdir(path);
return strdup(path);
}
{
remove_slash(prefix);
snprintf(path, sizeof(path), "%s/%s", prefix, suffix);
_mkdir(path);
return strdup(path);
}
return strdup("userdata");
}
@ -587,15 +598,16 @@ char *GetDefaultSaveDir(const char *suffix)
char *GetSystemFontDir(void)
{
char path[MAX_PATH];
const char *key = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
const char *key =
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
const char *option = "Fonts";
HRESULT hr = S_OK;
if (SUCCEEDED(hr = ReadRegistry(key, option, path, sizeof(path))))
{
remove_slash(path);
return strdup(path);
}
{
remove_slash(path);
return strdup(path);
}
return strdup("C:\\WINDOWS\\FONTS");
}
@ -609,15 +621,16 @@ char *GetUserImageDir(void);
char *GetUserImageDir(void)
{
char path[MAX_PATH];
const char *key = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
const char *key =
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
const char *option = "My Pictures";
HRESULT hr = S_OK;
if (SUCCEEDED(hr = ReadRegistry(key, option, path, sizeof(path))))
{
remove_slash(path);
return strdup(path);
}
{
remove_slash(path);
return strdup(path);
}
return strdup("C:\\Pictures");
}
@ -630,9 +643,9 @@ static char *GetUserTempDir(void)
const char *temp = getenv("TEMP");
if (!temp)
{
temp = "userdata";
}
{
temp = "userdata";
}
return strdup(temp);
}
@ -662,7 +675,8 @@ static int g_bWindowActive = 0;
/**
* FIXME
*/
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam,
LPARAM lParam);
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
int bEatKeystroke = 0;
@ -672,14 +686,15 @@ LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
return CallNextHookEx(g_hKeyboardHook, nCode, wParam, lParam);
switch (wParam)
{
case WM_KEYDOWN:
case WM_KEYUP:
{
case WM_KEYDOWN:
case WM_KEYUP:
{
bEatKeystroke = g_bWindowActive && ((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN));
break;
}
bEatKeystroke = g_bWindowActive && ((p->vkCode == VK_LWIN)
|| (p->vkCode == VK_RWIN));
break;
}
}
if (bEatKeystroke)
return 1;
@ -693,7 +708,9 @@ int InstallKeyboardHook(void)
{
if (g_hKeyboardHook)
return -1;
g_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0);
g_hKeyboardHook =
SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
GetModuleHandle(NULL), 0);
return g_hKeyboardHook ? 0 : -2;
}

View file

@ -15,7 +15,8 @@
#endif
/* if printcfg is NULL, uses the default printer */
extern const char *SurfacePrint(SDL_Window * window, SDL_Surface * surf, const char *printcfg, int showdialog);
extern const char *SurfacePrint(SDL_Window * window, SDL_Surface * surf,
const char *printcfg, int showdialog);
extern int IsPrinterAvailable(void);
/* additional windows functions requiring <windows.h> */

View file

@ -1,23 +1,26 @@
#include <windows.h>
#include <tchar.h>
int MoveFileToRecycleBin(const TCHAR *fullPathName);
int MoveFileToRecycleBin(const TCHAR * fullPathName);
int win32_trash(const char *path);
int MoveFileToRecycleBin(const TCHAR *fullPathName)
int MoveFileToRecycleBin(const TCHAR * fullPathName)
{
SHFILEOPSTRUCT fileOp;
const TCHAR *src = fullPathName;
TCHAR *dest;
fileOp.pFrom = dest = alloca(sizeof(*dest) * (_tcslen(fullPathName) + 2));
while((*dest++ = *src++) != _T('\0')) {}
while ((*dest++ = *src++) != _T('\0'))
{
}
*dest = _T('\0');
fileOp.hwnd = NULL;
fileOp.wFunc = FO_DELETE;
fileOp.pTo = NULL;
fileOp.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOF_ALLOWUNDO;
fileOp.fFlags =
FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOF_ALLOWUNDO;
return SHFileOperation(&fileOp);
}
@ -26,8 +29,10 @@ int win32_trash(const char *path)
char *p, *src;
src = p = strdup(path);
while(*p != '\0'){
if (*p == '/') *p = '\\';
while (*p != '\0')
{
if (*p == '/')
*p = '\\';
p++;
}
return MoveFileToRecycleBin(src);