예제 #1
0
/**
 * write_filled_rectangle: draw a filled rectangle.
 *
 * Uses an optimised algorithm which is similar to the horizontal
 * line writing algorithm, but optimised for writing the lines
 * multiple times without recalculating lots of stuff.
 *
 * @param       buff    pointer to buffer to write in
 * @param       x               x coordinate (left)
 * @param       y               y coordinate (top)
 * @param       width   rectangle width
 * @param       height  rectangle height
 * @param       mode    0 = clear, 1 = set, 2 = toggle
 */
void write_filled_rectangle(uint8_t *buff, int x, int y, int width, int height, int mode)
{
	int yy, addr0_old, addr1_old;

	CHECK_COORDS(x, y);
	CHECK_COORDS(x + width, y + height);
	if (width <= 0 || height <= 0) {
		return;
	}
	// Calculate as if the rectangle was only a horizontal line. We then
	// step these addresses through each row until we iterate `height` times.
	int addr0     = CALC_BUFF_ADDR(x, y);
	int addr1     = CALC_BUFF_ADDR(x + width, y);
	int addr0_bit = CALC_BIT_IN_WORD(x);
	int addr1_bit = CALC_BIT_IN_WORD(x + width);
	int mask, mask_l, mask_r, i;
	// If the addresses are equal, we need to write one word vertically.
	if (addr0 == addr1) {
		mask = COMPUTE_HLINE_ISLAND_MASK(addr0_bit, addr1_bit);
		while (height--) {
			WRITE_WORD_MODE(buff, addr0, mask, mode);
			addr0 += BUFFER_WIDTH;
		}
	} else {
		// Otherwise we need to write the edges and then the middle repeatedly.
		mask_l    = COMPUTE_HLINE_EDGE_L_MASK(addr0_bit);
		mask_r    = COMPUTE_HLINE_EDGE_R_MASK(addr1_bit);
		// Write edges first.
		yy        = 0;
		addr0_old = addr0;
		addr1_old = addr1;
		while (yy < height) {
			WRITE_WORD_MODE(buff, addr0, mask_l, mode);
			WRITE_WORD_MODE(buff, addr1, mask_r, mode);
			addr0 += BUFFER_WIDTH;
			addr1 += BUFFER_WIDTH;
			yy++;
		}
		// Now write 0xffff words from start+1 to end-1 for each row.
		yy    = 0;
		addr0 = addr0_old;
		addr1 = addr1_old;
		while (yy < height) {
			for (i = addr0 + 1; i <= addr1 - 1; i++) {
				uint8_t m = 0xff;
				WRITE_WORD_MODE(buff, i, m, mode);
			}
			addr0 += BUFFER_WIDTH;
			addr1 += BUFFER_WIDTH;
			yy++;
		}
	}
}
예제 #2
0
/**
 * write_circle_filled: fill a circle on a given buffer.
 *
 * @param       buff    pointer to buffer to write in
 * @param       cx              origin x coordinate
 * @param       cy              origin y coordinate
 * @param       r               radius
 * @param       mode    0 = clear, 1 = set, 2 = toggle
 */
void write_circle_filled(uint8_t *buff, int cx, int cy, int r, int mode)
{
	CHECK_COORDS(cx, cy);
	int error = -r, x = r, y = 0, xch = 0;
	// It turns out that filled circles can take advantage of the midpoint
	// circle algorithm. We simply draw very fast horizontal lines across each
	// pair of X,Y coordinates. In some cases, this can even be faster than
	// drawing an outlined circle!
	//
	// Due to multiple writes to each set of pixels, we have a special exception
	// for when using the toggling draw mode.
	while (x >= y) {
		if (y != 0) {
			write_hline(buff, cx - x, cx + x, cy + y, mode);
			write_hline(buff, cx - x, cx + x, cy - y, mode);
			if (mode != 2 || (mode == 2 && xch && (cx - x) != (cx - y))) {
				write_hline(buff, cx - y, cx + y, cy + x, mode);
				write_hline(buff, cx - y, cx + y, cy - x, mode);
				xch = 0;
			}
		}
		error += (y * 2) + 1;
		y++;
		if (error >= 0) {
			--x;
			xch    = 1;
			error -= x * 2;
		}
	}
	// Handle toggle mode.
	if (mode == 2) {
		write_hline(buff, cx - r, cx + r, cy, mode);
	}
}
예제 #3
0
/**
 * write_pixel: Write a pixel at an x,y position to a given surface.
 *
 * @param       buff    pointer to buffer to write in
 * @param       x               x coordinate
 * @param       y               y coordinate
 * @param       mode    0 = clear bit, 1 = set bit, 2 = toggle bit
 */
