Commit 5a29bab4 authored by devsaurus's avatar devsaurus
Browse files

Merge pull request #655 from devsaurus/dev-ucglib

Add bindings for ucglib
parents cb0f32d6 a6c9ba80
/*
ucg_dev_tft_240x320_ssd1289.c
Universal uC Color Graphics Library
Copyright (c) 2014, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ucg.h"
#ifdef NOT_YET_IMPLEMENTED
static const ucg_pgm_uint8_t ucg_tft_240x320_ssd1289_init_seq[] = {
UCG_CFG_CD(0,1), /* DC=0 for command mode, DC=1 for data and args */
UCG_RST(1),
UCG_CS(1), /* disable chip */
UCG_DLY_MS(5),
UCG_RST(0),
UCG_DLY_MS(5),
UCG_RST(1),
UCG_DLY_MS(50),
UCG_CS(0), /* enable chip */
UCG_C22(0x000, 0x000, 0x000, 0x001), /* enable oscilator */
UCG_C22(0x000, 0x003, 0x066, 0x064), /* Power control 1 (POR value) */
//UCG_C22(0x000, 0x002, 0x007, 0x000), /* LCD Driving Wave Control, bit 9: Set line inversion */
//UCG_C22(0x000, 0x003, 0x010, 0x030), /* Entry Mode, GRAM write direction and BGR (Bit 12)=1 (16 bit transfer, 65K Mode)*/
//UCG_C22(0x000, 0x004, 0x000, 0x000), /* Resize register, all 0: no resize */
UCG_C22(0x000, 0x008, 0x002, 0x007), /* Display Control 2: set the back porch and front porch */
//UCG_C22(0x000, 0x009, 0x000, 0x000), /* Display Control 3: normal scan */
//UCG_C22(0x000, 0x00a, 0x000, 0x000), /* Display Control 4: set to "no FMARK output" */
UCG_C22(0x000, 0x00c, 0x000, 0x000), /* RGB Display Interface Control 1, RIM=10 (3x6 Bit), 12 Jan 14: RIM=00 */
//UCG_C22(0x000, 0x00d, 0x000, 0x000), /* Frame Maker Position */
//UCG_C22(0x000, 0x00f, 0x000, 0x000), /* RGB Display Interface Control 2 */
UCG_C22(0x000, 0x010, 0x000, 0x000), /* Power Control 1: SAP, BT[3:0], AP, DSTB, SLP, STB, actual setting is done below */
UCG_C22(0x000, 0x011, 0x000, 0x007), /* Power Control 2: DC1[2:0], DC0[2:0], VC[2:0] */
UCG_C22(0x000, 0x012, 0x000, 0x000), /* Power Control 3: VREG1OUT voltage */
UCG_C22(0x000, 0x013, 0x000, 0x000), /* Power Control 4: VDV[4:0] for VCOM amplitude */
UCG_C22(0x000, 0x007, 0x000, 0x001), /* Display Control 1: Operate, but do not display */
UCG_DLY_MS(100), /* delay 100 ms */ /* ITDB02 none D verion: 50ms */
UCG_C22( 0x000, 0x010, 0x010, 0x090), /* Power Control 1: SAP, BT[3:0], AP, DSTB, SLP, STB */
/* 12. Jan 14. Prev value: 0x016, 0x090 */
/* ITDB02 none D verion: 0x010, 0x090 */
//UCG_C22( 0x000, 0x010, 0x017, 0x0f0), /* Power Control 1: Setting for max quality & power consumption: SAP(Bit 12)=1, BT[3:0]=7 (max), APE (Bit 8)=1, AP=7 (max), disable sleep: SLP=0, STB=0 */
UCG_C22( 0x000, 0x011, 0x002, 0x027), /* Power Control 2 VCI ration, step up circuits 1 & 2 */
UCG_DLY_MS(50), /* delay 50 ms */
UCG_C22( 0x000, 0x012, 0x000, 0x01f), /* Power Control 3: VCI: External, VCI*1.80 */
/* 12. Jan 14. Prev value: 0x000, 0x00d */
UCG_DLY_MS(50), /* delay 50 ms */
UCG_C22( 0x000, 0x013, 0x015, 0x000), /* Power Control 4: VDV[4:0] for VCOM amplitude */
/* 12. Jan 14. Prev value: 0x012, 0x009 */
UCG_C22( 0x000, 0x029, 0x000, 0x027), /* Power Control 7 */
/* 12. Jan 14. Prev value: 0x000, 0x00a */
UCG_C22( 0x000, 0x02b, 0x000, 0x00d), /* Frame Rate: 93 */
//UCG_C22( 0x000, 0x02b, 0x000, 0x00b), /* Frame Rate: 70, too less, some flicker visible */
UCG_DLY_MS(50), /* delay 50 ms */
/* Gamma Control, values from iteadstudio.com reference software on google code */
/*
UCG_C22(0x00,0x30,0x00,0x00),
UCG_C22(0x00,0x31,0x07,0x07),
UCG_C22(0x00,0x32,0x03,0x07),
UCG_C22(0x00,0x35,0x02,0x00),
UCG_C22(0x00,0x36,0x00,0x08),
UCG_C22(0x00,0x37,0x00,0x04),
UCG_C22(0x00,0x38,0x00,0x00),
UCG_C22(0x00,0x39,0x07,0x07),
UCG_C22(0x00,0x3C,0x00,0x02),
UCG_C22(0x00,0x3D,0x1D,0x04),
*/
UCG_C22( 0x000, 0x020, 0x000, 0x000), /* Horizontal GRAM Address Set */
UCG_C22( 0x000, 0x021, 0x000, 0x000), /* Vertical GRAM Address Set */
UCG_C22( 0x000, 0x050, 0x000, 0x000), /* Horizontal GRAM Start Address */
UCG_C22( 0x000, 0x051, 0x000, 0x0EF), /* Horizontal GRAM End Address: 239 */
UCG_C22( 0x000, 0x052, 0x000, 0x000), /* Vertical GRAM Start Address */
UCG_C22( 0x000, 0x053, 0x001, 0x03F), /* Vertical GRAM End Address: 319 */
UCG_C22( 0x000, 0x060, 0x0a7, 0x000), /* Driver Output Control 2, NL = 0x027 = 320 lines, GS (bit 15) = 1 */
UCG_C22( 0x000, 0x061, 0x000, 0x001), /* Base Image Display Control: NDL,VLE = 0 (Disbale Vertical Scroll), REV */
//UCG_C22( 0x000, 0x06a, 0x000, 0x000), /* Vertical Scroll Control */
//UCG_C22( 0x000, 0x080, 0x000, 0x000), /* Partial Image 1 Display Position */
//UCG_C22( 0x000, 0x081, 0x000, 0x000), /* Partial Image 1 RAM Start Address */
//UCG_C22( 0x000, 0x082, 0x000, 0x000), /* Partial Image 1 RAM End Address */
//UCG_C22( 0x000, 0x083, 0x000, 0x000), /* Partial Image 2 Display Position */
//UCG_C22( 0x000, 0x084, 0x000, 0x000), /* Partial Image 2 RAM Start Address */
//UCG_C22( 0x000, 0x085, 0x000, 0x000), /* Partial Image 2 RAM End Address */
UCG_C22( 0x000, 0x090, 0x000, 0x010), /* Panel Interface Control 1 */
UCG_C22( 0x000, 0x092, 0x000, 0x000), /* Panel Interface Control 2 */
/* 0x006, 0x000 */
UCG_C22( 0x000, 0x007, 0x001, 0x033), /* Display Control 1: Operate, display ON, Partial image off */
UCG_DLY_MS(10), /* delay 10 ms */
/* write test pattern */
//UCG_C22( 0x000, 0x020, 0x000, 0x000), /* Horizontal GRAM Address Set */
//UCG_C22( 0x000, 0x021, 0x000, 0x011), /* Vertical GRAM Address Set */
UCG_C20( 0x000, 0x022), /* Write Data to GRAM */
UCG_CS(1), /* disable chip */
UCG_END(), /* end of sequence */
};
ucg_int_t ucg_dev_ssd1289_18x240x320_itdb02(ucg_t *ucg, ucg_int_t msg, void *data)
{
switch(msg)
{
case UCG_MSG_DEV_POWER_UP:
/* 1. Call to the controller procedures to setup the com interface */
if ( ucg_dev_ic_ssd1289_18(ucg, msg, data) == 0 )
return 0;
/* 2. Send specific init sequence for this display module */
ucg_com_SendCmdSeq(ucg, ucg_tft_240x320_ssd1289_init_seq);
return 1;
case UCG_MSG_DEV_POWER_DOWN:
/* let do power down by the conroller procedures */
return ucg_dev_ic_ssd1289_18(ucg, msg, data);
case UCG_MSG_GET_DIMENSION:
((ucg_wh_t *)data)->w = 240;
((ucg_wh_t *)data)->h = 320;
return 1;
}
/* all other messages are handled by the controller procedures */
return ucg_dev_ic_ssd1289_18(ucg, msg, data);
}
#endif
\ No newline at end of file
/*
ucg_font.c
UCG Font High Level Interface; mostly taken over from U8glib
Universal uC Color Graphics Library
Copyright (c) 2013, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ucg.h"
/* font api */
/* pointer to the start adress of the glyph, points to progmem area on avr uC */
typedef void * ucg_glyph_t;
/*=================================================*/
/* OLD FONT FORMAT */
/* size of the font data structure, there is no struct or class... */
/* this is the size for the new font format */
#define UCG_FONT_DATA_STRUCT_SIZE 21
/*
OLD Font Data Struct
... instead the fields of the font data structure are accessed directly by offset
font information
offset
0 font format
1 FONTBOUNDINGBOX width unsigned
2 FONTBOUNDINGBOX height unsigned
3 FONTBOUNDINGBOX x-offset signed
4 FONTBOUNDINGBOX y-offset signed
5 capital A height unsigned
6 start 'A'
8 start 'a'
10 encoding start
11 encoding end
12 descent 'g' negative: below baseline
13 font max ascent
14 font min decent negative: below baseline
15 font xascent
16 font xdecent negative: below baseline
new font data:
offset bytes description
0 1 glyph_cnt number of glyphs
1 1 bbx_mode 0: proportional, 1: common height, 2: monospace, 3: multiple of 8
2 1 bits_per_0 glyph rle parameter
3 1 bits_per_1 glyph rle parameter
4 1 bits_per_char_width glyph rle parameter
5 1 bits_per_char_height glyph rle parameter
6 1 bits_per_char_x glyph rle parameter
7 1 bits_per_char_y glyph rle parameter
8 1 bits_per_delta_x glyph rle parameter
9 1 max_char_width
10 1 max_char_height
11 1 x offset
12 1 y offset (descent)
13 1 ascent (capital A)
14 1 descent (lower g)
15 1 ascent '('
16 1 descent ')'
17 1 start pos 'A' high byte
18 1 start pos 'A' low byte
19 1 start pos 'a' high byte
20 1 start pos 'a' low byte
Font build mode, 0: proportional, 1: common height, 2: monospace, 3: multiple of 8
Font build mode 0:
- "t"
- Ref height mode: UCG_FONT_HEIGHT_MODE_TEXT, UCG_FONT_HEIGHT_MODE_XTEXT or UCG_FONT_HEIGHT_MODE_ALL
- use in transparent mode only (does not look good in solid mode)
- most compact format
- different font heights possible
Font build mode 1:
- "h"
- Ref height mode: UCG_FONT_HEIGHT_MODE_ALL
- transparent or solid mode
- The height of the glyphs depend on the largest glyph in the font. This means font height depends on postfix "r", "f" and "n".
*/
/* use case: What is the width and the height of the minimal box into which string s fints? */
void ucg_font_GetStrSize(const void *font, const char *s, ucg_int_t *width, ucg_int_t *height);
void ucg_font_GetStrSizeP(const void *font, const char *s, ucg_int_t *width, ucg_int_t *height);
/* use case: lower left edge of a minimal box is known, what is the correct x, y position for the string draw procedure */
void ucg_font_AdjustXYToDraw(const void *font, const char *s, ucg_int_t *x, ucg_int_t *y);
void ucg_font_AdjustXYToDrawP(const void *font, const char *s, ucg_int_t *x, ucg_int_t *y);
/* use case: Baseline origin known, return minimal box */
void ucg_font_GetStrMinBox(ucg_t *ucg, const void *font, const char *s, ucg_int_t *x, ucg_int_t *y, ucg_int_t *width, ucg_int_t *height);
/* procedures */
/*========================================================================*/
/* low level byte and word access */
/* removed NOINLINE, because it leads to smaller code, might also be faster */
//static uint8_t ucg_font_get_byte(const ucg_fntpgm_uint8_t *font, uint8_t offset) UCG_NOINLINE;
static uint8_t ucg_font_get_byte(const ucg_fntpgm_uint8_t *font, uint8_t offset)
{
font += offset;
return ucg_pgm_read( (ucg_pgm_uint8_t *)font );
}
static uint16_t ucg_font_get_word(const ucg_fntpgm_uint8_t *font, uint8_t offset) UCG_NOINLINE;
static uint16_t ucg_font_get_word(const ucg_fntpgm_uint8_t *font, uint8_t offset)
{
uint16_t pos;
font += offset;
pos = ucg_pgm_read( (ucg_pgm_uint8_t *)font );
font++;
pos <<= 8;
pos += ucg_pgm_read( (ucg_pgm_uint8_t *)font);
return pos;
}
/*========================================================================*/
/* new font format */
void ucg_read_font_info(ucg_font_info_t *font_info, const ucg_fntpgm_uint8_t *font)
{
/* offset 0 */
font_info->glyph_cnt = ucg_font_get_byte(font, 0);
font_info->bbx_mode = ucg_font_get_byte(font, 1);
font_info->bits_per_0 = ucg_font_get_byte(font, 2);
font_info->bits_per_1 = ucg_font_get_byte(font, 3);
/* offset 4 */
font_info->bits_per_char_width = ucg_font_get_byte(font, 4);
font_info->bits_per_char_height = ucg_font_get_byte(font, 5);
font_info->bits_per_char_x = ucg_font_get_byte(font, 6);
font_info->bits_per_char_y = ucg_font_get_byte(font, 7);
font_info->bits_per_delta_x = ucg_font_get_byte(font, 8);
/* offset 9 */
font_info->max_char_width = ucg_font_get_byte(font, 9);
font_info->max_char_height = ucg_font_get_byte(font, 10);
font_info->x_offset = ucg_font_get_byte(font, 11);
font_info->y_offset = ucg_font_get_byte(font, 12);
/* offset 13 */
font_info->ascent_A = ucg_font_get_byte(font, 13);
font_info->descent_g = ucg_font_get_byte(font, 14);
font_info->ascent_para = ucg_font_get_byte(font, 15);
font_info->descent_para = ucg_font_get_byte(font, 16);
/* offset 17 */
font_info->start_pos_upper_A = ucg_font_get_word(font, 17);
font_info->start_pos_lower_a = ucg_font_get_word(font, 19);
}
/*========================================================================*/
/* direct access on the font */
// OBSOLETE
// static uint8_t ucg_font_GetFormat(const ucg_fntpgm_uint8_t *font) UCG_NOINLINE;
// static uint8_t ucg_font_GetFormat(const ucg_fntpgm_uint8_t *font)
// {
// return ucg_font_get_byte(font, 0);
// }
// OBSOLETE
// static uint8_t ucg_font_GetFontGlyphStructureSize(const ucg_fntpgm_uint8_t *font) UCG_NOINLINE;
// static uint8_t ucg_font_GetFontGlyphStructureSize(const ucg_fntpgm_uint8_t *font)
// {
// switch(ucg_font_GetFormat(font))
// {
// case 0: return 6;
// case 1: return 3;
// case 2: return 6;
// }
// return 3;
// }
// static uint8_t ucg_font_GetBBXWidth(const void *font)
// {
// return ucg_font_get_byte(font, 1);
// }
// static uint8_t ucg_font_GetBBXHeight(const void *font)
// {
// return ucg_font_get_byte(font, 2);
// }
// static int8_t ucg_font_GetBBXOffX(const void *font)
// {
// return ucg_font_get_byte(font, 3);
// }
// static int8_t ucg_font_GetBBXOffY(const void *font)
// {
// return ucg_font_get_byte(font, 4);
// }
uint8_t ucg_font_GetCapitalAHeight(const void *font)
{
return ucg_font_get_byte(font, 13);
}
/*
uint16_t ucg_font_GetEncoding65Pos(const void *font) UCG_NOINLINE;
uint16_t ucg_font_GetEncoding65Pos(const void *font)
{
return ucg_font_get_word(font, 6);
}
uint16_t ucg_font_GetEncoding97Pos(const void *font) UCG_NOINLINE;
uint16_t ucg_font_GetEncoding97Pos(const void *font)
{
return ucg_font_get_word(font, 8);
}
*/
uint8_t ucg_font_GetFontStartEncoding(const void *font_arg)
{
const uint8_t *font = font_arg;
font += UCG_FONT_DATA_STRUCT_SIZE;
return ucg_pgm_read( ((ucg_pgm_uint8_t *)font) );
}
uint8_t ucg_font_GetFontEndEncoding(const void *font_arg)
{
uint8_t encoding = 0;
const uint8_t *font = font_arg;
font += UCG_FONT_DATA_STRUCT_SIZE;
for(;;)
{
if ( ucg_pgm_read( ((ucg_pgm_uint8_t *)font) + 1 ) == 0 )
break;
encoding = ucg_pgm_read( ((ucg_pgm_uint8_t *)font) );
font += ucg_pgm_read( ((ucg_pgm_uint8_t *)font) + 1 );
}
return encoding;
}
int8_t ucg_font_GetLowerGDescent(const void *font)
{
return ucg_font_get_byte(font, 14);
}
/*
int8_t ucg_font_GetFontAscent(const void *font)
{
return ucg_font_get_byte(font, 13);
}
int8_t ucg_font_GetFontDescent(const void *font)
{
return ucg_font_get_byte(font, 14);
}
int8_t ucg_font_GetFontXAscent(const void *font)
{
return ucg_font_get_byte(font, 15);
}
int8_t ucg_font_GetFontXDescent(const void *font)
{
return ucg_font_get_byte(font, 16);
}
*/
/* return the data start for a font and the glyph pointer */
// static uint8_t *ucg_font_GetGlyphDataStart(const void *font, ucg_glyph_t g)
// {
// return ((ucg_fntpgm_uint8_t *)g) + ucg_font_GetFontGlyphStructureSize(font);
// }
/* calculate the overall length of the font, only used to create the picture for the google wiki */
size_t ucg_font_GetSize(const void *font_arg)
{
const uint8_t *font = font_arg;
font += UCG_FONT_DATA_STRUCT_SIZE;
for(;;)
{
if ( ucg_pgm_read( ((ucg_pgm_uint8_t *)font) + 1 ) == 0 )
break;
font += ucg_pgm_read( ((ucg_pgm_uint8_t *)font) + 1 );
}
return (font - (const uint8_t *)font_arg) + 2;
}
/*========================================================================*/
/* ucg interface, font access */
uint8_t ucg_GetFontBBXWidth(ucg_t *ucg)
{
// OBSOLETE return ucg_font_GetBBXWidth(ucg->font);
return ucg->font_info.max_char_width; /* new font info structure */
}
uint8_t ucg_GetFontBBXHeight(ucg_t *ucg)
{
// OBSOLETE return ucg_font_GetBBXHeight(ucg->font);
return ucg->font_info.max_char_height; /* new font info structure */
}
int8_t ucg_GetFontBBXOffX(ucg_t *ucg) UCG_NOINLINE;
int8_t ucg_GetFontBBXOffX(ucg_t *ucg)
{
// OBSOLETE return ucg_font_GetBBXOffX(ucg->font);
return ucg->font_info.x_offset; /* new font info structure */
}
int8_t ucg_GetFontBBXOffY(ucg_t *ucg) UCG_NOINLINE;
int8_t ucg_GetFontBBXOffY(ucg_t *ucg)
{
// OBSOLETE return ucg_font_GetBBXOffY(ucg->font);
return ucg->font_info.y_offset; /* new font info structure */
}
uint8_t ucg_GetFontCapitalAHeight(ucg_t *ucg) UCG_NOINLINE;
uint8_t ucg_GetFontCapitalAHeight(ucg_t *ucg)
{
// OBSOLETE return ucg_font_GetCapitalAHeight(ucg->font);
return ucg->font_info.ascent_A; /* new font info structure */
}
/*========================================================================*/
/* glyph handling */
/* optimized */
uint8_t ucg_font_decode_get_unsigned_bits(ucg_font_decode_t *f, uint8_t cnt)
{
uint8_t val;
uint8_t bit_pos = f->decode_bit_pos;
uint8_t bit_pos_plus_cnt;
//val = *(f->decode_ptr);
val = ucg_pgm_read( (ucg_pgm_uint8_t *)(f->decode_ptr) );
val >>= bit_pos;
bit_pos_plus_cnt = bit_pos;
bit_pos_plus_cnt += cnt;
if ( bit_pos_plus_cnt >= 8 )
{
uint8_t s = 8;
s -= bit_pos;
f->decode_ptr++;
//val |= *(f->decode_ptr) << (8-bit_pos);
val |= ucg_pgm_read( (ucg_pgm_uint8_t *)(f->decode_ptr) ) << (s);
//bit_pos -= 8;
bit_pos_plus_cnt -= 8;
}
val &= (1U<<cnt)-1;
//bit_pos += cnt;
f->decode_bit_pos = bit_pos_plus_cnt;
return val;
}
/*
2 bit --> cnt = 2
-2,-1,0. 1
3 bit --> cnt = 3
-2,-1,0. 1
-4,-3,-2,-1,0,1,2,3
if ( x < 0 )
r = bits(x-1)+1;
else
r = bits(x)+1;
*/
/* optimized */
int8_t ucg_font_decode_get_signed_bits(ucg_font_decode_t *f, uint8_t cnt)
{
int8_t v, d;
v = (int8_t)ucg_font_decode_get_unsigned_bits(f, cnt);
d = 1;
cnt--;
d <<= cnt;
v -= d;
return v;
//return (int8_t)ucg_font_decode_get_unsigned_bits(f, cnt) - ((1<<cnt)>>1);
}
/* OLD CODE
static void ucg_add_vector(ucg_int_t *dest_x, ucg_int_t *dest_y, int8_t x, int8_t y, uint8_t dir) UCG_NOINLINE;
static void ucg_add_vector(ucg_int_t *dest_x, ucg_int_t *dest_y, int8_t x, int8_t y, uint8_t dir)
{
switch(dir)
{
case 0:
*dest_x += x;
*dest_y += y;
break;
case 1:
*dest_y += x;
*dest_x -= y;
break;
case 2:
*dest_x -= x;
*dest_y -= y;
break;
default:
*dest_y -= x;
*dest_x += y;
break;
}
}
*/
static ucg_int_t ucg_add_vector_y(ucg_int_t dy, int8_t x, int8_t y, uint8_t dir) UCG_NOINLINE;
static ucg_int_t ucg_add_vector_y(ucg_int_t dy, int8_t x, int8_t y, uint8_t dir)
{
switch(dir)
{
case 0:
dy += y;
break;
case 1:
dy += x;
break;
case 2:
dy -= y;
break;
default:
dy -= x;
break;
}
return dy;
}
static ucg_int_t ucg_add_vector_x(ucg_int_t dx, int8_t x, int8_t y, uint8_t dir) UCG_NOINLINE;
static ucg_int_t ucg_add_vector_x(ucg_int_t dx, int8_t x, int8_t y, uint8_t dir)
{
switch(dir)
{
case 0:
dx += x;
break;
case 1:
dx -= y;
break;
case 2:
dx -= x;
break;
default:
dx += y;
break;
}
return dx;
}
#ifdef OBSOLETE
/*
Description:
Draw a line with "cnt" pixel as fore- or background color.
Args:
cnt: Length of the line
is_foreground foreground/background?
ucg->font_decode.target_x X position
ucg->font_decode.target_y Y position
ucg->font_decode.is_transparent Transparent mode
Return:
-
Calls:
ucg_font_decode_draw_pixel()
Called by:
ucg_font_decode_len()
*/
void ucg_font_decode_draw_pixel(ucg_t *ucg, uint8_t lx, uint8_t ly, uint8_t cnt, uint8_t is_foreground)
{
ucg_int_t x, y;
ucg_font_decode_t *decode = &(ucg->font_decode);
x = decode->target_x;
y = decode->target_y;
x = ucg_add_vector_x(x, lx, ly, decode->dir);
y = ucg_add_vector_y(y, lx, ly, decode->dir);
//ucg_add_vector(&x, &y, ucg->font_decode.x, ucg->font_decode.y, ucg->font_decode.dir);
if ( is_foreground )
{
ucg_Draw90Line(ucg,
x,
y,
cnt,
/* dir */ decode->dir,
/* col_idx */ 0);
}
else if ( decode->is_transparent == 0 )
{
ucg_Draw90Line(ucg,
x,
y,
cnt,
/* dir */ decode->dir,
/* col_idx */ 1);
}
}
#endif
/*
Description:
Draw a run-length area of the glyph. "len" can have any size and the line
length has to be wrapped at the glyph border.
Args:
len: Length of the line
is_foreground foreground/background?
ucg->font_decode.target_x X position
ucg->font_decode.target_y Y position
ucg->font_decode.is_transparent Transparent mode
Return:
-
Calls:
ucg_Draw90Line()
Called by:
ucg_font_decode_glyph()
*/
/* optimized */
void ucg_font_decode_len(ucg_t *ucg, uint8_t len, uint8_t is_foreground)
{
uint8_t cnt; /* total number of remaining pixels, which have to be drawn */
uint8_t rem; /* remaining pixel to the right edge of the glyph */
uint8_t current; /* number of pixels, which need to be drawn for the draw procedure */
/* current is either equal to cnt or equal to rem */
/* local coordinates of the glyph */
uint8_t lx,ly;
/* target position on the screen */
ucg_int_t x, y;
ucg_font_decode_t *decode = &(ucg->font_decode);
cnt = len;
/* get the local position */
lx = decode->x;
ly = decode->y;
for(;;)
{
/* calculate the number of pixel to the right edge of the glyph */
rem = decode->glyph_width;
rem -= lx;
/* calculate how many pixel to draw. This is either to the right edge */
/* or lesser, if not enough pixel are left */
current = rem;
if ( cnt < rem )
current = cnt;
/* now draw the line, but apply the rotation around the glyph target position */
//ucg_font_decode_draw_pixel(ucg, lx,ly,current, is_foreground);
/* get target position */
x = decode->target_x;
y = decode->target_y;
/* apply rotation */
x = ucg_add_vector_x(x, lx, ly, decode->dir);
y = ucg_add_vector_y(y, lx, ly, decode->dir);
/* draw foreground and background (if required) */
if ( is_foreground )
{
ucg_Draw90Line(ucg,
x,
y,
current,
/* dir */ decode->dir,
/* col_idx */ 0);
}
else if ( decode->is_transparent == 0 )
{
ucg_Draw90Line(ucg,
x,
y,
current,
/* dir */ decode->dir,
/* col_idx */ 1);
}
/* check, whether the end of the run length code has been reached */
if ( cnt < rem )
break;
cnt -= rem;
lx = 0;
ly++;
}
//ucg_font_decode_draw_pixel(ucg, x,y, cnt, is_foreground);
lx += cnt;
decode->x = lx;
decode->y = ly;
}
static void ucg_font_setup_decode(ucg_t *ucg, const uint8_t *glyph_data)
{
ucg_font_decode_t *decode = &(ucg->font_decode);
decode->decode_ptr = glyph_data;
decode->decode_bit_pos = 0;
decode->decode_ptr += 1;
decode->decode_ptr += 1;
decode->glyph_width = ucg_font_decode_get_unsigned_bits(decode, ucg->font_info.bits_per_char_width);
decode->glyph_height = ucg_font_decode_get_unsigned_bits(decode,ucg->font_info.bits_per_char_height);
}
/*
Description:
Decode and draw a glyph.
Args:
glyph_data: Pointer to the compressed glyph data of the font
ucg->font_decode.target_x X position
ucg->font_decode.target_y Y position
ucg->font_decode.is_transparent Transparent mode
Return:
Width (delta x advance) of the glyph.
Calls:
ucg_font_decode_len()
*/
/* optimized */
int8_t ucg_font_decode_glyph(ucg_t *ucg, const uint8_t *glyph_data)
{
uint8_t a, b;
int8_t x, y;
int8_t d;
int8_t h;
ucg_font_decode_t *decode = &(ucg->font_decode);
ucg_font_setup_decode(ucg, glyph_data);
h = ucg->font_decode.glyph_height;
x = ucg_font_decode_get_signed_bits(decode, ucg->font_info.bits_per_char_x);
y = ucg_font_decode_get_signed_bits(decode, ucg->font_info.bits_per_char_y);
d = ucg_font_decode_get_signed_bits(decode, ucg->font_info.bits_per_delta_x);
if ( decode->glyph_width > 0 )
{
decode->target_x = ucg_add_vector_x(decode->target_x, x, -(h+y), decode->dir);
decode->target_y = ucg_add_vector_y(decode->target_y, x, -(h+y), decode->dir);
//ucg_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir);
/* reset local x/y position */
decode->x = 0;
decode->y = 0;
/* decode glyph */
for(;;)
{
a = ucg_font_decode_get_unsigned_bits(decode, ucg->font_info.bits_per_0);
b = ucg_font_decode_get_unsigned_bits(decode, ucg->font_info.bits_per_1);
do
{
ucg_font_decode_len(ucg, a, 0);
ucg_font_decode_len(ucg, b, 1);
} while( ucg_font_decode_get_unsigned_bits(decode, 1) != 0 );
if ( decode->y >= h )
break;
}
}
return d;
}
/*
Description:
Find the starting point of the glyph data.
Args:
encoding: Encoding (ASCII code) of the glyph
Return:
Address of the glyph data or NULL, if the encoding is not avialable in the font.
*/
const uint8_t *ucg_font_get_glyph_data(ucg_t *ucg, uint8_t encoding)
{
const uint8_t *font = ucg->font;
font += UCG_FONT_DATA_STRUCT_SIZE;
if ( encoding >= 'a' )
{
font += ucg->font_info.start_pos_lower_a;
}
else if ( encoding >= 'A' )
{
font += ucg->font_info.start_pos_upper_A;
}
for(;;)
{
if ( ucg_pgm_read( ((ucg_pgm_uint8_t *)font) + 1 ) == 0 )
break;
if ( ucg_pgm_read( (ucg_pgm_uint8_t *)font ) == encoding )
{
return font;
}
font += ucg_pgm_read( ((ucg_pgm_uint8_t *)font) + 1 );
}
return NULL;
}
ucg_int_t ucg_font_draw_glyph(ucg_t *ucg, ucg_int_t x, ucg_int_t y, uint8_t dir, uint8_t encoding)
{
ucg_int_t dx = 0;
ucg->font_decode.target_x = x;
ucg->font_decode.target_y = y;
//ucg->font_decode.is_transparent = is_transparent; this is already set
ucg->font_decode.dir = dir;
const uint8_t *glyph_data = ucg_font_get_glyph_data(ucg, encoding);
if ( glyph_data != NULL )
{
dx = ucg_font_decode_glyph(ucg, glyph_data);
}
return dx;
}
uint8_t ucg_IsGlyph(ucg_t *ucg, uint8_t requested_encoding)
{
/* updated to new code */
if ( ucg_font_get_glyph_data(ucg, requested_encoding) != NULL )
return 1;
return 0;
}
/*
int8_t ucg_GetGlyphDeltaX(ucg_t *ucg, uint8_t requested_encoding)
{
if ( ucg_GetGlyph(ucg, requested_encoding) == NULL )
return 0;
return ucg->glyph_dx;
}
*/
int8_t ucg_GetGlyphWidth(ucg_t *ucg, uint8_t requested_encoding)
{
const uint8_t *glyph_data = ucg_font_get_glyph_data(ucg, requested_encoding);
if ( glyph_data == NULL )
return 0;
ucg_font_setup_decode(ucg, glyph_data);
ucg_font_decode_get_signed_bits(&(ucg->font_decode), ucg->font_info.bits_per_char_x);
ucg_font_decode_get_signed_bits(&(ucg->font_decode), ucg->font_info.bits_per_char_y);
//return ucg->font_decode.glyph_width;
return ucg_font_decode_get_signed_bits(&(ucg->font_decode), ucg->font_info.bits_per_delta_x);
}
/*
set one of:
UCG_FONT_MODE_TRANSPARENT
UCG_FONT_MODE_SOLID
UCG_FONT_MODE_NONE
This has been changed for the new font procedures
*/
void ucg_SetFontMode(ucg_t *ucg, uint8_t is_transparent)
{
ucg->font_decode.is_transparent = is_transparent; // new font procedures
}
ucg_int_t ucg_DrawGlyph(ucg_t *ucg, ucg_int_t x, ucg_int_t y, uint8_t dir, uint8_t encoding)
{
switch(dir)
{
case 0:
y += ucg->font_calc_vref(ucg);
break;
case 1:
x -= ucg->font_calc_vref(ucg);
break;
case 2:
y -= ucg->font_calc_vref(ucg);
break;
case 3:
x += ucg->font_calc_vref(ucg);
break;
}
return ucg_font_draw_glyph(ucg, x, y, dir, encoding);
}
ucg_int_t ucg_DrawString(ucg_t *ucg, ucg_int_t x, ucg_int_t y, uint8_t dir, const char *str)
{
ucg_int_t delta, sum;
sum = 0;
while( *str != '\0' )
{
delta = ucg_DrawGlyph(ucg, x, y, dir, (uint8_t)*str);
switch(dir)
{
case 0:
x += delta;
break;
case 1:
y += delta;
break;
case 2:
x -= delta;
break;
case 3:
y -= delta;
break;
}
sum += delta;
str++;
}
return sum;
}
/*===============================================*/
/* set ascent/descent for reference point calculation */
void ucg_UpdateRefHeight(ucg_t *ucg)
{
if ( ucg->font == NULL )
return;
ucg->font_ref_ascent = ucg->font_info.ascent_A;
ucg->font_ref_descent = ucg->font_info.descent_g;
if ( ucg->font_height_mode == UCG_FONT_HEIGHT_MODE_TEXT )
{
}
else if ( ucg->font_height_mode == UCG_FONT_HEIGHT_MODE_XTEXT )
{
if ( ucg->font_ref_ascent < ucg->font_info.ascent_para )
ucg->font_ref_ascent = ucg->font_info.ascent_para;
if ( ucg->font_ref_descent > ucg->font_info.descent_para )
ucg->font_ref_descent = ucg->font_info.descent_para;
}
else
{
if ( ucg->font_ref_ascent < ucg->font_info.max_char_height+ucg->font_info.y_offset )
ucg->font_ref_ascent = ucg->font_info.max_char_height+ucg->font_info.y_offset;
if ( ucg->font_ref_descent > ucg->font_info.y_offset )
ucg->font_ref_descent = ucg->font_info.y_offset;
}
}
void ucg_SetFontRefHeightText(ucg_t *ucg)
{
ucg->font_height_mode = UCG_FONT_HEIGHT_MODE_TEXT;
ucg_UpdateRefHeight(ucg);
}
void ucg_SetFontRefHeightExtendedText(ucg_t *ucg)
{
ucg->font_height_mode = UCG_FONT_HEIGHT_MODE_XTEXT;
ucg_UpdateRefHeight(ucg);
}
void ucg_SetFontRefHeightAll(ucg_t *ucg)
{
ucg->font_height_mode = UCG_FONT_HEIGHT_MODE_ALL;
ucg_UpdateRefHeight(ucg);
}
/*===============================================*/
/* callback procedures to correct the y position */
ucg_int_t ucg_font_calc_vref_font(ucg_t *ucg)
{
return 0;
}
void ucg_SetFontPosBaseline(ucg_t *ucg)
{
ucg->font_calc_vref = ucg_font_calc_vref_font;
}
ucg_int_t ucg_font_calc_vref_bottom(ucg_t *ucg)
{
return (ucg_int_t)(ucg->font_ref_descent);
}
void ucg_SetFontPosBottom(ucg_t *ucg)
{
ucg->font_calc_vref = ucg_font_calc_vref_bottom;
}
ucg_int_t ucg_font_calc_vref_top(ucg_t *ucg)
{
ucg_int_t tmp;
/* reference pos is one pixel above the upper edge of the reference glyph */
tmp = (ucg_int_t)(ucg->font_ref_ascent);
tmp++;
return tmp;
}
void ucg_SetFontPosTop(ucg_t *ucg)
{
ucg->font_calc_vref = ucg_font_calc_vref_top;
}
ucg_int_t ucg_font_calc_vref_center(ucg_t *ucg)
{
int8_t tmp;
tmp = ucg->font_ref_ascent;
tmp -= ucg->font_ref_descent;
tmp /= 2;
tmp += ucg->font_ref_descent;
return tmp;
}
void ucg_SetFontPosCenter(ucg_t *ucg)
{
ucg->font_calc_vref = ucg_font_calc_vref_center;
}
/*===============================================*/
void ucg_SetFont(ucg_t *ucg, const ucg_fntpgm_uint8_t *font)
{
if ( ucg->font != font )
{
ucg->font = font;
ucg_read_font_info(&(ucg->font_info), font);
ucg_UpdateRefHeight(ucg);
//ucg_SetFontPosBaseline(ucg);
}
}
/*===============================================*/
ucg_int_t ucg_GetStrWidth(ucg_t *ucg, const char *s)
{
ucg_int_t w;
uint8_t encoding;
/* reset the total width to zero, this will be expanded during calculation */
w = 0;
for(;;)
{
encoding = *s;
if ( encoding == 0 )
break;
/* load glyph information */
// OBSOLETE ucg_GetGlyph(ucg, encoding);
// OBSOLETE w += ucg->glyph_dx;
// replaced by this:
w += ucg_GetGlyphWidth(ucg, encoding);
/* goto next char */
s++;
}
return w;
}
/*
ucg_init.c
Universal uC Color Graphics Library
Copyright (c) 2013, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ucg.h"
#include <string.h> /* memset */
#ifdef __AVR__
uint8_t global_SREG_backup; // used by the atomic macros
#endif
void ucg_init_struct(ucg_t *ucg)
{
//memset(ucg, 0, sizeof(ucg_t));
ucg->is_power_up = 0;
ucg->rotate_chain_device_cb = 0;
ucg->arg.scale = 1;
//ucg->display_offset.x = 0;
//ucg->display_offset.y = 0;
ucg->font = 0;
//ucg->font_mode = UCG_FONT_MODE_NONE; Old font procedures
ucg->font_decode.is_transparent = 1; // new font procedures
ucg->com_initial_change_sent = 0;
ucg->com_status = 0;
ucg->com_cfg_cd = 0;
}
ucg_int_t ucg_Init(ucg_t *ucg, ucg_dev_fnptr device_cb, ucg_dev_fnptr ext_cb, ucg_com_fnptr com_cb)
{
ucg_int_t r;
ucg_init_struct(ucg);
if ( ext_cb == (ucg_dev_fnptr)0 )
ucg->ext_cb = ucg_ext_none;
else
ucg->ext_cb = ext_cb;
ucg->device_cb = device_cb;
ucg->com_cb = com_cb;
ucg_SetFontPosBaseline(ucg);
r = ucg_PowerUp(ucg);
ucg_GetDimension(ucg);
return r;
}
/*
ucg_line.c
Universal uC Color Graphics Library
Copyright (c) 2013, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ucg.h"
void ucg_Draw90Line(ucg_t *ucg, ucg_int_t x, ucg_int_t y, ucg_int_t len, ucg_int_t dir, ucg_int_t col_idx)
{
ucg->arg.pixel.rgb.color[0] = ucg->arg.rgb[col_idx].color[0];
ucg->arg.pixel.rgb.color[1] = ucg->arg.rgb[col_idx].color[1];
ucg->arg.pixel.rgb.color[2] = ucg->arg.rgb[col_idx].color[2];
ucg->arg.pixel.pos.x = x;
ucg->arg.pixel.pos.y = y;
ucg->arg.len = len;
ucg->arg.dir = dir;
ucg_DrawL90FXWithArg(ucg);
}
void ucg_DrawHLine(ucg_t *ucg, ucg_int_t x, ucg_int_t y, ucg_int_t len)
{
ucg_Draw90Line(ucg, x, y, len, 0, 0);
}
void ucg_DrawVLine(ucg_t *ucg, ucg_int_t x, ucg_int_t y, ucg_int_t len)
{
ucg_Draw90Line(ucg, x, y, len, 1, 0);
}
void ucg_DrawHRLine(ucg_t *ucg, ucg_int_t x, ucg_int_t y, ucg_int_t len)
{
ucg_Draw90Line(ucg, x, y, len, 2, 0);
}
void ucg_DrawGradientLine(ucg_t *ucg, ucg_int_t x, ucg_int_t y, ucg_int_t len, ucg_int_t dir)
{
/* color goes from ucg->arg.rgb[0] to ucg->arg.rgb[1] */
ucg->arg.pixel.pos.x = x;
ucg->arg.pixel.pos.y = y;
ucg->arg.len = len;
ucg->arg.dir = dir;
ucg_DrawL90SEWithArg(ucg);
}
void ucg_DrawLine(ucg_t *ucg, ucg_int_t x1, ucg_int_t y1, ucg_int_t x2, ucg_int_t y2)
{
ucg_int_t tmp;
ucg_int_t x,y;
ucg_int_t dx, dy;
ucg_int_t err;
ucg_int_t ystep;
uint8_t swapxy = 0;
/* no BBX intersection check at the moment... */
ucg->arg.pixel.rgb.color[0] = ucg->arg.rgb[0].color[0];
ucg->arg.pixel.rgb.color[1] = ucg->arg.rgb[0].color[1];
ucg->arg.pixel.rgb.color[2] = ucg->arg.rgb[0].color[2];
if ( x1 > x2 ) dx = x1-x2; else dx = x2-x1;
if ( y1 > y2 ) dy = y1-y2; else dy = y2-y1;
if ( dy > dx )
{
swapxy = 1;
tmp = dx; dx =dy; dy = tmp;
tmp = x1; x1 =y1; y1 = tmp;
tmp = x2; x2 =y2; y2 = tmp;
}
if ( x1 > x2 )
{
tmp = x1; x1 =x2; x2 = tmp;
tmp = y1; y1 =y2; y2 = tmp;
}
err = dx >> 1;
if ( y2 > y1 ) ystep = 1; else ystep = -1;
y = y1;
for( x = x1; x <= x2; x++ )
{
if ( swapxy == 0 )
{
ucg->arg.pixel.pos.x = x;
ucg->arg.pixel.pos.y = y;
}
else
{
ucg->arg.pixel.pos.x = y;
ucg->arg.pixel.pos.y = x;
}
ucg_DrawPixelWithArg(ucg);
err -= (uint8_t)dy;
if ( err < 0 )
{
y += ystep;
err += dx;
}
}
}
/*
ucg_pixel.c
Universal uC Color Graphics Library
Copyright (c) 2013, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ucg.h"
void ucg_SetColor(ucg_t *ucg, uint8_t idx, uint8_t r, uint8_t g, uint8_t b)
{
//ucg->arg.pixel.rgb.color[0] = r;
//ucg->arg.pixel.rgb.color[1] = g;
//ucg->arg.pixel.rgb.color[2] = b;
ucg->arg.rgb[idx].color[0] = r;
ucg->arg.rgb[idx].color[1] = g;
ucg->arg.rgb[idx].color[2] = b;
}
void ucg_DrawPixel(ucg_t *ucg, ucg_int_t x, ucg_int_t y)
{
ucg->arg.pixel.rgb.color[0] = ucg->arg.rgb[0].color[0];
ucg->arg.pixel.rgb.color[1] = ucg->arg.rgb[0].color[1];
ucg->arg.pixel.rgb.color[2] = ucg->arg.rgb[0].color[2];
ucg->arg.pixel.pos.x = x;
ucg->arg.pixel.pos.y = y;
ucg_DrawPixelWithArg(ucg);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
ucg_polygon.c
Universal uC Color Graphics Library
Copyright (c) 2014, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ucg.h"
/*===========================================*/
/* procedures, which should not be inlined (save as much flash ROM as possible) */
static uint8_t pge_Next(struct pg_edge_struct *pge) PG_NOINLINE;
static uint8_t pg_inc(pg_struct *pg, uint8_t i) PG_NOINLINE;
static uint8_t pg_dec(pg_struct *pg, uint8_t i) PG_NOINLINE;
static void pg_expand_min_y(pg_struct *pg, pg_word_t min_y, uint8_t pge_idx) PG_NOINLINE;
static void pg_line_init(pg_struct * const pg, uint8_t pge_index) PG_NOINLINE;
/*===========================================*/
/* line draw algorithm */
static uint8_t pge_Next(struct pg_edge_struct *pge)
{
if ( pge->current_y >= pge->max_y )
return 0;
pge->current_x += pge->current_x_offset;
pge->error += pge->error_offset;
if ( pge->error > 0 )
{
pge->current_x += pge->x_direction;
pge->error -= pge->height;
}
pge->current_y++;
return 1;
}
/* assumes y2 > y1 */
static void pge_Init(struct pg_edge_struct *pge, pg_word_t x1, pg_word_t y1, pg_word_t x2, pg_word_t y2)
{
pg_word_t dx = x2 - x1;
pg_word_t width;
pge->height = y2 - y1;
pge->max_y = y2;
pge->current_y = y1;
pge->current_x = x1;
if ( dx >= 0 )
{
pge->x_direction = 1;
width = dx;
pge->error = 0;
}
else
{
pge->x_direction = -1;
width = -dx;
pge->error = 1 - pge->height;
}
pge->current_x_offset = dx / pge->height;
pge->error_offset = width % pge->height;
}
/*===========================================*/
/* convex polygon algorithm */
static uint8_t pg_inc(pg_struct *pg, uint8_t i)
{
i++;
if ( i >= pg->cnt )
i = 0;
return i;
}
static uint8_t pg_dec(pg_struct *pg, uint8_t i)
{
i--;
if ( i >= pg->cnt )
i = pg->cnt-1;
return i;
}
static void pg_expand_min_y(pg_struct *pg, pg_word_t min_y, uint8_t pge_idx)
{
uint8_t i = pg->pge[pge_idx].curr_idx;
for(;;)
{
i = pg->pge[pge_idx].next_idx_fn(pg, i);
if ( pg->list[i].y != min_y )
break;
pg->pge[pge_idx].curr_idx = i;
}
}
static uint8_t pg_prepare(pg_struct *pg)
{
pg_word_t max_y;
pg_word_t min_y;
uint8_t i;
/* setup the next index procedures */
pg->pge[PG_RIGHT].next_idx_fn = pg_inc;
pg->pge[PG_LEFT].next_idx_fn = pg_dec;
/* search for highest and lowest point */
max_y = pg->list[0].y;
min_y = pg->list[0].y;
pg->pge[PG_LEFT].curr_idx = 0;
for( i = 1; i < pg->cnt; i++ )
{
if ( max_y < pg->list[i].y )
{
max_y = pg->list[i].y;
}
if ( min_y > pg->list[i].y )
{
pg->pge[PG_LEFT].curr_idx = i;
min_y = pg->list[i].y;
}
}
/* calculate total number of scan lines */
pg->total_scan_line_cnt = max_y;
pg->total_scan_line_cnt -= min_y;
/* exit if polygon height is zero */
if ( pg->total_scan_line_cnt == 0 )
return 0;
/* if the minimum y side is flat, try to find the lowest and highest x points */
pg->pge[PG_RIGHT].curr_idx = pg->pge[PG_LEFT].curr_idx;
pg_expand_min_y(pg, min_y, PG_RIGHT);
pg_expand_min_y(pg, min_y, PG_LEFT);
/* check if the min side is really flat (depends on the x values) */
pg->is_min_y_not_flat = 1;
if ( pg->list[pg->pge[PG_LEFT].curr_idx].x != pg->list[pg->pge[PG_RIGHT].curr_idx].x )
{
pg->is_min_y_not_flat = 0;
}
else
{
pg->total_scan_line_cnt--;
if ( pg->total_scan_line_cnt == 0 )
return 0;
}
return 1;
}
static void pg_hline(pg_struct *pg, ucg_t *ucg)
{
pg_word_t x1, x2, y;
x1 = pg->pge[PG_LEFT].current_x;
x2 = pg->pge[PG_RIGHT].current_x;
y = pg->pge[PG_RIGHT].current_y;
if ( y < 0 )
return;
if ( y >= ucg_GetHeight(ucg) )
return;
if ( x1 < x2 )
{
if ( x2 < 0 )
return;
if ( x1 >= ucg_GetWidth(ucg) )
return;
if ( x1 < 0 )
x1 = 0;
if ( x2 >= ucg_GetWidth(ucg) )
x2 = ucg_GetWidth(ucg);
ucg_DrawHLine(ucg, x1, y, x2 - x1);
}
else
{
if ( x1 < 0 )
return;
if ( x2 >= ucg_GetWidth(ucg) )
return;
if ( x2 < 0 )
x1 = 0;
if ( x1 >= ucg_GetWidth(ucg) )
x1 = ucg_GetWidth(ucg);
ucg_DrawHLine(ucg, x2, y, x1 - x2);
}
}
static void pg_line_init(pg_struct * pg, uint8_t pge_index)
{
struct pg_edge_struct *pge = pg->pge+pge_index;
uint8_t idx;
pg_word_t x1;
pg_word_t y1;
pg_word_t x2;
pg_word_t y2;
idx = pge->curr_idx;
y1 = pg->list[idx].y;
x1 = pg->list[idx].x;
idx = pge->next_idx_fn(pg, idx);
y2 = pg->list[idx].y;
x2 = pg->list[idx].x;
pge->curr_idx = idx;
pge_Init(pge, x1, y1, x2, y2);
}
static void pg_exec(pg_struct *pg, ucg_t *ucg)
{
pg_word_t i = pg->total_scan_line_cnt;
/* first line is skipped if the min y line is not flat */
pg_line_init(pg, PG_LEFT);
pg_line_init(pg, PG_RIGHT);
if ( pg->is_min_y_not_flat != 0 )
{
pge_Next(&(pg->pge[PG_LEFT]));
pge_Next(&(pg->pge[PG_RIGHT]));
}
do
{
pg_hline(pg, ucg);
while ( pge_Next(&(pg->pge[PG_LEFT])) == 0 )
{
pg_line_init(pg, PG_LEFT);
}
while ( pge_Next(&(pg->pge[PG_RIGHT])) == 0 )
{
pg_line_init(pg, PG_RIGHT);
}
i--;
} while( i > 0 );
}
/*===========================================*/
/* API procedures */
void ucg_pg_ClearPolygonXY(pg_struct *pg)
{
pg->cnt = 0;
}
void ucg_pg_AddPolygonXY(pg_struct *pg, ucg_t *ucg, int16_t x, int16_t y)
{
if ( pg->cnt < PG_MAX_POINTS )
{
pg->list[pg->cnt].x = x;
pg->list[pg->cnt].y = y;
pg->cnt++;
}
}
void ucg_pg_DrawPolygon(pg_struct *pg, ucg_t *ucg)
{
if ( pg_prepare(pg) == 0 )
return;
pg_exec(pg, ucg);
}
pg_struct ucg_pg;
void ucg_ClearPolygonXY(void)
{
ucg_pg_ClearPolygonXY(&ucg_pg);
}
void ucg_AddPolygonXY(ucg_t *ucg, int16_t x, int16_t y)
{
ucg_pg_AddPolygonXY(&ucg_pg, ucg, x, y);
}
void ucg_DrawPolygon(ucg_t *ucg)
{
ucg_pg_DrawPolygon(&ucg_pg, ucg);
}
void ucg_DrawTriangle(ucg_t *ucg, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
{
ucg_ClearPolygonXY();
ucg_AddPolygonXY(ucg, x0, y0);
ucg_AddPolygonXY(ucg, x1, y1);
ucg_AddPolygonXY(ucg, x2, y2);
ucg_DrawPolygon(ucg);
}
void ucg_DrawTetragon(ucg_t *ucg, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3)
{
ucg_ClearPolygonXY();
ucg_AddPolygonXY(ucg, x0, y0);
ucg_AddPolygonXY(ucg, x1, y1);
ucg_AddPolygonXY(ucg, x2, y2);
ucg_AddPolygonXY(ucg, x3, y3);
ucg_DrawPolygon(ucg);
}
/*
ucg_rotate.c
Universal uC Color Graphics Library
Copyright (c) 2014, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ucg.h"
#include <assert.h>
/* Side-Effects: Update dimension and reset clip range to max */
void ucg_UndoRotate(ucg_t *ucg)
{
if ( ucg->rotate_chain_device_cb != NULL )
{
ucg->device_cb = ucg->rotate_chain_device_cb;
ucg->rotate_chain_device_cb = NULL;
}
ucg_GetDimension(ucg);
ucg_SetMaxClipRange(ucg);
}
/*================================================*/
/* 90 degree */
static void ucg_rotate_90_xy(ucg_xy_t *xy, ucg_int_t display_width)
{
ucg_int_t x, y;
y = xy->x;
x = display_width;
x -= xy->y;
x--;
xy->x = x;
xy->y = y;
}
ucg_int_t ucg_dev_rotate90(ucg_t *ucg, ucg_int_t msg, void *data)
{
switch(msg)
{
case UCG_MSG_GET_DIMENSION:
ucg->rotate_chain_device_cb(ucg, msg, &(ucg->rotate_dimension));
((ucg_wh_t *)data)->h = ucg->rotate_dimension.w;
((ucg_wh_t *)data)->w = ucg->rotate_dimension.h;
//printf("rw=%d rh=%d\n", ucg->rotate_dimension.w, ucg->rotate_dimension.h);
//printf("aw=%d ah=%d\n", ((ucg_wh_t volatile * volatile )data)->w, ((ucg_wh_t volatile * volatile )data)->h);
//printf("dw=%d dh=%d\n", ucg->dimension.w, ucg->dimension.h);
return 1;
case UCG_MSG_SET_CLIP_BOX:
/* to rotate the box, the lower left corner will become the new xy value pair */
/* so the unrotated lower left is put into "ul" */
//printf("pre clipbox x=%d y=%d\n", ((ucg_box_t * )data)->ul.x, ((ucg_box_t * )data)->ul.y);
((ucg_box_t * )data)->ul.y += ((ucg_box_t * )data)->size.h-1;
//printf("pre clipbox lower left x=%d y=%d\n", ((ucg_box_t * )data)->ul.x, ((ucg_box_t * )data)->ul.y);
/* then apply rotation */
ucg_rotate_90_xy(&(((ucg_box_t * )data)->ul), ucg->rotate_dimension.w);
/* finally, swap dimensions */
{
ucg_int_t tmp;
tmp = ((ucg_box_t *)data)->size.w;
((ucg_box_t * )data)->size.w = ((ucg_box_t *)data)->size.h;
((ucg_box_t * )data)->size.h = tmp;
}
//printf("post clipbox x=%d y=%d\n", ((ucg_box_t * )data)->ul.x, ((ucg_box_t * )data)->ul.y);
break;
case UCG_MSG_DRAW_PIXEL:
case UCG_MSG_DRAW_L90FX:
#ifdef UCG_MSG_DRAW_L90TC
case UCG_MSG_DRAW_L90TC:
#endif /* UCG_MSG_DRAW_L90TC */
#ifdef UCG_MSG_DRAW_L90BF
case UCG_MSG_DRAW_L90BF:
#endif /* UCG_MSG_DRAW_L90BF */
case UCG_MSG_DRAW_L90SE:
//case UCG_MSG_DRAW_L90RL:
ucg->arg.dir+=1;
ucg->arg.dir&=3;
//ucg_rotate_90_xy(&(ucg->arg.pixel.pos), ucg->rotate_dimension.w);
//printf("dw=%d dh=%d\n", ucg->dimension.w, ucg->dimension.h);
//printf("pre x=%d y=%d\n", ucg->arg.pixel.pos.x, ucg->arg.pixel.pos.y);
ucg_rotate_90_xy(&(ucg->arg.pixel.pos), ucg->rotate_dimension.w);
//printf("post x=%d y=%d\n", ucg->arg.pixel.pos.x, ucg->arg.pixel.pos.y);
break;
}
return ucg->rotate_chain_device_cb(ucg, msg, data);
}
/* Side-Effects: Update dimension and reset clip range to max */
void ucg_SetRotate90(ucg_t *ucg)
{
ucg_UndoRotate(ucg);
ucg->rotate_chain_device_cb = ucg->device_cb;
ucg->device_cb = ucg_dev_rotate90;
ucg_GetDimension(ucg);
ucg_SetMaxClipRange(ucg);
}
/*================================================*/
/* 180 degree */
static void ucg_rotate_180_xy(ucg_t *ucg, ucg_xy_t *xy)
{
ucg_int_t x, y;
y = ucg->rotate_dimension.h;
y -= xy->y;
y--;
xy->y = y;
x = ucg->rotate_dimension.w;
x -= xy->x;
x--;
xy->x = x;
}
ucg_int_t ucg_dev_rotate180(ucg_t *ucg, ucg_int_t msg, void *data)
{
switch(msg)
{
case UCG_MSG_GET_DIMENSION:
ucg->rotate_chain_device_cb(ucg, msg, &(ucg->rotate_dimension));
*((ucg_wh_t *)data) = (ucg->rotate_dimension);
return 1;
case UCG_MSG_SET_CLIP_BOX:
/* calculate and rotate lower right point of the clip box */
((ucg_box_t * )data)->ul.y += ((ucg_box_t * )data)->size.h-1;
((ucg_box_t * )data)->ul.x += ((ucg_box_t * )data)->size.w-1;
ucg_rotate_180_xy(ucg, &(((ucg_box_t * )data)->ul));
/* box dimensions are the same */
break;
case UCG_MSG_DRAW_PIXEL:
case UCG_MSG_DRAW_L90FX:
#ifdef UCG_MSG_DRAW_L90TC
case UCG_MSG_DRAW_L90TC:
#endif /* UCG_MSG_DRAW_L90TC */
#ifdef UCG_MSG_DRAW_L90BF
case UCG_MSG_DRAW_L90BF:
#endif /* UCG_MSG_DRAW_L90BF */
case UCG_MSG_DRAW_L90SE:
//case UCG_MSG_DRAW_L90RL:
ucg->arg.dir+=2;
ucg->arg.dir&=3;
ucg_rotate_180_xy(ucg, &(ucg->arg.pixel.pos));
break;
}
return ucg->rotate_chain_device_cb(ucg, msg, data);
}
/* Side-Effects: Update dimension and reset clip range to max */
void ucg_SetRotate180(ucg_t *ucg)
{
ucg_UndoRotate(ucg);
ucg->rotate_chain_device_cb = ucg->device_cb;
ucg->device_cb = ucg_dev_rotate180;
ucg_GetDimension(ucg);
ucg_SetMaxClipRange(ucg);
}
/*================================================*/
/* 270 degree */
static void ucg_rotate_270_xy(ucg_t *ucg, ucg_xy_t *xy)
{
ucg_int_t x, y;
x = xy->y;
y = ucg->rotate_dimension.h;
y -= xy->x;
y--;
xy->y = y;
xy->x = x;
}
ucg_int_t ucg_dev_rotate270(ucg_t *ucg, ucg_int_t msg, void *data)
{
switch(msg)
{
case UCG_MSG_GET_DIMENSION:
ucg->rotate_chain_device_cb(ucg, msg, &(ucg->rotate_dimension));
((ucg_wh_t *)data)->h = ucg->rotate_dimension.w;
((ucg_wh_t *)data)->w = ucg->rotate_dimension.h;
return 1;
case UCG_MSG_SET_CLIP_BOX:
/* calculate and rotate upper right point of the clip box */
((ucg_box_t * )data)->ul.x += ((ucg_box_t * )data)->size.w-1;
ucg_rotate_270_xy(ucg, &(((ucg_box_t * )data)->ul));
/* finally, swap dimensions */
{
ucg_int_t tmp;
tmp = ((ucg_box_t *)data)->size.w;
((ucg_box_t * )data)->size.w = ((ucg_box_t *)data)->size.h;
((ucg_box_t * )data)->size.h = tmp;
}
break;
case UCG_MSG_DRAW_PIXEL:
case UCG_MSG_DRAW_L90FX:
#ifdef UCG_MSG_DRAW_L90TC
case UCG_MSG_DRAW_L90TC:
#endif /* UCG_MSG_DRAW_L90TC */
#ifdef UCG_MSG_DRAW_L90BF
case UCG_MSG_DRAW_L90BF:
#endif /* UCG_MSG_DRAW_L90BF */
case UCG_MSG_DRAW_L90SE:
// case UCG_MSG_DRAW_L90RL:
ucg->arg.dir+=3;
ucg->arg.dir&=3;
ucg_rotate_270_xy(ucg, &(ucg->arg.pixel.pos));
break;
}
return ucg->rotate_chain_device_cb(ucg, msg, data);
}
/* Side-Effects: Update dimension and reset clip range to max */
void ucg_SetRotate270(ucg_t *ucg)
{
ucg_UndoRotate(ucg);
ucg->rotate_chain_device_cb = ucg->device_cb;
ucg->device_cb = ucg_dev_rotate270;
ucg_GetDimension(ucg);
ucg_SetMaxClipRange(ucg);
}
/*
ucg_scale.c
Universal uC Color Graphics Library
Copyright (c) 2014, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ucg.h"
void ucg_UndoScale(ucg_t *ucg)
{
if ( ucg->scale_chain_device_cb != NULL )
{
ucg->device_cb = ucg->scale_chain_device_cb;
ucg->scale_chain_device_cb = NULL;
}
ucg_GetDimension(ucg);
ucg_SetMaxClipRange(ucg);
}
const ucg_fntpgm_uint8_t ucg_scale_2x2[16] UCG_FONT_SECTION("ucg_scale_2x2") =
{ 0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f, 0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff };
static void ucg_scale_2x2_send_next_half_byte(ucg_t *ucg, ucg_xy_t *xy, ucg_int_t msg, ucg_int_t len, ucg_int_t dir, uint8_t b)
{
b &= 15;
len *=2;
ucg->arg.pixel.pos = *xy;
switch(dir)
{
case 0: break;
case 1: break;
case 2: ucg->arg.pixel.pos.x++; break;
default: case 3: ucg->arg.pixel.pos.y++; break;
}
ucg->arg.bitmap = ucg_scale_2x2+b;
ucg->arg.len = len;
ucg->arg.dir = dir;
ucg->scale_chain_device_cb(ucg, msg, &(ucg->arg));
ucg->arg.pixel.pos = *xy;
switch(dir)
{
case 0: ucg->arg.pixel.pos.y++; break;
case 1: ucg->arg.pixel.pos.x++; break;
case 2: ucg->arg.pixel.pos.y++; ucg->arg.pixel.pos.x++; break;
default: case 3: ucg->arg.pixel.pos.x++; ucg->arg.pixel.pos.y++; break;
}
ucg->arg.bitmap = ucg_scale_2x2+b;
ucg->arg.len = len;
ucg->arg.dir = dir;
ucg->scale_chain_device_cb(ucg, msg, &(ucg->arg));
switch(dir)
{
case 0: xy->x+=len; break;
case 1: xy->y+=len; break;
case 2: xy->x-=len; break;
default: case 3: xy->y-=len; break;
}
}
ucg_int_t ucg_dev_scale2x2(ucg_t *ucg, ucg_int_t msg, void *data)
{
ucg_xy_t xy;
ucg_int_t len;
ucg_int_t dir;
switch(msg)
{
case UCG_MSG_GET_DIMENSION:
ucg->scale_chain_device_cb(ucg, msg, data);
((ucg_wh_t *)data)->h /= 2;
((ucg_wh_t *)data)->w /= 2;
//printf("rw=%d rh=%d\n", ucg->rotate_dimension.w, ucg->rotate_dimension.h);
//printf("aw=%d ah=%d\n", ((ucg_wh_t volatile * volatile )data)->w, ((ucg_wh_t volatile * volatile )data)->h);
//printf("dw=%d dh=%d\n", ucg->dimension.w, ucg->dimension.h);
return 1;
case UCG_MSG_SET_CLIP_BOX:
((ucg_box_t * )data)->ul.y *= 2;
((ucg_box_t * )data)->ul.x *= 2;
((ucg_box_t * )data)->size.h *= 2;
((ucg_box_t * )data)->size.w *= 2;
//printf("post clipbox x=%d y=%d\n", ((ucg_box_t * )data)->ul.x, ((ucg_box_t * )data)->ul.y);
break;
case UCG_MSG_DRAW_PIXEL:
xy = ucg->arg.pixel.pos;
ucg->arg.pixel.pos.x *= 2;
ucg->arg.pixel.pos.y *= 2;
ucg->scale_chain_device_cb(ucg, msg, data);
ucg->arg.pixel.pos.x++;
ucg->scale_chain_device_cb(ucg, msg, data);
ucg->arg.pixel.pos.y++;
ucg->scale_chain_device_cb(ucg, msg, data);
ucg->arg.pixel.pos.x--;
ucg->scale_chain_device_cb(ucg, msg, data);
ucg->arg.pixel.pos = xy;
return 1;
case UCG_MSG_DRAW_L90SE:
case UCG_MSG_DRAW_L90FX:
xy = ucg->arg.pixel.pos;
len = ucg->arg.len;
dir = ucg->arg.dir;
ucg->arg.pixel.pos.x *= 2;
ucg->arg.pixel.pos.y *= 2;
switch(dir)
{
case 0: break;
case 1: break;
case 2: ucg->arg.pixel.pos.x++; break;
default: case 3: ucg->arg.pixel.pos.y++; break;
}
ucg->arg.len *= 2;
ucg->scale_chain_device_cb(ucg, msg, data);
ucg->arg.pixel.pos = xy;
ucg->arg.pixel.pos.x *= 2;
ucg->arg.pixel.pos.y *= 2;
ucg->arg.len = len*2;
ucg->arg.dir = dir;
switch(dir)
{
case 0: ucg->arg.pixel.pos.y++; break;
case 1: ucg->arg.pixel.pos.x++; break;
case 2: ucg->arg.pixel.pos.y++; ucg->arg.pixel.pos.x++; break;
default: case 3: ucg->arg.pixel.pos.x++; ucg->arg.pixel.pos.y++; break;
}
ucg->scale_chain_device_cb(ucg, msg, data);
ucg->arg.pixel.pos = xy;
ucg->arg.len = len;
ucg->arg.dir = dir;
return 1;
#ifdef UCG_MSG_DRAW_L90TC
case UCG_MSG_DRAW_L90TC:
#endif /* UCG_MSG_DRAW_L90TC */
#ifdef UCG_MSG_DRAW_L90BF
case UCG_MSG_DRAW_L90BF:
#endif /* UCG_MSG_DRAW_L90BF */
#if defined(UCG_MSG_DRAW_L90TC) || defined(UCG_MSG_DRAW_L90BF)
xy = ucg->arg.pixel.pos;
len = ucg->arg.len;
dir = ucg->arg.dir;
ucg->arg.pixel.pos.x *= 2;
ucg->arg.pixel.pos.y *= 2;
{
const unsigned char *b = ucg->arg.bitmap;
ucg_xy_t my_xy = ucg->arg.pixel.pos;
ucg_int_t i;
for( i = 8; i < len; i+=8 )
{
ucg_scale_2x2_send_next_half_byte(ucg, &my_xy, msg, 4, dir, ucg_pgm_read(b)>>4);
ucg_scale_2x2_send_next_half_byte(ucg, &my_xy, msg, 4, dir, ucg_pgm_read(b));
b+=1;
}
i = len+8-i;
if ( i > 4 )
{
ucg_scale_2x2_send_next_half_byte(ucg, &my_xy, msg, 4, dir, ucg_pgm_read(b)>>4);
ucg_scale_2x2_send_next_half_byte(ucg, &my_xy, msg, i-4, dir, ucg_pgm_read(b));
}
else
{
ucg_scale_2x2_send_next_half_byte(ucg, &my_xy, msg, i, dir, ucg_pgm_read(b)>>4);
}
}
ucg->arg.pixel.pos = xy;
ucg->arg.len = len;
ucg->arg.dir = dir;
return 1;
#endif
}
return ucg->scale_chain_device_cb(ucg, msg, data);
}
/* Side-Effects: Update dimension and reset clip range to max */
void ucg_SetScale2x2(ucg_t *ucg)
{
ucg_UndoScale(ucg);
ucg->scale_chain_device_cb = ucg->device_cb;
ucg->device_cb = ucg_dev_scale2x2;
ucg_GetDimension(ucg);
ucg_SetMaxClipRange(ucg);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
local M, module = {}, ...
_G[module] = M
function M.run()
-- make this a volatile module:
package.loaded[module] = nil
print("Running component box...")
local x, y, w, h
local m
disp:setColor(0, 0, 40, 80)
disp:setColor(1, 60, 0, 40)
disp:setColor(2, 128, 0, 140)
disp:setColor(3, 0, 128, 140)
disp:drawGradientBox(0, 0, disp:getWidth(), disp:getHeight())
disp:setColor(255, 255, 255)
disp:setPrintPos(2,18)
disp:setPrintDir(0)
disp:print("Box")
m = millis() + T
while millis() < m do
disp:setColor(bit.band(lcg_rnd(), 127)+127, bit.band(lcg_rnd(), 127)+64, bit.band(lcg_rnd(), 31))
w = bit.band(lcg_rnd(), 31)
h = bit.band(lcg_rnd(), 31)
w = w + 10
h = h + 10
x = bit.rshift(lcg_rnd() * (disp:getWidth()-w), 8)
y = bit.rshift(lcg_rnd() * (disp:getHeight()-h-20), 8)
disp:drawBox(x, y+20, w, h)
end
print("...done")
end
return M
local M, module = {}, ...
_G[module] = M
function M.run()
-- make this a volatile module:
package.loaded[module] = nil
print("Running component clip...")
disp:setColor(0, 0x00, 0xd1, 0x5e) -- dark green
disp:setColor(1, 0xff, 0xf7, 0x61) -- yellow
disp:setColor(2, 0xd1, 0xc7, 0x00) -- dark yellow
disp:setColor(3, 0x61, 0xff, 0xa8) -- green
disp:drawGradientBox(0, 0, disp:getWidth(), disp:getHeight())
disp:setColor(255, 255, 255)
disp:setPrintPos(2,18)
disp:setPrintDir(0)
disp:print("ClipRange")
disp:setColor(0xd1, 0x00, 0x073)
disp:setFont(ucg.font_helvB18_hr)
disp:setPrintPos(25,45)
disp:setPrintDir(0)
disp:print("Ucg")
disp:setPrintDir(1)
disp:print("Ucg")
disp:setPrintDir(2)
disp:print("Ucg")
disp:setPrintDir(3)
disp:print("Ucg")
disp:setMaxClipRange()
disp:setColor(0xff, 0xff, 0xff)
disp:drawFrame(20-1,30-1,15+2,20+2)
disp:setClipRange(20, 30, 15, 20)
disp:setColor(0xff, 0x61, 0x0b8)
disp:setPrintPos(25,45)
disp:setPrintDir(0)
disp:print("Ucg")
disp:setPrintDir(1)
disp:print("Ucg")
disp:setPrintDir(2)
disp:print("Ucg")
disp:setPrintDir(3)
disp:print("Ucg")
disp:setMaxClipRange()
disp:setColor(0xff, 0xff, 0xff)
disp:drawFrame(60-1,35-1,25+2,18+2)
disp:setClipRange(60, 35, 25, 18)
disp:setColor(0xff, 0x61, 0x0b8)
disp:setPrintPos(25,45)
disp:setPrintDir(0)
disp:print("Ucg")
disp:setPrintDir(1)
disp:print("Ucg")
disp:setPrintDir(2)
disp:print("Ucg")
disp:setPrintDir(3)
disp:print("Ucg")
disp:setMaxClipRange()
disp:setColor(0xff, 0xff, 0xff)
disp:drawFrame(7-1,58-1,90+2,4+2)
disp:setClipRange(7, 58, 90, 4)
disp:setColor(0xff, 0x61, 0x0b8)
disp:setPrintPos(25,45)
disp:setPrintDir(0)
disp:print("Ucg")
disp:setPrintDir(1)
disp:print("Ucg")
disp:setPrintDir(2)
disp:print("Ucg")
disp:setPrintDir(3)
disp:print("Ucg")
disp:setFont(ucg.font_ncenR14_hr)
disp:setMaxClipRange()
print("...done")
end
return M
local M, module = {}, ...
_G[module] = M
function M.run()
-- make this a volatile module:
package.loaded[module] = nil
print("Running component color_test...")
local mx
local c, x
mx = disp:getWidth() / 2
--my = disp:getHeight() / 2
disp:setColor(0, 0, 0, 0)
disp:drawBox(0, 0, disp:getWidth(), disp:getHeight())
disp:setColor(255, 255, 255)
disp:setPrintPos(2,18)
disp:setPrintDir(0)
disp:print("Color Test")
disp:setColor(0, 127, 127, 127)
disp:drawBox(0, 20, 16*4+4, 5*8+4)
c = 0
x = 2
while c < 255 do
disp:setColor(0, c, c, c)
disp:drawBox(x, 22, 4, 8)
disp:setColor(0, c, 0, 0)
disp:drawBox(x, 22+8, 4, 8)
disp:setColor(0, 0, c, 0)
disp:drawBox(x, 22+2*8, 4, 8)
disp:setColor(0, 0, 0, c)
disp:drawBox(x, 22+3*8, 4, 8)
disp:setColor(0, c, 255-c, 0)
disp:drawBox(x, 22+4*8, 4, 8)
c = c + 17
x = x + 4
end
print("...done")
end
return M
local M, module = {}, ...
_G[module] = M
function M.run()
-- make this a volatile module:
package.loaded[module] = nil
print("Running component cross...")
local mx, my
disp:setColor(0, 250, 0, 0)
disp:setColor(1, 255, 255, 30)
disp:setColor(2, 220, 235, 10)
disp:setColor(3, 205, 0, 30)
disp:drawGradientBox(0, 0, disp:getWidth(), disp:getHeight())
mx = disp:getWidth() / 2
my = disp:getHeight() / 2
disp:setColor(0, 255, 255, 255)
disp:setPrintPos(2,18)
disp:print("Cross")
disp:setColor(0, 0, 0x66, 0xcc)
disp:setPrintPos(mx+15, my-5)
disp:print("dir0")
disp:setPrintPos(mx+5, my+26)
disp:print("dir1")
disp:setPrintPos(mx-40, my+20)
disp:print("dir2")
disp:setPrintPos(mx+5,my-25)
disp:print("dir3")
disp:setColor(0, 0, 0x66, 0xff)
disp:setColor(1, 0, 0x66, 0xcc)
disp:setColor(2, 0, 0, 0x99)
disp:draw90Line(mx+2, my-1, 20, 0, 0)
disp:draw90Line(mx+2, my, 20, 0, 1)
disp:draw90Line(mx+2, my+1, 20, 0, 2)
disp:draw90Line(mx+1, my+2, 20, 1, 0)
disp:draw90Line(mx, my+2, 20, 1, 1)
disp:draw90Line(mx-1, my+2, 20, 1, 2)
disp:draw90Line(mx-2, my+1, 20, 2, 0)
disp:draw90Line(mx-2, my, 20, 2, 1)
disp:draw90Line(mx-2, my-1, 20, 2, 2)
disp:draw90Line(mx-1, my-2, 20, 3, 0)
disp:draw90Line(mx, my-2, 20, 3, 1)
disp:draw90Line(mx+1, my-2, 20, 3, 2)
print("...done")
end
return M
local M, module = {}, ...
_G[module] = M
function M.run()
-- make this a volatile module:
package.loaded[module] = nil
print("Running component fonts...")
local d = 5
disp:setColor(0, 0, 40, 80)
disp:setColor(1, 150, 0, 200)
disp:setColor(2, 60, 0, 40)
disp:setColor(3, 0, 160, 160)
disp:drawGradientBox(0, 0, disp:getWidth(), disp:getHeight())
disp:setColor(255, 255, 255)
disp:setPrintDir(0)
disp:setPrintPos(2,18)
disp:print("Fonts")
disp:setFontMode(ucg.FONT_MODE_TRANSPARENT)
disp:setColor(255, 200, 170)
disp:setFont(ucg.font_helvB08_hr)
disp:setPrintPos(2,30+d)
disp:print("ABC abc 123")
disp:setFont(ucg.font_helvB10_hr)
disp:setPrintPos(2,45+d)
disp:print("ABC abc 123")
disp:setFont(ucg.font_helvB12_hr)
--disp:setPrintPos(2,62+d)
--disp:print("ABC abc 123")
disp:drawString(2,62+d, 0, "ABC abc 123") -- test drawString
disp:setFontMode(ucg.FONT_MODE_SOLID)
disp:setColor(255, 200, 170)
disp:setColor(1, 0, 100, 120) -- background color in solid mode
disp:setFont(ucg.font_helvB08_hr)
disp:setPrintPos(2,75+30+d)
disp:print("ABC abc 123")
disp:setFont(ucg.font_helvB10_hr)
disp:setPrintPos(2,75+45+d)
disp:print("ABC abc 123")
disp:setFont(ucg.font_helvB12_hr)
disp:setPrintPos(2,75+62+d)
disp:print("ABC abc 123")
disp:setFontMode(ucg.FONT_MODE_TRANSPARENT)
disp:setFont(ucg.font_ncenR14_hr)
print("...done")
end
return M
local M, module = {}, ...
_G[module] = M
function M.run()
-- make this a volatile module:
package.loaded[module] = nil
print("Running component gradient...")
disp:setColor(0, 0, 255, 0)
disp:setColor(1, 255, 0, 0)
disp:setColor(2, 255, 0, 255)
disp:setColor(3, 0, 255, 255)
disp:drawGradientBox(0, 0, disp:getWidth(), disp:getHeight())
disp:setColor(255, 255, 255)
disp:setPrintPos(2,18)
disp:setPrintDir(0)
disp:print("GradientBox")
disp:setColor(0, 0, 255, 0)
disp:drawBox(2, 25, 8, 8)
disp:setColor(0, 255, 0, 0)
disp:drawBox(2+10, 25, 8, 8)
disp:setColor(0, 255, 0, 255)
disp:drawBox(2, 25+10, 8, 8)
disp:setColor(0, 0, 255, 255)
disp:drawBox(2+10, 25+10, 8, 8)
print("...done")
end
return M
local M, module = {}, ...
_G[module] = M
function M.run()
-- make this a volatile module:
package.loaded[module] = nil
print("Running component graphics_test...")
--ucg.setMaxClipRange()
disp:setColor(0, 0, 40, 80)
disp:setColor(1, 80, 0, 40)
disp:setColor(2, 255, 0, 255)
disp:setColor(3, 0, 255, 255)
disp:drawGradientBox(0, 0, disp:getWidth(), disp:getHeight())
disp:setColor(255, 168, 0)
disp:setPrintDir(0)
disp:setPrintPos(2, 18)
disp:print("Ucglib")
disp:setPrintPos(2, 18+20)
disp:print("GraphicsTest")
print("...done")
end
return M
local M, module = {}, ...
_G[module] = M
function M.run()
-- make this a volatile module:
package.loaded[module] = nil
print("Running component pixel_and_lines...")
local mx
local x, xx
mx = disp:getWidth() / 2
--my = disp:getHeight() / 2
disp:setColor(0, 0, 0, 150)
disp:setColor(1, 0, 60, 40)
disp:setColor(2, 60, 0, 40)
disp:setColor(3, 120, 120, 200)
disp:drawGradientBox(0, 0, disp:getWidth(), disp:getHeight())
disp:setColor(255, 255, 255)
disp:setPrintPos(2, 18)
disp:setPrintDir(0)
disp:print("Pix&Line")
disp:drawPixel(0, 0)
disp:drawPixel(1, 0)
--disp:drawPixel(disp:getWidth()-1, 0)
--disp:drawPixel(0, disp:getHeight()-1)
disp:drawPixel(disp:getWidth()-1, disp:getHeight()-1)
disp:drawPixel(disp:getWidth()-1-1, disp:getHeight()-1)
x = 0
while x < mx do
xx = ((x)*255)/mx
disp:setColor(255, 255-xx/2, 255-xx)
disp:drawPixel(x, 24)
disp:drawVLine(x+7, 26, 13)
x = x + 1
end
print("...done")
end
return M
local M, module = {}, ...
_G[module] = M
function M.run()
-- make this a volatile module:
package.loaded[module] = nil
print("Running component text...")
local x, y, w, h, i
local m
disp:setColor(0, 80, 40, 0)
disp:setColor(1, 60, 0, 40)
disp:setColor(2, 20, 0, 20)
disp:setColor(3, 60, 0, 0)
disp:drawGradientBox(0, 0, disp:getWidth(), disp:getHeight())
disp:setColor(255, 255, 255)
disp:setPrintPos(2,18)
disp:setPrintDir(0)
disp:print("Text")
m = millis() + T
i = 0
while millis() < m do
disp:setColor(bit.band(lcg_rnd(), 31), bit.band(lcg_rnd(), 127) + 127, bit.band(lcg_rnd(), 127) + 64)
w = 40
h = 22
x = bit.rshift(lcg_rnd() * (disp:getWidth() - w), 8)
y = bit.rshift(lcg_rnd() * (disp:getHeight() - h), 8)
disp:setPrintPos(x, y+h)
disp:setPrintDir(bit.band(bit.rshift(i, 2), 3))
i = i + 1
disp:print("Ucglib")
end
disp:setPrintDir(0)
print("...done")
end
return M
local M, module = {}, ...
_G[module] = M
function M.run()
-- make this a volatile module:
package.loaded[module] = nil
print("Running component triangle...")
local m
disp:setColor(0, 0, 80, 20)
disp:setColor(1, 60, 80, 20)
disp:setColor(2, 60, 120, 0)
disp:setColor(3, 0, 140, 30)
disp:drawGradientBox(0, 0, disp:getWidth(), disp:getHeight())
disp:setColor(255, 255, 255)
disp:setPrintPos(2, 18)
disp:print("Triangle")
m = millis() + T
while millis() < m do
disp:setColor(bit.band(lcg_rnd(), 127)+127, bit.band(lcg_rnd(), 31), bit.band(lcg_rnd(), 127)+64)
disp:drawTriangle(
bit.rshift(lcg_rnd() * (disp:getWidth()), 8),
bit.rshift(lcg_rnd() * (disp:getHeight()-20), 8) + 20,
bit.rshift(lcg_rnd() * (disp:getWidth()), 8),
bit.rshift(lcg_rnd() * (disp:getHeight()-20), 8) + 20,
bit.rshift(lcg_rnd() * (disp:getWidth()), 8),
bit.rshift(lcg_rnd() * (disp:getHeight()-20), 8) + 20
)
tmr.wdclr()
end
print("...done")
end
return M
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment