Merge branch 'master' into nuttx-merge-5447

This commit is contained in:
px4dev
2013-01-11 00:39:22 -08:00
128 changed files with 12693 additions and 1007 deletions
+284 -89
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* graphics/nxglib/nxglib_splitline.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,8 @@
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <debug.h>
#include <nuttx/nx/nxglib.h>
@@ -48,12 +50,16 @@
* Pre-Processor Definitions
****************************************************************************/
#define SMALL_SIN 1966 /* 1966/65536 = 0.03 */
/****************************************************************************
* Private Types
****************************************************************************/
struct b16point_s
{
b16_t x;
b16_t y;
};
/****************************************************************************
* Private Data
****************************************************************************/
@@ -66,6 +72,12 @@
* Private Functions
****************************************************************************/
static b16_t nxgl_interpolate(b16_t x, b16_t dy, b16_t dxdy)
{
b16_t dx = b16mulb16(dy, dxdy);
return x + dx;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -116,15 +128,19 @@ int nxgl_splitline(FAR struct nxgl_vector_s *vector,
struct nxgl_vector_s line;
nxgl_coord_t iheight;
nxgl_coord_t iwidth;
nxgl_coord_t iy;
nxgl_coord_t triheight;
nxgl_coord_t halfheight;
b16_t adjwidth;
b16_t xoffset;
b16_t halfoffset;
nxgl_coord_t iyoffset;
struct b16point_s quad[4];
b16_t b16xoffset;
b16_t b16yoffset;
b16_t b16dxdy;
b16_t angle;
b16_t cosangle;
b16_t sinangle;
b16_t b16x;
b16_t b16y;
gvdbg("vector: (%d,%d)->(%d,%d) linewidth: %d\n",
vector->pt1.x, vector->pt1.y, vector->pt2.x, vector->pt2.y, linewidth);
/* First, check the linewidth */
@@ -152,7 +168,7 @@ int nxgl_splitline(FAR struct nxgl_vector_s *vector,
line.pt2.x = vector->pt1.x;
line.pt2.y = vector->pt1.y;
}
else
else /* if (vector->pt1.y == vector->pt2.y) */
{
/* First degenerate case: The line is horizontal. */
@@ -173,6 +189,10 @@ int nxgl_splitline(FAR struct nxgl_vector_s *vector,
rect->pt1.y = vector->pt1.y - (linewidth >> 1);
rect->pt2.y = rect->pt1.y + linewidth - 1;
gvdbg("Horizontal rect: (%d,%d),(%d,%d)\n",
rect->pt1.x, rect->pt1.y, rect->pt2.x, rect->pt2.y);
return 2;
}
@@ -187,14 +207,21 @@ int nxgl_splitline(FAR struct nxgl_vector_s *vector,
rect->pt1.x = line.pt1.x - (linewidth >> 1);
rect->pt2.x = rect->pt1.x + linewidth - 1;
gvdbg("Vertical rect: (%d,%d),(%d,%d)\n",
rect->pt1.x, rect->pt1.y, rect->pt2.x, rect->pt2.y);
return 2;
}
/* The final degenerate case */
if (linewidth == 1)
if (linewidth == 1 &&
abs(line.pt2.x - line.pt1.x) < (line.pt2.y - line.pt1.y))
{
/* A line of width 1 is basically a single parallelogram of width 1 */
/* A close to vertical line of width 1 is basically
* a single parallelogram of width 1.
*/
traps[1].top.x1 = itob16(line.pt1.x);
traps[1].top.x2 = traps[1].top.x1;
@@ -203,6 +230,11 @@ int nxgl_splitline(FAR struct nxgl_vector_s *vector,
traps[1].bot.x1 = itob16(line.pt2.x);
traps[1].bot.x2 = traps[1].bot.x1;
traps[1].bot.y = line.pt2.y;
gvdbg("Vertical traps[1]: (%08x,%08x,%d),(%08x,%08x, %d)\n",
traps[1].top.x1, traps[1].top.x2, traps[1].top.y,
traps[1].bot.x1, traps[1].bot.x2, traps[1].bot.y);
return 1;
}
@@ -222,103 +254,260 @@ int nxgl_splitline(FAR struct nxgl_vector_s *vector,
iwidth = line.pt1.x - line.pt2.x + 1;
}
/* Triangle height: linewidth * cosA
* Adjusted width: triheight / sinA
* X offset : linewidth * linewidth / adjusted line width
/* Applying the line width to the line results in a rotated, rectangle.
* Get the Y offset from an end of the original thin line to a corner of the fat line.
*
* Angle of line: angle = atan2(iheight, iwidth)
* Y offset from line: b16yoffset = linewidth * cos(angle)
*
* For near verical lines, b16yoffset is be nearly zero. For near horizontal
* lines, b16yOffset is be about the same as linewidth.
*/
angle = b16atan2(itob16(iheight), itob16(iwidth));
triheight = b16toi(linewidth * b16cos(angle) + b16HALF);
halfheight = (triheight >> 1);
angle = b16atan2(itob16(iheight), itob16(iwidth));
cosangle = b16cos(angle);
b16yoffset = (linewidth * cosangle + 1) >> 1;
/* If the sine of the angle is tiny (i.e., the line is nearly horizontal),
* then we cannot compute the adjusted width. In this case, just use
* the width of the line bounding box.
/* Get the X offset from an end of the original thin line to a corner of the fat line.
*
* For near vertical lines, b16xoffset is about the same as linewidth. For near
* horizontal lines, b16xoffset is nearly zero.
*/
sinangle = b16sin(angle);
if (sinangle < SMALL_SIN)
{
adjwidth = itob16(iwidth);
xoffset = 0;
}
else
{
adjwidth = b16divb16(itob16(linewidth), sinangle);
xoffset = itob16(linewidth * linewidth);
xoffset = b16divb16(xoffset, adjwidth);
}
sinangle = b16sin(angle);
b16xoffset = (linewidth * sinangle + 1) >> 1;
halfoffset = (xoffset >> 1);
gvdbg("height: %d width: %d angle: %08x b16yoffset: %08x b16xoffset: %08x\n",
iheight, iwidth, angle, b16yoffset, b16xoffset);
/* Return the top triangle (if there is one). NOTE that the horizontal
* (z) positions are represented with 16 bits of fraction. The vertical
* (y) positions, on the other hand, are integer.
*/
/* Now we know all four points of the rotated rectangle */
if (triheight > 0)
iyoffset = b16toi(b16yoffset + b16HALF);
if (iyoffset > 0)
{
/* Get the Y positions of each point */
b16y = itob16(line.pt1.y);
quad[0].y = b16y - b16yoffset;
quad[1].y = b16y + b16yoffset;
b16y = itob16(line.pt2.y);
quad[2].y = b16y - b16yoffset;
quad[3].y = b16y + b16yoffset;
if (line.pt1.x < line.pt2.x)
{
/* Line is going "south east" */
/* Line is going "south east". Get the X positions of each point */
b16x = itob16(line.pt1.x) - halfoffset;
iy = line.pt1.y + halfheight;
b16x = itob16(line.pt1.x);
quad[0].x = b16x + b16xoffset;
quad[1].x = b16x - b16xoffset;
traps[0].top.x1 = b16x + xoffset;
traps[0].top.x2 = traps[0].top.x1;
traps[0].top.y = iy - triheight + 1;
traps[0].bot.x1 = b16x;
traps[0].bot.x2 = b16x + adjwidth - b16ONE;
traps[0].bot.y = iy;
b16x = itob16(line.pt2.x);
quad[2].x = b16x + b16xoffset;
quad[3].x = b16x - b16xoffset;
b16x = itob16(line.pt2.x) + halfoffset;
iy = line.pt2.y - halfheight;
gvdbg("Southeast: quad (%08x,%08x),(%08x,%08x),(%08x,%08x),(%08x,%08x)\n",
quad[0].x, quad[0].y, quad[1].x, quad[1].y,
quad[2].x, quad[2].y, quad[3].x, quad[3].y);
traps[2].top.x1 = b16x - adjwidth + b16ONE;
traps[2].top.x2 = b16x;
traps[2].top.y = iy;
traps[2].bot.x1 = b16x - xoffset;
traps[2].bot.x2 = traps[2].bot.x1;
traps[2].bot.y = iy + triheight - 1;
/* Now we can form the trapezoids. The top of the first trapezoid
* (triangle) is at quad[0]
*/
traps[0].top.x1 = quad[0].x;
traps[0].top.x2 = quad[0].x;
traps[0].top.y = b16toi(quad[0].y + b16HALF);
/* The bottom of the first trapezoid (triangle) may be either at
* quad[1] or quad[2], depending upon orientation.
*/
if (quad[1]. y < quad[2].y)
{
/* quad[1] is at the bottom left of the triangle. Interpolate
* to get the corresponding point on the right side.
*
* Interpolation is from quad[0] along the line quad[0]->quad[2]
* which as the same slope as the line (positive)
*/
b16dxdy = itob16(iwidth) / iheight;
traps[0].bot.x1 = quad[1].x;
traps[0].bot.x2 = nxgl_interpolate(quad[0].x, quad[1].y - quad[0].y, b16dxdy);
traps[0].bot.y = b16toi(quad[1].y + b16HALF);
/* quad[1] is at the top left of the second trapezoid. quad[2} is
* at the bottom right of the second trapezoid. Interpolate to get
* corresponding point on the left side.
*
* Interpolation is from quad[1] along the line quad[1]->quad[3]
* which as the same slope as the line (positive)
*/
traps[1].top.x1 = traps[0].bot.x1;
traps[1].top.x2 = traps[0].bot.x2;
traps[1].top.y = traps[0].bot.y;
traps[1].bot.x1 = nxgl_interpolate(traps[1].top.x1, quad[2].y - quad[1].y, b16dxdy);
traps[1].bot.x2 = quad[2].x;
traps[1].bot.y = b16toi(quad[2].y + b16HALF);
}
else
{
/* quad[2] is at the bottom right of the triangle. Interpolate
* to get the corresponding point on the left side.
*
* Interpolation is from quad[0] along the line quad[0]->quad[1]
* which orthogonal to the slope of the line (and negative)
*/
b16dxdy = -itob16(iheight) / iwidth;
traps[0].bot.x1 = nxgl_interpolate(quad[0].x, quad[2].y - quad[0].y, b16dxdy);
traps[0].bot.x2 = quad[2].x;
traps[0].bot.y = b16toi(quad[2].y + b16HALF);
/* quad[2] is at the top right of the second trapezoid. quad[1} is
* at the bottom left of the second trapezoid. Interpolate to get
* corresponding point on the right side.
*
* Interpolation is from quad[2] along the line quad[2]->quad[3]
* which as the same slope as the previous interpolation.
*/
traps[1].top.x1 = traps[0].bot.x1;
traps[1].top.x2 = traps[0].bot.x2;
traps[1].top.y = traps[0].bot.y;
traps[1].bot.x1 = quad[1].x;
traps[1].bot.x2 = nxgl_interpolate(traps[1].top.x2, quad[1].y - quad[2].y, b16dxdy);
traps[1].bot.y = b16toi(quad[1].y + b16HALF);
}
/* The final trapezond (triangle) at the bottom is new well defined */
traps[2].top.x1 = traps[1].bot.x1;
traps[2].top.x2 = traps[1].bot.x2;
traps[2].top.y = traps[1].bot.y;
traps[2].bot.x1 = quad[3].x;
traps[2].bot.x2 = quad[3].x;
traps[2].bot.y = b16toi(quad[3].y + b16HALF);
}
else
{
/* Line is going "south west" */
/* Get the X positions of each point */
b16x = itob16(line.pt1.x) + halfoffset;
iy = line.pt1.y + halfheight;
b16x = itob16(line.pt1.x);
quad[0].x = b16x - b16xoffset;
quad[1].x = b16x + b16xoffset;
traps[0].top.x1 = b16x - xoffset;
traps[0].top.x2 = traps[0].top.x1;
traps[0].top.y = iy - triheight + 1;
traps[0].bot.x1 = b16x - adjwidth + b16ONE;
traps[0].bot.x2 = b16x;
traps[0].bot.y = iy;
b16x = itob16(line.pt2.x);
quad[2].x = b16x - b16xoffset;
quad[3].x = b16x + b16xoffset;
b16x = itob16(line.pt2.x) - halfoffset;
iy = line.pt2.y - halfheight;
gvdbg("Southwest: quad (%08x,%08x),(%08x,%08x),(%08x,%08x),(%08x,%08x)\n",
quad[0].x, quad[0].y, quad[1].x, quad[1].y,
quad[2].x, quad[2].y, quad[3].x, quad[3].y);
traps[2].top.x1 = b16x;
traps[2].top.x2 = b16x + adjwidth - b16ONE;
traps[2].top.y = iy;
traps[2].bot.x1 = b16x + xoffset;
traps[2].bot.x2 = traps[2].bot.x1;
traps[2].bot.y = iy + triheight - 1;
/* Now we can form the trapezoids. The top of the first trapezoid
* (triangle) is at quad[0]
*/
traps[0].top.x1 = quad[0].x;
traps[0].top.x2 = quad[0].x;
traps[0].top.y = b16toi(quad[0].y + b16HALF);
/* The bottom of the first trapezoid (triangle) may be either at
* quad[1] or quad[2], depending upon orientation.
*/
if (quad[1].y < quad[2].y)
{
/* quad[1] is at the bottom right of the triangle. Interpolate
* to get the corresponding point on the left side.
*
* Interpolation is from quad[0] along the line quad[0]->quad[2]
* which as the same slope as the line (negative)
*/
b16dxdy = -itob16(iwidth) / iheight;
traps[0].bot.x1 = nxgl_interpolate(traps[0].top.x1, quad[1].y - quad[0].y, b16dxdy);
traps[0].bot.x2 = quad[1].x;
traps[0].bot.y = b16toi(quad[1].y + b16HALF);
/* quad[1] is at the top right of the second trapezoid. quad[2} is
* at the bottom left of the second trapezoid. Interpolate to get
* corresponding point on the right side.
*
* Interpolation is from quad[1] along the line quad[1]->quad[3]
* which as the same slope as the line (negative)
*/
traps[1].top.x1 = traps[0].bot.x1;
traps[1].top.x2 = traps[0].bot.x2;
traps[1].top.y = traps[0].bot.y;
traps[1].bot.x1 = quad[2].x;
traps[1].bot.x2 = nxgl_interpolate(traps[1].top.x2, quad[2].y - quad[1].y, b16dxdy);
traps[1].bot.y = b16toi(quad[2].y + b16HALF);
}
else
{
/* quad[2] is at the bottom left of the triangle. Interpolate
* to get the corresponding point on the right side.
*
* Interpolation is from quad[0] along the line quad[0]->quad[1]
* which orthogonal to the slope of the line (and positive)
*/
b16dxdy = itob16(iheight) / iwidth;
traps[0].bot.x1 = quad[2].x;
traps[0].bot.x2 = nxgl_interpolate(traps[0].top.x2, quad[2].y - quad[0].y, b16dxdy);
traps[0].bot.y = b16toi(quad[2].y + b16HALF);
/* quad[2] is at the top left of the second trapezoid. quad[1} is
* at the bottom right of the second trapezoid. Interpolate to get
* corresponding point on the left side.
*
* Interpolation is from quad[2] along the line quad[2]->quad[3]
* which as the same slope as the previous interpolation.
*/
traps[1].top.x1 = traps[0].bot.x1;
traps[1].top.x2 = traps[0].bot.x2;
traps[1].top.y = traps[0].bot.y;
traps[1].bot.x1 = nxgl_interpolate(traps[1].top.x1, quad[1].y - quad[2].y, b16dxdy);
traps[1].bot.x2 = quad[1].x;
traps[1].bot.y = b16toi(quad[1].y + b16HALF);
}
/* The final trapezond (triangle) at the bottom is new well defined */
traps[2].top.x1 = traps[1].bot.x1;
traps[2].top.x2 = traps[1].bot.x2;
traps[2].top.y = traps[1].bot.y;
traps[2].bot.x1 = quad[3].x;
traps[2].bot.x2 = quad[3].x;
traps[2].bot.y = b16toi(quad[3].y + b16HALF);
}
/* The center parallelogram is the horizontal edge of each triangle.
* Note the minor inefficency: that horizontal edges are drawn twice.
*/
gvdbg("traps[0]: (%08x,%08x,%d),(%08x,%08x,%d)\n",
traps[0].top.x1, traps[0].top.x2, traps[0].top.y,
traps[0].bot.x1, traps[0].bot.x2, traps[0].bot.y);
gvdbg("traps[1]: (%08x,%08x,%d),(%08x,%08x,%d)\n",
traps[1].top.x1, traps[1].top.x2, traps[1].top.y,
traps[1].bot.x1, traps[1].bot.x2, traps[1].bot.y);
gvdbg("traps[2]: (%08x,%08x,%d),(%08x,%08x,%d)\n",
traps[2].top.x1, traps[2].top.x2, traps[2].top.y,
traps[2].bot.x1, traps[2].bot.x2, traps[2].bot.y);
traps[1].top.x1 = traps[0].bot.x1;
traps[1].top.x2 = traps[0].bot.x2;
traps[1].top.y = traps[0].bot.y;
traps[1].bot.x1 = traps[2].top.x1;
traps[1].bot.x2 = traps[2].top.x2;
traps[1].bot.y = traps[2].top.y;
return 0;
}
@@ -326,12 +515,18 @@ int nxgl_splitline(FAR struct nxgl_vector_s *vector,
* bottom. Just return the center parallelogram.
*/
traps[1].top.x1 = itob16(line.pt1.x) - halfoffset;
traps[1].top.x2 = traps[1].top.x1 + adjwidth - 1;
traps[1].top.x1 = itob16(line.pt1.x - (linewidth >> 1));
traps[1].top.x2 = traps[1].top.x1 + itob16(linewidth - 1);
traps[1].top.y = line.pt1.y;
traps[1].bot.x1 = itob16(line.pt2.x) - halfoffset;
traps[1].bot.x2 = traps[1].bot.x1 + adjwidth - 1;
traps[1].bot.x1 = itob16(line.pt2.x - (linewidth >> 1));
traps[1].bot.x2 = traps[1].bot.x1 + itob16(linewidth - 1);
traps[1].bot.y = line.pt2.y;
gvdbg("Horizontal traps[1]: (%08x,%08x,%d),(%08x,%08x, %d)\n",
traps[1].top.x1, traps[1].top.x2, traps[1].top.y,
traps[1].bot.x1, traps[1].bot.x2, traps[1].bot.y);
return 1;
}
+9 -2
View File
@@ -94,6 +94,7 @@ int nxtk_filltrapwindow(NXTKWINDOW hfwnd, FAR const struct nxgl_trapezoid_s *tra
{
FAR struct nxtk_framedwindow_s *fwnd = (FAR struct nxtk_framedwindow_s *)hfwnd;
struct nxgl_rect_s relclip;
struct nxgl_trapezoid_s reltrap;
#ifdef CONFIG_DEBUG
if (!hfwnd || !trap || !color)
@@ -103,8 +104,14 @@ int nxtk_filltrapwindow(NXTKWINDOW hfwnd, FAR const struct nxgl_trapezoid_s *tra
}
#endif
/* Perform the fill, clipping to the client window */
/* Move the trapezoid from window contents area to window area */
nxgl_trapoffset(&reltrap, trap,
fwnd->fwrect.pt1.x - fwnd->wnd.bounds.pt1.x,
fwnd->fwrect.pt1.y - fwnd->wnd.bounds.pt1.y);
/* Perform the fill, clipping to the client window */
nxgl_rectoffset(&relclip, &fwnd->fwrect, -fwnd->wnd.bounds.pt1.x, -fwnd->wnd.bounds.pt1.y);
return nx_filltrapezoid((NXWINDOW)hfwnd, &relclip, trap, color);
return nx_filltrapezoid((NXWINDOW)hfwnd, &relclip, &reltrap, color);
}
+7 -4
View File
@@ -110,12 +110,15 @@ int nxtk_getwindow(NXTKWINDOW hfwnd, FAR const struct nxgl_rect_s *rect,
}
#endif
/* Clip the rectangle so that it lies within the sub-window bounds
* then move the rectangle to that it is relative to the containing
* window.
/* Move the rectangle to that it is relative to the containing
* window. If part of the rectangle lies outside the window,
* it will contain garbage data, but the contained area will be
* valid.
*/
nxtk_subwindowclip(fwnd, &getrect, rect, &fwnd->fwrect);
nxgl_rectoffset(&getrect, rect,
fwnd->fwrect.pt1.x - fwnd->wnd.bounds.pt1.x,
fwnd->fwrect.pt1.y - fwnd->wnd.bounds.pt1.y);
/* Then get it */
+5 -7
View File
@@ -112,21 +112,19 @@ void nxtk_subwindowmove(FAR struct nxtk_framedwindow_s *fwnd,
nxgl_rectintersect(&abssrc, &abssrc, &fwnd->fwrect);
/* Clip the offset so that the source rectangle does not move out of the
* the client sub-window.
*/
/* Clip the source rectangle so that destination area is within the window. */
destoffset->x = srcoffset->x;
if (destoffset->x < 0)
{
if (abssrc.pt1.x + destoffset->x < bounds->pt1.x)
{
destoffset->x = bounds->pt1.x - abssrc.pt1.x;
abssrc.pt1.x = bounds->pt1.x - destoffset->x;
}
}
else if (abssrc.pt2.x + destoffset->x > bounds->pt2.x)
{
destoffset->x = bounds->pt2.x - abssrc.pt2.x;
abssrc.pt2.x = bounds->pt2.x - destoffset->x;
}
destoffset->y = srcoffset->y;
@@ -134,12 +132,12 @@ void nxtk_subwindowmove(FAR struct nxtk_framedwindow_s *fwnd,
{
if (abssrc.pt1.y + destoffset->y < bounds->pt1.y)
{
destoffset->y = bounds->pt1.y - abssrc.pt1.y;
abssrc.pt1.y = bounds->pt1.y - destoffset->y;
}
}
else if (abssrc.pt2.y + destoffset->y > bounds->pt2.y)
{
destoffset->y = bounds->pt2.y - abssrc.pt2.y;
abssrc.pt2.y = bounds->pt2.y - destoffset->y;
}