📄 gxj_putpixel.c
字号:
drawFilledRightTriangle(gxj_screen_buffer *sbuf, gxj_pixel_type color, const jshort *clip, int x1, int y1, int x2, int y2) { fill_triangle(sbuf, color, clip, x1, y1, x2, y1, x2, y2);}#define STEPx(_x,_xFRACT,_dx,_dy,_signDX) \ do { \ _xFRACT += _dx; \ while (_xFRACT >= _dy) { \ _x += _signDX; \ _xFRACT -= _dy; \ } \ } while (0)/** * Generates pixels for filled triangles that match the MIDP * specification. This function generates the set of pixels contained * within (x1,y1)->(x2,y2)->(x3,y3). The pixels selected lie within * the lines drawn along the edge of the triangle with drawLine. This * function uses an exact slope algorithm. The set of * pixels generated is within the bounds (CLIP_X1,CLIP_Y1) -> * (CLIP_X2-1,CLIP_Y2-1). * * @param sbuf Virtual Device Context * @param color gxj_pixel_type value for generated pixels * @param lineStyle SOLID to generate all pixels or DOTTED for a subset * @param x1,y1 coordinate of first pixel generated must be * between (-32768 to 32767) inclusive * @param x2,y2 coordinate of the last pixel generated must be * between (-32768 to 32767) inclusive * @param x3,y3 coordinate of first pixel generated must be * between (-32768 to 32767) inclusive * @param clip ->clipX1,clipY1,clipX2,clipY2 must be * between (0 to 32767) inclusive * * Clip constraints: (per the MIDP specification) * if clipX2-1 is less than clipX1 or * if clipY2-1 is less than clipY1 then * the clip bounds are empty and no pixels are generated * */voidfill_triangle(gxj_screen_buffer *sbuf, gxj_pixel_type color, const jshort *clip, int x1, int y1, int x2, int y2, int x3, int y3) { int y; int dxa, dya, signDXa; int dxb, dyb, signDXb; int dxc, dyc, signDXc; const jshort clipX1 = clip[0]; const jshort clipY1 = clip[1]; const jshort clipX2 = clip[2]; const jshort clipY2 = clip[3]; CHECK_SBUF_CLIP_BOUNDS(sbuf, clip); /* sort axis points (y1<=y2<=y3) */ if (y1 > y2) { SWAP(y1, y2); SWAP(x1, x2); } if (y1 > y3) { SWAP(y1, y3); SWAP(x1, x3); } if (y2 > y3) { SWAP(y2, y3); SWAP(x2, x3); } /* compute dx,dy and step directions */ signDXa = 1; if ((dxa = x2 - x1) < 0) { dxa = -dxa; signDXa = -1; } dya = y2 - y1; signDXb = 1; if ((dxb = x3 - x1) < 0) { dxb = -dxb; signDXb = -1; } dyb = y3 - y1; signDXc = 1; if ((dxc = x3 - x2) < 0) { dxc = -dxc; signDXc = -1; } dyc = y3 - y2; /* look for edge case horizontal line * (sort above and triangle angles allow simple test) */ if (/* dya == 0 && */ dyb == 0 /* && dyc == 0 */) { draw_clipped_line(sbuf, color, 0 /*lineStyle*/, clip, x1, y1, x2, y2); draw_clipped_line(sbuf, color, 0 /*lineStyle*/, clip, x2, y2, x3, y3); return; } /* y2 not checked because of sort on y1,y2,y3 */ if ((y1 >= clipY1) && (y1 < clipY2) && (y3 >= clipY1) && (y3 < clipY2) && (x1 >= clipX1) && (x1 < clipX2) && (x2 >= clipX1) && (x2 < clipX2) && (x3 >= clipX1) && (x3 < clipX2)) { /* handle first edge x1,y1->x2,y2 */ int xa = x1; int xb = x1; int xFRACTa = 0; int xFRACTb = 0; for (y=0; y < dya; y++) { CHECK_XY_CLIP(sbuf, xa, y1+y); CHECK_XY_CLIP(sbuf, xb, y1+y); primDrawHorzLine(sbuf, color, xa, y1 + y, xb, y1 + y); STEPx(xa,xFRACTa,dxa,dya,signDXa); STEPx(xb,xFRACTb,dxb,dyb,signDXb); } /* handle second edge x2,y2->x3,y3 */ xa = x2; xFRACTa = 0; /* handle edge case (STEPx cannot take dyc == 0) * bottom of triangle is horizontal */ if (dyc == 0) { CHECK_XY_CLIP(sbuf, x2, y1+y); CHECK_XY_CLIP(sbuf, x3, y1+y); primDrawHorzLine(sbuf, color, x2, y1 + y, x3, y1 + y); goto done; } for (y=dya; y <= dyb; y++) { CHECK_XY_CLIP(sbuf, xa, y1+y); CHECK_XY_CLIP(sbuf, xb, y1+y); primDrawHorzLine(sbuf, color, xa, y1 + y, xb, y1 + y); STEPx(xa,xFRACTa,dxc,dyc,signDXc); STEPx(xb,xFRACTb,dxb,dyb,signDXb); } return; }/*clip: */ { /* handle first edge x1,y1->x2,y2 */ int xFRACTa = 0; int xFRACTb = 0; int xa, xa1, xb, xb1; xa = xa1 = x1; xb = xb1 = x1; for (y=0; y < dya; y++) { /* don't draw outside the clip */ if (y1 + y < clipY1) { /* above the clip */ goto nextStepTop; } if (y1 + y >= clipY2) { /* below the clip */ goto done; } { /* complication is xa,xb are not ordered and cannot be swapped */ int xaChanged, xbChanged; if ((xaChanged = (xa < clipX1))) xa1 = clipX1; if ((xbChanged = (xb < clipX1))) xb1 = clipX1; if (xaChanged && xbChanged) /* both to left */ goto nextStepTop; if ((xaChanged = !xaChanged)) /* toggle changed */ if ((xaChanged = (xa >= clipX2))) xa1 = clipX2-1; if ((xbChanged = !xbChanged)) if ((xbChanged = (xb >= clipX2))) xb1 = clipX2-1; if (xaChanged && xbChanged) /* both to right */ goto nextStepTop; } CHECK_XY_CLIP(sbuf, xa1, y1+y); CHECK_XY_CLIP(sbuf, xb1, y1+y); primDrawHorzLine(sbuf, color, xa1, y1 + y, xb1, y1 + y);nextStepTop: STEPx(xa,xFRACTa,dxa,dya,signDXa); STEPx(xb,xFRACTb,dxb,dyb,signDXb); xa1 = xa; xb1 = xb; } /* handle second edge x2,y2->x3,y3 */ xa = xa1 = x2; xFRACTa = 0; /* handle edge case (STEPx cannot take dyc == 0) * bottom of triangle is horizontal */ if (dyc == 0) { if ((clipY1 < (y1 + y)) || ((y1 + y) >= clipY2) || (clipX1 < (x2 )) || ((x2 ) >= clipX2) || (clipX1 < (x3 )) || ((x3 ) >= clipX2)) goto done; CHECK_XY_CLIP(sbuf, x2, y1+y); CHECK_XY_CLIP(sbuf, x3, y1+y); primDrawHorzLine(sbuf, color, x2, y1 + y, x3, y1 + y); goto done; } for (y=dya; y <= dyb; y++) { /* don't draw outside the clip */ if (y1 + y < clipY1) { /* above the clip */ goto nextStepBottom; } if (y1 + y >= clipY2) { /* below the clip */ goto done; } { /* complication is xa,xb are not ordered and cannot be swapped */ int xaChanged, xbChanged; if ((xaChanged = (xa < clipX1))) xa1 = clipX1; if ((xbChanged = (xb < clipX1))) xb1 = clipX1; if (xaChanged && xbChanged) /* both to left */ goto nextStepBottom; if ((xaChanged = !xaChanged)) /* toggle (changed) */ if ((xaChanged = (xa >= clipX2))) xa1 = clipX2-1; if ((xbChanged = !xbChanged)) if ((xbChanged = (xb >= clipX2))) xb1 = clipX2-1; if (xaChanged && xbChanged) /* both to right */ goto nextStepBottom; } CHECK_XY_CLIP(sbuf, xa1, y1+y); CHECK_XY_CLIP(sbuf, xb1, y1+y); primDrawHorzLine(sbuf, color, xa1, y1 + y, xb1, y1 + y);nextStepBottom: STEPx(xa,xFRACTa,dxc,dyc,signDXc); STEPx(xb,xFRACTb,dxb,dyb,signDXb); xa1 = xa; xb1 = xb; }done: ; }}static voiddrawClippedFilledArc(gxj_screen_buffer *sbuf, gxj_pixel_type color, const jshort *clip, int startQuadrant, int startRatio, int endQuadrant, int endRatio, int quadrantStatus[4], int x, int y, int w, int h) { int a,b; int a2,b2, S, T; int xCenter, yCenter; int evenXOffset, evenYOffset; int x_point, y_point; int start_x, start_y, end_x, end_y, start_x1, start_x2, start_y1, start_y2, end_x1, end_x2, end_y1, end_y2; int nQuadrantsToDraw, curQuadrant, quadrantsToDraw[4]; int point_x1, point_x2, point_y1, point_y2; int i,j; CHECK_SBUF_CLIP_BOUNDS(sbuf, clip); SetUpArcEndPoints(x, y, w, h, startQuadrant, startRatio, endQuadrant, endRatio, &start_x, &start_y, &end_x, &end_y, &start_x1, &start_y1, &end_x1, &end_y1, &start_x2, &start_y2, &end_x2, &end_y2); SetUpEllipseParams(x, y, x + w, y + h, &a, &b, &a2, &b2, &S, &T, &xCenter, &yCenter, &evenXOffset, &evenYOffset); /* now check for fully clipped quadrants or quadrants outside of the arc * we won't be drawing them, so we won't check them on every pixel * Also - draw the triangles in the quadrants which are partially filled */ nQuadrantsToDraw = 0; for (i = 0; i < 4; ++i) { if ((quadrantStatus[i] & QUADRANT_STATUS_NO_ARC) || (quadrantStatus[i] & QUADRANT_STATUS_TOTALLY_CLIPPED)) { continue; } else { curQuadrant = i + 1; quadrantsToDraw[nQuadrantsToDraw++] = curQuadrant; if (quadrantStatus[i] & QUADRANT_STATUS_PARTIAL_ARC) { if ((curQuadrant == startQuadrant) && (curQuadrant == endQuadrant) && ((((curQuadrant == 1) || (curQuadrant == 3)) && (startRatio <= endRatio)) || (((curQuadrant == 2) || (curQuadrant == 4)) && (startRatio >= endRatio)))) { /* need to make sure that the first point * is the one further from the x-axis */ if (curQuadrant == 1) { fill_triangle(sbuf, color, clip, end_x1, end_y1, start_x1, start_y1, xCenter, yCenter); } else if (curQuadrant == 2) { fill_triangle(sbuf, color, clip, start_x2, start_y1, end_x2, end_y1, xCenter, yCenter); } else if (curQuadrant == 3) { fill_triangle(sbuf, color, clip, end_x2, end_y2, start_x2, start_y2, xCenter, yCenter); } else { fill_triangle(sbuf, color, clip, start_x1, start_y2, end_x1, end_y2, xCenter, yCenter); } } else { if (curQuadrant == startQuadrant) { /* draw the appropriate triangle */ if (curQuadrant == 1) { drawFilledRightTriangle(sbuf, color, clip, start_x1, start_y1, xCenter, yCenter); } else if (curQuadrant == 2) { drawFilledRightTriangle(sbuf, color, clip, xCenter - evenXOffset, yCenter, start_x2, start_y1); } else if (curQuadrant == 3) { drawFilledRightTriangle(sbuf, color, clip, start_x2, start_y2, xCenter - evenXOffset, yCenter + evenYOffset); } else { drawFilledRightTriangle(sbuf, color, clip, xCenter, yCenter + evenYOffset, start_x1, start_y2); } } if (curQuadrant == endQuadrant) { /* draw the appropriate triangle */ if (curQuadrant == 1) { drawFilledRightTriangle(sbuf, color, clip, xCenter, yCenter, end_x1, end_y1); } else if (curQuadrant == 2) { drawFilledRightTriangle(sbuf, color, clip, end_x2, end_y1, xCenter - evenXOffset, yCenter); } else if (curQuadrant == 3) { drawFilledRightTriangle(sbuf, color, clip, xCenter - evenXOffset, yCenter + evenYOffset, end_x2, end_y2); } else { drawFilledRightTriangle(sbuf, color, clip, end_x1, end_y2, xCenter, yCenter + evenYOffset); } } } } } } /* now we loop through the ellipse co-ordinates again * and finish drawing what's left of the arcs after the triangles * we already did SetUpEllipseParams above and didn't use * the variables which change */ x_point = 0; y_point = b; while (y_point >= 0) { point_x1 = xCenter + x_point; point_y1 = yCenter - y_point; point_x2 = xCenter - x_point - evenXOffset; point_y2 = yCenter + y_point + evenYOffset; for (j = 0; j < nQuadrantsToDraw; ++j) { curQuadrant = quadrantsToDraw[j]; if (quadrantStatus[curQuadrant - 1] & QUADRANT_STATUS_FULL_ARC) { if (curQuadrant == 1) { draw_clipped_line(sbuf, color, SOLID, clip, point_x1, point_y1, point_x1, yCenter); } else if (curQuadrant == 2) { draw_clipped_line(sbuf, color, SOLID, clip, point_x2, point_y1, point_x2, yCenter); } else if (curQuadrant == 3) { draw_clipped_line(sbuf, color, SOLID, clip, point_x2, point_y2, point_x2, yCenter + evenYOffset); } else { /* (curQuadrant == 4) */ draw_clipped_line(sbuf, color, SOLID, clip, point_x1, point_y2, point_x1, yCenter + evenYOffset); } } else { /* must be partial arc * case of pie slice fully inside quadrant */ if ((curQuadrant == startQuadrant) && (curQuadrant == endQuadrant) && ((((curQuadrant == 1) || (curQuadrant == 3)) && (startRatio <= endRatio)) || (((curQuadrant == 2) || (curQuadrant == 4)) && (startRatio >= endRatio)))) { if ((((curQuadrant == 1) || (curQuadrant == 3)) && ((x_point <= start_x) && (y_point >= start_y)) && ((x_point >= end_x) && (y_point <= end_y))) || (((curQuadrant == 2) || (curQuadrant == 4)) && ((x_point >= start_x) && (y_point <= start_y)) && ((x_point < end_x) || (y_point > end_y)))) { if (curQuadrant == 1) { draw_clipped_line(sbuf, color, SOLID, clip, point_x1, point_y1, point_x1, yCenter - start_y); } else if (curQuadrant == 2) { draw_clipped_line(sbuf, color, SOLID, clip, point_x2, point_y1, point_x2, yCenter - end_y); } else if (curQuadrant == 3) { draw_clipped_line(sbuf, color, SOLID, clip, point_x2, point_y2, point_x2, yCenter + evenYOffset + start_y); } else if (curQuadrant == 4) { draw_clipped_line(sbuf, color, SOLID, clip, point_x1, point_y2, point_x1,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -