[Horus] More bitmaps on SD. PNG format used instead of BMP. And yes it's a bad idea given the resources we have.
BIN
radio/sdcard/horus/THEMES/Darkblue/thumb.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
radio/sdcard/horus/THEMES/Darkblue/topmenu_opentx.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
radio/sdcard/horus/THEMES/Default/aboutbg.png
Normal file
After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
BIN
radio/sdcard/horus/THEMES/Default/mainbg.png
Normal file
After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
BIN
radio/sdcard/horus/THEMES/Default/sleep.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
radio/sdcard/horus/THEMES/Default/thumb.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
47
radio/sdcard/horus/THEMES/TBS/main.lua
Normal file
|
@ -0,0 +1,47 @@
|
|||
local function load()
|
||||
lcd.setColor(TEXT_COLOR_INDEX, WHITE)
|
||||
lcd.setColor(TEXT_BGCOLOR_INDEX, BLACK)
|
||||
lcd.setColor(TEXT_INVERTED_COLOR_INDEX, BLACK)
|
||||
lcd.setColor(TEXT_INVERTED_BGCOLOR_INDEX, YELLOW)
|
||||
lcd.setColor(LINE_COLOR_INDEX, GREY)
|
||||
lcd.setColor(SCROLLBOX_COLOR_INDEX, BLUE)
|
||||
lcd.setColor(MENU_TITLE_BGCOLOR_INDEX, DARKGREY)
|
||||
lcd.setColor(MENU_TITLE_COLOR_INDEX, WHITE)
|
||||
lcd.setColor(MENU_TITLE_DISABLE_COLOR_INDEX, BLACK)
|
||||
lcd.setColor(HEADER_COLOR_INDEX, lcd.RGB(32, 34, 42))
|
||||
lcd.setColor(ALARM_COLOR_INDEX, lcd.RGB(32, 34, 42))
|
||||
lcd.setColor(WARNING_COLOR_INDEX, YELLOW)
|
||||
lcd.setColor(TEXT_DISABLE_COLOR_INDEX, GREY)
|
||||
lcd.setColor(CURVE_AXIS_COLOR_INDEX, LIGHTGREY)
|
||||
lcd.setColor(CURVE_COLOR_INDEX, lcd.RGB(32, 34, 42))
|
||||
lcd.setColor(CURVE_CURSOR_COLOR_INDEX, lcd.RGB(32, 34, 42))
|
||||
lcd.setColor(TITLE_BGCOLOR_INDEX, lcd.RGB(32, 34, 42))
|
||||
lcd.setColor(TRIM_BGCOLOR_INDEX, YELLOW)
|
||||
lcd.setColor(TRIM_SHADOW_COLOR_INDEX, lcd.RGB(100, 100, 100))
|
||||
lcd.setColor(MAINVIEW_PANES_COLOR_INDEX, GREY)
|
||||
lcd.setColor(MAINVIEW_GRAPHICS_COLOR_INDEX, WHITE)
|
||||
lcd.setColor(HEADER_BGCOLOR_INDEX, BLACK)
|
||||
lcd.setColor(HEADER_ICON_BGCOLOR_INDEX, BLACK)
|
||||
lcd.setColor(HEADER_CURRENT_BGCOLOR_INDEX, lcd.RGB(10, 78, 121))
|
||||
lcd.setColor(OVERLAY_COLOR_INDEX, BLACK)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function drawBackground()
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, LCD_H, TEXT_BGCOLOR);
|
||||
end
|
||||
|
||||
local function drawTopbarBackground(icon)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, MENU_HEADER_HEIGHT, HEADER_BGCOLOR);
|
||||
lcd.drawLine(0, MENU_HEADER_HEIGHT, LCD_W, MENU_HEADER_HEIGHT, SOLID, TEXT_COLOR)
|
||||
|
||||
--if (icon) then
|
||||
--lcd.drawBitmapPattern(5, 7, icon, MENU_TITLE_COLOR);
|
||||
--else
|
||||
--lcd.drawBitmap(5, 7, LBM_TOPMENU_BMP_OPENTX);
|
||||
--end
|
||||
|
||||
--lcd.drawTopbarDatetime();
|
||||
end
|
||||
|
||||
return { name="TBS", load=load, drawBackground=drawBackground, drawTopbarBackground=drawTopbarBackground }
|
BIN
radio/sdcard/horus/THEMES/TBS/thumb.png
Normal file
After Width: | Height: | Size: 620 B |
|
@ -238,7 +238,10 @@ elseif(PCB STREQUAL SKY9X OR PCB STREQUAL 9XRPRO OR PCB STREQUAL AR9X)
|
|||
)
|
||||
set(SRC ${SRC} debug.cpp)
|
||||
set(FIRMWARE_SRC ${FIRMWARE_SRC} loadboot.cpp)
|
||||
elseif(PCB STREQUAL 9X OR PCB STREQUAL 9XR)
|
||||
elseif(PCB STREQUAL 9X OR PCB STREQUAL 9XR OR PCB STREQUAL 9X128 OR PCB STREQUAL 9XR128)
|
||||
option(SP22 "SmartieParts 2.2 Backlight support" OFF)
|
||||
option(HAPTIC "Haptic support" OFF)
|
||||
option(PWM_BACKLIGHT "PWM Backlight" OFF)
|
||||
set(ARCH AVR)
|
||||
set(MCU atmega64)
|
||||
string(TOLOWER ${PCB} FLAVOUR)
|
||||
|
@ -250,6 +253,51 @@ elseif(PCB STREQUAL 9X OR PCB STREQUAL 9XR)
|
|||
add_definitions(-DPCBSTD -DPCB${PCB} -DCPUM64)
|
||||
set(TARGET_SRC ${TARGET_SRC} board_stock.cpp)
|
||||
set(GUI_SRC ${GUI_SRC} ${9X_GUI_SRC})
|
||||
if(HAPTIC)
|
||||
add_definitions(-DHAPTIC)
|
||||
set(SRC ${SRC} haptic.cpp)
|
||||
endif()
|
||||
if(SP22)
|
||||
add_definitions(-DSP22)
|
||||
endif()
|
||||
if(PWM_BACKLIGHT)
|
||||
add_definitions(-DPWM_BACKLIGHT)
|
||||
endif()
|
||||
elseif(PCB STREQUAL 9X2561)
|
||||
set(ARCH AVR)
|
||||
set(MCU atmega2561)
|
||||
string(TOLOWER ${PCB} FLAVOUR)
|
||||
set(EEPROM EEPROM_RLC)
|
||||
add_definitions(-DEEPROM_VARIANT=${M2561_VARIANT})
|
||||
set(GUI_DIR 9x)
|
||||
set(TARGET_DIR 9x)
|
||||
set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} 9x_bitmaps)
|
||||
add_definitions(-DPCBSTD -DPCB${PCB} -DCPUM2561)
|
||||
set(TARGET_SRC ${TARGET_SRC} board_stock.cpp)
|
||||
set(GUI_SRC ${GUI_SRC} ${9X_GUI_SRC})
|
||||
if(HAPTIC)
|
||||
add_definitions(-DHAPTIC)
|
||||
set(SRC ${SRC} haptic.cpp)
|
||||
endif()
|
||||
if(SP22)
|
||||
add_definitions(-DSP22)
|
||||
endif()
|
||||
if(PWM_BACKLIGHT)
|
||||
add_definitions(-DPWM_BACKLIGHT)
|
||||
endif()
|
||||
elseif(PCB STREQUAL GRUVIN9X)
|
||||
set(ARCH AVR)
|
||||
set(MCU atmega2560)
|
||||
string(TOLOWER ${PCB} FLAVOUR)
|
||||
set(EEPROM EEPROM_RLC)
|
||||
add_definitions(-DEEPROM_VARIANT=0)
|
||||
set(GUI_DIR 9x)
|
||||
set(TARGET_DIR gruvin9x)
|
||||
set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} 9x_bitmaps)
|
||||
add_definitions(-DPCB${PCB} -DCPUM2560)
|
||||
set(TARGET_SRC ${TARGET_SRC} board_gruvin9x.cpp)
|
||||
set(GUI_SRC ${GUI_SRC} ${9X_GUI_SRC})
|
||||
elseif(PCB STREQUAL MEGA2560)
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown PCB '${PCB}'")
|
||||
endif()
|
||||
|
|
|
@ -461,7 +461,7 @@ const stbi_io_callbacks stbCallbacks = {
|
|||
stbc_eof
|
||||
};
|
||||
|
||||
BitmapBuffer * BitmapBuffer::load(const char * filename, bool transparent)
|
||||
BitmapBuffer * BitmapBuffer::load(const char * filename)
|
||||
{
|
||||
FIL imgFile;
|
||||
|
||||
|
@ -471,46 +471,45 @@ BitmapBuffer * BitmapBuffer::load(const char * filename, bool transparent)
|
|||
}
|
||||
|
||||
int w, h, n;
|
||||
unsigned char *img = stbi_load_from_callbacks(&stbCallbacks, &imgFile, &w, &h, &n, transparent ? 4 : 3);
|
||||
unsigned char * img = stbi_load_from_callbacks(&stbCallbacks, &imgFile, &w, &h, &n, 4);
|
||||
f_close(&imgFile);
|
||||
|
||||
if (!img) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//convert to RGB565 or ARGB4444 fromat
|
||||
// todo use dma2d for conversion from 888 to 565
|
||||
unsigned char * p = img;
|
||||
BitmapBuffer * bmp = new BitmapBuffer(w, h);
|
||||
uint16_t * dest = bmp->data;
|
||||
// convert to RGB565 or ARGB4444 format
|
||||
BitmapBuffer * bmp = new BitmapBuffer(n == 4 ? BMP_ARGB4444 : BMP_RGB565, w, h);
|
||||
if (bmp == NULL) {
|
||||
TRACE("load_stb() malloc failed");
|
||||
stbi_image_free(img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (transparent) {
|
||||
#if 0
|
||||
DMABitmapConvert(bmp->data, img, w, h, n == 4 ? DMA2D_ARGB4444 : DMA2D_RGB565);
|
||||
#else
|
||||
uint16_t * dest = bmp->getData();
|
||||
const uint8_t * p = img;
|
||||
if (n == 4) {
|
||||
for(int row = 0; row < h; ++row) {
|
||||
unsigned char *l = p;
|
||||
for(int col = 0; col < w; ++col) {
|
||||
*dest = ARGB(l[3], l[0], l[1], l[2]);
|
||||
*dest = ARGB(p[3], p[0], p[1], p[2]);
|
||||
++dest;
|
||||
l += 4;
|
||||
p += 4;
|
||||
}
|
||||
p += 4 * w;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int row = 0; row < h; ++row) {
|
||||
unsigned char *l = p;
|
||||
for(int col = 0; col < w; ++col) {
|
||||
*dest = RGB(l[0], l[1], l[2]);
|
||||
*dest = RGB(p[0], p[1], p[2]);
|
||||
++dest;
|
||||
l += 3;
|
||||
}
|
||||
p += 3 * w;
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
stbi_image_free(img);
|
||||
return bmp;
|
||||
|
|
|
@ -31,32 +31,48 @@ typedef int coord_t;
|
|||
typedef uint32_t LcdFlags;
|
||||
typedef uint16_t display_t;
|
||||
|
||||
enum BitmapFormats
|
||||
{
|
||||
BMP_RGB565,
|
||||
BMP_ARGB4444
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class BitmapBufferBase
|
||||
{
|
||||
public:
|
||||
BitmapBufferBase(int width, int height, T * data):
|
||||
BitmapBufferBase(uint8_t format, uint16_t width, uint16_t height, T * data):
|
||||
format(format),
|
||||
width(width),
|
||||
height(height),
|
||||
data(data)
|
||||
{
|
||||
}
|
||||
|
||||
int getWidth() const
|
||||
inline uint8_t getFormat() const
|
||||
{
|
||||
return format;
|
||||
}
|
||||
|
||||
inline uint16_t getWidth() const
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
int getHeight() const
|
||||
inline uint16_t getHeight() const
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
protected:
|
||||
int width;
|
||||
int height;
|
||||
inline T * getData() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
public: // TODO protected
|
||||
protected:
|
||||
uint8_t format;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
T * data;
|
||||
};
|
||||
|
||||
|
@ -69,22 +85,24 @@ class BitmapBuffer: public BitmapBufferBase<uint16_t>
|
|||
|
||||
public:
|
||||
|
||||
BitmapBuffer(int width, int height):
|
||||
BitmapBufferBase<uint16_t>(width, height, NULL),
|
||||
BitmapBuffer(uint8_t format, uint16_t width, uint16_t height):
|
||||
BitmapBufferBase<uint16_t>(format, width, height, NULL),
|
||||
dataAllocated(true)
|
||||
{
|
||||
data = (uint16_t *)malloc(width*height*sizeof(uint16_t));
|
||||
}
|
||||
|
||||
BitmapBuffer(int width, int height, uint16_t * data):
|
||||
BitmapBufferBase<uint16_t>(width, height, data),
|
||||
BitmapBuffer(uint8_t format, uint16_t width, uint16_t height, uint16_t * data):
|
||||
BitmapBufferBase<uint16_t>(format, width, height, data),
|
||||
dataAllocated(false)
|
||||
{
|
||||
}
|
||||
|
||||
~BitmapBuffer()
|
||||
{
|
||||
if (dataAllocated) free(data);
|
||||
if (dataAllocated) {
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
|
@ -137,7 +155,7 @@ class BitmapBuffer: public BitmapBufferBase<uint16_t>
|
|||
|
||||
void drawBitmapPatternPie(coord_t x0, coord_t y0, const uint8_t * img, LcdFlags flags, int startAngle, int endAngle);
|
||||
|
||||
static BitmapBuffer * load(const char * filename, bool transparent = false);
|
||||
static BitmapBuffer * load(const char * filename);
|
||||
|
||||
void drawBitmapPattern(coord_t x, coord_t y, const uint8_t * bmp, LcdFlags flags, coord_t offset=0, coord_t width=0);
|
||||
|
||||
|
@ -148,6 +166,8 @@ class BitmapBuffer: public BitmapBufferBase<uint16_t>
|
|||
template<class T>
|
||||
void drawBitmap(coord_t x, coord_t y, const T * bmp, coord_t srcx=0, coord_t srcy=0, coord_t w=0, coord_t h=0, float scale=0)
|
||||
{
|
||||
if (!bmp) return;
|
||||
|
||||
int srcw = bmp->getWidth();
|
||||
int srch = bmp->getHeight();
|
||||
|
||||
|
@ -167,7 +187,12 @@ class BitmapBuffer: public BitmapBufferBase<uint16_t>
|
|||
if (y + h > height) {
|
||||
h = height - y;
|
||||
}
|
||||
DMACopyBitmap(data, width, x, y, bmp->data, srcw, srcx, srcy, w, h);
|
||||
if (bmp->getFormat() == BMP_ARGB4444) {
|
||||
DMACopyAlphaBitmap(data, this->width, x, y, bmp->getData(), srcw, srcx, srcy, w, h);
|
||||
}
|
||||
else {
|
||||
DMACopyBitmap(data, width, x, y, bmp->getData(), srcw, srcx, srcy, w, h);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int scaledw = w * scale;
|
||||
|
@ -180,7 +205,7 @@ class BitmapBuffer: public BitmapBufferBase<uint16_t>
|
|||
|
||||
for (int i = 0; i < scaledh; i++) {
|
||||
uint16_t * p = &data[(y + i) * width + x];
|
||||
const uint16_t * qstart = &bmp->data[(srcy + int(i / scale)) * bmp->getWidth() + srcx];
|
||||
const uint16_t * qstart = &bmp->getData()[(srcy + int(i / scale)) * bmp->getWidth() + srcx];
|
||||
for (int j = 0; j < scaledw; j++) {
|
||||
const uint16_t * q = qstart + int(j / scale);
|
||||
*p = *q;
|
||||
|
@ -205,19 +230,6 @@ class BitmapBuffer: public BitmapBufferBase<uint16_t>
|
|||
drawBitmap(x+(w-width)/2, y, bitmap, 0, 0, 0, 0, scale);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void drawAlphaBitmap(coord_t x, coord_t y, const T * bmp)
|
||||
{
|
||||
int width = bmp->getWidth();
|
||||
int height = bmp->getHeight();
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
DMACopyAlphaBitmap(data, this->width, x, y, bmp->data, width, height);
|
||||
}
|
||||
};
|
||||
|
||||
extern BitmapBuffer * lcd;
|
||||
|
|
|
@ -248,6 +248,10 @@ const uint8_t LBM_LIBRARY_SLOT[] = {
|
|||
#include "mask_library_slot.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_ACTIVE_MODEL[] = {
|
||||
#include "mask_library_active_model.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_LIBRARY_CURSOR[] = {
|
||||
#include "mask_library_category_index.lbm"
|
||||
};
|
||||
|
|
|
@ -59,6 +59,7 @@ extern const uint8_t * const LBM_MAINVIEWS_ICONS[];
|
|||
// Model selection icons
|
||||
extern const uint8_t LBM_LIBRARY_ICON[];
|
||||
extern const uint8_t LBM_LIBRARY_SLOT[];
|
||||
extern const uint8_t LBM_ACTIVE_MODEL[];
|
||||
extern const uint8_t LBM_LIBRARY_CURSOR[];
|
||||
extern const uint8_t LBM_SCORE0[];
|
||||
extern const uint8_t LBM_SCORE1[];
|
||||
|
|
|
@ -100,3 +100,4 @@ void Layout2P1::refresh()
|
|||
}
|
||||
|
||||
BaseLayoutFactory<Layout2P1> layout2P1("Layout2P1", LBM_LAYOUT_2P1, OPTIONS_LAYOUT_2P1);
|
||||
const LayoutFactory * defaultLayout = &layout2P1;
|
||||
|
|
|
@ -659,7 +659,7 @@ void lcdDrawBlackOverlay()
|
|||
}
|
||||
|
||||
#if defined(SIMU)
|
||||
BitmapBuffer _lcd(LCD_W, LCD_H, displayBuf);
|
||||
BitmapBuffer _lcd(BMP_RGB565, LCD_W, LCD_H, displayBuf);
|
||||
BitmapBuffer * lcd = &_lcd;
|
||||
|
||||
void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)
|
||||
|
@ -678,12 +678,12 @@ void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, cons
|
|||
}
|
||||
}
|
||||
|
||||
void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t h)
|
||||
void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h)
|
||||
{
|
||||
for (coord_t line=0; line<h; line++) {
|
||||
uint16_t * p = dest + (y+line)*destw + x;
|
||||
const uint16_t * q = src + line*srcw;
|
||||
for (coord_t col=0; col<srcw; col++) {
|
||||
const uint16_t * q = src + (srcy+line)*srcw + srcx;
|
||||
for (coord_t col=0; col<w; col++) {
|
||||
uint8_t alpha = *q >> 12;
|
||||
uint8_t red = ((((*q >> 8) & 0x0f) << 1) * alpha + (*p >> 11) * (0x0f-alpha)) / 0x0f;
|
||||
uint8_t green = ((((*q >> 4) & 0x0f) << 2) * alpha + ((*p >> 5) & 0x3f) * (0x0f-alpha)) / 0x0f;
|
||||
|
@ -693,4 +693,26 @@ void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t h, uint32_t format)
|
||||
{
|
||||
if (format == DMA2D_ARGB4444) {
|
||||
for (int row = 0; row < h; ++row) {
|
||||
for (int col = 0; col < w; ++col) {
|
||||
*dest = ARGB(src[0], src[1], src[2], src[3]);
|
||||
++dest;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int row = 0; row < h; ++row) {
|
||||
for(int col = 0; col < w; ++col) {
|
||||
*dest = RGB(src[1], src[2], src[3]);
|
||||
++dest;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
#if defined(SIMU)
|
||||
extern display_t displayBuf[DISPLAY_BUFFER_SIZE];
|
||||
#else
|
||||
#define displayBuf lcd->data
|
||||
#define displayBuf lcd->getData()
|
||||
#endif
|
||||
|
||||
#define lcdRefreshWait()
|
||||
|
@ -157,7 +157,7 @@ inline void lcdDrawAlphaPixel(coord_t x, coord_t y, uint8_t opacity, uint16_t co
|
|||
#if !defined(SIMU)
|
||||
inline void lcdDrawSolidFilledRect(coord_t x, coord_t y, coord_t w, coord_t h, LcdFlags flags)
|
||||
{
|
||||
DMAFillRect(lcd->data, LCD_W, x, y, w, h, lcdColorTable[COLOR_IDX(flags)]);
|
||||
DMAFillRect(lcd->getData(), LCD_W, x, y, w, h, lcdColorTable[COLOR_IDX(flags)]);
|
||||
}
|
||||
#else
|
||||
void lcdDrawSolidFilledRect(coord_t x, coord_t y, coord_t w, coord_t h, LcdFlags flags);
|
||||
|
|
|
@ -63,8 +63,6 @@ void drawPots()
|
|||
OPTION_SLIDER_SQUARE_BUTTON);
|
||||
}
|
||||
|
||||
#include "alpha_horus.lbm"
|
||||
|
||||
bool menuCommonCalib(evt_t event)
|
||||
{
|
||||
drawScreenTemplate(NULL, LBM_CALIBRATION_ICON, OPTION_MENU_NO_FOOTER);
|
||||
|
@ -194,7 +192,10 @@ bool menuCommonCalib(evt_t event)
|
|||
break;
|
||||
}
|
||||
|
||||
lcd->drawAlphaBitmap((LCD_W-206)/2, LCD_H-220, &ALPHA_HORUS);
|
||||
static const BitmapBuffer * horus = BitmapBuffer::load(getThemePath("horus.png"));
|
||||
if (horus) {
|
||||
lcd->drawBitmap((LCD_W-horus->getWidth())/2, LCD_H-20-horus->getHeight(), horus);
|
||||
}
|
||||
drawSticks();
|
||||
drawPots();
|
||||
|
||||
|
|
|
@ -366,11 +366,11 @@ bool menuGeneralSdManager(evt_t _event)
|
|||
if (currentBitmapIndex != menuVerticalPosition) {
|
||||
currentBitmapIndex = menuVerticalPosition;
|
||||
delete currentBitmap;
|
||||
currentBitmap = BitmapBuffer::load(reusableBuffer.sdmanager.lines[index], true);
|
||||
currentBitmap = BitmapBuffer::load(reusableBuffer.sdmanager.lines[index]);
|
||||
// TODO scale in case of a too large bitmap
|
||||
}
|
||||
if (currentBitmap) {
|
||||
lcd->drawAlphaBitmap(LCD_W / 2, LCD_H / 2, currentBitmap);
|
||||
lcd->drawBitmap(LCD_W / 2, LCD_H / 2, currentBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "../../opentx.h"
|
||||
#include "opentx.h"
|
||||
|
||||
const char *warningText = NULL;
|
||||
const char *warningInfoText;
|
||||
|
|
|
@ -52,11 +52,9 @@ void Theme::drawThumb(uint16_t x, uint16_t y, uint32_t flags)
|
|||
#define THUMB_WIDTH 51
|
||||
#define THUMB_HEIGHT 31
|
||||
if (!thumb) {
|
||||
thumb = BitmapBuffer::load(getFilePath("thumb.bmp"));
|
||||
thumb = BitmapBuffer::load(getFilePath("thumb.png"));
|
||||
}
|
||||
if (thumb) {
|
||||
lcd->drawBitmap(x, y, thumb);
|
||||
}
|
||||
if (flags == LINE_COLOR) {
|
||||
lcdDrawFilledRect(x, y, THUMB_WIDTH, THUMB_HEIGHT, SOLID, OVERLAY_COLOR | OPACITY(10));
|
||||
}
|
||||
|
@ -72,20 +70,20 @@ void Theme::drawAboutBackground() const
|
|||
drawBackground();
|
||||
}
|
||||
|
||||
#include "alpha_asterisk.lbm"
|
||||
|
||||
void Theme::drawMessageBox(const char * title, const char * text, const char * action, uint32_t flags) const
|
||||
{
|
||||
static const BitmapBuffer * asterisk = BitmapBuffer::load(getThemePath("asterisk.png"));
|
||||
|
||||
//if (flags & MESSAGEBOX_TYPE_ALERT) {
|
||||
drawBackground();
|
||||
lcdDrawFilledRect(0, POPUP_Y, LCD_W, POPUP_H, SOLID, TEXT_INVERTED_COLOR | OPACITY(8));
|
||||
//}
|
||||
|
||||
if ((flags & MESSAGEBOX_TYPE_ALERT) || (flags & MESSAGEBOX_TYPE_WARNING)) {
|
||||
lcd->drawAlphaBitmap(POPUP_X-80, POPUP_Y+12, &ALPHA_ASTERISK);
|
||||
lcd->drawBitmap(POPUP_X-80, POPUP_Y+12, asterisk);
|
||||
}
|
||||
else {
|
||||
lcd->drawAlphaBitmap(POPUP_X-80, POPUP_Y+12, &ALPHA_ASTERISK);
|
||||
lcd->drawBitmap(POPUP_X-80, POPUP_Y+12, asterisk);
|
||||
}
|
||||
|
||||
#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || defined(TRANSLATIONS_CZ)
|
||||
|
|
|
@ -66,7 +66,7 @@ class DarkblueTheme: public Theme
|
|||
lcdDrawBitmapPattern(5, 7, icon, MENU_TITLE_COLOR);
|
||||
}
|
||||
else {
|
||||
static BitmapBuffer * thumb = BitmapBuffer::load(getFilePath("topmenu_opentx.bmp"));
|
||||
static BitmapBuffer * thumb = BitmapBuffer::load(getFilePath("topmenu_opentx.png"));
|
||||
lcd->drawBitmap(5, 7, thumb);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ class DefaultTheme: public Theme
|
|||
|
||||
virtual void drawBackground() const
|
||||
{
|
||||
static BitmapBuffer * backgroundBitmap = BitmapBuffer::load(getThemePath("mainbg.bmp"));
|
||||
static BitmapBuffer * backgroundBitmap = BitmapBuffer::load(getThemePath("mainbg.png"));
|
||||
if (backgroundBitmap) {
|
||||
lcd->drawBitmap(0, 0, backgroundBitmap);
|
||||
}
|
||||
|
@ -80,11 +80,9 @@ class DefaultTheme: public Theme
|
|||
|
||||
virtual void drawAboutBackground() const
|
||||
{
|
||||
static BitmapBuffer * backgroundBitmap = BitmapBuffer::load(getThemePath("aboutbg.bmp"));
|
||||
if (backgroundBitmap) {
|
||||
static BitmapBuffer * backgroundBitmap = BitmapBuffer::load(getThemePath("aboutbg.png"));
|
||||
lcd->drawBitmap(0, 0, backgroundBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void drawTopbarBackground(const uint8_t * icon) const
|
||||
{
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#define TRIM_LEN 80
|
||||
#define POTS_LINE_Y 252
|
||||
|
||||
Layout * customScreens[MAX_CUSTOM_SCREENS];
|
||||
Layout * customScreens[MAX_CUSTOM_SCREENS] = { 0, 0, 0, 0, 0 };
|
||||
Topbar * topbar;
|
||||
|
||||
void drawMainPots()
|
||||
|
|
|
@ -52,8 +52,8 @@ void drawTopbarDatetime()
|
|||
#define STICK_PANEL_WIDTH 68
|
||||
void drawStick(coord_t x, coord_t y, int16_t xval, int16_t yval)
|
||||
{
|
||||
lcd->drawAlphaBitmap(x, y, &ALPHA_STICK_BACKGROUND);
|
||||
lcd->drawAlphaBitmap(x + 2 + STICK_PANEL_WIDTH/2 + STICK_PANEL_WIDTH/2 * xval/RESX, y + 2 + STICK_PANEL_WIDTH/2 - STICK_PANEL_WIDTH/2 * yval/RESX, &ALPHA_STICK_POINTER);
|
||||
lcd->drawBitmap(x, y, &ALPHA_STICK_BACKGROUND);
|
||||
lcd->drawBitmap(x + 2 + STICK_PANEL_WIDTH/2 + STICK_PANEL_WIDTH/2 * xval/RESX, y + 2 + STICK_PANEL_WIDTH/2 - STICK_PANEL_WIDTH/2 * yval/RESX, &ALPHA_STICK_POINTER);
|
||||
}
|
||||
|
||||
#include "alpha_button_on.lbm"
|
||||
|
@ -75,9 +75,9 @@ void drawButton(coord_t x, coord_t y, const char * label, LcdFlags attr)
|
|||
lcdDrawText(x+padding+8, y, label, TEXT_COLOR);
|
||||
}
|
||||
if (attr & BUTTON_OFF)
|
||||
lcd->drawAlphaBitmap(x-6, y+3, &ALPHA_BUTTON_OFF);
|
||||
lcd->drawBitmap(x-6, y+3, &ALPHA_BUTTON_OFF);
|
||||
else if (attr & BUTTON_ON)
|
||||
lcd->drawAlphaBitmap(x-6, y+3, &ALPHA_BUTTON_ON);
|
||||
lcd->drawBitmap(x-6, y+3, &ALPHA_BUTTON_ON);
|
||||
}
|
||||
|
||||
void drawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr)
|
||||
|
@ -424,23 +424,24 @@ int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int
|
|||
void drawSleepBitmap()
|
||||
{
|
||||
lcd->clear();
|
||||
const BitmapBuffer * bitmap = BitmapBuffer::load(getThemePath("sleep.bmp"));
|
||||
const BitmapBuffer * bitmap = BitmapBuffer::load(getThemePath("sleep.png"));
|
||||
if (bitmap) {
|
||||
lcd->drawBitmap((LCD_W-bitmap->getWidth())/2, (LCD_H-bitmap->getHeight())/2, bitmap);
|
||||
}
|
||||
lcdRefresh();
|
||||
}
|
||||
|
||||
#include "alpha_shutdown.lbm"
|
||||
|
||||
#define SHUTDOWN_CIRCLE_DIAMETER 150
|
||||
void drawShutdownBitmap(uint32_t index)
|
||||
{
|
||||
static uint32_t last_index = 0xffffffff;
|
||||
static const BitmapBuffer * shutdown = BitmapBuffer::load(getThemePath("shutdown.png"));
|
||||
|
||||
if (index < last_index) {
|
||||
theme->drawBackground();
|
||||
lcd->drawAlphaBitmap((LCD_W-ALPHA_SHUTDOWN.getWidth())/2, (LCD_H-ALPHA_SHUTDOWN.getHeight())/2, &ALPHA_SHUTDOWN);
|
||||
if (shutdown) {
|
||||
lcd->drawBitmap((LCD_W-shutdown->getWidth())/2, (LCD_H-shutdown->getHeight())/2, shutdown);
|
||||
}
|
||||
lcdStoreBackupBuffer();
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -41,7 +41,7 @@ class ModelBitmapWidget: public Widget
|
|||
void refreshBuffer()
|
||||
{
|
||||
delete buffer;
|
||||
buffer = new BitmapBuffer(zone.w, zone.h);
|
||||
buffer = new BitmapBuffer(BMP_RGB565, zone.w, zone.h);
|
||||
if (buffer) {
|
||||
buffer->drawBitmap(0, 0, lcd, zone.x, zone.y, zone.w, zone.h);
|
||||
GET_FILENAME(filename, BITMAPS_PATH, g_model.header.bitmap, BITMAPS_EXT);
|
||||
|
@ -82,3 +82,4 @@ class ModelBitmapWidget: public Widget
|
|||
};
|
||||
|
||||
BaseWidgetFactory<ModelBitmapWidget> modelBitmapWidget("ModelBmp", NULL);
|
||||
const WidgetFactory * defaultWidget = &modelBitmapWidget;
|
||||
|
|
|
@ -454,6 +454,15 @@ void modelDefault(uint8_t id)
|
|||
g_model.header.name[5] = '\033' + id/10;
|
||||
g_model.header.name[6] = '\033' + id%10;
|
||||
#endif
|
||||
|
||||
#if defined(COLORLCD)
|
||||
extern const LayoutFactory * defaultLayout;
|
||||
delete customScreens[0];
|
||||
customScreens[0] = defaultLayout->create(&g_model.screenData[0].layoutData);
|
||||
strcpy(g_model.screenData[0].layoutName, "Layout2P1");
|
||||
extern const WidgetFactory * defaultWidget;
|
||||
customScreens[0]->createWidget(0, defaultWidget);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(VIRTUALINPUTS)
|
||||
|
|
|
@ -261,7 +261,8 @@ void lcdInit(void);
|
|||
void lcdRefresh(void);
|
||||
void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color);
|
||||
void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h);
|
||||
void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t h);
|
||||
void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h);
|
||||
void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t h, uint32_t format);
|
||||
void lcdStoreBackupBuffer(void);
|
||||
int lcdRestoreBackupBuffer(void);
|
||||
|
||||
|
|
|
@ -380,8 +380,8 @@ void LCD_Init(void)
|
|||
LCD_ControlLight(100);
|
||||
}
|
||||
|
||||
BitmapBuffer lcdBuffer1(LCD_W, LCD_H, (uint16_t *)LCD_FIRST_FRAME_BUFFER);
|
||||
BitmapBuffer lcdBuffer2(LCD_W, LCD_H, (uint16_t *)LCD_SECOND_FRAME_BUFFER);
|
||||
BitmapBuffer lcdBuffer1(BMP_RGB565, LCD_W, LCD_H, (uint16_t *)LCD_FIRST_FRAME_BUFFER);
|
||||
BitmapBuffer lcdBuffer2(BMP_RGB565, LCD_W, LCD_H, (uint16_t *)LCD_SECOND_FRAME_BUFFER);
|
||||
BitmapBuffer * lcd = &lcdBuffer1;
|
||||
|
||||
/**
|
||||
|
@ -469,7 +469,7 @@ void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, cons
|
|||
DMA2D_InitTypeDef DMA2D_InitStruct;
|
||||
DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M;
|
||||
DMA2D_InitStruct.DMA2D_CMode = DMA2D_RGB565;
|
||||
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = CONVERT_PTR_UINT(dest) + 2*(destw*y + x);
|
||||
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = CONVERT_PTR_UINT(dest + y*destw + x);
|
||||
DMA2D_InitStruct.DMA2D_OutputGreen = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputBlue = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputRed = 0;
|
||||
|
@ -495,27 +495,27 @@ void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, cons
|
|||
while (DMA2D_GetFlagStatus(DMA2D_FLAG_TC) == RESET);
|
||||
}
|
||||
|
||||
void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t h)
|
||||
void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h)
|
||||
{
|
||||
DMA2D_DeInit();
|
||||
|
||||
DMA2D_InitTypeDef DMA2D_InitStruct;
|
||||
DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M_BLEND;
|
||||
DMA2D_InitStruct.DMA2D_CMode = DMA2D_RGB565;
|
||||
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = CONVERT_PTR_UINT(dest) + 2*(destw*y + x);
|
||||
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = CONVERT_PTR_UINT(dest + y*destw + x);
|
||||
DMA2D_InitStruct.DMA2D_OutputGreen = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputBlue = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputRed = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputAlpha = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputOffset = destw - srcw;
|
||||
DMA2D_InitStruct.DMA2D_OutputOffset = destw - w;
|
||||
DMA2D_InitStruct.DMA2D_NumberOfLine = h;
|
||||
DMA2D_InitStruct.DMA2D_PixelPerLine = srcw;
|
||||
DMA2D_InitStruct.DMA2D_PixelPerLine = w;
|
||||
DMA2D_Init(&DMA2D_InitStruct);
|
||||
|
||||
DMA2D_FG_InitTypeDef DMA2D_FG_InitStruct;
|
||||
DMA2D_FG_StructInit(&DMA2D_FG_InitStruct);
|
||||
DMA2D_FG_InitStruct.DMA2D_FGMA = CONVERT_PTR_UINT(src);
|
||||
DMA2D_FG_InitStruct.DMA2D_FGO = 0;
|
||||
DMA2D_FG_InitStruct.DMA2D_FGMA = CONVERT_PTR_UINT(src + srcy*srcw + srcx);
|
||||
DMA2D_FG_InitStruct.DMA2D_FGO = srcw - w;
|
||||
DMA2D_FG_InitStruct.DMA2D_FGCM = CM_ARGB4444;
|
||||
DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_MODE = NO_MODIF_ALPHA_VALUE;
|
||||
DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_VALUE = 0;
|
||||
|
@ -523,8 +523,8 @@ void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y,
|
|||
|
||||
DMA2D_BG_InitTypeDef DMA2D_BG_InitStruct;
|
||||
DMA2D_BG_StructInit(&DMA2D_BG_InitStruct);
|
||||
DMA2D_BG_InitStruct.DMA2D_BGMA = CONVERT_PTR_UINT(dest) + 2*(destw*y + x);
|
||||
DMA2D_BG_InitStruct.DMA2D_BGO = destw - srcw;
|
||||
DMA2D_BG_InitStruct.DMA2D_BGMA = CONVERT_PTR_UINT(dest + y*destw + x);
|
||||
DMA2D_BG_InitStruct.DMA2D_BGO = destw - w;
|
||||
DMA2D_BG_InitStruct.DMA2D_BGCM = CM_RGB565;
|
||||
DMA2D_BG_InitStruct.DMA2D_BGPFC_ALPHA_MODE = NO_MODIF_ALPHA_VALUE;
|
||||
DMA2D_BG_InitStruct.DMA2D_BGPFC_ALPHA_VALUE = 0;
|
||||
|
@ -537,6 +537,39 @@ void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y,
|
|||
while (DMA2D_GetFlagStatus(DMA2D_FLAG_TC) == RESET);
|
||||
}
|
||||
|
||||
void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t h, uint32_t format)
|
||||
{
|
||||
DMA2D_DeInit();
|
||||
|
||||
DMA2D_InitTypeDef DMA2D_InitStruct;
|
||||
DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M_PFC;
|
||||
DMA2D_InitStruct.DMA2D_CMode = format;
|
||||
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = CONVERT_PTR_UINT(dest);
|
||||
DMA2D_InitStruct.DMA2D_OutputGreen = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputBlue = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputRed = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputAlpha = 0;
|
||||
DMA2D_InitStruct.DMA2D_OutputOffset = 0;
|
||||
DMA2D_InitStruct.DMA2D_NumberOfLine = h;
|
||||
DMA2D_InitStruct.DMA2D_PixelPerLine = w;
|
||||
DMA2D_Init(&DMA2D_InitStruct);
|
||||
|
||||
DMA2D_FG_InitTypeDef DMA2D_FG_InitStruct;
|
||||
DMA2D_FG_StructInit(&DMA2D_FG_InitStruct);
|
||||
DMA2D_FG_InitStruct.DMA2D_FGMA = CONVERT_PTR_UINT(src);
|
||||
DMA2D_FG_InitStruct.DMA2D_FGO = 0;
|
||||
DMA2D_FG_InitStruct.DMA2D_FGCM = CM_ARGB8888;
|
||||
DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_MODE = REPLACE_ALPHA_VALUE;
|
||||
DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_VALUE = 0;
|
||||
DMA2D_FGConfig(&DMA2D_FG_InitStruct);
|
||||
|
||||
/* Start Transfer */
|
||||
DMA2D_StartTransfer();
|
||||
|
||||
/* Wait for CTC Flag activation */
|
||||
while (DMA2D_GetFlagStatus(DMA2D_FLAG_TC) == RESET);
|
||||
}
|
||||
|
||||
void DMAcopy(void * src, void * dest, int len)
|
||||
{
|
||||
DMA2D_DeInit();
|
||||
|
@ -572,12 +605,12 @@ void DMAcopy(void * src, void * dest, int len)
|
|||
|
||||
void lcdStoreBackupBuffer()
|
||||
{
|
||||
DMAcopy(lcd->data, LCD_BACKUP_FRAME_BUFFER, DISPLAY_BUFFER_SIZE);
|
||||
DMAcopy(lcd->getData(), LCD_BACKUP_FRAME_BUFFER, DISPLAY_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
int lcdRestoreBackupBuffer()
|
||||
{
|
||||
DMAcopy(LCD_BACKUP_FRAME_BUFFER, lcd->data, DISPLAY_BUFFER_SIZE);
|
||||
DMAcopy(LCD_BACKUP_FRAME_BUFFER, lcd->getData(), DISPLAY_BUFFER_SIZE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ with open(sys.argv[2], "w") as f:
|
|||
val = ((Qt.qAlpha(pixel) // 16) << 12) + ((Qt.qRed(pixel) // 16) << 8) + ((Qt.qGreen(pixel) // 16) << 4) + ((Qt.qBlue(pixel) // 16) << 0)
|
||||
values.append(str(val))
|
||||
f.write("const uint16_t __%s[] __ALIGNED = { %s };\n" % (constant, ",".join(values)))
|
||||
f.write("const Bitmap %s(%d, %d, __%s);\n" % (constant, width, height, constant))
|
||||
f.write("const Bitmap %s(BMP_ARGB4444, %d, %d, __%s);\n" % (constant, width, height, constant))
|
||||
elif what == "5/6/5":
|
||||
constant = sys.argv[2].upper()[:-4]
|
||||
values = []
|
||||
|
@ -59,7 +59,7 @@ with open(sys.argv[2], "w") as f:
|
|||
val = ((Qt.qRed(pixel) >> 3) << 11) + ((Qt.qGreen(pixel) >> 2) << 5) + ((Qt.qBlue(pixel) >> 3) << 0)
|
||||
values.append(str(val))
|
||||
f.write("const uint16_t __%s[] __ALIGNED = { %s };\n" % (constant, ",".join(values)))
|
||||
f.write("const Bitmap %s(%d, %d, __%s);\n" % (constant, width, height, constant))
|
||||
f.write("const Bitmap %s(BMP_RGB565, %d, %d, __%s);\n" % (constant, width, height, constant))
|
||||
elif what == "5/6/5/8":
|
||||
colors = []
|
||||
writeSize(f, width, height)
|
||||
|
|