📄 gxj_putpixel.c
字号:
/* * * * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */#include <kni.h>#include <midpMalloc.h>#include <midp_logging.h>#include "gxj_intern_putpixel.h"#include "gxj_intern_graphics.h"typedef struct _registers_4 { unsigned int r0; unsigned int r1; unsigned int r2; unsigned int r3;} registers_4;typedef struct _dotted_draw_state { /* the draw state */ int solidcount; /* how many dots are drawn in the solid fragment */ int emptycount; /* how many dots are skipped in the empty fragment */ int drawing; /* are we drawing (1) or skipping (0) now? */} dotted_draw_state;static const dotted_draw_state HALF_STROKE = { DOTTED_SOLID_SIZE/2, 0, TRUE };static const dotted_draw_state START_STROKE = { 0, 0, TRUE };int aTangents[91] = { /* _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 */ /* 0_ */ 0, 17, 35, 52, 70, 87, 105, 123, 141, 158, /* 1_ */ 176, 194, 213, 231, 249, 268, 287, 306, 325, 344, /* 2_ */ 364, 384, 404, 424, 445, 466, 488, 510, 532, 554, /* 3_ */ 577, 601, 625, 649, 675, 700, 727, 754, 781, 810, /* 4_ */ 839, 869, 900, 933, 966, 1000, 1036, 1072, 1111, 1150, /* 5_ */ 1192, 1235, 1280, 1327, 1376, 1428, 1483, 1540, 1600, 1664, /* 6_ */ 1732, 1804, 1881, 1963, 2050, 2145, 2246, 2356, 2475, 2605, /* 7_ */ 2747, 2904, 3078, 3271, 3487, 3732, 4011, 4331, 4705, 5145, /* 8_ */ 5671, 6314, 7115, 8144, 9514, 11430, 14301, 19081, 28636, 57290, /* 9_ */ MAXINT32 };/* degrees must be between 0 and 360 * returns abs(int(tan(degrees) * 1000)) */static intabsIntTan1000(int degrees){ if (degrees > 180) { degrees = degrees - 180; } if (degrees > 90) { degrees = 180 - degrees; } return aTangents[degrees];}/** Overview of the SetPixel based implementation of the lcdui graphics functions This implementation is meant to be usable as the basis for implementing lcdui graphics on any platform which offers SetPixel(color, x, y) or better graphics function. It is implemented so that with minimal finessing, it can be optimized for speed for any level of graphics support. This is achieved by providing a number of routines which are prefixed with prim (for primitive). These routines are written in terms of SetPixel but are often available directly on systems with graphics support. They do no clipping. These routines (or the calls to them) can be replaced with direct calls to the underlying system routines where available. THe code is currently also written so that the lcdui functions themselves are kept short, handling only the peculiarities of the midp spec and other system dependent things such as setting up device contexts, redrawing the screen, and color. Also, where it's simple, we check to see if there is no clipping and then immediately call primitive routines. The clipped case (and the case of partial arcs) are handled in separate routines. The code currently has been somewhat biased in favor of readability and debuggability - there is no use of macros, and there is fairly heavy breakdown into meaningful functions. After profiling we will have a better idea of exactly where we need to make things "dirtier", though some seem obvious immediately (such as putting drawSymmetricPixel inside drawClippedOutlineArc). Note that lines which are not vertical/horizontal and all arcs cannot be implemented as primitive functions because of the demand of the midp spec that partial lines draw the same pixels as the complete line, and the fact that they use the Midpoint algorithm for calculating their points - that means you always have to start from the beginning point even when you know most of the line is clipped, because you can't predict which point will be drawn at any point along the line without calculating from the beginning. This means that all of the relevant code would have to be replaced as an atomic whole by code which provided *all* of the relevant functionality. There are currently some known bugs in the code in certain cases arcs, and filled partial arcs in particular. *//** * draw pattern pixel at pixelData[y*width+x] * partial clipping to sbuf[width,height] and (y*width+x < 0) * pattern is (0->SOLID) then (SOLID->(SOLID+EMPTY)) then repeat */staticvoiddrawDottedPixel(gxj_screen_buffer *sbuf, gxj_pixel_type color, int x, int y, dotted_draw_state * dds) { if (dds->solidcount >= DOTTED_SOLID_SIZE) { dds->drawing = FALSE; dds->solidcount = 0; } else { if (dds->emptycount >= DOTTED_EMPTY_SIZE) { dds->drawing = TRUE; dds->emptycount = 0; } } if (dds->drawing) { PRIMDRAWPIXEL(sbuf, color, x, y); ++(dds->solidcount); } else { ++(dds->emptycount); }}#define SWAP(_x,_y) do {_x ^= _y; _y ^= _x; _x ^= _y;} while (0)/* all line drawing routines, including prim routines, * draw both endpoints. if replacing these routines by * system routines which don't draw the second endpoint, * remember to add one to x2 and y2 *//** * draw pixels from <x1,y1) through (x1,y2) * y1 should be <= y2, x1 == x2 */static voidprimDrawVertLine(gxj_screen_buffer *sbuf, gxj_pixel_type color, int x1, int y1, int x2, int y2) { int width = sbuf->width; int height = sbuf->height; int count; gxj_pixel_type* pPtr; (void)x2;#if PRIM_CLIPPING if ((x1 < 0) || (x1 >= width)) return; y1 = (y1 < 0) ? 0 : ((y1 >= height) ? height-1 : y1); y2 = (y2 < 0) ? 0 : ((y2 >= height) ? height-1 : y2);#endif if ((count=y2-y1) < 0) { y1 = y2; count = -count; } pPtr = &(sbuf->pixelData[y1 * width + x1]); while (count & ~0x7) { CHECK_PTR_CLIP(sbuf,pPtr); *pPtr = color; pPtr += width; *pPtr = color; pPtr += width; *pPtr = color; pPtr += width; *pPtr = color; pPtr += width; *pPtr = color; pPtr += width; *pPtr = color; pPtr += width; *pPtr = color; pPtr += width; *pPtr = color; CHECK_PTR_CLIP(sbuf,pPtr); pPtr += width; count -= 8; } while (count >= 0) { CHECK_PTR_CLIP(sbuf,pPtr); *pPtr = color; pPtr += width; count -= 1; }}/** * draw pixels from <x1,y1) through (x2,y1) * x1 should be <= x2, y1 == y2 */static voidprimDrawHorzLine(gxj_screen_buffer *sbuf, gxj_pixel_type color, int x1, int y1, int x2, int y2) {#if 0 int width = sbuf->width; int height = sbuf->height; int count; gxj_pixel_type* pPtr;#if PRIM_CLIPPING if ((y1 < 0) || (y1 >= height)) return; x1 = (x1 < 0) ? 0 : ((x1 >= width) ? width-1 : x1); x2 = (x2 < 0) ? 0 : ((x2 >= width) ? width-1 : x2);#endif if ((count=x2-x1) < 0) { x1 = x2; count = -count; } pPtr = &(sbuf->pixelData[y1 * width + x1]); while (count & ~0x7) { CHECK_PTR_CLIP(sbuf,pPtr); *pPtr = color; pPtr += 1; *pPtr = color; pPtr += 1; *pPtr = color; pPtr += 1; *pPtr = color; pPtr += 1; *pPtr = color; pPtr += 1; *pPtr = color; pPtr += 1; *pPtr = color; pPtr += 1; *pPtr = color; CHECK_PTR_CLIP(sbuf,pPtr); pPtr += 1; count -= 8; } while (count >= 0) { CHECK_PTR_CLIP(sbuf,pPtr); *pPtr = color; pPtr += 1; count -= 1; }#else int width = sbuf->width; int height = sbuf->height; int count; gxj_pixel_type* pPtr; unsigned int c = ((unsigned int)color) << 16 | ((unsigned int)color); jlong lcol = ((jlong) c) << 32 | ((jlong) c); registers_4 regs; regs.r0 = regs.r1 = regs.r2 = regs.r3 = c; (void)y2;#if PRIM_CLIPPING if ((y1 < 0) || (y1 >= height)) return; x1 = (x1 < 0) ? 0 : ((x1 >= width) ? width-1 : x1); x2 = (x2 < 0) ? 0 : ((x2 >= width) ? width-1 : x2);#endif y1 *= width; if ((count=x2-x1) < 0) { x1 = x2; count = -count; } pPtr = &(sbuf->pixelData[y1 + x1]); if (((unsigned int)pPtr & 0x3) && (count > 0)) { CHECK_PTR_CLIP(sbuf,pPtr); *pPtr++ = color; --count; } while (count >= 16) { CHECK_LLPTR_CLIP(sbuf,pPtr); *((registers_4 *)pPtr) = regs; pPtr += 8; CHECK_LLPTR_CLIP(sbuf,pPtr); *((registers_4 *)pPtr) = regs; pPtr += 8; count -= 16; } if (count >= 8) { CHECK_LLPTR_CLIP(sbuf,pPtr); *((registers_4 *)pPtr) = regs; pPtr += 8; count -= 8; } if (count >= 4) { CHECK_LLPTR_CLIP(sbuf,pPtr); *((jlong *)pPtr) = lcol; pPtr += 4; count -= 4; } while (count >= 0) { CHECK_PTR_CLIP(sbuf,pPtr); *pPtr = color; pPtr += 1; count -= 1; }#endif}/** * draw dotted line pixels from (x1,y1) through (x1,y2) * y1 should be <= y2, x1 == x2 starting from specified * stroke state, and returning final stroke state */static voiddrawDottedVertLine(gxj_screen_buffer *sbuf, gxj_pixel_type color, int x1, int y1, int x2, int y2, dotted_draw_state dds) { int y; /* Surpress unused parameter warnings */ (void)x2; #if PRIM_CLIPPING if ((x1 < 0) || (x1 >= sbuf->width)) return; y1 = (y1 < 0) ? 0 : ((y1 >= sbuf->height) ? sbuf->height-1 : y1); y2 = (y2 < 0) ? 0 : ((y2 >= sbuf->height) ? sbuf->height-1 : y2);#endif for (y = y1; y <= y2; ++y) { drawDottedPixel(sbuf, color, x1, y, &dds); }}/** * draw dotted line pixels from (x1,y1) through (x2,y1) * x1 should be <= x2, y1 == y2 starting from specified * stroke state, and returning final stroke state */static voiddrawDottedHorzLine(gxj_screen_buffer *sbuf, gxj_pixel_type color, int x1, int y1, int x2, int y2, dotted_draw_state dds) { int x; /* Surpress unused parameter warnings */ (void)y2;#if PRIM_CLIPPING if ((y1 < 0) || (y1 >= sbuf->height)) return; x1 = (x1 < 0) ? 0 : ((x1 >= sbuf->width) ? sbuf->width-1 : x1); x2 = (x2 < 0) ? 0 : ((x2 >= sbuf->width) ? sbuf->width-1 : x2);#endif for (x = x1; x <= x2; ++x) { drawDottedPixel(sbuf, color, x, y1, &dds); }}/** * draw pixels from (x1,y1) through (x1,y2) * y1 should be <= y2, x1 == x2 starting from solid stroke */static voidprimDrawDottedVertLine(gxj_screen_buffer *sbuf, gxj_pixel_type color, int x1, int y1, int x2, int y2) { drawDottedVertLine(sbuf, color, x1, y1, x2, y2, START_STROKE);}/** * draw dotted line pixels from (x1,y1) through (x2,y1) * x1 should be <= x2, y1 == y2 starting from solid stroke */static voidprimDrawDottedHorzLine(gxj_screen_buffer *sbuf, gxj_pixel_type color, int x1, int y1, int x2, int y2) { drawDottedHorzLine(sbuf, color, x1, y1, x2, y2, START_STROKE);}#define REFLECT 16 /* ymajor octants (2/3/6/7) mapped to xmajor (1/4/5/8) */#define CLIPPED 8 /* some leading pixels clipped (x1,y1 changed) */#define POINT 4 /* delta x and y are zero */#define HORIZONTAL 2 /* delta x or y is zero (see REFLECT) */#define INSIDE 1 /* some pixels inside clip */#define OUTSIDE 0 /* all pixles are outside clip *//** * Perform clip testing and clipping of the line segment x1,y1 to x2,y2. * If all the pixels of the line segment are beyond the bounds of the * clip this function returns OUTSIDE. When SetUpClippedLineParams * returns INSIDE it has computed and updated the starting pixel x1,y1, * computed a new mayor axis ending value xyEnd, computed a Bresenham * decision variable, decision variable increments incX,incY, octant * specifier (REFLECT) and quadrant specifiers adjIncX,adjIncY. This * function also looks for empty clip bounds and returns OUTSIDE. * * If the line is both horizontal (no deltax) and vertical (no deltay) * the return value is (POINT) with x1,y1 left untouched. * If the line is horizontal (deltay is zero) the return value is (HORIZONTAL) * with the x1,y1 and xyEnd clipped. If the segment is vertical (deltax is * zero) the value (HORIZONTAL|REFLECT) is returned with x1,y1 swapped * then clipped (CLIPPED) and xyEnd clipped. Both horizontal and vertical lines * have the correct Bresenham decision, increments and x,y adjustment * values computed. * * For all other angle lines the correct quadrant is computed (adjIncX,adjIncY),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -