Ver código fonte

* Allow to rotate canvases with an odd width.

* Added a few additional character pairs of the left/right rotations.
  * Added missing errno sets.
tags/v0.99.beta14
Sam Hocevar sam 17 anos atrás
pai
commit
91d8c9352b
1 arquivos alterados com 85 adições e 53 exclusões
  1. +85
    -53
      cucul/transform.c

+ 85
- 53
cucul/transform.c Ver arquivo

@@ -229,12 +229,11 @@ int cucul_rotate_180(cucul_canvas_t *cv)
* not guaranteed to be reversible at all.
*
* Note that the width of the canvas is divided by two and becomes the
* new height. Height is multiplied by two and becomes the new width. It
* is illegal to pass a canvas with an odd width to this function.
* new height. Height is multiplied by two and becomes the new width. If
* the original width is an odd number, the division is rounded up.
*
* If an error occurs, -1 is returned and \b errno is set accordingly:
* - \c EBUSY The canvas is in use by a display driver and cannot be rotated.
* - \c EINVAL The canvas' width is odd.
* - \c ENOMEM Not enough memory to allocate the new canvas size. If this
* happens, the previous canvas handle is still valid.
*
@@ -244,7 +243,7 @@ int cucul_rotate_180(cucul_canvas_t *cv)
int cucul_rotate_left(cucul_canvas_t *cv)
{
uint32_t *newchars, *newattrs;
unsigned int x, y, subwidth, subheight;
unsigned int x, y, w2, h2;

if(cv->refcount)
{
@@ -252,46 +251,55 @@ int cucul_rotate_left(cucul_canvas_t *cv)
return -1;
}

if(cv->width & 1)
{
seterrno(EINVAL);
return -1;
}

/* Save the current frame shortcuts */
_cucul_save_frame_info(cv);

newchars = malloc(cv->width * cv->height * sizeof(uint32_t));
w2 = (cv->width + 1) / 2;
h2 = cv->height;

newchars = malloc(w2 * h2 * 2 * sizeof(uint32_t));
if(!newchars)
{
seterrno(ENOMEM);
return -1;
}

newattrs = malloc(cv->width * cv->height * sizeof(uint32_t));
newattrs = malloc(w2 * h2 * 2 * sizeof(uint32_t));
if(!newattrs)
{
free(newchars);
seterrno(ENOMEM);
return -1;
}

subwidth = cv->width / 2;
subheight = cv->height;

for(y = 0; y < subheight; y++)
for(y = 0; y < h2; y++)
{
for(x = 0; x < subwidth; x++)
for(x = 0; x < w2; x++)
{
uint32_t pair[2], attr1, attr2;

pair[0] = cv->chars[(subwidth * y + x) * 2];
attr1 = cv->attrs[(subwidth * y + x) * 2];
pair[1] = cv->chars[(subwidth * y + x) * 2 + 1];
attr2 = cv->attrs[(subwidth * y + x) * 2 + 1];
pair[0] = cv->chars[cv->width * y + x * 2];
attr1 = cv->attrs[cv->width * y + x * 2];

if((cv->width & 1) && x == w2 - 1)
{
/* Special case: odd column */
pair[1] = ' ';
attr2 = attr1;
}
else
{
pair[1] = cv->chars[cv->width * y + x * 2 + 1];
attr2 = cv->attrs[cv->width * y + x * 2 + 1];
}


leftpair(pair);

newchars[(subheight * (subwidth - 1 - x) + y) * 2] = pair[0];
newattrs[(subheight * (subwidth - 1 - x) + y) * 2] = attr1;
newchars[(subheight * (subwidth - 1 - x) + y) * 2 + 1] = pair[1];
newattrs[(subheight * (subwidth - 1 - x) + y) * 2 + 1] = attr2;
newchars[(h2 * (w2 - 1 - x) + y) * 2] = pair[0];
newattrs[(h2 * (w2 - 1 - x) + y) * 2] = attr1;
newchars[(h2 * (w2 - 1 - x) + y) * 2 + 1] = pair[1];
newattrs[(h2 * (w2 - 1 - x) + y) * 2 + 1] = attr2;
}
}

@@ -310,7 +318,7 @@ int cucul_rotate_left(cucul_canvas_t *cv)
cv->frames[cv->frame].handley = (cv->width - 1 - x) / 2;

cv->frames[cv->frame].width = cv->height * 2;
cv->frames[cv->frame].height = cv->width / 2;
cv->frames[cv->frame].height = (cv->width + 1) / 2;

cv->frames[cv->frame].chars = newchars;
cv->frames[cv->frame].attrs = newattrs;
@@ -331,12 +339,11 @@ int cucul_rotate_left(cucul_canvas_t *cv)
* not guaranteed to be reversible at all.
*
* Note that the width of the canvas is divided by two and becomes the
* new height. Height is multiplied by two and becomes the new width. It
* is illegal to pass a canvas with an odd width to this function.
* new height. Height is multiplied by two and becomes the new width. If
* the original width is an odd number, the division is rounded up.
*
* If an error occurs, -1 is returned and \b errno is set accordingly:
* - \c EBUSY The canvas is in use by a display driver and cannot be rotated.
* - \c EINVAL The canvas' width is odd.
* - \c ENOMEM Not enough memory to allocate the new canvas size. If this
* happens, the previous canvas handle is still valid.
*
@@ -346,7 +353,7 @@ int cucul_rotate_left(cucul_canvas_t *cv)
int cucul_rotate_right(cucul_canvas_t *cv)
{
uint32_t *newchars, *newattrs;
unsigned int x, y, subwidth, subheight;
unsigned int x, y, w2, h2;

if(cv->refcount)
{
@@ -354,46 +361,54 @@ int cucul_rotate_right(cucul_canvas_t *cv)
return -1;
}

if(cv->width & 1)
{
seterrno(EINVAL);
return -1;
}

/* Save the current frame shortcuts */
_cucul_save_frame_info(cv);

newchars = malloc(cv->width * cv->height * sizeof(uint32_t));
w2 = (cv->width + 1) / 2;
h2 = cv->height;

newchars = malloc(w2 * h2 * 2 * sizeof(uint32_t));
if(!newchars)
{
seterrno(ENOMEM);
return -1;
}

newattrs = malloc(cv->width * cv->height * sizeof(uint32_t));
newattrs = malloc(w2 * h2 * 2 * sizeof(uint32_t));
if(!newattrs)
{
free(newchars);
seterrno(ENOMEM);
return -1;
}

subwidth = cv->width / 2;
subheight = cv->height;

for(y = 0; y < subheight; y++)
for(y = 0; y < h2; y++)
{
for(x = 0; x < subwidth; x++)
for(x = 0; x < w2; x++)
{
uint32_t pair[2], attr1, attr2;

pair[0] = cv->chars[(subwidth * y + x) * 2];
attr1 = cv->attrs[(subwidth * y + x) * 2];
pair[1] = cv->chars[(subwidth * y + x) * 2 + 1];
attr2 = cv->attrs[(subwidth * y + x) * 2 + 1];
pair[0] = cv->chars[cv->width * y + x * 2];
attr1 = cv->attrs[cv->width * y + x * 2];

if((cv->width & 1) && x == w2 - 1)
{
/* Special case: odd column */
pair[1] = ' ';
attr2 = attr1;
}
else
{
pair[1] = cv->chars[cv->width * y + x * 2 + 1];
attr2 = cv->attrs[cv->width * y + x * 2 + 1];
}

rightpair(pair);

newchars[(subheight * x + subheight - 1 - y) * 2] = pair[0];
newattrs[(subheight * x + subheight - 1 - y) * 2] = attr1;
newchars[(subheight * x + subheight - 1 - y) * 2 + 1] = pair[1];
newattrs[(subheight * x + subheight - 1 - y) * 2 + 1] = attr2;
newchars[(h2 * x + h2 - 1 - y) * 2] = pair[0];
newattrs[(h2 * x + h2 - 1 - y) * 2] = attr1;
newchars[(h2 * x + h2 - 1 - y) * 2 + 1] = pair[1];
newattrs[(h2 * x + h2 - 1 - y) * 2 + 1] = attr2;
}
}

@@ -412,7 +427,7 @@ int cucul_rotate_right(cucul_canvas_t *cv)
cv->frames[cv->frame].handley = x / 2;

cv->frames[cv->frame].width = cv->height * 2;
cv->frames[cv->frame].height = cv->width / 2;
cv->frames[cv->frame].height = (cv->width + 1) / 2;

cv->frames[cv->frame].chars = newchars;
cv->frames[cv->frame].attrs = newattrs;
@@ -458,12 +473,16 @@ int cucul_stretch_left(cucul_canvas_t *cv)

newchars = malloc(cv->width * cv->height * sizeof(uint32_t));
if(!newchars)
{
seterrno(ENOMEM);
return -1;
}

newattrs = malloc(cv->width * cv->height * sizeof(uint32_t));
if(!newattrs)
{
free(newchars);
seterrno(ENOMEM);
return -1;
}

@@ -967,6 +986,7 @@ static uint32_t const leftright2x2[] =
{
/* ASCII / Unicode */
'-', '-', 0x4e28, CUCUL_MAGIC_FULLWIDTH, /* -- 丨 */
'|', '|', 0x2f06, CUCUL_MAGIC_FULLWIDTH, /* || ⼆ */
/* Unicode */
0x2584, 0x2580, 0x2580, 0x2584, /* ▄▀ ▀▄ */
0, 0, 0, 0
@@ -987,19 +1007,31 @@ static uint32_t const leftright2x4[] =
'\\', ' ', '.', '-', ' ', '\\', '-', '\'', /* fallback ASCII */
'\\', ' ', '_', ',', ' ', '\\', 0x00b4, 0x203e, /* \ _, \ ´‾ */
'\\', '_', '_', '/', 0x203e, '\\', '/', 0x203e, /* \_ _/ ‾\ /‾ */
'_', '\\', 0x203e, '/', '\\', 0x203e, '/', '_', /* _\ ‾/ \‾ /_ */
'|', ' ', '_', '_', ' ', '|', 0x203e, 0x203e, /* | __ | ‾‾ */
'_', '|', 0x203e, '|', '|', 0x203e, '|', '_', /* _| ‾| |‾ |_ */
'|', '_', '_', '|', 0x203e, '|', '|', 0x203e, /* |_ _| ‾| |‾ */
'_', ' ', ' ', 0x2577, ' ', 0x203e, 0x2575, ' ', /* _ ╷ ‾ ╵ */
' ', '_', ' ', 0x2575, 0x203e, ' ', 0x2577, ' ', /* _ ╵ ‾ ╷ */
'.', '_', '.', 0x2575, 0x203e, '\'', 0x2577, '\'', /* ._ .╵ ‾' ╷' */
'(', '_', 0x203f, '|', 0x203e, ')', '|', 0x2040, /* (_ ‿| ‾) |⁀ */
'(', 0x203e, '|', 0x203f, '_', ')', 0x2040, '|', /* (‾ |‿ _) ⁀| */
'\\', '/', 0xff1e, CUCUL_MAGIC_FULLWIDTH,
'/', '\\', 0xff1c, CUCUL_MAGIC_FULLWIDTH, /* \/ > /\ < */
')', ' ', 0xfe35, CUCUL_MAGIC_FULLWIDTH,
' ', '(', 0xfe36, CUCUL_MAGIC_FULLWIDTH, /* ) ︵ ( ︶ */
'}', ' ', 0xfe37, CUCUL_MAGIC_FULLWIDTH,
' ', '{', 0xfe38, CUCUL_MAGIC_FULLWIDTH, /* } ︷ { ︸ */
/* Not perfect, but better than nothing */
'(', ' ', 0x02ce, ',', ' ', ')', 0x00b4, '`', /* ( ˎ, ) ´` */
')', ' ', ',', 0x02ce, ' ', '(', '`', 0x00b4, /* ) ,ˎ ( `´ */
' ', 'v', '>', ' ', 0x028c, ' ', ' ', '<', /* v > ʌ < */
' ', 'V', '>', ' ', 0x039b, ' ', ' ', '<', /* V > Λ < */
'v', ' ', '>', ' ', ' ', 0x028c, ' ', '<', /* v > ʌ < */
'V', ' ', '>', ' ', ' ', 0x039b, ' ', '<', /* V > Λ < */
'\\', '|', 0xff1e, CUCUL_MAGIC_FULLWIDTH,
'|', '\\', 0xff1c, CUCUL_MAGIC_FULLWIDTH, /* \| > |\ < */
'|', '/', 0xff1e, CUCUL_MAGIC_FULLWIDTH,
'/', '|', 0xff1c, CUCUL_MAGIC_FULLWIDTH, /* |/ > /| < */
/* Unicode */
0x2584, ' ', ' ', 0x2584, ' ', 0x2580, 0x2580, ' ', /* ▄ ▄ ▀ ▀ */
0x2588, ' ', 0x2584, 0x2584, ' ', 0x2588, 0x2580, 0x2580, /* █ ▄▄ █ ▀▀ */


Carregando…
Cancelar
Salvar