void write_pixel(uint8_t *buff, int x, int y, int mode)
{
	CHECK_COORDS(x, y);
	// Determine the bit in the word to be set and the word
	// index to set it in.
	int bitnum    = CALC_BIT_IN_WORD(x);
	int wordnum   = CALC_BUFF_ADDR(x, y);
	// Apply a mask.
	uint16_t mask = 1 << (7 - bitnum);
	WRITE_WORD_MODE(buff, wordnum, mask, mode);
}
예제 #4
0
/**
 * write_pixel_lm: write the pixel on both surfaces (level and mask.)
 * Uses current draw buffer.
 *
 * @param       x               x coordinate
 * @param       y               y coordinate
 * @param       mmode   0 = clear, 1 = set, 2 = toggle
 * @param       lmode   0 = black, 1 = white, 2 = toggle
 */
void write_pixel_lm(int x, int y, int mmode, int lmode)
{
	CHECK_COORDS(x, y);
	// Determine the bit in the word to be set and the word
	// index to set it in.
	int bitnum    = CALC_BIT_IN_WORD(x);
	int wordnum   = CALC_BUFF_ADDR(x, y);
	// Apply the masks.
	uint16_t mask = 1 << (7 - bitnum);
	WRITE_WORD_MODE(draw_buffer_mask, wordnum, mask, mmode);
	WRITE_WORD_MODE(draw_buffer_level, wordnum, mask, lmode);
}
예제 #5
0
void write_upper_arc_outlined(int cx, int cy, int r, int x1, int x2, int dashp, int bmode, int mode, int mmode)
{
	int stroke, fill;

	CHECK_COORDS(cx, cy);
	SETUP_STROKE_FILL(stroke, fill, mode);
	// This is a two step procedure. First, we draw the outline of the
	// circle, then we draw the inner part.
	int error = -r, x = r, y = 0;
	while (x >= y) {
		if (dashp == 0 || (y % dashp) < (dashp / 2)) {
			UPPER_ARC_PLOT_8(draw_buffer_mask, cx, cy, x + 1, y, x1, x2, mmode);
			UPPER_ARC_PLOT_8(draw_buffer_level, cx, cy, x + 1, y, x1, x2, stroke);
			UPPER_ARC_PLOT_8(draw_buffer_mask, cx, cy, x, y + 1, x1, x2, mmode);
			UPPER_ARC_PLOT_8(draw_buffer_level, cx, cy, x, y + 1, x1, x2, stroke);
			UPPER_ARC_PLOT_8(draw_buffer_mask, cx, cy, x - 1, y, x1, x2, mmode);
			UPPER_ARC_PLOT_8(draw_buffer_level, cx, cy, x - 1, y, x1, x2, stroke);
			UPPER_ARC_PLOT_8(draw_buffer_mask, cx, cy, x, y - 1, x1, x2, mmode);
			UPPER_ARC_PLOT_8(draw_buffer_level, cx, cy, x, y - 1, x1, x2, stroke);
			if (bmode == 1) {
				UPPER_ARC_PLOT_8(draw_buffer_mask, cx, cy, x + 1, y + 1, x1, x2, mmode);
				UPPER_ARC_PLOT_8(draw_buffer_level, cx, cy, x + 1, y + 1, x1, x2, stroke);
				UPPER_ARC_PLOT_8(draw_buffer_mask, cx, cy, x - 1, y - 1, x1, x2, mmode);
				UPPER_ARC_PLOT_8(draw_buffer_level, cx, cy, x - 1, y - 1, x1, x2, stroke);
			}
		}

		error += (y * 2) + 1;
		y++;
		if (error >= 0) {
			--x;
			error -= x * 2;
		}
	}
	error = -r;
	x     = r;
	y     = 0;
	while (x >= y) {
		if (dashp == 0 || (y % dashp) < (dashp / 2)) {
			UPPER_ARC_PLOT_8(draw_buffer_mask, cx, cy, x, y, x1, x2, mmode);
			UPPER_ARC_PLOT_8(draw_buffer_level, cx, cy, x, y, x1, x2, fill);
		}
		error += (y * 2) + 1;
		y++;
		if (error >= 0) {
			--x;
			error -= x * 2;
		}
	}
}
예제 #6
0
/**
 * write_circle: draw the outline of a circle on a given buffer,
 * with an optional dash pattern for the line instead of a normal line.
 *
 * @param       buff    pointer to buffer to write in
 * @param       cx              origin x coordinate
 * @param       cy              origin y coordinate
 * @param       r               radius
 * @param       dashp   dash period (pixels) - zero for no dash
 * @param       mode    0 = clear, 1 = set, 2 = toggle
 */
void write_circle(uint8_t *buff, int cx, int cy, int r, int dashp, int mode)
{
	CHECK_COORDS(cx, cy);
	int error = -r, x = r, y = 0;
	while (x >= y) {
		if (dashp == 0 || (y % dashp) < (dashp / 2)) {
			CIRCLE_PLOT_8(buff, cx, cy, x, y, mode);
		}
		error += (y * 2) + 1;
		y++;
		if (error >= 0) {
			--x;
			error -= x * 2;
		}
	}
}
TEST(MeshLib, CoordinatesMappingLocalLowerDimLineZ)
{
    auto ele = TestLine2::createZ();
    MeshLib::ElementCoordinatesMappingLocal mapping(*ele,
            MeshLib::CoordinateSystem(MeshLib::CoordinateSystemType::Z));
    auto matR(mapping.getRotationMatrixToGlobal());
    //debugOutput(ele, mapping);

    double exp_R[3*3] = {0, 0, -1, 0, 1, 0, 1, 0, 0};
    const double eps(std::numeric_limits<double>::epsilon());
    ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps);
    CHECK_COORDS(ele,mapping);

    for (std::size_t n = 0; n < ele->getNumberOfNodes(); ++n)
        delete ele->getNode(n);
}
TEST(MeshLib, CoordinatesMappingLocalLowerDimLineXYZ)
{
    auto ele = TestLine2::createXYZ();
    MeshLib::ElementCoordinatesMappingLocal mapping(*ele, MeshLib::CoordinateSystem(*ele));
    auto matR(mapping.getRotationMatrixToGlobal());
    //debugOutput(ele, mapping);

    double exp_R[3*3] = {0.57735026918962584, -0.81649658092772626,  0,
                         0.57735026918962584,  0.40824829046386313, -0.70710678118654757,
                         0.57735026918962584,  0.40824829046386313,  0.70710678118654757};
    const double eps(std::numeric_limits<double>::epsilon());
    ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps);
    CHECK_COORDS(ele,mapping);

    for (std::size_t n = 0; n < ele->getNumberOfNodes(); ++n)
        delete ele->getNode(n);
}
TEST(MeshLib, CoordinatesMappingLocalLowerDimQuadXYZ)
{
    auto ele = TestQuad4::createXYZ();
    MeshLib::ElementCoordinatesMappingLocal mapping(*ele, MeshLib::CoordinateSystem(*ele));
    auto matR(mapping.getRotationMatrixToGlobal());
    //debugOutput(ele, mapping);

    // results when using GeoLib::ComputeRotationMatrixToXY()
    double exp_R[3*3] = {  1, 0, 0,
                           0, 0.70710678118654757, -0.70710678118654757,
                           0, 0.70710678118654757,  0.70710678118654757};

    const double eps(std::numeric_limits<double>::epsilon());
    ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps);
    CHECK_COORDS(ele,mapping);

    for (std::size_t n = 0; n < ele->getNumberOfNodes(); ++n)
        delete ele->getNode(n);
}