mirror of
https://github.com/BernardoGiordano/Checkpoint
synced 2024-11-14 21:57:13 +00:00
Use Switch hardware acceleration (#162)
* preliminar changes * enhance hid logic * refactor switch UI
This commit is contained in:
parent
e3796b04f8
commit
dd69a50441
40 changed files with 3017 additions and 1790 deletions
|
@ -30,6 +30,8 @@
|
|||
#include <3ds.h>
|
||||
#include "ihid.hpp"
|
||||
|
||||
#define DELAY_TICKS 50000000
|
||||
|
||||
class Hid : public IHid
|
||||
{
|
||||
public:
|
||||
|
@ -50,10 +52,11 @@ public:
|
|||
|
||||
void update(size_t count)
|
||||
{
|
||||
IHid::update(count);
|
||||
if (mSleep)
|
||||
mCurrentTime = svcGetSystemTick();
|
||||
if ((mCurrentTime > mLastTime + DELAY_TICKS))
|
||||
{
|
||||
svcSleepThread(FASTSCROLL_WAIT);
|
||||
IHid::update(count);
|
||||
mLastTime = mCurrentTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define FASTSCROLL_WAIT 1.5e8
|
||||
|
||||
namespace DateTime
|
||||
{
|
||||
std::string timeStr(void);
|
||||
|
|
|
@ -96,7 +96,6 @@ void IHid::update(size_t count) {
|
|||
|
||||
u64 kHeld = held();
|
||||
u64 kDown = down();
|
||||
mSleep = false;
|
||||
|
||||
if (kDown & _KEY_ZL())
|
||||
{
|
||||
|
@ -127,7 +126,6 @@ void IHid::update(size_t count) {
|
|||
page_back();
|
||||
mIndex = maxEntries(count);
|
||||
}
|
||||
mSleep = true;
|
||||
}
|
||||
else if (kHeld & _KEY_RIGHT())
|
||||
{
|
||||
|
@ -140,7 +138,6 @@ void IHid::update(size_t count) {
|
|||
page_forward();
|
||||
mIndex = 0;
|
||||
}
|
||||
mSleep = true;
|
||||
}
|
||||
else if (kHeld & _KEY_UP())
|
||||
{
|
||||
|
@ -164,7 +161,6 @@ void IHid::update(size_t count) {
|
|||
{
|
||||
mIndex -= mColumns;
|
||||
}
|
||||
mSleep = true;
|
||||
}
|
||||
else if (kHeld & _KEY_DOWN())
|
||||
{
|
||||
|
@ -189,7 +185,6 @@ void IHid::update(size_t count) {
|
|||
mIndex = maxEntries(count);
|
||||
}
|
||||
}
|
||||
mSleep = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,7 +201,6 @@ void IHid::update(size_t count) {
|
|||
page_back();
|
||||
mIndex = maxEntries(count);
|
||||
}
|
||||
mSleep = true;
|
||||
}
|
||||
else if (kHeld & _KEY_DOWN())
|
||||
{
|
||||
|
@ -219,7 +213,6 @@ void IHid::update(size_t count) {
|
|||
page_forward();
|
||||
mIndex = 0;
|
||||
}
|
||||
mSleep = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,12 +28,11 @@
|
|||
#define IHID_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
typedef uint64_t u64;
|
||||
|
||||
#include <cmath>
|
||||
#include "common.hpp"
|
||||
|
||||
typedef uint64_t u64;
|
||||
|
||||
class IHid
|
||||
{
|
||||
public:
|
||||
|
@ -42,6 +41,8 @@ public:
|
|||
{
|
||||
reset();
|
||||
mMaxPages = 0;
|
||||
mCurrentTime = 0;
|
||||
mLastTime = 0;
|
||||
}
|
||||
|
||||
virtual ~IHid(void) { }
|
||||
|
@ -74,7 +75,8 @@ protected:
|
|||
size_t mMaxPages;
|
||||
size_t mMaxVisibleEntries;
|
||||
size_t mColumns;
|
||||
bool mSleep;
|
||||
u64 mCurrentTime;
|
||||
u64 mLastTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -98,6 +98,11 @@ def putSave():
|
|||
if not serial or not metadata or not attachment:
|
||||
return createAndLogResult("INVALID_PARAMETERS")
|
||||
# TODO: check consistenza valori in metadata
|
||||
if metadata.hash and len(metadata.hash) == 32 \
|
||||
and metadata.name \
|
||||
and metadata.serial and len(metadata.serial) == 64 \
|
||||
and metadata.type:
|
||||
print(metadata.name)
|
||||
# mockRequest = "{hash, private, product_code, serial, title_id, type, username}"
|
||||
result = createSave(metadata)
|
||||
# TODO: se result positivo, salva file su disco
|
||||
|
@ -217,6 +222,7 @@ def createDatabase(hostname, username, password):
|
|||
PRIMARY KEY (id))
|
||||
""")
|
||||
except mysql.connector.errors.ProgrammingError as e:
|
||||
trace(e)
|
||||
print("Couldn't setup database. Closing...")
|
||||
exit()
|
||||
finally:
|
||||
|
|
|
@ -52,12 +52,14 @@ ROMFS := romfs
|
|||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE
|
||||
|
||||
CFLAGS := -g -Wall -O3 -ffunction-sections \
|
||||
CFLAGS := -g -O3 -ffunction-sections \
|
||||
-Wall -Wno-write-strings \
|
||||
$(ARCH) $(DEFINES) \
|
||||
-DVERSION_MAJOR=${VERSION_MAJOR} \
|
||||
-DVERSION_MINOR=${VERSION_MINOR} \
|
||||
-DVERSION_MICRO=${VERSION_MICRO} \
|
||||
`freetype-config --cflags`
|
||||
`freetype-config --cflags` \
|
||||
`sdl2-config --cflags`
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__SWITCH__ -D_GNU_SOURCE=1
|
||||
|
||||
|
@ -66,7 +68,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17
|
|||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-no-as-needed,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := `freetype-config --libs`
|
||||
LIBS := -lSDL2_ttf -lSDL2_gfx -lSDL2_image -lpng -ljpeg `sdl2-config --libs` `freetype-config --libs` -lnx
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -33,16 +33,15 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
#include "clickable.hpp"
|
||||
#include "draw.hpp"
|
||||
#include "SDLHelper.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
extern u8* framebuf;
|
||||
extern u32 framebuf_width;
|
||||
#define DELAY_TICKS 3500000
|
||||
|
||||
class HbkbdButton : public Clickable
|
||||
{
|
||||
public:
|
||||
HbkbdButton(u32 x, u32 y, u16 w, u16 h, color_t colorBg, color_t colorText, const std::string& message, bool centered)
|
||||
HbkbdButton(u32 x, u32 y, u16 w, u16 h, SDL_Color colorBg, SDL_Color colorText, const std::string& message, bool centered)
|
||||
: Clickable(x, y, w, h, colorBg, colorText, message, centered)
|
||||
{
|
||||
mSelected = false;
|
||||
|
@ -59,12 +58,12 @@ public:
|
|||
// outline
|
||||
if (mSelected)
|
||||
{
|
||||
color_t color = MakeColor(138, 138, 138, 255);
|
||||
SDL_Color color = FC_MakeColor(138, 138, 138, 255);
|
||||
static const size_t size = 2;
|
||||
rectangled(mx - size, my - size, mw + 2*size, size, color); // top
|
||||
rectangled(mx - size, my, size, mh, color); // left
|
||||
rectangled(mx + mw, my, size, mh, color); // right
|
||||
rectangled(mx - size, my + mh, mw + 2*size, size, color); // bottom
|
||||
SDLH_DrawRect(mx - size, my - size, mw + 2*size, size, color); // top
|
||||
SDLH_DrawRect(mx - size, my, size, mh, color); // left
|
||||
SDLH_DrawRect(mx + mw, my, size, mh, color); // right
|
||||
SDLH_DrawRect(mx - size, my + mh, mw + 2*size, size, color); // bottom
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,6 +109,9 @@ private:
|
|||
const u32 marginlr = 54;
|
||||
const u32 starty = 720 - 356 + margintb;
|
||||
|
||||
u64 currentTime = 0;
|
||||
u64 lastTime = 0;
|
||||
|
||||
const std::string letters = "1234567890@qwertyuiop+asdfghjkl_:zxcvbnm,.-/";
|
||||
std::vector<HbkbdButton*> buttons;
|
||||
size_t prevSelectedButtonIndex;
|
||||
|
|
28
switch/include/SDLHelper.hpp
Normal file
28
switch/include/SDLHelper.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef SDLHELPER_HPP
|
||||
#define SDLHELPER_HPP
|
||||
|
||||
#include <switch.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL2_gfxPrimitives.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "SDL_FontCache.h"
|
||||
|
||||
bool SDLH_Init(void);
|
||||
void SDLH_Exit(void);
|
||||
|
||||
void SDLH_ClearScreen(SDL_Color color);
|
||||
void SDLH_DrawRect(int x, int y, int w, int h, SDL_Color color);
|
||||
void SDLH_DrawCircle(int x, int y, int r, SDL_Color color);
|
||||
void SDLH_DrawText(int size, int x, int y, SDL_Color color, const char *text);
|
||||
void SDLH_LoadImage(SDL_Texture **texture, char *path);
|
||||
void SDLH_LoadImage(SDL_Texture** texture, u8* buff, size_t size);
|
||||
void SDLH_DrawImage(SDL_Texture *texture, int x, int y);
|
||||
void SDLH_DrawImageScale(SDL_Texture *texture, int x, int y, int w, int h);
|
||||
void SDLH_DrawIcon(std::string icon, int x, int y);
|
||||
void SDLH_GetTextDimensions(int size, const char* text, u32* w, u32* h);
|
||||
void SDLH_DrawTextBox(int size, int x, int y, SDL_Color color, int max, const char* text);
|
||||
void SDLH_Render(void);
|
||||
|
||||
#endif
|
268
switch/include/SDL_FontCache.h
Normal file
268
switch/include/SDL_FontCache.h
Normal file
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
SDL_FontCache v0.9.0: A font cache for SDL and SDL_ttf
|
||||
by Jonathan Dearborn
|
||||
Dedicated to the memory of Florian Hufsky
|
||||
|
||||
License:
|
||||
The short:
|
||||
Use it however you'd like, but keep the copyright and license notice
|
||||
whenever these files or parts of them are distributed in uncompiled form.
|
||||
|
||||
The long:
|
||||
Copyright (c) 2016 Jonathan Dearborn
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _SDL_FONTCACHE_H__
|
||||
#define _SDL_FONTCACHE_H__
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_ttf.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Let's pretend this exists...
|
||||
#define TTF_STYLE_OUTLINE 16
|
||||
|
||||
#define FC_Rect SDL_Rect
|
||||
#define FC_Target SDL_Renderer
|
||||
#define FC_Image SDL_Texture
|
||||
#define FC_Log SDL_Log
|
||||
|
||||
// SDL_FontCache types
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FC_ALIGN_LEFT,
|
||||
FC_ALIGN_CENTER,
|
||||
FC_ALIGN_RIGHT
|
||||
} FC_AlignEnum;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FC_FILTER_NEAREST,
|
||||
FC_FILTER_LINEAR
|
||||
} FC_FilterEnum;
|
||||
|
||||
typedef struct FC_Scale
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
|
||||
} FC_Scale;
|
||||
|
||||
typedef struct FC_Effect
|
||||
{
|
||||
FC_AlignEnum alignment;
|
||||
FC_Scale scale;
|
||||
SDL_Color color;
|
||||
|
||||
} FC_Effect;
|
||||
|
||||
// Opaque type
|
||||
typedef struct FC_Font FC_Font;
|
||||
|
||||
typedef struct FC_GlyphData
|
||||
{
|
||||
SDL_Rect rect;
|
||||
int cache_level;
|
||||
|
||||
} FC_GlyphData;
|
||||
|
||||
// Object creation
|
||||
|
||||
FC_Rect FC_MakeRect(float x, float y, float w, float h);
|
||||
|
||||
FC_Scale FC_MakeScale(float x, float y);
|
||||
|
||||
SDL_Color FC_MakeColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
||||
|
||||
FC_Effect FC_MakeEffect(FC_AlignEnum alignment, FC_Scale scale, SDL_Color color);
|
||||
|
||||
FC_GlyphData FC_MakeGlyphData(int cache_level, Sint16 x, Sint16 y, Uint16 w, Uint16 h);
|
||||
|
||||
// Font object
|
||||
|
||||
FC_Font* FC_CreateFont(void);
|
||||
|
||||
Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, TTF_Font* ext, SDL_Color color);
|
||||
|
||||
Uint8 FC_LoadFont_RW(FC_Font* font, SDL_Renderer* renderer, SDL_RWops* file_rwops_ttf, SDL_RWops* file_rwops_ext, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style);
|
||||
|
||||
void FC_ClearFont(FC_Font* font);
|
||||
|
||||
void FC_FreeFont(FC_Font* font);
|
||||
|
||||
// Built-in loading strings
|
||||
|
||||
char* FC_GetStringASCII(void);
|
||||
|
||||
|
||||
// UTF-8 to SDL_FontCache codepoint conversion
|
||||
|
||||
/*!
|
||||
Returns the Uint32 codepoint (not UTF-32) parsed from the given UTF-8 string.
|
||||
\param c A pointer to a string of proper UTF-8 character values.
|
||||
\param advance_pointer If true, the source pointer will be incremented to skip the extra bytes from multibyte codepoints.
|
||||
*/
|
||||
Uint32 FC_GetCodepointFromUTF8(const char** c, Uint8 advance_pointer);
|
||||
|
||||
/*!
|
||||
Parses the given codepoint and stores the UTF-8 bytes in 'result'. The result is NULL terminated.
|
||||
\param result A memory buffer for the UTF-8 values. Must be at least 5 bytes long.
|
||||
\param codepoint The Uint32 codepoint to parse (not UTF-32).
|
||||
*/
|
||||
void FC_GetUTF8FromCodepoint(char* result, Uint32 codepoint);
|
||||
|
||||
|
||||
// UTF-8 string operations
|
||||
|
||||
/*! Allocates a new string of 'size' bytes that is already NULL-terminated. The NULL byte counts toward the size limit, as usual. Returns NULL if size is 0. */
|
||||
char* U8_alloc(unsigned int size);
|
||||
|
||||
/*! Deallocates the given string. */
|
||||
void U8_free(char* string);
|
||||
|
||||
/*! Allocates a copy of the given string. */
|
||||
char* U8_strdup(const char* string);
|
||||
|
||||
/*! Returns the number of UTF-8 characters in the given string. */
|
||||
int U8_strlen(const char* string);
|
||||
|
||||
/*! Returns the number of bytes in the UTF-8 multibyte character pointed at by 'character'. */
|
||||
int U8_charsize(const char* character);
|
||||
|
||||
/*! Copies the source multibyte character into the given buffer without overrunning it. Returns 0 on failure. */
|
||||
int U8_charcpy(char* buffer, const char* source, int buffer_size);
|
||||
|
||||
/*! Returns a pointer to the next UTF-8 character. */
|
||||
const char* U8_next(const char* string);
|
||||
|
||||
/*! Inserts a UTF-8 string into 'string' at the given position. Use a position of -1 to append. Returns 0 when unable to insert the string. */
|
||||
int U8_strinsert(char* string, int position, const char* source, int max_bytes);
|
||||
|
||||
/*! Erases the UTF-8 character at the given position, moving the subsequent characters down. */
|
||||
void U8_strdel(char* string, int position);
|
||||
|
||||
|
||||
// Internal settings
|
||||
|
||||
/*! Sets the string from which to load the initial glyphs. Use this if you need upfront loading for any reason (such as lack of render-target support). */
|
||||
void FC_SetLoadingString(FC_Font* font, const char* string);
|
||||
|
||||
/*! Returns the size of the internal buffer which is used for unpacking variadic text data. This buffer is shared by all FC_Fonts. */
|
||||
unsigned int FC_GetBufferSize(void);
|
||||
|
||||
/*! Changes the size of the internal buffer which is used for unpacking variadic text data. This buffer is shared by all FC_Fonts. */
|
||||
void FC_SetBufferSize(unsigned int size);
|
||||
|
||||
void FC_SetRenderCallback(FC_Rect (*callback)(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale));
|
||||
|
||||
FC_Rect FC_DefaultRenderCallback(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale);
|
||||
|
||||
|
||||
// Custom caching
|
||||
|
||||
/*! Returns the number of cache levels that are active. */
|
||||
int FC_GetNumCacheLevels(FC_Font* font);
|
||||
|
||||
/*! Returns the cache source texture at the given cache level. */
|
||||
FC_Image* FC_GetGlyphCacheLevel(FC_Font* font, int cache_level);
|
||||
|
||||
// TODO: Specify ownership of the texture (should be shareable)
|
||||
/*! Sets a cache source texture for rendering. New cache levels must be sequential. */
|
||||
Uint8 FC_SetGlyphCacheLevel(FC_Font* font, int cache_level, FC_Image* cache_texture);
|
||||
|
||||
/*! Copies the given surface to the given cache level as a texture. New cache levels must be sequential. */
|
||||
Uint8 FC_UploadGlyphCache(FC_Font* font, int cache_level, SDL_Surface* data_surface);
|
||||
|
||||
|
||||
/*! Returns the number of codepoints that are stored in the font's glyph data map. */
|
||||
unsigned int FC_GetNumCodepoints(FC_Font* font);
|
||||
|
||||
/*! Copies the stored codepoints into the given array. */
|
||||
void FC_GetCodepoints(FC_Font* font, Uint32* result);
|
||||
|
||||
/*! Stores the glyph data for the given codepoint in 'result'. Returns 0 if the codepoint was not found in the cache. */
|
||||
Uint8 FC_GetGlyphData(FC_Font* font, FC_GlyphData* result, Uint32 codepoint);
|
||||
|
||||
/*! Sets the glyph data for the given codepoint. Duplicates are not checked. Returns a pointer to the stored data. */
|
||||
FC_GlyphData* FC_SetGlyphData(FC_Font* font, Uint32 codepoint, FC_GlyphData glyph_data);
|
||||
|
||||
|
||||
// Rendering
|
||||
|
||||
FC_Rect FC_Draw(FC_Font* font, FC_Target* dest, float x, float y, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawAlign(FC_Font* font, FC_Target* dest, float x, float y, FC_AlignEnum align, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawScale(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawColor(FC_Font* font, FC_Target* dest, float x, float y, SDL_Color color, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawEffect(FC_Font* font, FC_Target* dest, float x, float y, FC_Effect effect, const char* formatted_text, ...);
|
||||
|
||||
FC_Rect FC_DrawBox(FC_Font* font, FC_Target* dest, FC_Rect box, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawBoxAlign(FC_Font* font, FC_Target* dest, FC_Rect box, FC_AlignEnum align, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawBoxScale(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Scale scale, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawBoxColor(FC_Font* font, FC_Target* dest, FC_Rect box, SDL_Color color, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawBoxEffect(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Effect effect, const char* formatted_text, ...);
|
||||
|
||||
FC_Rect FC_DrawColumn(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawColumnAlign(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_AlignEnum align, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawColumnScale(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Scale scale, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawColumnColor(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, SDL_Color color, const char* formatted_text, ...);
|
||||
FC_Rect FC_DrawColumnEffect(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Effect effect, const char* formatted_text, ...);
|
||||
|
||||
// Getters
|
||||
|
||||
FC_FilterEnum FC_GetFilterMode(FC_Font* font);
|
||||
Uint16 FC_GetLineHeight(FC_Font* font);
|
||||
Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...);
|
||||
Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...);
|
||||
|
||||
// Returns a 1-pixel wide box in front of the character in the given position (index)
|
||||
FC_Rect FC_GetCharacterOffset(FC_Font* font, Uint16 position_index, int column_width, const char* formatted_text, ...);
|
||||
Uint16 FC_GetColumnHeight(FC_Font* font, Uint16 width, const char* formatted_text, ...);
|
||||
|
||||
int FC_GetAscent(FC_Font* font, const char* formatted_text, ...);
|
||||
int FC_GetDescent(FC_Font* font, const char* formatted_text, ...);
|
||||
int FC_GetBaseline(FC_Font* font);
|
||||
int FC_GetSpacing(FC_Font* font);
|
||||
int FC_GetLineSpacing(FC_Font* font);
|
||||
Uint16 FC_GetMaxWidth(FC_Font* font);
|
||||
SDL_Color FC_GetDefaultColor(FC_Font* font);
|
||||
|
||||
Uint8 FC_InRect(float x, float y, FC_Rect input_rect);
|
||||
// Given an offset (x,y) from the text draw position (the upper-left corner), returns the character position (UTF-8 index)
|
||||
Uint16 FC_GetPositionFromOffset(FC_Font* font, float x, float y, int column_width, FC_AlignEnum align, const char* formatted_text, ...);
|
||||
|
||||
// Setters
|
||||
|
||||
void FC_SetFilterMode(FC_Font* font, FC_FilterEnum filter);
|
||||
void FC_SetSpacing(FC_Font* font, int LetterSpacing);
|
||||
void FC_SetLineSpacing(FC_Font* font, int LineSpacing);
|
||||
void FC_SetDefaultColor(FC_Font* font, SDL_Color color);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -32,19 +32,15 @@
|
|||
#include <switch.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "draw.hpp"
|
||||
#include "SDLHelper.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "nanojpeg.h"
|
||||
}
|
||||
|
||||
#define USER_ICON_SIZE 80
|
||||
|
||||
struct User {
|
||||
u128 id;
|
||||
std::string name;
|
||||
u8* icon;
|
||||
u128 id;
|
||||
std::string name;
|
||||
SDL_Texture* icon;
|
||||
};
|
||||
|
||||
namespace Account
|
||||
|
@ -53,9 +49,9 @@ namespace Account
|
|||
void exit(void);
|
||||
|
||||
std::vector
|
||||
<u128> ids(void);
|
||||
u8* icon(u128 id);
|
||||
std::string username(u128 id);
|
||||
<u128> ids(void);
|
||||
SDL_Texture* icon(u128 id);
|
||||
std::string username(u128 id);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -30,12 +30,12 @@
|
|||
#include <string>
|
||||
#include <switch.h>
|
||||
#include "iclickable.hpp"
|
||||
#include "draw.hpp"
|
||||
#include "SDLHelper.hpp"
|
||||
|
||||
class Clickable : public IClickable<color_t>
|
||||
class Clickable : public IClickable<SDL_Color>
|
||||
{
|
||||
public:
|
||||
Clickable(int x, int y, u16 w, u16 h, color_t colorBg, color_t colorText, const std::string& message, bool centered)
|
||||
Clickable(int x, int y, u16 w, u16 h, SDL_Color colorBg, SDL_Color colorText, const std::string& message, bool centered)
|
||||
: IClickable(x, y, w, h, colorBg, colorText, message, centered) { }
|
||||
virtual ~Clickable(void) { };
|
||||
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
#ifndef COLORS_HPP
|
||||
#define COLORS_HPP
|
||||
|
||||
#include "draw.hpp"
|
||||
#include "SDLHelper.hpp"
|
||||
|
||||
#define COLOR_WHITE MakeColor(255, 255, 255, 255)
|
||||
#define COLOR_BLACK MakeColor(0, 0, 0, 255)
|
||||
#define COLOR_BLUE MakeColor(29, 50, 243, 255)
|
||||
#define COLOR_GREEN MakeColor(0, 254, 197, 255)
|
||||
#define COLOR_RED MakeColor(255, 81, 48, 255)
|
||||
#define COLOR_GOLD MakeColor(255, 215, 0, 255)
|
||||
#define COLOR_WHITE FC_MakeColor(255, 255, 255, 255)
|
||||
#define COLOR_BLACK FC_MakeColor(0, 0, 0, 255)
|
||||
#define COLOR_BLUE FC_MakeColor(29, 50, 243, 255)
|
||||
#define COLOR_GREEN FC_MakeColor(0, 254, 197, 255)
|
||||
#define COLOR_RED FC_MakeColor(255, 81, 48, 255)
|
||||
#define COLOR_GOLD FC_MakeColor(255, 215, 0, 255)
|
||||
|
||||
#define COLOR_GREY_DARKER MakeColor(70, 70, 70, 255)
|
||||
#define COLOR_GREY_DARK MakeColor(79, 79, 79, 255)
|
||||
#define COLOR_GREY_MEDIUM MakeColor(94, 94, 94, 255)
|
||||
#define COLOR_GREY_LIGHT MakeColor(138, 138, 138, 255)
|
||||
#define COLOR_GREY_BG FC_MakeColor(51, 51, 51, 255)
|
||||
#define COLOR_GREY_DARKER FC_MakeColor(70, 70, 70, 255)
|
||||
#define COLOR_GREY_DARK FC_MakeColor(79, 79, 79, 255)
|
||||
#define COLOR_GREY_MEDIUM FC_MakeColor(94, 94, 94, 255)
|
||||
#define COLOR_GREY_LIGHT FC_MakeColor(138, 138, 138, 255)
|
||||
|
||||
#endif
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright 2017-2018 nx-hbmenu Authors
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
* with or without fee is hereby granted, provided that the above copyright notice
|
||||
* and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
|
||||
* OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
* OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DRAW_HPP
|
||||
#define DRAW_HPP
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include <switch.h>
|
||||
#include "types.hpp"
|
||||
|
||||
#define FONT_FACES_MAX PlSharedFontType_Total
|
||||
|
||||
extern u8* framebuf;
|
||||
extern u32 framebuf_width;
|
||||
|
||||
// the following code is from nx-hbmenu
|
||||
// https://github.com/switchbrew/nx-hbmenu/blob/master/common/common.h#L63
|
||||
|
||||
static inline u8 BlendColor(u32 src, u32 dst, u8 alpha)
|
||||
{
|
||||
u8 one_minus_alpha = (u8)255 - alpha;
|
||||
return (dst*alpha + src*one_minus_alpha)/(u8)255;
|
||||
}
|
||||
|
||||
static inline color_t MakeColor(u8 r, u8 g, u8 b, u8 a)
|
||||
{
|
||||
color_t clr;
|
||||
clr.r = r;
|
||||
clr.g = g;
|
||||
clr.b = b;
|
||||
clr.a = a;
|
||||
return clr;
|
||||
}
|
||||
|
||||
static inline void DrawPixel(u32 x, u32 y, color_t clr)
|
||||
{
|
||||
if (x >= 1280 || y >= 720)
|
||||
return;
|
||||
u32 off = (y * framebuf_width + x)*4;
|
||||
framebuf[off] = BlendColor(framebuf[off], clr.r, clr.a); off++;
|
||||
framebuf[off] = BlendColor(framebuf[off], clr.g, clr.a); off++;
|
||||
framebuf[off] = BlendColor(framebuf[off], clr.b, clr.a); off++;
|
||||
framebuf[off] = 0xff;
|
||||
}
|
||||
|
||||
static inline void Draw4PixelsRaw(u32 x, u32 y, color_t clr)
|
||||
{
|
||||
if (x >= 1280 || y >= 720 || x > 1280-4)
|
||||
return;
|
||||
|
||||
u32 color = clr.r | (clr.g<<8) | (clr.b<<16) | (0xff<<24);
|
||||
u128 val = color | ((u128)color<<32) | ((u128)color<<64) | ((u128)color<<96);
|
||||
u32 off = (y * framebuf_width + x)*4;
|
||||
*((u128*)&framebuf[off]) = val;
|
||||
}
|
||||
|
||||
Result textInit(void);
|
||||
bool fontInitialize(void);
|
||||
void fontExit();
|
||||
|
||||
void rectangle(u32 x, u32 y, u32 w, u32 h, color_t color);
|
||||
void rectangled(u32 x, u32 y, u32 w, u32 h, color_t color);
|
||||
void DrawPixel(u32 x, u32 y, color_t clr);
|
||||
void DrawText(u32 font, u32 x, u32 y, color_t clr, const char* text);
|
||||
void DrawTextTruncate(u32 font, u32 x, u32 y, color_t clr, const char* text, u32 max_width, const char* end_text);
|
||||
void GetTextDimensions(u32 font, const char* text, u32* width_out, u32* height_out);
|
||||
void DrawImage(int x, int y, int width, int height, const u8 *image, ImageMode mode);
|
||||
void downscaleRGBImg(const u8 *image, u8* out, int srcWidth, int srcHeight, int destWidth, int destHeight);
|
||||
|
||||
#endif
|
|
@ -33,7 +33,7 @@
|
|||
#include "account.hpp"
|
||||
#include "colors.hpp"
|
||||
#include "clickable.hpp"
|
||||
#include "draw.hpp"
|
||||
#include "SDLHelper.hpp"
|
||||
#include "info.hpp"
|
||||
#include "hid.hpp"
|
||||
#include "main.hpp"
|
||||
|
@ -43,10 +43,6 @@
|
|||
#include "types.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
#include "checkbox_bin.h"
|
||||
#include "flag_bin.h"
|
||||
#include "star_bin.h"
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
void init(void);
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include <switch.h>
|
||||
#include "ihid.hpp"
|
||||
|
||||
#define DELAY_TICKS 3500000
|
||||
|
||||
class Hid : public IHid
|
||||
{
|
||||
public:
|
||||
|
@ -50,10 +52,11 @@ public:
|
|||
|
||||
void update(size_t count)
|
||||
{
|
||||
IHid::update(count);
|
||||
if (mSleep)
|
||||
mCurrentTime = armGetSystemTick();
|
||||
if ((mCurrentTime > mLastTime + DELAY_TICKS))
|
||||
{
|
||||
svcSleepThread(FASTSCROLL_WAIT);
|
||||
IHid::update(count);
|
||||
mLastTime = mCurrentTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include <switch.h>
|
||||
#include <string>
|
||||
#include "draw.hpp"
|
||||
#include "SDLHelper.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -31,13 +31,13 @@
|
|||
#include <string>
|
||||
#include <switch.h>
|
||||
#include <vector>
|
||||
#include "draw.hpp"
|
||||
#include "SDLHelper.hpp"
|
||||
#include "colors.hpp"
|
||||
|
||||
class MessageBox
|
||||
{
|
||||
public:
|
||||
MessageBox(color_t colorbg, color_t colormessage);
|
||||
MessageBox(SDL_Color colorbg, SDL_Color colormessage);
|
||||
~MessageBox() { };
|
||||
|
||||
void push_message(const std::string& str);
|
||||
|
@ -47,8 +47,8 @@ public:
|
|||
private:
|
||||
std::vector
|
||||
<std::string> mList;
|
||||
color_t mColorBg;
|
||||
color_t mColorText;
|
||||
SDL_Color mColorBg;
|
||||
SDL_Color mColorText;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,66 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// HEADER SECTION //
|
||||
// copy and paste this into nanojpeg.h if you want //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _NANOJPEG_H
|
||||
#define _NANOJPEG_H
|
||||
|
||||
// nj_result_t: Result codes for njDecode().
|
||||
typedef enum _nj_result {
|
||||
NJ_OK = 0, // no error, decoding successful
|
||||
NJ_NO_JPEG, // not a JPEG file
|
||||
NJ_UNSUPPORTED, // unsupported format
|
||||
NJ_OUT_OF_MEM, // out of memory
|
||||
NJ_INTERNAL_ERR, // internal error
|
||||
NJ_SYNTAX_ERROR, // syntax error
|
||||
__NJ_FINISHED, // used internally, will never be reported
|
||||
} nj_result_t;
|
||||
|
||||
// njInit: Initialize NanoJPEG.
|
||||
// For safety reasons, this should be called at least one time before using
|
||||
// using any of the other NanoJPEG functions.
|
||||
void njInit(void);
|
||||
|
||||
// njDecode: Decode a JPEG image.
|
||||
// Decodes a memory dump of a JPEG file into internal buffers.
|
||||
// Parameters:
|
||||
// jpeg = The pointer to the memory dump.
|
||||
// size = The size of the JPEG file.
|
||||
// Return value: The error code in case of failure, or NJ_OK (zero) on success.
|
||||
nj_result_t njDecode(const void* jpeg, const int size);
|
||||
|
||||
// njGetWidth: Return the width (in pixels) of the most recently decoded
|
||||
// image. If njDecode() failed, the result of njGetWidth() is undefined.
|
||||
int njGetWidth(void);
|
||||
|
||||
// njGetHeight: Return the height (in pixels) of the most recently decoded
|
||||
// image. If njDecode() failed, the result of njGetHeight() is undefined.
|
||||
int njGetHeight(void);
|
||||
|
||||
// njIsColor: Return 1 if the most recently decoded image is a color image
|
||||
// (RGB) or 0 if it is a grayscale image. If njDecode() failed, the result
|
||||
// of njGetWidth() is undefined.
|
||||
int njIsColor(void);
|
||||
|
||||
// njGetImage: Returns the decoded image data.
|
||||
// Returns a pointer to the most recently image. The memory layout it byte-
|
||||
// oriented, top-down, without any padding between lines. Pixels of color
|
||||
// images will be stored as three consecutive bytes for the red, green and
|
||||
// blue channels. This data format is thus compatible with the PGM or PPM
|
||||
// file formats and the OpenGL texture formats GL_LUMINANCE8 or GL_RGB8.
|
||||
// If njDecode() failed, the result of njGetImage() is undefined.
|
||||
unsigned char* njGetImage(void);
|
||||
|
||||
// njGetImageSize: Returns the size (in bytes) of the image data returned
|
||||
// by njGetImage(). If njDecode() failed, the result of njGetImageSize() is
|
||||
// undefined.
|
||||
int njGetImageSize(void);
|
||||
|
||||
// njDone: Uninitialize NanoJPEG.
|
||||
// Resets NanoJPEG's internal state and frees all memory that has been
|
||||
// allocated at run-time by NanoJPEG. It is still possible to decode another
|
||||
// image after a njDone() call.
|
||||
void njDone(void);
|
||||
|
||||
#endif//_NANOJPEG_H
|
|
@ -32,10 +32,10 @@
|
|||
#include "iscrollable.hpp"
|
||||
#include "clickable.hpp"
|
||||
#include "colors.hpp"
|
||||
#include "draw.hpp"
|
||||
#include "SDLHelper.hpp"
|
||||
#include "hid.hpp"
|
||||
|
||||
class Scrollable : public IScrollable<color_t>
|
||||
class Scrollable : public IScrollable<SDL_Color>
|
||||
{
|
||||
public:
|
||||
Scrollable(u32 x, u32 y, u32 w, u32 h, size_t visibleEntries)
|
||||
|
@ -51,7 +51,7 @@ public:
|
|||
|
||||
void draw(void) override;
|
||||
void setIndex(size_t i);
|
||||
void push_back(color_t color, color_t colorMessage, const std::string& message) override;
|
||||
void push_back(SDL_Color color, SDL_Color colorMessage, const std::string& message) override;
|
||||
void resetIndex(void) override;
|
||||
void updateSelection(void) override;
|
||||
|
||||
|
|
|
@ -34,14 +34,11 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include "SDLHelper.hpp"
|
||||
#include "configuration.hpp"
|
||||
#include "filesystem.hpp"
|
||||
#include "io.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "nanojpeg.h"
|
||||
}
|
||||
|
||||
class Title
|
||||
{
|
||||
public:
|
||||
|
@ -49,8 +46,7 @@ public:
|
|||
~Title(void) { };
|
||||
|
||||
std::string author(void);
|
||||
u8* smallIcon(void);
|
||||
u8* icon(void);
|
||||
SDL_Texture* icon(void);
|
||||
u64 id(void);
|
||||
std::string name(void);
|
||||
std::string path(void);
|
||||
|
@ -82,8 +78,8 @@ void getTitle(Title &dst, u128 uid, size_t i);
|
|||
size_t getTitleCount(u128 uid);
|
||||
void loadTitles(void);
|
||||
void refreshDirectories(u64 id);
|
||||
u8* smallIcon(u128 id, size_t i);
|
||||
bool favorite(u128 uid, int i);
|
||||
void freeIcons(void);
|
||||
SDL_Texture* smallIcon(u128 uid, size_t i);
|
||||
|
||||
#endif
|
|
@ -6,23 +6,4 @@ typedef enum {
|
|||
CELLS
|
||||
} entryType_t;
|
||||
|
||||
typedef union {
|
||||
u32 abgr;
|
||||
struct {
|
||||
u8 r,g,b,a;
|
||||
};
|
||||
} color_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IMAGE_MODE_RGB24,
|
||||
IMAGE_MODE_RGBA32
|
||||
} ImageMode;
|
||||
|
||||
typedef struct {
|
||||
u8 width, height;
|
||||
int8_t posX, posY, advance, pitch;
|
||||
const u8* data;
|
||||
} glyph_t;
|
||||
|
||||
#endif
|
BIN
switch/romfs/checkbox.png
Normal file
BIN
switch/romfs/checkbox.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 646 B |
BIN
switch/romfs/flag.png
Normal file
BIN
switch/romfs/flag.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 695 B |
BIN
switch/romfs/star.png
Normal file
BIN
switch/romfs/star.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 805 B |
|
@ -31,7 +31,16 @@ void KeyboardManager::hid(size_t& currentEntry)
|
|||
static const size_t columns = 11;
|
||||
|
||||
u64 kHeld = hidKeysHeld(CONTROLLER_P1_AUTO);
|
||||
bool sleep = false;
|
||||
|
||||
currentTime = armGetSystemTick();
|
||||
if ((currentTime > lastTime + DELAY_TICKS))
|
||||
{
|
||||
lastTime = currentTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
kHeld &= 0;
|
||||
}
|
||||
|
||||
if (kHeld & KEY_LEFT)
|
||||
{
|
||||
|
@ -58,7 +67,6 @@ void KeyboardManager::hid(size_t& currentEntry)
|
|||
default:
|
||||
currentEntry--;
|
||||
}
|
||||
sleep = true;
|
||||
}
|
||||
else if (kHeld & KEY_RIGHT)
|
||||
{
|
||||
|
@ -85,7 +93,6 @@ void KeyboardManager::hid(size_t& currentEntry)
|
|||
default:
|
||||
currentEntry++;
|
||||
}
|
||||
sleep = true;
|
||||
}
|
||||
else if (kHeld & KEY_UP)
|
||||
{
|
||||
|
@ -109,7 +116,6 @@ void KeyboardManager::hid(size_t& currentEntry)
|
|||
default:
|
||||
currentEntry -= 11;
|
||||
}
|
||||
sleep = true;
|
||||
}
|
||||
else if (kHeld & KEY_DOWN)
|
||||
{
|
||||
|
@ -134,12 +140,6 @@ void KeyboardManager::hid(size_t& currentEntry)
|
|||
default:
|
||||
currentEntry += 11;
|
||||
}
|
||||
sleep = true;
|
||||
}
|
||||
|
||||
if (sleep)
|
||||
{
|
||||
svcSleepThread(FASTSCROLL_WAIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -312,24 +312,23 @@ std::pair<bool, std::string> KeyboardManager::keyboard(const std::string& sugges
|
|||
}
|
||||
}
|
||||
|
||||
framebuf = gfxGetFramebuffer(&framebuf_width, NULL);
|
||||
memset(framebuf, 51, gfxGetFramebufferSize());
|
||||
SDLH_ClearScreen(COLOR_GREY_BG);
|
||||
|
||||
rectangle(marginlr, 140, 1280 - marginlr*2, 84, COLOR_GREY_MEDIUM);
|
||||
rectangle(0, starty - margintb, 1280, 356, COLOR_GREY_DARKER);
|
||||
SDLH_DrawRect(marginlr, 140, 1280 - marginlr*2, 84, COLOR_GREY_MEDIUM);
|
||||
SDLH_DrawRect(0, starty - margintb, 1280, 356, COLOR_GREY_DARKER);
|
||||
|
||||
u32 texth, counter_width;
|
||||
std::string counter = StringUtils::format("Custom name length: %d/%d", str.empty() ? suggestion.length() : str.length(), CUSTOM_PATH_LEN);
|
||||
GetTextDimensions(7, " ", NULL, &texth);
|
||||
GetTextDimensions(4, counter.c_str(), &counter_width, NULL);
|
||||
DrawText(4, 1280 - marginlr - counter_width, 236, COLOR_WHITE, counter.c_str());
|
||||
SDLH_GetTextDimensions(30, " ", NULL, &texth);
|
||||
SDLH_GetTextDimensions(20, counter.c_str(), &counter_width, NULL);
|
||||
SDLH_DrawText(20, 1280 - marginlr - counter_width, 236, COLOR_WHITE, counter.c_str());
|
||||
if (str.empty())
|
||||
{
|
||||
DrawText(7, marginlr*2, 140 + (84 - texth) / 2, COLOR_GREY_LIGHT, suggestion.c_str());
|
||||
SDLH_DrawTextBox(30, marginlr*2, 140 + (84 - texth) / 2, COLOR_GREY_LIGHT, 1280 - marginlr*2, suggestion.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText(7, marginlr*2, 140 + (84 - texth) / 2, COLOR_WHITE, str.c_str());
|
||||
SDLH_DrawTextBox(30, marginlr*2, 140 + (84 - texth) / 2, COLOR_WHITE, 1280 - marginlr*2, str.c_str());
|
||||
}
|
||||
|
||||
for (size_t i = 0, sz = buttons.size(); i < sz; i++)
|
||||
|
@ -356,8 +355,7 @@ std::pair<bool, std::string> KeyboardManager::keyboard(const std::string& sugges
|
|||
buttons.at(i)->draw();
|
||||
}
|
||||
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
SDLH_Render();
|
||||
}
|
||||
|
||||
return std::make_pair(false, suggestion);
|
||||
|
|
166
switch/source/SDLHelper.cpp
Normal file
166
switch/source/SDLHelper.cpp
Normal file
|
@ -0,0 +1,166 @@
|
|||
#include "SDLHelper.hpp"
|
||||
|
||||
static SDL_Window* s_window;
|
||||
static SDL_Renderer* s_renderer;
|
||||
static SDL_Texture* s_star;
|
||||
static SDL_Texture* s_checkbox;
|
||||
static SDL_Texture* s_flag;
|
||||
|
||||
static PlFontData fontData, fontExtData;
|
||||
static std::unordered_map<int, FC_Font*> s_fonts;
|
||||
|
||||
static FC_Font* getFontFromMap(int size)
|
||||
{
|
||||
std::unordered_map<int, FC_Font*>::const_iterator got = s_fonts.find(size);
|
||||
if (got == s_fonts.end() || got->second == NULL)
|
||||
{
|
||||
FC_Font* f = FC_CreateFont();
|
||||
FC_LoadFont_RW(f, s_renderer, SDL_RWFromMem((void*)fontData.address, fontData.size), SDL_RWFromMem((void*)fontExtData.address, fontExtData.size), 1, size, FC_MakeColor(0, 0, 0, 255), TTF_STYLE_NORMAL);
|
||||
s_fonts.insert({size, f});
|
||||
return f;
|
||||
}
|
||||
return got->second;
|
||||
}
|
||||
|
||||
bool SDLH_Init(void)
|
||||
{
|
||||
bool ok = false;
|
||||
SDL_Init(SDL_INIT_EVERYTHING);
|
||||
s_window = SDL_CreateWindow("Checkpoint", 0, 0, 1280, 720, SDL_WINDOW_FULLSCREEN);
|
||||
s_renderer = SDL_CreateRenderer(s_window, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
SDL_SetRenderDrawBlendMode(s_renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
|
||||
IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
|
||||
|
||||
plGetSharedFontByType(&fontData, PlSharedFontType_Standard);
|
||||
plGetSharedFontByType(&fontExtData, PlSharedFontType_NintendoExt);
|
||||
|
||||
SDLH_LoadImage(&s_flag, "romfs:/flag.png");
|
||||
SDLH_LoadImage(&s_star, "romfs:/star.png");
|
||||
SDLH_LoadImage(&s_checkbox, "romfs:/checkbox.png");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SDLH_Exit(void)
|
||||
{
|
||||
for (auto& value : s_fonts)
|
||||
{
|
||||
FC_FreeFont(value.second);
|
||||
}
|
||||
|
||||
TTF_Quit();
|
||||
SDL_DestroyTexture(s_flag);
|
||||
SDL_DestroyTexture(s_star);
|
||||
SDL_DestroyTexture(s_checkbox);
|
||||
IMG_Quit();
|
||||
SDL_DestroyRenderer(s_renderer);
|
||||
SDL_DestroyWindow(s_window);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void SDLH_ClearScreen(SDL_Color color)
|
||||
{
|
||||
SDL_SetRenderDrawColor(s_renderer, color.r, color.g, color.b, color.a);
|
||||
SDL_RenderClear(s_renderer);
|
||||
}
|
||||
|
||||
void SDLH_Render(void)
|
||||
{
|
||||
SDL_RenderPresent(s_renderer);
|
||||
}
|
||||
|
||||
void SDLH_DrawRect(int x, int y, int w, int h, SDL_Color color)
|
||||
{
|
||||
SDL_Rect rect;
|
||||
rect.x = x; rect.y = y; rect.w = w; rect.h = h;
|
||||
SDL_SetRenderDrawColor(s_renderer, color.r, color.g, color.b, color.a);
|
||||
SDL_RenderFillRect(s_renderer, &rect);
|
||||
}
|
||||
|
||||
void SDLH_DrawCircle(int x, int y, int r, SDL_Color color)
|
||||
{
|
||||
filledCircleRGBA(s_renderer, x, y, r, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
void SDLH_DrawText(int size, int x, int y, SDL_Color color, const char* text)
|
||||
{
|
||||
FC_DrawColor(getFontFromMap(size), s_renderer, x, y, color, text);
|
||||
}
|
||||
|
||||
void SDLH_DrawTextBox(int size, int x, int y, SDL_Color color, int max, const char* text)
|
||||
{
|
||||
u32 h;
|
||||
FC_Font* font = getFontFromMap(size);
|
||||
SDLH_GetTextDimensions(size, text, NULL, &h);
|
||||
FC_Rect rect = FC_MakeRect(x, y, max, h);
|
||||
FC_DrawBoxColor(font, s_renderer, rect, color, text);
|
||||
}
|
||||
|
||||
void SDLH_LoadImage(SDL_Texture** texture, char* path)
|
||||
{
|
||||
SDL_Surface* loaded_surface = NULL;
|
||||
loaded_surface = IMG_Load(path);
|
||||
|
||||
if (loaded_surface)
|
||||
{
|
||||
Uint32 colorkey = SDL_MapRGB(loaded_surface->format, 0, 0, 0);
|
||||
SDL_SetColorKey(loaded_surface, SDL_TRUE, colorkey);
|
||||
*texture = SDL_CreateTextureFromSurface(s_renderer, loaded_surface);
|
||||
}
|
||||
|
||||
SDL_FreeSurface(loaded_surface);
|
||||
}
|
||||
|
||||
void SDLH_LoadImage(SDL_Texture** texture, u8* buff, size_t size)
|
||||
{
|
||||
SDL_Surface* loaded_surface = NULL;
|
||||
loaded_surface = IMG_Load_RW(SDL_RWFromMem(buff, size), 1);
|
||||
|
||||
if (loaded_surface)
|
||||
{
|
||||
Uint32 colorkey = SDL_MapRGB(loaded_surface->format, 0, 0, 0);
|
||||
SDL_SetColorKey(loaded_surface, SDL_TRUE, colorkey);
|
||||
*texture = SDL_CreateTextureFromSurface(s_renderer, loaded_surface);
|
||||
}
|
||||
|
||||
SDL_FreeSurface(loaded_surface);
|
||||
}
|
||||
|
||||
void SDLH_DrawImage(SDL_Texture* texture, int x, int y)
|
||||
{
|
||||
SDL_Rect position;
|
||||
position.x = x; position.y = y;
|
||||
SDL_QueryTexture(texture, NULL, NULL, &position.w, &position.h);
|
||||
SDL_RenderCopy(s_renderer, texture, NULL, &position);
|
||||
}
|
||||
|
||||
void SDLH_DrawImageScale(SDL_Texture* texture, int x, int y, int w, int h)
|
||||
{
|
||||
SDL_Rect position;
|
||||
position.x = x; position.y = y; position.w = w; position.h = h;
|
||||
SDL_RenderCopy(s_renderer, texture, NULL, &position);
|
||||
}
|
||||
|
||||
void SDLH_GetTextDimensions(int size, const char* text, u32* w, u32* h)
|
||||
{
|
||||
FC_Font* f = getFontFromMap(size);
|
||||
if (w != NULL) *w = FC_GetWidth(f, text);
|
||||
if (h != NULL) *h = FC_GetHeight(f, text);
|
||||
}
|
||||
|
||||
void SDLH_DrawIcon(std::string icon, int x, int y)
|
||||
{
|
||||
SDL_Texture* t = nullptr;
|
||||
if (icon.compare("flag") == 0) {
|
||||
t = s_flag;
|
||||
} else if (icon.compare("checkbox") == 0) {
|
||||
t = s_checkbox;
|
||||
} else if (icon.compare("star") == 0) {
|
||||
t = s_star;
|
||||
}
|
||||
|
||||
if (t != nullptr) {
|
||||
SDLH_DrawImage(t, x, y);
|
||||
}
|
||||
}
|
2341
switch/source/SDL_FontCache.c
Normal file
2341
switch/source/SDL_FontCache.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -37,7 +37,7 @@ void Account::exit(void)
|
|||
{
|
||||
for (auto& value : mUsers)
|
||||
{
|
||||
free(value.second.icon);
|
||||
SDL_DestroyTexture(value.second.icon);
|
||||
}
|
||||
accountExit();
|
||||
}
|
||||
|
@ -71,21 +71,8 @@ static User getUser(u128 id)
|
|||
(buffer = (u8*)malloc(image_size)) != NULL &&
|
||||
R_SUCCEEDED(accountProfileLoadImage(&profile, buffer, image_size, &real_size)))
|
||||
{
|
||||
njInit();
|
||||
size_t fullsize = 256*256*3;
|
||||
if (njDecode(buffer, real_size) == NJ_OK &&
|
||||
njGetWidth() == 256 &&
|
||||
njGetHeight() == 256 &&
|
||||
(size_t)njGetImageSize() == fullsize &&
|
||||
njIsColor() == 1)
|
||||
{
|
||||
u8* decoded_buffer = njGetImage();
|
||||
user.icon = (u8*)malloc(USER_ICON_SIZE*USER_ICON_SIZE*3);
|
||||
downscaleRGBImg(decoded_buffer, user.icon, 256, 256, USER_ICON_SIZE, USER_ICON_SIZE);
|
||||
decoded_buffer = NULL;
|
||||
}
|
||||
SDLH_LoadImage(&user.icon, buffer, image_size);
|
||||
free(buffer);
|
||||
njDone();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,9 +93,10 @@ std::string Account::username(u128 id)
|
|||
return got->second.name;
|
||||
}
|
||||
|
||||
u8* Account::icon(u128 id)
|
||||
SDL_Texture* Account::icon(u128 id)
|
||||
{
|
||||
std::map<u128, User>::const_iterator got = mUsers.find(id);
|
||||
// TODO: remove the null check
|
||||
// the null check in the icon is to handle the bad memory issue that isn't yet fixed
|
||||
if (got == mUsers.end() || got->second.icon == NULL)
|
||||
{
|
||||
|
@ -116,6 +104,5 @@ u8* Account::icon(u128 id)
|
|||
mUsers.insert({id, user});
|
||||
return user.icon;
|
||||
}
|
||||
|
||||
return got->second.icon;
|
||||
}
|
|
@ -59,23 +59,22 @@ bool Clickable::released(void)
|
|||
void Clickable::draw(void)
|
||||
{
|
||||
u32 textw, texth;
|
||||
GetTextDimensions(7, mText.c_str(), &textw, &texth);
|
||||
SDLH_GetTextDimensions(36, mText.c_str(), &textw, &texth);
|
||||
const u32 messageWidth = mCentered ? textw : mw - 8;
|
||||
bool hld = held();
|
||||
const color_t bgColor = hld ? mColorText : mColorBg;
|
||||
const color_t msgColor = hld ? mColorBg : mColorText;
|
||||
const SDL_Color bgColor = hld ? mColorText : mColorBg;
|
||||
const SDL_Color msgColor = hld ? mColorBg : mColorText;
|
||||
|
||||
rectangle(mx, my, mw, mh, bgColor);
|
||||
DrawText(7, mx + (mw - messageWidth)/2, my + (mh - texth)/2, msgColor, mText.c_str());
|
||||
SDLH_DrawRect(mx, my, mw, mh, bgColor);
|
||||
SDLH_DrawText(36, mx + (mw - messageWidth)/2, my + (mh - texth)/2, msgColor, mText.c_str());
|
||||
}
|
||||
|
||||
void Clickable::draw(float font)
|
||||
{
|
||||
u32 textw, texth, dotlen;
|
||||
GetTextDimensions(font, mText.c_str(), &textw, &texth);
|
||||
GetTextDimensions(font, "...", &dotlen, NULL);
|
||||
u32 textw, texth;
|
||||
SDLH_GetTextDimensions(font, mText.c_str(), &textw, &texth);
|
||||
const u32 messageWidth = mCentered ? textw : mw - 8;
|
||||
|
||||
rectangled(mx, my, mw, mh, mColorBg);
|
||||
DrawTextTruncate(font, mx + (mw - messageWidth)/2, my + (mh - texth)/2, mColorText, mText.c_str(), mw - 4*2 - 40 - dotlen, "...");
|
||||
SDLH_DrawRect(mx, my, mw, mh, mColorBg);
|
||||
SDLH_DrawTextBox(font, mx + (mw - messageWidth)/2, my + (mh - texth)/2, mColorText, mw - 4*2, mText.c_str());
|
||||
}
|
|
@ -1,422 +0,0 @@
|
|||
/*
|
||||
* Copyright 2017-2018 nx-hbmenu Authors
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
* with or without fee is hereby granted, provided that the above copyright notice
|
||||
* and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
|
||||
* OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
* OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "draw.hpp"
|
||||
|
||||
static FT_Error s_font_libret = 1;
|
||||
static FT_Error s_font_facesret[FONT_FACES_MAX];
|
||||
static FT_Library s_font_library;
|
||||
static FT_Face s_font_faces[FONT_FACES_MAX];
|
||||
static FT_Face s_font_lastusedface;
|
||||
static size_t s_font_faces_total = 0;
|
||||
static u64 s_textLanguageCode = 0;
|
||||
|
||||
Result textInit(void)
|
||||
{
|
||||
Result res = setInitialize();
|
||||
if (R_SUCCEEDED(res))
|
||||
{
|
||||
res = setGetSystemLanguage(&s_textLanguageCode);
|
||||
}
|
||||
setExit();
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool FontSetType(u32 scale)
|
||||
{
|
||||
FT_Error ret = 0;
|
||||
for (u32 i = 0; i < s_font_faces_total; i++)
|
||||
{
|
||||
ret = FT_Set_Char_Size(s_font_faces[i], 0, scale*64, 300, 300);
|
||||
if (ret) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool FontLoadGlyph(glyph_t* glyph, u32 font, u32 codepoint)
|
||||
{
|
||||
FT_Face face;
|
||||
FT_Error ret = 0;
|
||||
FT_GlyphSlot slot;
|
||||
FT_UInt glyph_index;
|
||||
FT_Bitmap* bitmap;
|
||||
|
||||
if (s_font_faces_total == 0) return false;
|
||||
|
||||
for (u32 i = 0; i < s_font_faces_total; i++)
|
||||
{
|
||||
face = s_font_faces[i];
|
||||
s_font_lastusedface = face;
|
||||
glyph_index = FT_Get_Char_Index(face, codepoint);
|
||||
if (glyph_index == 0) continue;
|
||||
|
||||
ret = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
|
||||
if (ret == 0)
|
||||
{
|
||||
ret = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL);
|
||||
}
|
||||
if (ret) return false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
slot = face->glyph;
|
||||
bitmap = &slot->bitmap;
|
||||
|
||||
glyph->width = bitmap->width;
|
||||
glyph->height = bitmap->rows;
|
||||
glyph->pitch = bitmap->pitch;
|
||||
glyph->data = bitmap->buffer;
|
||||
glyph->advance = slot->advance.x >> 6;
|
||||
glyph->posX = slot->bitmap_left;
|
||||
glyph->posY = slot->bitmap_top;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void DrawGlyph(u32 x, u32 y, color_t clr, const glyph_t* glyph)
|
||||
{
|
||||
const u8* data = glyph->data;
|
||||
x += glyph->posX;
|
||||
y -= glyph->posY;
|
||||
for (u32 j = 0; j < glyph->height; j ++)
|
||||
{
|
||||
for (u32 i = 0; i < glyph->width; i ++)
|
||||
{
|
||||
clr.a = data[i];
|
||||
if (!clr.a) continue;
|
||||
DrawPixel(x+i, y+j, clr);
|
||||
}
|
||||
data += glyph->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static inline u8 DecodeByte(const char** ptr)
|
||||
{
|
||||
u8 c = (u8)**ptr;
|
||||
*ptr += 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
// UTF-8 code adapted from http://www.json.org/JSON_checker/utf8_decode.c
|
||||
static inline int8_t DecodeUTF8Cont(const char** ptr)
|
||||
{
|
||||
int c = DecodeByte(ptr);
|
||||
return ((c & 0xC0) == 0x80) ? (c & 0x3F) : -1;
|
||||
}
|
||||
|
||||
static inline u32 DecodeUTF8(const char** ptr)
|
||||
{
|
||||
u32 r;
|
||||
u8 c;
|
||||
int8_t c1, c2, c3;
|
||||
|
||||
c = DecodeByte(ptr);
|
||||
if ((c & 0x80) == 0)
|
||||
return c;
|
||||
if ((c & 0xE0) == 0xC0)
|
||||
{
|
||||
c1 = DecodeUTF8Cont(ptr);
|
||||
if (c1 >= 0)
|
||||
{
|
||||
r = ((c & 0x1F) << 6) | c1;
|
||||
if (r >= 0x80)
|
||||
return r;
|
||||
}
|
||||
} else if ((c & 0xF0) == 0xE0)
|
||||
{
|
||||
c1 = DecodeUTF8Cont(ptr);
|
||||
if (c1 >= 0)
|
||||
{
|
||||
c2 = DecodeUTF8Cont(ptr);
|
||||
if (c2 >= 0)
|
||||
{
|
||||
r = ((c & 0x0F) << 12) | (c1 << 6) | c2;
|
||||
if (r >= 0x800 && (r < 0xD800 || r >= 0xE000))
|
||||
return r;
|
||||
}
|
||||
}
|
||||
} else if ((c & 0xF8) == 0xF0)
|
||||
{
|
||||
c1 = DecodeUTF8Cont(ptr);
|
||||
if (c1 >= 0)
|
||||
{
|
||||
c2 = DecodeUTF8Cont(ptr);
|
||||
if (c2 >= 0)
|
||||
{
|
||||
c3 = DecodeUTF8Cont(ptr);
|
||||
if (c3 >= 0)
|
||||
{
|
||||
r = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
|
||||
if (r >= 0x10000 && r < 0x110000)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0xFFFD;
|
||||
}
|
||||
|
||||
static void DrawText_(u32 font, u32 x, u32 y, color_t clr, const char* text, u32 max_width, const char* end_text)
|
||||
{
|
||||
u32 origX = x;
|
||||
if (s_font_faces_total == 0) return;
|
||||
if (!FontSetType(font)) return;
|
||||
s_font_lastusedface = s_font_faces[0];
|
||||
|
||||
while (*text)
|
||||
{
|
||||
if (max_width && x-origX >= max_width) {
|
||||
text = end_text;
|
||||
max_width = 0;
|
||||
}
|
||||
|
||||
glyph_t glyph;
|
||||
u32 codepoint = DecodeUTF8(&text);
|
||||
|
||||
if (codepoint == '\n')
|
||||
{
|
||||
if (max_width) {
|
||||
text = end_text;
|
||||
max_width = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
x = origX;
|
||||
y += s_font_lastusedface->size->metrics.height / 64;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!FontLoadGlyph(&glyph, font, codepoint))
|
||||
{
|
||||
if (!FontLoadGlyph(&glyph, font, '?'))
|
||||
continue;
|
||||
}
|
||||
|
||||
DrawGlyph(x, y + font*3, clr, &glyph);
|
||||
x += glyph.advance;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawText(u32 font, u32 x, u32 y, color_t clr, const char* text)
|
||||
{
|
||||
DrawText_(font, x, y, clr, text, 0, NULL);
|
||||
}
|
||||
|
||||
void DrawTextTruncate(u32 font, u32 x, u32 y, color_t clr, const char* text, u32 max_width, const char* end_text)
|
||||
{
|
||||
DrawText_(font, x, y, clr, text, max_width, end_text);
|
||||
}
|
||||
|
||||
void GetTextDimensions(u32 font, const char* text, u32* width_out, u32* height_out)
|
||||
{
|
||||
if (s_font_faces_total == 0) return;
|
||||
if (!FontSetType(font)) return;
|
||||
s_font_lastusedface = s_font_faces[0];
|
||||
u32 x = 0;
|
||||
u32 width = 0, height = s_font_lastusedface->size->metrics.height / 64 - font*3;
|
||||
|
||||
while (*text)
|
||||
{
|
||||
glyph_t glyph;
|
||||
u32 codepoint = DecodeUTF8(&text);
|
||||
|
||||
if (codepoint == '\n')
|
||||
{
|
||||
x = 0;
|
||||
height += s_font_lastusedface->size->metrics.height / 64;
|
||||
height -= font*3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!FontLoadGlyph(&glyph, font, codepoint))
|
||||
{
|
||||
if (!FontLoadGlyph(&glyph, font, '?'))
|
||||
continue;
|
||||
}
|
||||
|
||||
x += glyph.advance;
|
||||
|
||||
if (x > width)
|
||||
width = x;
|
||||
}
|
||||
|
||||
if (width_out)
|
||||
*width_out = width;
|
||||
if (height_out)
|
||||
*height_out = height;
|
||||
}
|
||||
|
||||
bool fontInitialize(void)
|
||||
{
|
||||
FT_Error ret = 0;
|
||||
|
||||
for (u32 i = 0; i < FONT_FACES_MAX; i++)
|
||||
{
|
||||
s_font_facesret[i] = 1;
|
||||
}
|
||||
|
||||
ret = FT_Init_FreeType(&s_font_library);
|
||||
s_font_libret = ret;
|
||||
if (s_font_libret) return false;
|
||||
|
||||
PlFontData fonts[PlSharedFontType_Total];
|
||||
Result rc = 0;
|
||||
rc = plGetSharedFont(s_textLanguageCode, fonts, FONT_FACES_MAX, &s_font_faces_total);
|
||||
if (R_FAILED(rc)) return false;
|
||||
|
||||
for (u32 i = 0; i < s_font_faces_total; i++)
|
||||
{
|
||||
ret = FT_New_Memory_Face(
|
||||
s_font_library,
|
||||
(const FT_Byte*)fonts[i].address,
|
||||
fonts[i].size,
|
||||
0,
|
||||
&s_font_faces[i]
|
||||
);
|
||||
|
||||
s_font_facesret[i] = ret;
|
||||
if (ret) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void fontExit()
|
||||
{
|
||||
for (u32 i = 0; i < s_font_faces_total; i++)
|
||||
{
|
||||
if (s_font_facesret[i] == 0)
|
||||
{
|
||||
FT_Done_Face(s_font_faces[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_font_libret == 0)
|
||||
{
|
||||
FT_Done_FreeType(s_font_library);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawImage(int x, int y, int width, int height, const u8 *image, ImageMode mode)
|
||||
{
|
||||
int tmpx, tmpy;
|
||||
int pos;
|
||||
color_t current_color;
|
||||
|
||||
for (tmpy = 0; tmpy < height; tmpy++)
|
||||
{
|
||||
for (tmpx = 0; tmpx < width; tmpx++)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case IMAGE_MODE_RGB24:
|
||||
pos = ((tmpy*width) + tmpx) * 3;
|
||||
current_color = MakeColor(image[pos+0], image[pos+1], image[pos+2], 255);
|
||||
break;
|
||||
case IMAGE_MODE_RGBA32:
|
||||
pos = ((tmpy*width) + tmpx) * 4;
|
||||
current_color = MakeColor(image[pos+0], image[pos+1], image[pos+2], image[pos+3]);
|
||||
break;
|
||||
}
|
||||
DrawPixel(x+tmpx, y+tmpy, current_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rectangled(u32 x, u32 y, u32 w, u32 h, color_t color)
|
||||
{
|
||||
for (u32 j = y; j < y + h; j++)
|
||||
{
|
||||
for (u32 i = x; i < x + w; i++)
|
||||
{
|
||||
DrawPixel(i, j, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rectangle(u32 x, u32 y, u32 w, u32 h, color_t color)
|
||||
{
|
||||
for (u32 j = y; j < y + h; j++)
|
||||
{
|
||||
for (u32 i = x; i < x + w; i+=4)
|
||||
{
|
||||
Draw4PixelsRaw(i, j, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void downscaleRGBImg(const u8 *image, u8* out, int srcWidth, int srcHeight, int destWidth, int destHeight)
|
||||
{
|
||||
int tmpx, tmpy;
|
||||
int pos;
|
||||
float sourceX, sourceY;
|
||||
float xScale = (float)srcWidth / (float)destWidth;
|
||||
float yScale = (float)srcHeight / (float)destHeight;
|
||||
int pixelX, pixelY;
|
||||
u8 r1, r2, r3, r4;
|
||||
u8 g1, g2, g3, g4;
|
||||
u8 b1, b2, b3, b4;
|
||||
float fx, fy, fx1, fy1;
|
||||
int w1, w2, w3, w4;
|
||||
|
||||
for (tmpx=0; tmpx<destWidth; tmpx++)
|
||||
{
|
||||
for (tmpy=0; tmpy<destHeight; tmpy++)
|
||||
{
|
||||
sourceX = tmpx * xScale;
|
||||
sourceY = tmpy * yScale;
|
||||
pixelX = (int)sourceX;
|
||||
pixelY = (int)sourceY;
|
||||
|
||||
// get colours from four surrounding pixels
|
||||
pos = ((pixelY + 0) * srcWidth + pixelX + 0) * 3;
|
||||
r1 = image[pos+0];
|
||||
g1 = image[pos+1];
|
||||
b1 = image[pos+2];
|
||||
|
||||
pos = ((pixelY + 0) * srcWidth + pixelX + 1) * 3;
|
||||
r2 = image[pos+0];
|
||||
g2 = image[pos+1];
|
||||
b2 = image[pos+2];
|
||||
|
||||
pos = ((pixelY + 1) * srcWidth + pixelX + 0) * 3;
|
||||
r3 = image[pos+0];
|
||||
g3 = image[pos+1];
|
||||
b3 = image[pos+2];
|
||||
|
||||
pos = ((pixelY + 1) * srcWidth + pixelX + 1) * 3;
|
||||
r4 = image[pos+0];
|
||||
g4 = image[pos+1];
|
||||
b4 = image[pos+2];
|
||||
|
||||
// determine weights
|
||||
fx = sourceX - pixelX;
|
||||
fy = sourceY - pixelY;
|
||||
fx1 = 1.0f - fx;
|
||||
fy1 = 1.0f - fy;
|
||||
|
||||
w1 = (int)(fx1*fy1*256.0);
|
||||
w2 = (int)(fx*fy1*256.0);
|
||||
w3 = (int)(fx1*fy*256.0);
|
||||
w4 = (int)(fx*fy*256.0);
|
||||
|
||||
// set output pixels
|
||||
pos = ((tmpy*destWidth) + tmpx) * 3;
|
||||
out[pos+0] = (u8)((r1 * w1 + r2 * w2 + r3 * w3 + r4 * w4) >> 8);
|
||||
out[pos+1] = (u8)((g1 * w1 + g2 * w2 + g3 * w3 + g4 * w4) >> 8);
|
||||
out[pos+2] = (u8)((b1 * w1 + b2 * w2 + b3 * w3 + b4 * w4) >> 8);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,9 +26,6 @@
|
|||
|
||||
#include "gui.hpp"
|
||||
|
||||
u8* framebuf;
|
||||
u32 framebuf_width;
|
||||
|
||||
static Info* info;
|
||||
static Clickable* buttonBackup;
|
||||
static Clickable* buttonRestore;
|
||||
|
@ -43,7 +40,7 @@ static bool backupScrollEnabled;
|
|||
static Hid* hid;
|
||||
static entryType_t type;
|
||||
|
||||
static float timer = 0;
|
||||
static float currentTime = 0;
|
||||
static int selectorX(size_t i);
|
||||
static int selectorY(size_t i);
|
||||
|
||||
|
@ -146,34 +143,33 @@ void Gui::addSelectedEntry(size_t idx)
|
|||
|
||||
/// Gui implementation
|
||||
|
||||
static void drawOutline(u32 x, u32 y, u16 w, u16 h, u8 size, color_t color)
|
||||
static void drawOutline(u32 x, u32 y, u16 w, u16 h, u8 size, SDL_Color color)
|
||||
{
|
||||
rectangled(x - size, y - size, w + 2*size, size, color); // top
|
||||
rectangled(x - size, y, size, h, color); // left
|
||||
rectangled(x + w, y, size, h, color); // right
|
||||
rectangled(x - size, y + h, w + 2*size, size, color); // bottom
|
||||
SDLH_DrawRect(x - size, y - size, w + 2*size, size, color); // top
|
||||
SDLH_DrawRect(x - size, y, size, h, color); // left
|
||||
SDLH_DrawRect(x + w, y, size, h, color); // right
|
||||
SDLH_DrawRect(x - size, y + h, w + 2*size, size, color); // bottom
|
||||
}
|
||||
|
||||
static void drawBackground(void)
|
||||
{
|
||||
framebuf = gfxGetFramebuffer(&framebuf_width, NULL);
|
||||
memset(framebuf, 51, gfxGetFramebufferSize());
|
||||
SDLH_ClearScreen(COLOR_GREY_BG);
|
||||
|
||||
const u8 bar_height = 28;
|
||||
const u8 image_dim = 32;
|
||||
rectangle(0, 0, 1280, bar_height, COLOR_GREY_DARK);
|
||||
rectangle(0, 720 - bar_height, 1280, bar_height, COLOR_GREY_DARK);
|
||||
SDLH_DrawRect(0, 0, 1280, bar_height, COLOR_GREY_DARK);
|
||||
SDLH_DrawRect(0, 720 - bar_height, 1280, bar_height, COLOR_GREY_DARK);
|
||||
|
||||
u32 ver_w, ver_h, checkpoint_w;
|
||||
GetTextDimensions(5, ver, &ver_w, &ver_h);
|
||||
GetTextDimensions(6, "checkpoint", &checkpoint_w, NULL);
|
||||
SDLH_GetTextDimensions(23, ver, &ver_w, &ver_h);
|
||||
SDLH_GetTextDimensions(30, "checkpoint", &checkpoint_w, NULL);
|
||||
u32 h = (bar_height - ver_h) / 2 - 1;
|
||||
DrawText(5, 10, h + 3, COLOR_GREY_LIGHT, DateTime::timeStr().c_str());
|
||||
DrawText(6, 1280 - 10 - ver_w - image_dim - 12 - checkpoint_w, h, COLOR_WHITE, "checkpoint");
|
||||
DrawText(5, 1280 - 10 - ver_w, h + 3, COLOR_GREY_LIGHT, ver);
|
||||
DrawImage(1280 - 10 - ver_w - image_dim - 6, -2, image_dim, image_dim, flag_bin, IMAGE_MODE_RGBA32);
|
||||
SDLH_DrawText(23, 10, h + 3, COLOR_GREY_LIGHT, DateTime::timeStr().c_str());
|
||||
SDLH_DrawText(30, 1280 - 10 - ver_w - image_dim - 12 - checkpoint_w, h, COLOR_WHITE, "checkpoint");
|
||||
SDLH_DrawText(23, 1280 - 10 - ver_w, h + 3, COLOR_GREY_LIGHT, ver);
|
||||
SDLH_DrawIcon("flag", 1280 - 10 - ver_w - image_dim - 6, -2);
|
||||
// shadow
|
||||
rectangle(0, bar_height, 1280, 2, COLOR_GREY_DARKER);
|
||||
SDLH_DrawRect(0, bar_height, 1280, 2, COLOR_GREY_DARKER);
|
||||
}
|
||||
|
||||
void Gui::drawCopy(const std::string& src, u64 offset, u64 size)
|
||||
|
@ -190,25 +186,23 @@ void Gui::drawCopy(const std::string& src, u64 offset, u64 size)
|
|||
static const int spacingFromBars = 220 + (720 - barHeight * 2 - progressBarHeight) / 2;
|
||||
static const int width = 1280 - spacingFromSides * 2;
|
||||
|
||||
rectangle(spacingFromSides - 2, barHeight + spacingFromBars - 2, width + 4, progressBarHeight + 4, COLOR_GREY_LIGHT);
|
||||
rectangle(spacingFromSides, barHeight + spacingFromBars, width, progressBarHeight, COLOR_WHITE);
|
||||
rectangle(spacingFromSides, barHeight + spacingFromBars, (float)offset / (float)size * width, progressBarHeight, MakeColor(116, 222, 126, 255));
|
||||
SDLH_DrawRect(spacingFromSides - 2, barHeight + spacingFromBars - 2, width + 4, progressBarHeight + 4, COLOR_GREY_LIGHT);
|
||||
SDLH_DrawRect(spacingFromSides, barHeight + spacingFromBars, width, progressBarHeight, COLOR_WHITE);
|
||||
SDLH_DrawRect(spacingFromSides, barHeight + spacingFromBars, (float)offset / (float)size * width, progressBarHeight, FC_MakeColor(116, 222, 126, 255));
|
||||
|
||||
std::string sizeString = StringUtils::sizeString(offset) + " of " + StringUtils::sizeString(size);
|
||||
|
||||
u32 textw, texth;
|
||||
GetTextDimensions(6, sizeString.c_str(), &textw, &texth);
|
||||
DrawText(6, ceilf((1280 - textw)/2), spacingFromBars + barHeight + (progressBarHeight - texth) / 2, COLOR_BLACK, sizeString.c_str());
|
||||
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
SDLH_GetTextDimensions(30, sizeString.c_str(), &textw, &texth);
|
||||
SDLH_DrawText(30, ceilf((1280 - textw)/2), spacingFromBars + barHeight + (progressBarHeight - texth) / 2, COLOR_BLACK, sizeString.c_str());
|
||||
SDLH_Render();
|
||||
}
|
||||
|
||||
bool Gui::askForConfirmation(const std::string& text)
|
||||
{
|
||||
bool ret = false;
|
||||
Clickable* buttonYes = new Clickable(293, 540, 200, 80, COLOR_WHITE, COLOR_BLACK, "Yes \uE000", true);
|
||||
Clickable* buttonNo = new Clickable(786, 540, 200, 80, COLOR_WHITE, COLOR_BLACK, "No \uE001", true);
|
||||
Clickable* buttonYes = new Clickable(293, 540, 200, 80, COLOR_WHITE, COLOR_BLACK, "Yes \ue000", true);
|
||||
Clickable* buttonNo = new Clickable(786, 540, 200, 80, COLOR_WHITE, COLOR_BLACK, "No \ue001", true);
|
||||
MessageBox* message = new MessageBox(COLOR_GREY_DARK, COLOR_WHITE);
|
||||
message->push_message(text);
|
||||
|
||||
|
@ -229,8 +223,7 @@ bool Gui::askForConfirmation(const std::string& text)
|
|||
buttonYes->draw();
|
||||
buttonNo->draw();
|
||||
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
SDLH_Render();
|
||||
}
|
||||
|
||||
delete message;
|
||||
|
@ -241,26 +234,26 @@ bool Gui::askForConfirmation(const std::string& text)
|
|||
|
||||
void Gui::init(void)
|
||||
{
|
||||
gfxInitDefault();
|
||||
SDLH_Init();
|
||||
sprintf(ver, "v%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO);
|
||||
backupScrollEnabled = false;
|
||||
info = new Info();
|
||||
info->init("", "", 0, TYPE_INFO);
|
||||
hid = new Hid(rowlen * collen, collen);
|
||||
backupList = new Scrollable(540, 462, 506, 222, cols);
|
||||
buttonBackup = new Clickable(1050, 462, 220, 109, COLOR_WHITE, COLOR_GREY_LIGHT, "Backup \uE004", true);
|
||||
buttonRestore = new Clickable(1050, 575, 220, 109, COLOR_WHITE, COLOR_GREY_LIGHT, "Restore \uE005", true);
|
||||
buttonBackup = new Clickable(1050, 462, 220, 109, COLOR_WHITE, COLOR_GREY_LIGHT, "Backup \ue004", true);
|
||||
buttonRestore = new Clickable(1050, 575, 220, 109, COLOR_WHITE, COLOR_GREY_LIGHT, "Restore \ue005", true);
|
||||
copyList = new MessageBox(COLOR_GREY_DARK, COLOR_WHITE);
|
||||
messageBox = new MessageBox(COLOR_GREY_DARK, COLOR_WHITE);
|
||||
messageBox->push_message("Press \uE000 to enter target.");
|
||||
messageBox->push_message("Press \uE001 to exit target or deselect all titles.");
|
||||
messageBox->push_message("Press \uE004 to backup target.");
|
||||
messageBox->push_message("Press \uE005 to restore target.");
|
||||
messageBox->push_message("Press \uE002 to delete a backup.");
|
||||
messageBox->push_message("Press \uE003 to multiselect a title.");
|
||||
messageBox->push_message("Hold \uE003 to multiselect all titles.");
|
||||
messageBox->push_message("Press \uE041 to move between titles.");
|
||||
messageBox->push_message("Press \uE085/\uE086 to switch user.");
|
||||
messageBox->push_message("Press \ue000 to enter target.");
|
||||
messageBox->push_message("Press \ue001 to exit target or deselect all titles.");
|
||||
messageBox->push_message("Press \ue004 to backup target.");
|
||||
messageBox->push_message("Press \ue005 to restore target.");
|
||||
messageBox->push_message("Press \ue002 to delete a backup.");
|
||||
messageBox->push_message("Press \ue003 to multiselect a title.");
|
||||
messageBox->push_message("Hold \ue003 to multiselect all titles.");
|
||||
messageBox->push_message("Press \ue041 to move between titles.");
|
||||
messageBox->push_message("Press \ue085/\ue086 to switch user.");
|
||||
}
|
||||
|
||||
void Gui::exit(void)
|
||||
|
@ -272,7 +265,7 @@ void Gui::exit(void)
|
|||
delete buttonBackup;
|
||||
delete buttonRestore;
|
||||
delete messageBox;
|
||||
gfxExit();
|
||||
SDLH_Exit();
|
||||
}
|
||||
|
||||
void Gui::draw(u128 uid)
|
||||
|
@ -284,7 +277,7 @@ void Gui::draw(u128 uid)
|
|||
|
||||
// draw
|
||||
drawBackground();
|
||||
rectangled(0, bar_height + 2, 532, 720 - 2*bar_height - 2, MakeColor(55, 55, 55, 255));
|
||||
SDLH_DrawRect(0, bar_height + 2, 532, 720 - 2*bar_height - 2, FC_MakeColor(55, 55, 55, 255));
|
||||
|
||||
// user icons
|
||||
std::vector<u128> userIds = Account::ids();
|
||||
|
@ -294,19 +287,19 @@ void Gui::draw(u128 uid)
|
|||
const u32 y = bar_height + spacing;
|
||||
if (i == g_currentUserIndex)
|
||||
{
|
||||
float highlight_multiplier = fmax(0.0, fabs(fmod(timer, 1.0) - 0.5) / 0.5);
|
||||
color_t color = COLOR_GREEN;
|
||||
color = MakeColor(color.r + (255 - color.r) * highlight_multiplier, color.g + (255 - color.g) * highlight_multiplier, color.b + (255 - color.b) * highlight_multiplier, 255);
|
||||
float highlight_multiplier = fmax(0.0, fabs(fmod(currentTime, 1.0) - 0.5) / 0.5);
|
||||
SDL_Color color = COLOR_GREEN;
|
||||
color = FC_MakeColor(color.r + (255 - color.r) * highlight_multiplier, color.g + (255 - color.g) * highlight_multiplier, color.b + (255 - color.b) * highlight_multiplier, 255);
|
||||
drawOutline(x, y, USER_ICON_SIZE, USER_ICON_SIZE, 4, color);
|
||||
}
|
||||
|
||||
if (Account::icon(userIds.at(i)) != NULL)
|
||||
{
|
||||
DrawImage(x, y, USER_ICON_SIZE, USER_ICON_SIZE, Account::icon(userIds.at(i)), IMAGE_MODE_RGB24);
|
||||
SDLH_DrawImageScale(Account::icon(userIds.at(i)), x, y, USER_ICON_SIZE, USER_ICON_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
rectangle(x, y, USER_ICON_SIZE, USER_ICON_SIZE, COLOR_BLACK);
|
||||
SDLH_DrawRect(x, y, USER_ICON_SIZE, USER_ICON_SIZE, COLOR_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,22 +310,22 @@ void Gui::draw(u128 uid)
|
|||
int selectory = selectorY(k);
|
||||
if (smallIcon(g_currentUId, k) != NULL)
|
||||
{
|
||||
DrawImage(selectorx, selectory, 128, 128, smallIcon(g_currentUId, k), IMAGE_MODE_RGB24);
|
||||
SDLH_DrawImageScale(smallIcon(g_currentUId, k), selectorx, selectory, 128, 128);
|
||||
}
|
||||
else
|
||||
{
|
||||
rectangle(selectorx, selectory, 128, 128, COLOR_BLACK);
|
||||
SDLH_DrawRect(selectorx, selectory, 128, 128, COLOR_BLACK);
|
||||
}
|
||||
|
||||
if (!selEnt.empty() && std::find(selEnt.begin(), selEnt.end(), k) != selEnt.end())
|
||||
{
|
||||
DrawImage(selectorx + 86, selectory + 86, 40, 40, checkbox_bin, IMAGE_MODE_RGBA32);
|
||||
SDLH_DrawIcon("checkbox", selectorx + 86, selectory + 86);
|
||||
}
|
||||
|
||||
if (favorite(g_currentUId, k))
|
||||
{
|
||||
rectangle(selectorx + 94, selectory + 8, 24, 24, COLOR_GOLD);
|
||||
DrawImage(selectorx + 86, selectory, 40, 40, star_bin, IMAGE_MODE_RGBA32);
|
||||
SDLH_DrawRect(selectorx + 94, selectory + 8, 24, 24, COLOR_GOLD);
|
||||
SDLH_DrawIcon("star", selectorx + 86, selectory);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,11 +334,11 @@ void Gui::draw(u128 uid)
|
|||
{
|
||||
const int x = selectorX(hid->index()) + spacing/2;
|
||||
const int y = selectorY(hid->index()) + spacing/2;
|
||||
float highlight_multiplier = fmax(0.0, fabs(fmod(timer, 1.0) - 0.5) / 0.5);
|
||||
color_t color = COLOR_BLUE;
|
||||
color = MakeColor(color.r + (255 - color.r) * highlight_multiplier, color.g + (255 - color.g) * highlight_multiplier, color.b + (255 - color.b) * highlight_multiplier, 255);
|
||||
float highlight_multiplier = fmax(0.0, fabs(fmod(currentTime, 1.0) - 0.5) / 0.5);
|
||||
SDL_Color color = COLOR_BLUE;
|
||||
color = FC_MakeColor(color.r + (255 - color.r) * highlight_multiplier, color.g + (255 - color.g) * highlight_multiplier, color.b + (255 - color.b) * highlight_multiplier, 255);
|
||||
drawOutline(x, y, 124, 124, spacing, color);
|
||||
rectangled(x, y, 124, 124, MakeColor(255, 255, 255, 80));
|
||||
SDLH_DrawRect(x, y, 124, 124, FC_MakeColor(255, 255, 255, 80));
|
||||
}
|
||||
|
||||
if (getTitleCount(g_currentUId) > 0)
|
||||
|
@ -368,38 +361,37 @@ void Gui::draw(u128 uid)
|
|||
if (title.icon() != NULL)
|
||||
{
|
||||
drawOutline(1016, 157, 256, 256, 4, COLOR_BLACK);
|
||||
DrawImage(1016, 157, 256, 256, title.icon(), IMAGE_MODE_RGB24);
|
||||
SDLH_DrawImage(title.icon(), 1016, 157);
|
||||
}
|
||||
|
||||
// draw infos
|
||||
u32 info_w, info_h, title_w, h, dotlen, titleid_w, producer_w, user_w;
|
||||
GetTextDimensions(7, "Title Information", &info_w, &info_h);
|
||||
GetTextDimensions(5, "...", &dotlen, NULL);
|
||||
GetTextDimensions(5, "Title: ", &title_w, &h);
|
||||
GetTextDimensions(5, "Title ID: ", &titleid_w, NULL);
|
||||
GetTextDimensions(5, "Author: ", &producer_w, NULL);
|
||||
GetTextDimensions(5, "User: ", &user_w, NULL);
|
||||
u32 info_w, info_h, title_w, h, titleid_w, producer_w, user_w;
|
||||
SDLH_GetTextDimensions(36, "Title Information", &info_w, &info_h);
|
||||
SDLH_GetTextDimensions(23, "Title: ", &title_w, &h);
|
||||
SDLH_GetTextDimensions(23, "Title ID: ", &titleid_w, NULL);
|
||||
SDLH_GetTextDimensions(23, "Author: ", &producer_w, NULL);
|
||||
SDLH_GetTextDimensions(23, "User: ", &user_w, NULL);
|
||||
|
||||
h += 12;
|
||||
u32 offset = 159 + 16 + info_h + h/2;
|
||||
|
||||
rectangle(536, 159, 468, 16 + info_h, COLOR_GREY_DARK);
|
||||
rectangle(536, offset - h/2, 468, h*4 + h/2, COLOR_GREY_DARKER);
|
||||
SDLH_DrawRect(536, 159, 468, 16 + info_h, COLOR_GREY_DARK);
|
||||
SDLH_DrawRect(536, offset - h/2, 468, h*4 + h/2, COLOR_GREY_DARKER);
|
||||
|
||||
DrawText(7, 540 - 12 + 468 - info_w, 169, COLOR_GREY_LIGHT, "Title Information");
|
||||
DrawText(5, 540, offset, COLOR_GREY_LIGHT, "Title: ");
|
||||
DrawText(5, 540, offset + h, COLOR_GREY_LIGHT, "Title ID: ");
|
||||
DrawText(5, 540, offset + h*2, COLOR_GREY_LIGHT, "Author: ");
|
||||
DrawText(5, 540, offset + h*3, COLOR_GREY_LIGHT, "User: ");
|
||||
SDLH_DrawText(36, 540 - 12 + 468 - info_w, 169, COLOR_GREY_LIGHT, "Title Information");
|
||||
SDLH_DrawText(23, 540, offset, COLOR_GREY_LIGHT, "Title: ");
|
||||
SDLH_DrawText(23, 540, offset + h, COLOR_GREY_LIGHT, "Title ID: ");
|
||||
SDLH_DrawText(23, 540, offset + h*2, COLOR_GREY_LIGHT, "Author: ");
|
||||
SDLH_DrawText(23, 540, offset + h*3, COLOR_GREY_LIGHT, "User: ");
|
||||
|
||||
DrawTextTruncate(5, 540 + title_w, offset, COLOR_WHITE, title.name().c_str(), 1012 - 540 - title_w - 4*2 - 20 - dotlen, "...");
|
||||
DrawTextTruncate(5, 540 + titleid_w, offset + h, COLOR_WHITE, StringUtils::format("0x%016llX", title.id()).c_str(), 1012 - 540 - titleid_w - 4*2 - 20 - dotlen, "...");
|
||||
DrawTextTruncate(5, 540 + producer_w, offset + h*2, COLOR_WHITE, title.author().c_str(), 1012 - 540 - producer_w - 4*2 - 20 - dotlen, "...");
|
||||
DrawTextTruncate(5, 540 + user_w, offset + h*3, COLOR_WHITE, title.userName().c_str(), 1012 - 540 - user_w - 4*2 - 20 - dotlen, "...");
|
||||
SDLH_DrawTextBox(23, 540 + title_w, offset, COLOR_WHITE, 1012 - 540 - title_w - 4*2, title.name().c_str());
|
||||
SDLH_DrawTextBox(23, 540 + titleid_w, offset + h, COLOR_WHITE, 1012 - 540 - titleid_w - 4*2, StringUtils::format("0x%016llX", title.id()).c_str());
|
||||
SDLH_DrawTextBox(23, 540 + producer_w, offset + h*2, COLOR_WHITE, 1012 - 540 - producer_w - 4*2, title.author().c_str());
|
||||
SDLH_DrawTextBox(23, 540 + user_w, offset + h*3, COLOR_WHITE, 1012 - 540 - user_w - 4*2, title.userName().c_str());
|
||||
|
||||
drawOutline(540, 462, 730, 222, 4, COLOR_GREY_LIGHT);
|
||||
rectangled(1046, 462, 4, 222, COLOR_GREY_LIGHT);
|
||||
rectangled(1048, 571, 222, 4, COLOR_GREY_LIGHT);
|
||||
SDLH_DrawRect(1046, 462, 4, 222, COLOR_GREY_LIGHT);
|
||||
SDLH_DrawRect(1048, 571, 222, 4, COLOR_GREY_LIGHT);
|
||||
backupList->draw();
|
||||
buttonBackup->draw();
|
||||
buttonRestore->draw();
|
||||
|
@ -413,15 +405,14 @@ void Gui::draw(u128 uid)
|
|||
}
|
||||
|
||||
u32 ins_w, ins_h;
|
||||
const char* instructions = "Hold \uE046 to see commands. Press \uE045 to exit.";
|
||||
GetTextDimensions(5, instructions, &ins_w, &ins_h);
|
||||
DrawText(5, ceil((1280 - ins_w) / 2), 720 - bar_height + (bar_height - ins_h) / 2, COLOR_WHITE, instructions);
|
||||
const char* instructions = "Hold \ue046 to see commands. Press \ue045 to exit.";
|
||||
SDLH_GetTextDimensions(23, instructions, &ins_w, &ins_h);
|
||||
SDLH_DrawText(23, ceil((1280 - ins_w) / 2), 720 - bar_height + (bar_height - ins_h) / 2, COLOR_WHITE, instructions);
|
||||
|
||||
// increase timer
|
||||
timer += 0.05f;
|
||||
// increase currentTime
|
||||
currentTime = SDL_GetTicks() / 1000.f;
|
||||
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
SDLH_Render();
|
||||
}
|
||||
|
||||
bool Gui::isBackupReleased(void)
|
||||
|
|
|
@ -58,27 +58,27 @@ void Info::draw(void)
|
|||
{
|
||||
u32 w, hres = 44, hmessage;
|
||||
u8 alpha = mTTL > 255 ? 255 : mTTL;
|
||||
color_t color, bordercolor, bgcolor;
|
||||
SDL_Color color, bordercolor, bgcolor;
|
||||
|
||||
if (mType == TYPE_ERROR)
|
||||
{
|
||||
color = MakeColor(255, 255, 255, alpha);
|
||||
bordercolor = MakeColor(70, 70, 70, alpha);
|
||||
bgcolor = MakeColor(79, 79, 79, alpha);
|
||||
color = FC_MakeColor(255, 255, 255, alpha);
|
||||
bordercolor = FC_MakeColor(70, 70, 70, alpha);
|
||||
bgcolor = FC_MakeColor(79, 79, 79, alpha);
|
||||
}
|
||||
else if (mType == TYPE_INFO)
|
||||
{
|
||||
color = MakeColor(255, 255, 255, alpha);
|
||||
bordercolor = MakeColor(70, 70, 70, alpha);
|
||||
bgcolor = MakeColor(138, 138, 138, alpha);
|
||||
color = FC_MakeColor(255, 255, 255, alpha);
|
||||
bordercolor = FC_MakeColor(70, 70, 70, alpha);
|
||||
bgcolor = FC_MakeColor(138, 138, 138, alpha);
|
||||
}
|
||||
|
||||
GetTextDimensions(7, mTitle.c_str(), &w, &hmessage);
|
||||
SDLH_GetTextDimensions(36, mTitle.c_str(), &w, &hmessage);
|
||||
const u32 spacing = (mh - hres - hmessage) / 3;
|
||||
rectangle(mx - 2, my - 2, mw + 4, mh + 4, bordercolor);
|
||||
rectangle(mx, my, mw, mh, bgcolor);
|
||||
DrawText(7, mx + (mw - w) / 2, my + spacing, color, mTitle.c_str());
|
||||
DrawText(4, mx + 10, my + 2*spacing + hres, color, mMessage.c_str());
|
||||
SDLH_DrawRect(mx - 2, my - 2, mw + 4, mh + 4, bordercolor);
|
||||
SDLH_DrawRect(mx, my, mw, mh, bgcolor);
|
||||
SDLH_DrawText(36, mx + (mw - w) / 2, my + spacing, color, mTitle.c_str());
|
||||
SDLH_DrawText(20, mx + 10, my + 2*spacing + hres, color, mMessage.c_str());
|
||||
|
||||
mTTL--;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include "messagebox.hpp"
|
||||
|
||||
MessageBox::MessageBox(color_t colorBg, color_t colorText)
|
||||
MessageBox::MessageBox(SDL_Color colorBg, SDL_Color colorText)
|
||||
{
|
||||
mColorBg = colorBg;
|
||||
mColorText = colorText;
|
||||
|
@ -52,7 +52,7 @@ void MessageBox::draw(void)
|
|||
u32 widths[mList.size()];
|
||||
for (size_t i = 0, sz = mList.size(); i < sz; i++)
|
||||
{
|
||||
GetTextDimensions(6, mList.at(i).c_str(), &widths[i], &mh);
|
||||
SDLH_GetTextDimensions(30, mList.at(i).c_str(), &widths[i], &mh);
|
||||
if (widths[i] > w)
|
||||
{
|
||||
w = widths[i];
|
||||
|
@ -65,11 +65,11 @@ void MessageBox::draw(void)
|
|||
const u32 x = (1280-w)/2;
|
||||
const u32 y = (720-h)/2;
|
||||
|
||||
rectangle(x - 2, y - 2, w + 4, h + 4, COLOR_BLACK);
|
||||
rectangle(x, y, w, h, mColorBg);
|
||||
SDLH_DrawRect(x - 2, y - 2, w + 4, h + 4, COLOR_BLACK);
|
||||
SDLH_DrawRect(x, y, w, h, mColorBg);
|
||||
|
||||
for (size_t i = 0, sz = mList.size(); i < sz; i++)
|
||||
{
|
||||
DrawText(6, ceil((1280 - widths[i]) / 2), y + spacingFromEdges + mh*i, mColorText, mList.at(i).c_str());
|
||||
SDLH_DrawText(30, ceil((1280 - widths[i]) / 2), y + spacingFromEdges + mh*i, mColorText, mList.at(i).c_str());
|
||||
}
|
||||
}
|
|
@ -1,916 +0,0 @@
|
|||
// NanoJPEG -- KeyJ's Tiny Baseline JPEG Decoder
|
||||
// version 1.3.5 (2016-11-14)
|
||||
// Copyright (c) 2009-2016 Martin J. Fiedler <martin.fiedler@gmx.net>
|
||||
// published under the terms of the MIT license
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// DOCUMENTATION SECTION //
|
||||
// read this if you want to know what this is all about //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INTRODUCTION
|
||||
// ============
|
||||
//
|
||||
// This is a minimal decoder for baseline JPEG images. It accepts memory dumps
|
||||
// of JPEG files as input and generates either 8-bit grayscale or packed 24-bit
|
||||
// RGB images as output. It does not parse JFIF or Exif headers; all JPEG files
|
||||
// are assumed to be either grayscale or YCbCr. CMYK or other color spaces are
|
||||
// not supported. All YCbCr subsampling schemes with power-of-two ratios are
|
||||
// supported, as are restart intervals. Progressive or lossless JPEG is not
|
||||
// supported.
|
||||
// Summed up, NanoJPEG should be able to decode all images from digital cameras
|
||||
// and most common forms of other non-progressive JPEG images.
|
||||
// The decoder is not optimized for speed, it's optimized for simplicity and
|
||||
// small code. Image quality should be at a reasonable level. A bicubic chroma
|
||||
// upsampling filter ensures that subsampled YCbCr images are rendered in
|
||||
// decent quality. The decoder is not meant to deal with broken JPEG files in
|
||||
// a graceful manner; if anything is wrong with the bitstream, decoding will
|
||||
// simply fail.
|
||||
// The code should work with every modern C compiler without problems and
|
||||
// should not emit any warnings. It uses only (at least) 32-bit integer
|
||||
// arithmetic and is supposed to be endianness independent and 64-bit clean.
|
||||
// However, it is not thread-safe.
|
||||
|
||||
|
||||
// COMPILE-TIME CONFIGURATION
|
||||
// ==========================
|
||||
//
|
||||
// The following aspects of NanoJPEG can be controlled with preprocessor
|
||||
// defines:
|
||||
//
|
||||
// _NJ_EXAMPLE_PROGRAM = Compile a main() function with an example
|
||||
// program.
|
||||
// _NJ_INCLUDE_HEADER_ONLY = Don't compile anything, just act as a header
|
||||
// file for NanoJPEG. Example:
|
||||
// #define _NJ_INCLUDE_HEADER_ONLY
|
||||
// #include "nanojpeg.c"
|
||||
// int main(void) {
|
||||
// njInit();
|
||||
// // your code here
|
||||
// njDone();
|
||||
// }
|
||||
// NJ_USE_LIBC=1 = Use the malloc(), free(), memset() and memcpy()
|
||||
// functions from the standard C library (default).
|
||||
// NJ_USE_LIBC=0 = Don't use the standard C library. In this mode,
|
||||
// external functions njAlloc(), njFreeMem(),
|
||||
// njFillMem() and njCopyMem() need to be defined
|
||||
// and implemented somewhere.
|
||||
// NJ_USE_WIN32=0 = Normal mode (default).
|
||||
// NJ_USE_WIN32=1 = If compiling with MSVC for Win32 and
|
||||
// NJ_USE_LIBC=0, NanoJPEG will use its own
|
||||
// implementations of the required C library
|
||||
// functions (default if compiling with MSVC and
|
||||
// NJ_USE_LIBC=0).
|
||||
// NJ_CHROMA_FILTER=1 = Use the bicubic chroma upsampling filter
|
||||
// (default).
|
||||
// NJ_CHROMA_FILTER=0 = Use simple pixel repetition for chroma upsampling
|
||||
// (bad quality, but faster and less code).
|
||||
|
||||
|
||||
// API
|
||||
// ===
|
||||
//
|
||||
// For API documentation, read the "header section" below.
|
||||
|
||||
|
||||
// EXAMPLE
|
||||
// =======
|
||||
//
|
||||
// A few pages below, you can find an example program that uses NanoJPEG to
|
||||
// convert JPEG files into PGM or PPM. To compile it, use something like
|
||||
// gcc -O3 -D_NJ_EXAMPLE_PROGRAM -o nanojpeg nanojpeg.c
|
||||
// You may also add -std=c99 -Wall -Wextra -pedantic -Werror, if you want :)
|
||||
// The only thing you might need is -Wno-shift-negative-value, because this
|
||||
// code relies on the target machine using two's complement arithmetic, but
|
||||
// the C standard does not, even though *any* practically useful machine
|
||||
// nowadays uses two's complement.
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// HEADER SECTION //
|
||||
// copy and pase this into nanojpeg.h if you want //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _NANOJPEG_H
|
||||
#define _NANOJPEG_H
|
||||
|
||||
// nj_result_t: Result codes for njDecode().
|
||||
typedef enum _nj_result {
|
||||
NJ_OK = 0, // no error, decoding successful
|
||||
NJ_NO_JPEG, // not a JPEG file
|
||||
NJ_UNSUPPORTED, // unsupported format
|
||||
NJ_OUT_OF_MEM, // out of memory
|
||||
NJ_INTERNAL_ERR, // internal error
|
||||
NJ_SYNTAX_ERROR, // syntax error
|
||||
__NJ_FINISHED, // used internally, will never be reported
|
||||
} nj_result_t;
|
||||
|
||||
// njInit: Initialize NanoJPEG.
|
||||
// For safety reasons, this should be called at least one time before using
|
||||
// using any of the other NanoJPEG functions.
|
||||
void njInit(void);
|
||||
|
||||
// njDecode: Decode a JPEG image.
|
||||
// Decodes a memory dump of a JPEG file into internal buffers.
|
||||
// Parameters:
|
||||
// jpeg = The pointer to the memory dump.
|
||||
// size = The size of the JPEG file.
|
||||
// Return value: The error code in case of failure, or NJ_OK (zero) on success.
|
||||
nj_result_t njDecode(const void* jpeg, const int size);
|
||||
|
||||
// njGetWidth: Return the width (in pixels) of the most recently decoded
|
||||
// image. If njDecode() failed, the result of njGetWidth() is undefined.
|
||||
int njGetWidth(void);
|
||||
|
||||
// njGetHeight: Return the height (in pixels) of the most recently decoded
|
||||
// image. If njDecode() failed, the result of njGetHeight() is undefined.
|
||||
int njGetHeight(void);
|
||||
|
||||
// njIsColor: Return 1 if the most recently decoded image is a color image
|
||||
// (RGB) or 0 if it is a grayscale image. If njDecode() failed, the result
|
||||
// of njGetWidth() is undefined.
|
||||
int njIsColor(void);
|
||||
|
||||
// njGetImage: Returns the decoded image data.
|
||||
// Returns a pointer to the most recently image. The memory layout it byte-
|
||||
// oriented, top-down, without any padding between lines. Pixels of color
|
||||
// images will be stored as three consecutive bytes for the red, green and
|
||||
// blue channels. This data format is thus compatible with the PGM or PPM
|
||||
// file formats and the OpenGL texture formats GL_LUMINANCE8 or GL_RGB8.
|
||||
// If njDecode() failed, the result of njGetImage() is undefined.
|
||||
unsigned char* njGetImage(void);
|
||||
|
||||
// njGetImageSize: Returns the size (in bytes) of the image data returned
|
||||
// by njGetImage(). If njDecode() failed, the result of njGetImageSize() is
|
||||
// undefined.
|
||||
int njGetImageSize(void);
|
||||
|
||||
// njDone: Uninitialize NanoJPEG.
|
||||
// Resets NanoJPEG's internal state and frees all memory that has been
|
||||
// allocated at run-time by NanoJPEG. It is still possible to decode another
|
||||
// image after a njDone() call.
|
||||
void njDone(void);
|
||||
|
||||
#endif//_NANOJPEG_H
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CONFIGURATION SECTION //
|
||||
// adjust the default settings for the NJ_ defines here //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef NJ_USE_LIBC
|
||||
#define NJ_USE_LIBC 1
|
||||
#endif
|
||||
|
||||
#ifndef NJ_USE_WIN32
|
||||
#ifdef _MSC_VER
|
||||
#define NJ_USE_WIN32 (!NJ_USE_LIBC)
|
||||
#else
|
||||
#define NJ_USE_WIN32 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NJ_CHROMA_FILTER
|
||||
#define NJ_CHROMA_FILTER 1
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EXAMPLE PROGRAM //
|
||||
// just define _NJ_EXAMPLE_PROGRAM to compile this (requires NJ_USE_LIBC) //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef _NJ_EXAMPLE_PROGRAM
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int size;
|
||||
char *buf;
|
||||
FILE *f;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <input.jpg> [<output.ppm>]\n", argv[0]);
|
||||
return 2;
|
||||
}
|
||||
f = fopen(argv[1], "rb");
|
||||
if (!f) {
|
||||
printf("Error opening the input file.\n");
|
||||
return 1;
|
||||
}
|
||||
fseek(f, 0, SEEK_END);
|
||||
size = (int) ftell(f);
|
||||
buf = (char*) malloc(size);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
size = (int) fread(buf, 1, size, f);
|
||||
fclose(f);
|
||||
|
||||
njInit();
|
||||
if (njDecode(buf, size)) {
|
||||
free((void*)buf);
|
||||
printf("Error decoding the input file.\n");
|
||||
return 1;
|
||||
}
|
||||
free((void*)buf);
|
||||
|
||||
f = fopen((argc > 2) ? argv[2] : (njIsColor() ? "nanojpeg_out.ppm" : "nanojpeg_out.pgm"), "wb");
|
||||
if (!f) {
|
||||
printf("Error opening the output file.\n");
|
||||
return 1;
|
||||
}
|
||||
fprintf(f, "P%d\n%d %d\n255\n", njIsColor() ? 6 : 5, njGetWidth(), njGetHeight());
|
||||
fwrite(njGetImage(), 1, njGetImageSize(), f);
|
||||
fclose(f);
|
||||
njDone();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPLEMENTATION SECTION //
|
||||
// you may stop reading here //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _NJ_INCLUDE_HEADER_ONLY
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define NJ_INLINE static __inline
|
||||
#define NJ_FORCE_INLINE static __forceinline
|
||||
#else
|
||||
#define NJ_INLINE static inline
|
||||
#define NJ_FORCE_INLINE static inline
|
||||
#endif
|
||||
|
||||
#if NJ_USE_LIBC
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define njAllocMem malloc
|
||||
#define njFreeMem free
|
||||
#define njFillMem memset
|
||||
#define njCopyMem memcpy
|
||||
#elif NJ_USE_WIN32
|
||||
#include <windows.h>
|
||||
#define njAllocMem(size) ((void*) LocalAlloc(LMEM_FIXED, (SIZE_T)(size)))
|
||||
#define njFreeMem(block) ((void) LocalFree((HLOCAL) block))
|
||||
NJ_INLINE void njFillMem(void* block, unsigned char value, int count) { __asm {
|
||||
mov edi, block
|
||||
mov al, value
|
||||
mov ecx, count
|
||||
rep stosb
|
||||
} }
|
||||
NJ_INLINE void njCopyMem(void* dest, const void* src, int count) { __asm {
|
||||
mov edi, dest
|
||||
mov esi, src
|
||||
mov ecx, count
|
||||
rep movsb
|
||||
} }
|
||||
#else
|
||||
extern void* njAllocMem(int size);
|
||||
extern void njFreeMem(void* block);
|
||||
extern void njFillMem(void* block, unsigned char byte, int size);
|
||||
extern void njCopyMem(void* dest, const void* src, int size);
|
||||
#endif
|
||||
|
||||
typedef struct _nj_code {
|
||||
unsigned char bits, code;
|
||||
} nj_vlc_code_t;
|
||||
|
||||
typedef struct _nj_cmp {
|
||||
int cid;
|
||||
int ssx, ssy;
|
||||
int width, height;
|
||||
int stride;
|
||||
int qtsel;
|
||||
int actabsel, dctabsel;
|
||||
int dcpred;
|
||||
unsigned char *pixels;
|
||||
} nj_component_t;
|
||||
|
||||
typedef struct _nj_ctx {
|
||||
nj_result_t error;
|
||||
const unsigned char *pos;
|
||||
int size;
|
||||
int length;
|
||||
int width, height;
|
||||
int mbwidth, mbheight;
|
||||
int mbsizex, mbsizey;
|
||||
int ncomp;
|
||||
nj_component_t comp[3];
|
||||
int qtused, qtavail;
|
||||
unsigned char qtab[4][64];
|
||||
nj_vlc_code_t vlctab[4][65536];
|
||||
int buf, bufbits;
|
||||
int block[64];
|
||||
int rstinterval;
|
||||
unsigned char *rgb;
|
||||
} nj_context_t;
|
||||
|
||||
static nj_context_t nj;
|
||||
|
||||
static const char njZZ[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18,
|
||||
11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
|
||||
42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45,
|
||||
38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 };
|
||||
|
||||
NJ_FORCE_INLINE unsigned char njClip(const int x) {
|
||||
return (x < 0) ? 0 : ((x > 0xFF) ? 0xFF : (unsigned char) x);
|
||||
}
|
||||
|
||||
#define W1 2841
|
||||
#define W2 2676
|
||||
#define W3 2408
|
||||
#define W5 1609
|
||||
#define W6 1108
|
||||
#define W7 565
|
||||
|
||||
NJ_INLINE void njRowIDCT(int* blk) {
|
||||
int x0, x1, x2, x3, x4, x5, x6, x7, x8;
|
||||
if (!((x1 = blk[4] << 11)
|
||||
| (x2 = blk[6])
|
||||
| (x3 = blk[2])
|
||||
| (x4 = blk[1])
|
||||
| (x5 = blk[7])
|
||||
| (x6 = blk[5])
|
||||
| (x7 = blk[3])))
|
||||
{
|
||||
blk[0] = blk[1] = blk[2] = blk[3] = blk[4] = blk[5] = blk[6] = blk[7] = blk[0] << 3;
|
||||
return;
|
||||
}
|
||||
x0 = (blk[0] << 11) + 128;
|
||||
x8 = W7 * (x4 + x5);
|
||||
x4 = x8 + (W1 - W7) * x4;
|
||||
x5 = x8 - (W1 + W7) * x5;
|
||||
x8 = W3 * (x6 + x7);
|
||||
x6 = x8 - (W3 - W5) * x6;
|
||||
x7 = x8 - (W3 + W5) * x7;
|
||||
x8 = x0 + x1;
|
||||
x0 -= x1;
|
||||
x1 = W6 * (x3 + x2);
|
||||
x2 = x1 - (W2 + W6) * x2;
|
||||
x3 = x1 + (W2 - W6) * x3;
|
||||
x1 = x4 + x6;
|
||||
x4 -= x6;
|
||||
x6 = x5 + x7;
|
||||
x5 -= x7;
|
||||
x7 = x8 + x3;
|
||||
x8 -= x3;
|
||||
x3 = x0 + x2;
|
||||
x0 -= x2;
|
||||
x2 = (181 * (x4 + x5) + 128) >> 8;
|
||||
x4 = (181 * (x4 - x5) + 128) >> 8;
|
||||
blk[0] = (x7 + x1) >> 8;
|
||||
blk[1] = (x3 + x2) >> 8;
|
||||
blk[2] = (x0 + x4) >> 8;
|
||||
blk[3] = (x8 + x6) >> 8;
|
||||
blk[4] = (x8 - x6) >> 8;
|
||||
blk[5] = (x0 - x4) >> 8;
|
||||
blk[6] = (x3 - x2) >> 8;
|
||||
blk[7] = (x7 - x1) >> 8;
|
||||
}
|
||||
|
||||
NJ_INLINE void njColIDCT(const int* blk, unsigned char *out, int stride) {
|
||||
int x0, x1, x2, x3, x4, x5, x6, x7, x8;
|
||||
if (!((x1 = blk[8*4] << 8)
|
||||
| (x2 = blk[8*6])
|
||||
| (x3 = blk[8*2])
|
||||
| (x4 = blk[8*1])
|
||||
| (x5 = blk[8*7])
|
||||
| (x6 = blk[8*5])
|
||||
| (x7 = blk[8*3])))
|
||||
{
|
||||
x1 = njClip(((blk[0] + 32) >> 6) + 128);
|
||||
for (x0 = 8; x0; --x0) {
|
||||
*out = (unsigned char) x1;
|
||||
out += stride;
|
||||
}
|
||||
return;
|
||||
}
|
||||
x0 = (blk[0] << 8) + 8192;
|
||||
x8 = W7 * (x4 + x5) + 4;
|
||||
x4 = (x8 + (W1 - W7) * x4) >> 3;
|
||||
x5 = (x8 - (W1 + W7) * x5) >> 3;
|
||||
x8 = W3 * (x6 + x7) + 4;
|
||||
x6 = (x8 - (W3 - W5) * x6) >> 3;
|
||||
x7 = (x8 - (W3 + W5) * x7) >> 3;
|
||||
x8 = x0 + x1;
|
||||
x0 -= x1;
|
||||
x1 = W6 * (x3 + x2) + 4;
|
||||
x2 = (x1 - (W2 + W6) * x2) >> 3;
|
||||
x3 = (x1 + (W2 - W6) * x3) >> 3;
|
||||
x1 = x4 + x6;
|
||||
x4 -= x6;
|
||||
x6 = x5 + x7;
|
||||
x5 -= x7;
|
||||
x7 = x8 + x3;
|
||||
x8 -= x3;
|
||||
x3 = x0 + x2;
|
||||
x0 -= x2;
|
||||
x2 = (181 * (x4 + x5) + 128) >> 8;
|
||||
x4 = (181 * (x4 - x5) + 128) >> 8;
|
||||
*out = njClip(((x7 + x1) >> 14) + 128); out += stride;
|
||||
*out = njClip(((x3 + x2) >> 14) + 128); out += stride;
|
||||
*out = njClip(((x0 + x4) >> 14) + 128); out += stride;
|
||||
*out = njClip(((x8 + x6) >> 14) + 128); out += stride;
|
||||
*out = njClip(((x8 - x6) >> 14) + 128); out += stride;
|
||||
*out = njClip(((x0 - x4) >> 14) + 128); out += stride;
|
||||
*out = njClip(((x3 - x2) >> 14) + 128); out += stride;
|
||||
*out = njClip(((x7 - x1) >> 14) + 128);
|
||||
}
|
||||
|
||||
#define njThrow(e) do { nj.error = e; return; } while (0)
|
||||
#define njCheckError() do { if (nj.error) return; } while (0)
|
||||
|
||||
static int njShowBits(int bits) {
|
||||
unsigned char newbyte;
|
||||
if (!bits) return 0;
|
||||
while (nj.bufbits < bits) {
|
||||
if (nj.size <= 0) {
|
||||
nj.buf = (nj.buf << 8) | 0xFF;
|
||||
nj.bufbits += 8;
|
||||
continue;
|
||||
}
|
||||
newbyte = *nj.pos++;
|
||||
nj.size--;
|
||||
nj.bufbits += 8;
|
||||
nj.buf = (nj.buf << 8) | newbyte;
|
||||
if (newbyte == 0xFF) {
|
||||
if (nj.size) {
|
||||
unsigned char marker = *nj.pos++;
|
||||
nj.size--;
|
||||
switch (marker) {
|
||||
case 0x00:
|
||||
case 0xFF:
|
||||
break;
|
||||
case 0xD9: nj.size = 0; break;
|
||||
default:
|
||||
if ((marker & 0xF8) != 0xD0)
|
||||
nj.error = NJ_SYNTAX_ERROR;
|
||||
else {
|
||||
nj.buf = (nj.buf << 8) | marker;
|
||||
nj.bufbits += 8;
|
||||
}
|
||||
}
|
||||
} else
|
||||
nj.error = NJ_SYNTAX_ERROR;
|
||||
}
|
||||
}
|
||||
return (nj.buf >> (nj.bufbits - bits)) & ((1 << bits) - 1);
|
||||
}
|
||||
|
||||
NJ_INLINE void njSkipBits(int bits) {
|
||||
if (nj.bufbits < bits)
|
||||
(void) njShowBits(bits);
|
||||
nj.bufbits -= bits;
|
||||
}
|
||||
|
||||
NJ_INLINE int njGetBits(int bits) {
|
||||
int res = njShowBits(bits);
|
||||
njSkipBits(bits);
|
||||
return res;
|
||||
}
|
||||
|
||||
NJ_INLINE void njByteAlign(void) {
|
||||
nj.bufbits &= 0xF8;
|
||||
}
|
||||
|
||||
static void njSkip(int count) {
|
||||
nj.pos += count;
|
||||
nj.size -= count;
|
||||
nj.length -= count;
|
||||
if (nj.size < 0) nj.error = NJ_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
NJ_INLINE unsigned short njDecode16(const unsigned char *pos) {
|
||||
return (pos[0] << 8) | pos[1];
|
||||
}
|
||||
|
||||
static void njDecodeLength(void) {
|
||||
if (nj.size < 2) njThrow(NJ_SYNTAX_ERROR);
|
||||
nj.length = njDecode16(nj.pos);
|
||||
if (nj.length > nj.size) njThrow(NJ_SYNTAX_ERROR);
|
||||
njSkip(2);
|
||||
}
|
||||
|
||||
NJ_INLINE void njSkipMarker(void) {
|
||||
njDecodeLength();
|
||||
njSkip(nj.length);
|
||||
}
|
||||
|
||||
NJ_INLINE void njDecodeSOF(void) {
|
||||
int i, ssxmax = 0, ssymax = 0;
|
||||
nj_component_t* c;
|
||||
njDecodeLength();
|
||||
njCheckError();
|
||||
if (nj.length < 9) njThrow(NJ_SYNTAX_ERROR);
|
||||
if (nj.pos[0] != 8) njThrow(NJ_UNSUPPORTED);
|
||||
nj.height = njDecode16(nj.pos+1);
|
||||
nj.width = njDecode16(nj.pos+3);
|
||||
if (!nj.width || !nj.height) njThrow(NJ_SYNTAX_ERROR);
|
||||
nj.ncomp = nj.pos[5];
|
||||
njSkip(6);
|
||||
switch (nj.ncomp) {
|
||||
case 1:
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
njThrow(NJ_UNSUPPORTED);
|
||||
}
|
||||
if (nj.length < (nj.ncomp * 3)) njThrow(NJ_SYNTAX_ERROR);
|
||||
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
|
||||
c->cid = nj.pos[0];
|
||||
if (!(c->ssx = nj.pos[1] >> 4)) njThrow(NJ_SYNTAX_ERROR);
|
||||
if (c->ssx & (c->ssx - 1)) njThrow(NJ_UNSUPPORTED); // non-power of two
|
||||
if (!(c->ssy = nj.pos[1] & 15)) njThrow(NJ_SYNTAX_ERROR);
|
||||
if (c->ssy & (c->ssy - 1)) njThrow(NJ_UNSUPPORTED); // non-power of two
|
||||
if ((c->qtsel = nj.pos[2]) & 0xFC) njThrow(NJ_SYNTAX_ERROR);
|
||||
njSkip(3);
|
||||
nj.qtused |= 1 << c->qtsel;
|
||||
if (c->ssx > ssxmax) ssxmax = c->ssx;
|
||||
if (c->ssy > ssymax) ssymax = c->ssy;
|
||||
}
|
||||
if (nj.ncomp == 1) {
|
||||
c = nj.comp;
|
||||
c->ssx = c->ssy = ssxmax = ssymax = 1;
|
||||
}
|
||||
nj.mbsizex = ssxmax << 3;
|
||||
nj.mbsizey = ssymax << 3;
|
||||
nj.mbwidth = (nj.width + nj.mbsizex - 1) / nj.mbsizex;
|
||||
nj.mbheight = (nj.height + nj.mbsizey - 1) / nj.mbsizey;
|
||||
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
|
||||
c->width = (nj.width * c->ssx + ssxmax - 1) / ssxmax;
|
||||
c->height = (nj.height * c->ssy + ssymax - 1) / ssymax;
|
||||
c->stride = nj.mbwidth * c->ssx << 3;
|
||||
if (((c->width < 3) && (c->ssx != ssxmax)) || ((c->height < 3) && (c->ssy != ssymax))) njThrow(NJ_UNSUPPORTED);
|
||||
if (!(c->pixels = (unsigned char*) njAllocMem(c->stride * nj.mbheight * c->ssy << 3))) njThrow(NJ_OUT_OF_MEM);
|
||||
}
|
||||
if (nj.ncomp == 3) {
|
||||
nj.rgb = (unsigned char*) njAllocMem(nj.width * nj.height * nj.ncomp);
|
||||
if (!nj.rgb) njThrow(NJ_OUT_OF_MEM);
|
||||
}
|
||||
njSkip(nj.length);
|
||||
}
|
||||
|
||||
NJ_INLINE void njDecodeDHT(void) {
|
||||
int codelen, currcnt, remain, spread, i, j;
|
||||
nj_vlc_code_t *vlc;
|
||||
static unsigned char counts[16];
|
||||
njDecodeLength();
|
||||
njCheckError();
|
||||
while (nj.length >= 17) {
|
||||
i = nj.pos[0];
|
||||
if (i & 0xEC) njThrow(NJ_SYNTAX_ERROR);
|
||||
if (i & 0x02) njThrow(NJ_UNSUPPORTED);
|
||||
i = (i | (i >> 3)) & 3; // combined DC/AC + tableid value
|
||||
for (codelen = 1; codelen <= 16; ++codelen)
|
||||
counts[codelen - 1] = nj.pos[codelen];
|
||||
njSkip(17);
|
||||
vlc = &nj.vlctab[i][0];
|
||||
remain = spread = 65536;
|
||||
for (codelen = 1; codelen <= 16; ++codelen) {
|
||||
spread >>= 1;
|
||||
currcnt = counts[codelen - 1];
|
||||
if (!currcnt) continue;
|
||||
if (nj.length < currcnt) njThrow(NJ_SYNTAX_ERROR);
|
||||
remain -= currcnt << (16 - codelen);
|
||||
if (remain < 0) njThrow(NJ_SYNTAX_ERROR);
|
||||
for (i = 0; i < currcnt; ++i) {
|
||||
register unsigned char code = nj.pos[i];
|
||||
for (j = spread; j; --j) {
|
||||
vlc->bits = (unsigned char) codelen;
|
||||
vlc->code = code;
|
||||
++vlc;
|
||||
}
|
||||
}
|
||||
njSkip(currcnt);
|
||||
}
|
||||
while (remain--) {
|
||||
vlc->bits = 0;
|
||||
++vlc;
|
||||
}
|
||||
}
|
||||
if (nj.length) njThrow(NJ_SYNTAX_ERROR);
|
||||
}
|
||||
|
||||
NJ_INLINE void njDecodeDQT(void) {
|
||||
int i;
|
||||
unsigned char *t;
|
||||
njDecodeLength();
|
||||
njCheckError();
|
||||
while (nj.length >= 65) {
|
||||
i = nj.pos[0];
|
||||
if (i & 0xFC) njThrow(NJ_SYNTAX_ERROR);
|
||||
nj.qtavail |= 1 << i;
|
||||
t = &nj.qtab[i][0];
|
||||
for (i = 0; i < 64; ++i)
|
||||
t[i] = nj.pos[i + 1];
|
||||
njSkip(65);
|
||||
}
|
||||
if (nj.length) njThrow(NJ_SYNTAX_ERROR);
|
||||
}
|
||||
|
||||
NJ_INLINE void njDecodeDRI(void) {
|
||||
njDecodeLength();
|
||||
njCheckError();
|
||||
if (nj.length < 2) njThrow(NJ_SYNTAX_ERROR);
|
||||
nj.rstinterval = njDecode16(nj.pos);
|
||||
njSkip(nj.length);
|
||||
}
|
||||
|
||||
static int njGetVLC(nj_vlc_code_t* vlc, unsigned char* code) {
|
||||
int value = njShowBits(16);
|
||||
int bits = vlc[value].bits;
|
||||
if (!bits) { nj.error = NJ_SYNTAX_ERROR; return 0; }
|
||||
njSkipBits(bits);
|
||||
value = vlc[value].code;
|
||||
if (code) *code = (unsigned char) value;
|
||||
bits = value & 15;
|
||||
if (!bits) return 0;
|
||||
value = njGetBits(bits);
|
||||
if (value < (1 << (bits - 1)))
|
||||
value += ((-1) << bits) + 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
NJ_INLINE void njDecodeBlock(nj_component_t* c, unsigned char* out) {
|
||||
unsigned char code = 0;
|
||||
int value, coef = 0;
|
||||
njFillMem(nj.block, 0, sizeof(nj.block));
|
||||
c->dcpred += njGetVLC(&nj.vlctab[c->dctabsel][0], NULL);
|
||||
nj.block[0] = (c->dcpred) * nj.qtab[c->qtsel][0];
|
||||
do {
|
||||
value = njGetVLC(&nj.vlctab[c->actabsel][0], &code);
|
||||
if (!code) break; // EOB
|
||||
if (!(code & 0x0F) && (code != 0xF0)) njThrow(NJ_SYNTAX_ERROR);
|
||||
coef += (code >> 4) + 1;
|
||||
if (coef > 63) njThrow(NJ_SYNTAX_ERROR);
|
||||
nj.block[(int) njZZ[coef]] = value * nj.qtab[c->qtsel][coef];
|
||||
} while (coef < 63);
|
||||
for (coef = 0; coef < 64; coef += 8)
|
||||
njRowIDCT(&nj.block[coef]);
|
||||
for (coef = 0; coef < 8; ++coef)
|
||||
njColIDCT(&nj.block[coef], &out[coef], c->stride);
|
||||
}
|
||||
|
||||
NJ_INLINE void njDecodeScan(void) {
|
||||
int i, mbx, mby, sbx, sby;
|
||||
int rstcount = nj.rstinterval, nextrst = 0;
|
||||
nj_component_t* c;
|
||||
njDecodeLength();
|
||||
njCheckError();
|
||||
if (nj.length < (4 + 2 * nj.ncomp)) njThrow(NJ_SYNTAX_ERROR);
|
||||
if (nj.pos[0] != nj.ncomp) njThrow(NJ_UNSUPPORTED);
|
||||
njSkip(1);
|
||||
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
|
||||
if (nj.pos[0] != c->cid) njThrow(NJ_SYNTAX_ERROR);
|
||||
if (nj.pos[1] & 0xEE) njThrow(NJ_SYNTAX_ERROR);
|
||||
c->dctabsel = nj.pos[1] >> 4;
|
||||
c->actabsel = (nj.pos[1] & 1) | 2;
|
||||
njSkip(2);
|
||||
}
|
||||
if (nj.pos[0] || (nj.pos[1] != 63) || nj.pos[2]) njThrow(NJ_UNSUPPORTED);
|
||||
njSkip(nj.length);
|
||||
for (mbx = mby = 0;;) {
|
||||
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c)
|
||||
for (sby = 0; sby < c->ssy; ++sby)
|
||||
for (sbx = 0; sbx < c->ssx; ++sbx) {
|
||||
njDecodeBlock(c, &c->pixels[((mby * c->ssy + sby) * c->stride + mbx * c->ssx + sbx) << 3]);
|
||||
njCheckError();
|
||||
}
|
||||
if (++mbx >= nj.mbwidth) {
|
||||
mbx = 0;
|
||||
if (++mby >= nj.mbheight) break;
|
||||
}
|
||||
if (nj.rstinterval && !(--rstcount)) {
|
||||
njByteAlign();
|
||||
i = njGetBits(16);
|
||||
if (((i & 0xFFF8) != 0xFFD0) || ((i & 7) != nextrst)) njThrow(NJ_SYNTAX_ERROR);
|
||||
nextrst = (nextrst + 1) & 7;
|
||||
rstcount = nj.rstinterval;
|
||||
for (i = 0; i < 3; ++i)
|
||||
nj.comp[i].dcpred = 0;
|
||||
}
|
||||
}
|
||||
nj.error = __NJ_FINISHED;
|
||||
}
|
||||
|
||||
#if NJ_CHROMA_FILTER
|
||||
|
||||
#define CF4A (-9)
|
||||
#define CF4B (111)
|
||||
#define CF4C (29)
|
||||
#define CF4D (-3)
|
||||
#define CF3A (28)
|
||||
#define CF3B (109)
|
||||
#define CF3C (-9)
|
||||
#define CF3X (104)
|
||||
#define CF3Y (27)
|
||||
#define CF3Z (-3)
|
||||
#define CF2A (139)
|
||||
#define CF2B (-11)
|
||||
#define CF(x) njClip(((x) + 64) >> 7)
|
||||
|
||||
NJ_INLINE void njUpsampleH(nj_component_t* c) {
|
||||
const int xmax = c->width - 3;
|
||||
unsigned char *out, *lin, *lout;
|
||||
int x, y;
|
||||
out = (unsigned char*) njAllocMem((c->width * c->height) << 1);
|
||||
if (!out) njThrow(NJ_OUT_OF_MEM);
|
||||
lin = c->pixels;
|
||||
lout = out;
|
||||
for (y = c->height; y; --y) {
|
||||
lout[0] = CF(CF2A * lin[0] + CF2B * lin[1]);
|
||||
lout[1] = CF(CF3X * lin[0] + CF3Y * lin[1] + CF3Z * lin[2]);
|
||||
lout[2] = CF(CF3A * lin[0] + CF3B * lin[1] + CF3C * lin[2]);
|
||||
for (x = 0; x < xmax; ++x) {
|
||||
lout[(x << 1) + 3] = CF(CF4A * lin[x] + CF4B * lin[x + 1] + CF4C * lin[x + 2] + CF4D * lin[x + 3]);
|
||||
lout[(x << 1) + 4] = CF(CF4D * lin[x] + CF4C * lin[x + 1] + CF4B * lin[x + 2] + CF4A * lin[x + 3]);
|
||||
}
|
||||
lin += c->stride;
|
||||
lout += c->width << 1;
|
||||
lout[-3] = CF(CF3A * lin[-1] + CF3B * lin[-2] + CF3C * lin[-3]);
|
||||
lout[-2] = CF(CF3X * lin[-1] + CF3Y * lin[-2] + CF3Z * lin[-3]);
|
||||
lout[-1] = CF(CF2A * lin[-1] + CF2B * lin[-2]);
|
||||
}
|
||||
c->width <<= 1;
|
||||
c->stride = c->width;
|
||||
njFreeMem((void*)c->pixels);
|
||||
c->pixels = out;
|
||||
}
|
||||
|
||||
NJ_INLINE void njUpsampleV(nj_component_t* c) {
|
||||
const int w = c->width, s1 = c->stride, s2 = s1 + s1;
|
||||
unsigned char *out, *cin, *cout;
|
||||
int x, y;
|
||||
out = (unsigned char*) njAllocMem((c->width * c->height) << 1);
|
||||
if (!out) njThrow(NJ_OUT_OF_MEM);
|
||||
for (x = 0; x < w; ++x) {
|
||||
cin = &c->pixels[x];
|
||||
cout = &out[x];
|
||||
*cout = CF(CF2A * cin[0] + CF2B * cin[s1]); cout += w;
|
||||
*cout = CF(CF3X * cin[0] + CF3Y * cin[s1] + CF3Z * cin[s2]); cout += w;
|
||||
*cout = CF(CF3A * cin[0] + CF3B * cin[s1] + CF3C * cin[s2]); cout += w;
|
||||
cin += s1;
|
||||
for (y = c->height - 3; y; --y) {
|
||||
*cout = CF(CF4A * cin[-s1] + CF4B * cin[0] + CF4C * cin[s1] + CF4D * cin[s2]); cout += w;
|
||||
*cout = CF(CF4D * cin[-s1] + CF4C * cin[0] + CF4B * cin[s1] + CF4A * cin[s2]); cout += w;
|
||||
cin += s1;
|
||||
}
|
||||
cin += s1;
|
||||
*cout = CF(CF3A * cin[0] + CF3B * cin[-s1] + CF3C * cin[-s2]); cout += w;
|
||||
*cout = CF(CF3X * cin[0] + CF3Y * cin[-s1] + CF3Z * cin[-s2]); cout += w;
|
||||
*cout = CF(CF2A * cin[0] + CF2B * cin[-s1]);
|
||||
}
|
||||
c->height <<= 1;
|
||||
c->stride = c->width;
|
||||
njFreeMem((void*) c->pixels);
|
||||
c->pixels = out;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
NJ_INLINE void njUpsample(nj_component_t* c) {
|
||||
int x, y, xshift = 0, yshift = 0;
|
||||
unsigned char *out, *lin, *lout;
|
||||
while (c->width < nj.width) { c->width <<= 1; ++xshift; }
|
||||
while (c->height < nj.height) { c->height <<= 1; ++yshift; }
|
||||
out = (unsigned char*) njAllocMem(c->width * c->height);
|
||||
if (!out) njThrow(NJ_OUT_OF_MEM);
|
||||
lin = c->pixels;
|
||||
lout = out;
|
||||
for (y = 0; y < c->height; ++y) {
|
||||
lin = &c->pixels[(y >> yshift) * c->stride];
|
||||
for (x = 0; x < c->width; ++x)
|
||||
lout[x] = lin[x >> xshift];
|
||||
lout += c->width;
|
||||
}
|
||||
c->stride = c->width;
|
||||
njFreeMem((void*) c->pixels);
|
||||
c->pixels = out;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
NJ_INLINE void njConvert(void) {
|
||||
int i;
|
||||
nj_component_t* c;
|
||||
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
|
||||
#if NJ_CHROMA_FILTER
|
||||
while ((c->width < nj.width) || (c->height < nj.height)) {
|
||||
if (c->width < nj.width) njUpsampleH(c);
|
||||
njCheckError();
|
||||
if (c->height < nj.height) njUpsampleV(c);
|
||||
njCheckError();
|
||||
}
|
||||
#else
|
||||
if ((c->width < nj.width) || (c->height < nj.height))
|
||||
njUpsample(c);
|
||||
#endif
|
||||
if ((c->width < nj.width) || (c->height < nj.height)) njThrow(NJ_INTERNAL_ERR);
|
||||
}
|
||||
if (nj.ncomp == 3) {
|
||||
// convert to RGB
|
||||
int x, yy;
|
||||
unsigned char *prgb = nj.rgb;
|
||||
const unsigned char *py = nj.comp[0].pixels;
|
||||
const unsigned char *pcb = nj.comp[1].pixels;
|
||||
const unsigned char *pcr = nj.comp[2].pixels;
|
||||
for (yy = nj.height; yy; --yy) {
|
||||
for (x = 0; x < nj.width; ++x) {
|
||||
register int y = py[x] << 8;
|
||||
register int cb = pcb[x] - 128;
|
||||
register int cr = pcr[x] - 128;
|
||||
*prgb++ = njClip((y + 359 * cr + 128) >> 8);
|
||||
*prgb++ = njClip((y - 88 * cb - 183 * cr + 128) >> 8);
|
||||
*prgb++ = njClip((y + 454 * cb + 128) >> 8);
|
||||
}
|
||||
py += nj.comp[0].stride;
|
||||
pcb += nj.comp[1].stride;
|
||||
pcr += nj.comp[2].stride;
|
||||
}
|
||||
} else if (nj.comp[0].width != nj.comp[0].stride) {
|
||||
// grayscale -> only remove stride
|
||||
unsigned char *pin = &nj.comp[0].pixels[nj.comp[0].stride];
|
||||
unsigned char *pout = &nj.comp[0].pixels[nj.comp[0].width];
|
||||
int y;
|
||||
for (y = nj.comp[0].height - 1; y; --y) {
|
||||
njCopyMem(pout, pin, nj.comp[0].width);
|
||||
pin += nj.comp[0].stride;
|
||||
pout += nj.comp[0].width;
|
||||
}
|
||||
nj.comp[0].stride = nj.comp[0].width;
|
||||
}
|
||||
}
|
||||
|
||||
void njInit(void) {
|
||||
njFillMem(&nj, 0, sizeof(nj_context_t));
|
||||
}
|
||||
|
||||
void njDone(void) {
|
||||
int i;
|
||||
for (i = 0; i < 3; ++i)
|
||||
if (nj.comp[i].pixels) njFreeMem((void*) nj.comp[i].pixels);
|
||||
if (nj.rgb) njFreeMem((void*) nj.rgb);
|
||||
njInit();
|
||||
}
|
||||
|
||||
nj_result_t njDecode(const void* jpeg, const int size) {
|
||||
njDone();
|
||||
nj.pos = (const unsigned char*) jpeg;
|
||||
nj.size = size & 0x7FFFFFFF;
|
||||
if (nj.size < 2) return NJ_NO_JPEG;
|
||||
if ((nj.pos[0] ^ 0xFF) | (nj.pos[1] ^ 0xD8)) return NJ_NO_JPEG;
|
||||
njSkip(2);
|
||||
while (!nj.error) {
|
||||
if ((nj.size < 2) || (nj.pos[0] != 0xFF)) return NJ_SYNTAX_ERROR;
|
||||
njSkip(2);
|
||||
switch (nj.pos[-1]) {
|
||||
case 0xC0: njDecodeSOF(); break;
|
||||
case 0xC4: njDecodeDHT(); break;
|
||||
case 0xDB: njDecodeDQT(); break;
|
||||
case 0xDD: njDecodeDRI(); break;
|
||||
case 0xDA: njDecodeScan(); break;
|
||||
case 0xFE: njSkipMarker(); break;
|
||||
default:
|
||||
if ((nj.pos[-1] & 0xF0) == 0xE0)
|
||||
njSkipMarker();
|
||||
else
|
||||
return NJ_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
if (nj.error != __NJ_FINISHED) return nj.error;
|
||||
nj.error = NJ_OK;
|
||||
njConvert();
|
||||
return nj.error;
|
||||
}
|
||||
|
||||
int njGetWidth(void) { return nj.width; }
|
||||
int njGetHeight(void) { return nj.height; }
|
||||
int njIsColor(void) { return (nj.ncomp != 1); }
|
||||
unsigned char* njGetImage(void) { return (nj.ncomp == 1) ? nj.comp[0].pixels : nj.rgb; }
|
||||
int njGetImageSize(void) { return nj.width * nj.height * nj.ncomp; }
|
||||
|
||||
#endif // _NJ_INCLUDE_HEADER_ONLY
|
|
@ -39,7 +39,7 @@ void Scrollable::resetIndex(void)
|
|||
mHid->page(0);
|
||||
}
|
||||
|
||||
void Scrollable::push_back(color_t color, color_t colorMessage, const std::string& message)
|
||||
void Scrollable::push_back(SDL_Color color, SDL_Color colorMessage, const std::string& message)
|
||||
{
|
||||
static const float spacing = mh / mVisibleEntries;
|
||||
Clickable* cell = new Clickable(mx, my + (size() % mVisibleEntries)*spacing, mw, spacing, color, colorMessage, message, false);
|
||||
|
@ -68,10 +68,10 @@ void Scrollable::draw(void)
|
|||
const size_t sz = size() - baseIndex > mVisibleEntries ? mVisibleEntries : size() - baseIndex;
|
||||
for (size_t i = baseIndex; i < baseIndex + sz; i++)
|
||||
{
|
||||
mCells.at(i)->draw(4);
|
||||
mCells.at(i)->draw(20);
|
||||
}
|
||||
|
||||
size_t blankRows = mVisibleEntries - sz;
|
||||
size_t rowHeight = mh / mVisibleEntries;
|
||||
rectangled(mx, my + sz * rowHeight, mw, rowHeight * blankRows, COLOR_GREY_DARKER);
|
||||
SDLH_DrawRect(mx, my + sz * rowHeight, mw, rowHeight * blankRows, COLOR_GREY_DARKER);
|
||||
}
|
|
@ -27,14 +27,13 @@
|
|||
#include "title.hpp"
|
||||
|
||||
static std::unordered_map<u128, std::vector<Title>> titles;
|
||||
static std::unordered_map<u64, std::pair<u8*, u8*>> icons;
|
||||
static std::unordered_map<u64, SDL_Texture*> icons;
|
||||
|
||||
void freeIcons(void)
|
||||
{
|
||||
for (auto& i : icons)
|
||||
{
|
||||
free(i.second.first);
|
||||
free(i.second.second);
|
||||
SDL_DestroyTexture(i.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,39 +42,9 @@ static void loadIcon(u64 id, NsApplicationControlData* nsacd, size_t iconsize)
|
|||
auto it = icons.find(id);
|
||||
if (it == icons.end())
|
||||
{
|
||||
uint8_t* imageptr = NULL;
|
||||
size_t imagesize = 256*256*3;
|
||||
|
||||
njInit();
|
||||
if (njDecode(nsacd->icon, iconsize) != NJ_OK)
|
||||
{
|
||||
njDone();
|
||||
return;
|
||||
}
|
||||
|
||||
if (njGetWidth() != 256 || njGetHeight() != 256 || (size_t)njGetImageSize() != imagesize || njIsColor() != 1)
|
||||
{
|
||||
njDone();
|
||||
return;
|
||||
}
|
||||
|
||||
imageptr = njGetImage();
|
||||
if (imageptr == NULL)
|
||||
{
|
||||
njDone();
|
||||
return;
|
||||
}
|
||||
|
||||
u8* mIcon = (u8*)malloc(imagesize);
|
||||
std::copy(imageptr, imageptr + imagesize, mIcon);
|
||||
|
||||
u8* mSmallIcon = (u8*)malloc(128*128*3);
|
||||
downscaleRGBImg(mIcon, mSmallIcon, 256, 256, 128, 128);
|
||||
|
||||
icons.insert({id, std::make_pair(mIcon, mSmallIcon)});
|
||||
|
||||
imageptr = NULL;
|
||||
njDone();
|
||||
SDL_Texture* texture;
|
||||
SDLH_LoadImage(&texture, nsacd->icon, iconsize);
|
||||
icons.insert({id, texture});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,16 +117,10 @@ std::vector<std::string> Title::saves()
|
|||
return mSaves;
|
||||
}
|
||||
|
||||
u8* Title::icon(void)
|
||||
SDL_Texture* Title::icon(void)
|
||||
{
|
||||
auto it = icons.find(mId);
|
||||
return it != icons.end() ? it->second.first : NULL;
|
||||
}
|
||||
|
||||
u8* Title::smallIcon(void)
|
||||
{
|
||||
auto it = icons.find(mId);
|
||||
return it != icons.end() ? it->second.second : NULL;
|
||||
return it != icons.end() ? it->second : NULL;
|
||||
}
|
||||
|
||||
void Title::refreshDirectories(void)
|
||||
|
@ -323,8 +286,8 @@ void refreshDirectories(u64 id)
|
|||
}
|
||||
}
|
||||
|
||||
u8* smallIcon(u128 uid, size_t i)
|
||||
SDL_Texture* smallIcon(u128 uid, size_t i)
|
||||
{
|
||||
std::unordered_map<u128, std::vector<Title>>::iterator it = titles.find(uid);
|
||||
return it != titles.end() ? it->second.at(i).smallIcon() : NULL;
|
||||
return it != titles.end() ? it->second.at(i).icon() : NULL;
|
||||
}
|
|
@ -34,7 +34,6 @@ void servicesExit(void)
|
|||
nsExit();
|
||||
Account::exit();
|
||||
Gui::exit();
|
||||
fontExit();
|
||||
plExit();
|
||||
romfsExit();
|
||||
}
|
||||
|
@ -56,11 +55,6 @@ Result servicesInit(void)
|
|||
return res;
|
||||
}
|
||||
|
||||
if (!fontInitialize())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (R_FAILED(res = Account::init()))
|
||||
{
|
||||
return res;
|
||||
|
|
Loading…
Reference in a new issue