📄 raster_op.c
字号:
/*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory and to the University * of California at Berkeley by Jef Poskanzer. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)raster_op.c 8.1 (Berkeley) 6/11/93 * * from: $Header: raster_op.c,v 1.22 92/06/17 08:14:44 torek Exp $ *//* * Bitblit routine for raster library. * * This raster-op is machined to exacting tolerances by skilled native * craftsmen with pride in their work. * * The various cases are broken down like this: * * src required * 1-bit to 1-bit * 1-bit to 8-bits * 8-bits to 8-bits * no src required * 1-bit no-src * 8-bits no-src */#include <sys/types.h>#include <sparc/rcons/raster.h>/* CONFIGURE: To save on executable size, you can configure out the seldom-used** logical operations. With this variable set, the only operations implemented** are: RAS_SRC, RAS_CLEAR, RAS_SET, RAS_INVERT, RAS_XOR, RAS_INVERTSRC.*/#ifdef KERNEL#define PARTIAL_LOGICAL_OPS#endif/* CONFIGURE: bcopy() is supposed to be the ultimately fastest way to move** bytes, overlapping or not, ignoring the startup cost. Unfortunately** this is not true on some systems. For example, on a Sun 3 running** SunOS 3.5, bcopy() is about five times slower than a simple for loop** on overlapping copies. And on a 4.1.1 SPARC, bcopy() is about 2/3rds** as fast on backwards overlaps. So, only define this if your bcopy is ok.*/#undef BCOPY_FASTER/* End of configurable definitions. *//* Definitions. *//* Raster-op macros. These encapsulate the switch statements and so make** the source code 16 times smaller. The pre and pst args are code** fragments to put before and after the assignment in each case. They** can be the beginning and end of a loop. If the pst fragment includes a** masked assignment, for example to handle the left or right edge cases,** a good optimizing compiler will simplify the boolean expressions very** nicely - both cc and gcc on the SPARC will do this.*/#ifndef PARTIAL_LOGICAL_OPS#define ROP_DST(op,pre,d,pst) \ switch ( op ) \ { \ case RAS_CLEAR: \ pre \ (d) = 0; \ pst \ break; \ case RAS_INVERT: \ pre \ (d) = ~(d); \ pst \ break; \ case RAS_DST: \ /* noop */ \ break; \ case RAS_SET: \ pre \ (d) = ~0; \ pst \ break; \ default: \ return -1; \ }#define ROP_DSTCOLOR(op,pre,d,c,pst) \ switch ( op ) \ { \ case RAS_CLEAR: \ pre \ (d) = 0; \ pst \ break; \ case RAS_INVERT: \ pre \ (d) = ~(d); \ pst \ break; \ case RAS_DST: \ /* noop */ \ break; \ case RAS_SET: \ pre \ (d) = (c); \ pst \ break; \ default: \ return -1; \ }#define ROP_SRCDST(op,pre,s,d,pst) \ switch ( op ) \ { \ case RAS_NOTOR: \ pre \ (d) = ~( (s) | (d) ); \ pst \ break; \ case RAS_NOTSRC_AND_DST: \ pre \ (d) = ~(s) & (d); \ pst \ break; \ case RAS_INVERTSRC: \ pre \ (d) = ~(s); \ pst \ break; \ case RAS_SRC_AND_NOTDST: \ pre \ (d) = (s) & ~(d); \ pst \ break; \ case RAS_XOR: \ pre \ (d) = (s) ^ (d); \ pst \ break; \ case RAS_NOTAND: \ pre \ (d) = ~( (s) & (d) ); \ pst \ break; \ case RAS_AND: \ pre \ (d) = (s) & (d); \ pst \ break; \ case RAS_NOTXOR: \ pre \ (d) = ~( (s) ^ (d) ); \ pst \ break; \ case RAS_NOTSRC_OR_DST: \ pre \ (d) = ~(s) | (d); \ pst \ break; \ case RAS_SRC: \ pre \ (d) = (s); \ pst \ break; \ case RAS_SRC_OR_NOTDST: \ pre \ (d) = (s) | ~(d); \ pst \ break; \ case RAS_OR: \ pre \ (d) = (s) | (d); \ pst \ break; \ default: \ return -1; \ }#define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \ switch ( op ) \ { \ case RAS_NOTOR: \ pre \ if ( s ) \ (d) = ~( (c) | (d) ); \ else \ (d) = ~(d); \ pst \ break; \ case RAS_NOTSRC_AND_DST: \ pre \ if ( s ) \ (d) = ~(c) & (d); \ pst \ break; \ case RAS_INVERTSRC: \ pre \ if ( s ) \ (d) = ~(c); \ else \ (d) = ~0; \ pst \ break; \ case RAS_SRC_AND_NOTDST: \ pre \ if ( s ) \ (d) = (c) & ~(d); \ else \ (d) = 0; \ pst \ break; \ case RAS_XOR: \ pre \ if ( s ) \ (d) = (c) ^ (d); \ pst \ break; \ case RAS_NOTAND: \ pre \ if ( s ) \ (d) = ~( (c) & (d) ); \ else \ (d) = ~0; \ pst \ break; \ case RAS_AND: \ pre \ if ( s ) \ (d) = (c) & (d); \ else \ (d) = 0; \ pst \ break; \ case RAS_NOTXOR: \ pre \ if ( s ) \ (d) = ~( (c) ^ (d) ); \ else \ (d) = ~(d); \ pst \ break; \ case RAS_NOTSRC_OR_DST: \ pre \ if ( s ) \ (d) = ~(c) | (d); \ else \ (d) = ~0; \ pst \ break; \ case RAS_SRC: \ pre \ if ( s ) \ (d) = (c); \ else \ (d) = 0; \ pst \ break; \ case RAS_SRC_OR_NOTDST: \ pre \ if ( s ) \ (d) = (c) | ~(d); \ else \ (d) = ~(d); \ pst \ break; \ case RAS_OR: \ pre \ if ( s ) \ (d) = (c) | (d); \ pst \ break; \ default: \ return -1; \ }#else /*PARTIAL_LOGICAL_OPS*/#define ROP_DST(op,pre,d,pst) \ switch ( op ) \ { \ case RAS_CLEAR: \ pre \ (d) = 0; \ pst \ break; \ case RAS_INVERT: \ pre \ (d) = ~(d); \ pst \ break; \ case RAS_SET: \ pre \ (d) = ~0; \ pst \ break; \ default: \ return -1; \ }#define ROP_DSTCOLOR(op,pre,d,c,pst) \ switch ( op ) \ { \ case RAS_CLEAR: \ pre \ (d) = 0; \ pst \ break; \ case RAS_INVERT: \ pre \ (d) = ~(d); \ pst \ break; \ case RAS_SET: \ pre \ (d) = (c); \ pst \ break; \ default: \ return -1; \ }#define ROP_SRCDST(op,pre,s,d,pst) \ switch ( op ) \ { \ case RAS_INVERTSRC: \ pre \ (d) = ~(s); \ pst \ break; \ case RAS_XOR: \ pre \ (d) = (s) ^ (d); \ pst \ break; \ case RAS_SRC: \ pre \ (d) = (s); \ pst \ break; \ default: \ return -1; \ }#define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \ switch ( op ) \ { \ case RAS_INVERTSRC: \ pre \ if ( s ) \ (d) = ~(c); \ else \ (d) = ~0; \ pst \ break; \ case RAS_XOR: \ pre \ if ( s ) \ (d) = (c) ^ (d); \ pst \ break; \ case RAS_SRC: \ pre \ if ( s ) \ (d) = (c); \ else \ (d) = 0; \ pst \ break; \ default: \ return -1; \ }#endif /*PARTIAL_LOGICAL_OPS*//* Variables. */static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 };/* CLEAR INVERT DST SET */#ifdef MSBIT_FIRSTu_long raster_bitmask[32] = { 0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000, 0x01000000, 0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000, 0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100, 0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001 };#ifdef MSBYTE_FIRSTstatic u_long leftmask[32] = { 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };static u_long rightmask[32] = { 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };#endif /*MSBYTE_FIRST*/#else /*MSBIT_FIRST*/u_long raster_bitmask[32] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000 };#ifndef MSBYTE_FIRSTstatic u_long leftmask[32] = { 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };static u_long rightmask[32] = { 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };#endif /*not MSBYTE_FIRST*/#endif /*MSBIT_FIRST*//* (The odd combinations MSBIT+~MSBYTE and ~MSBIT+MSBYTE could be added.) */#ifdef MSBYTE_FIRSTstatic u_long bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };#else /*MSBYTE_FIRST*/static u_long bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };#endif /*MSBYTE_FIRST*//* Forward routines. */static int raster_blit();/* Raster operations. *//* Performs a bitblit. Returns 0 on success, -1 on failure. */intraster_op( dst, dx, dy, w, h, rop, src, sx, sy ) struct raster* dst; int dx, dy, w, h, rop; struct raster* src; int sx, sy; { if ( dst == (struct raster*) 0 ) return -1; /* no destination */ if ( needsrc[RAS_GETOP( rop )] ) { /* Two-operand blit. */ if ( src == (struct raster*) 0 ) return -1; /* no source */ /* Clip against source. */ if ( sx < 0 ) { w += sx; sx = 0; } if ( sy < 0 ) { h += sy; sy = 0; } if ( sx + w > src->width ) w = src->width - sx; if ( sy + h > src->height ) h = src->height - sy; /* Clip against dest. */ if ( dx < 0 ) { w += dx; sx -= dx; dx = 0; } if ( dy < 0 ) { h += dy; sy -= dy; dy = 0; } if ( dx + w > dst->width ) w = dst->width - dx; if ( dy + h > dst->height ) h = dst->height - dy; if ( w <= 0 || h <= 0 ) return 0; /* nothing to do */ return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy ); } /* No source necessary - one-operand blit. */ if ( src != (struct raster*) 0 ) return -1; /* unwanted source */ /* Clip against dest. */ if ( dx < 0 ) { w += dx; dx = 0; } if ( dy < 0 ) { h += dy; dy = 0; } if ( dx + w > dst->width ) w = dst->width - dx; if ( dy + h > dst->height ) h = dst->height - dy; if ( w <= 0 || h <= 0 ) return 0; /* nothing to do */ return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop ); }/* Semi-public routine to do a bitblit without clipping. Returns 0 on** success, -1 on failure.*/intraster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy ) struct raster* dst; int dx, dy, w, h, rop; struct raster* src; int sx, sy; { int op; op = RAS_GETOP( rop ); if ( src->depth == 1 ) { /* One-bit to ? blit. */ if ( dst->depth == 1 ) { /* One to one blit. */ u_long* srclin1; u_long* dstlin1; int srcleftignore, srcrightignore, srclongs; int dstleftignore, dstrightignore, dstlongs; srclin1 = RAS_ADDR( src, sx, sy ); dstlin1 = RAS_ADDR( dst, dx, dy );#ifdef BCOPY_FASTER /* Special-case full-width to full-width copies. */ if ( op == RAS_SRC && src->width == w && dst->width == w && src->linelongs == dst->linelongs && src->linelongs == w >> 5 ) { bcopy( (char*) srclin1, (char*) dstlin1, h * src->linelongs * sizeof(u_long) ); return 0; }#endif /*BCOPY_FASTER*/ srcleftignore = ( sx & 31 ); srclongs = ( srcleftignore + w + 31 ) >> 5; srcrightignore = ( srclongs * 32 - w - srcleftignore ) & 31; dstleftignore = ( dx & 31 ); dstlongs = ( dstleftignore + w + 31 ) >> 5; dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31; return raster_blit( src, srclin1, srcleftignore, srcrightignore, srclongs, dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op ); } else { /* One to eight, using the color in the rop. This could ** probably be sped up by handling each four-bit source nybble ** as a group, indexing into a 16-element runtime-constructed ** table of longwords. */ u_long* srclin1; u_long* dstlin1; u_long* srclin2; u_long* srclin; u_long* dstlin; register u_long* srclong; register u_long* dstlong; register u_long color, dl; register int srcbit, dstbyte, i; color = RAS_GETCOLOR( rop ); if ( color == 0 ) color = 255; /* Make 32 bits of color so we can do the ROP without shifting. */ color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 ); /* Don't have to worry about overlapping blits here. */ srclin1 = RAS_ADDR( src, sx, sy ); srclin2 = srclin1 + h * src->linelongs; dstlin1 = RAS_ADDR( dst, dx, dy ); srclin = srclin1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -