Commit 6dc0dfc0 authored by devsaurus's avatar devsaurus
Browse files
parent f5ae0ed7
/*
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 pg_ClearPolygonXY(pg_struct *pg)
{
pg->cnt = 0;
}
void 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 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)
{
pg_ClearPolygonXY(&ucg_pg);
}
void ucg_AddPolygonXY(ucg_t *ucg, int16_t x, int16_t y)
{
pg_AddPolygonXY(&ucg_pg, ucg, x, y);
}
void ucg_DrawPolygon(ucg_t *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.
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