|
|
1.1 ! root 1: /* $Header: text.h,v 10.1 86/11/19 10:46:56 jg Exp $ */ ! 2: /* text.h - macros and global data used by X text functions ! 3: * ! 4: * Author: ! 5: * Dan Stone & Scott Bates ! 6: * Brown University ! 7: * IRIS, Box 1946 ! 8: * Providence, RI 02912 ! 9: * ! 10: * ! 11: * Copyright (c) 1986 Brown University ! 12: * ! 13: * Permission to use, copy, modify and distribute this software and its ! 14: * documentation for any purpose and without fee is hereby granted, provided ! 15: * that the above copyright notice appear in all copies, and that both ! 16: * that copyright notice and this permission notice appear in supporting ! 17: * documentation, and that the name of Brown University not be used in ! 18: * advertising or publicity pertaining to distribution of the software ! 19: * without specific, written prior permission. Brown University makes no ! 20: * representations about the suitability of this software for any purpose. ! 21: * It is provided "as-is" without express or implied warranty. ! 22: */ ! 23: ! 24: /* ! 25: * Macros for all the combination rules which can be used. ! 26: */ ! 27: ! 28: #define GXcopy_OP(src, dst) dst = (src) ! 29: #define GXor_OP(src, dst) dst = (dst) | (src) ! 30: #define GXxor_OP(src, dst) dst = (dst) ^ (src) ! 31: #define GXand_OP(src, dst) dst = (dst) & (src) ! 32: #define GXcopyInverted_OP(src, dst) dst = ~(src) ! 33: #define GXorInverted_OP(src, dst) dst = (dst) | ~(src) ! 34: #define GXequiv_OP(src, dst) dst = (dst) ^ ~(src) ! 35: #define GXandInverted_OP(src, dst) dst = (dst) & ~(src) ! 36: #define GXorReverse_OP(src, dst) dst = (~(dst) | (src)) ! 37: #define GXandReverse_OP(src, dst) dst = (~(dst) & (src)) ! 38: #define GXinvert_OP(src, dst) dst = ~(dst) ! 39: #define GXnand_OP(src, dst) dst = (~(dst) | ~(src)) ! 40: #define GXnor_OP(src, dst) dst = (~(dst) & ~(src)) ! 41: #define GXclear_OP(src, dst) dst = 0 ! 42: #define GXset_OP(src, dst) dst = 0xFFFF ! 43: #define GXnoop_OP(src, dst) dst = dst ! 44: ! 45: #define GXcopy_MASK(src, dst, mask) dst = ((dst) & ~(mask)) | \ ! 46: ((src) & mask) ! 47: #define GXor_MASK(src, dst, mask) dst = ((dst) | ((src) & mask)) ! 48: #define GXxor_MASK(src, dst, mask) dst = ((dst) ^ ((src) & mask)) ! 49: #define GXand_MASK(src, dst, mask) dst = ((dst) & ~(mask)) | \ ! 50: (((dst) & (src)) & mask) ! 51: #define GXcopyInverted_MASK(src, dst, mask) dst = ((dst) & ~(mask)) | \ ! 52: (~(src) & mask) ! 53: #define GXorInverted_MASK(src, dst, mask) dst = ((dst) | (~(src) & mask)) ! 54: #define GXequiv_MASK(src, dst, mask) dst = ((dst) ^ (~(src) & mask)) ! 55: #define GXandInverted_MASK(src, dst, mask) dst = ((dst) & ~(mask)) | \ ! 56: (((dst) & ~(src)) & mask) ! 57: #define GXandReverse_MASK(src, dst, mask) dst = ((dst) & ~(mask)) | \ ! 58: ((~(dst) & (src)) & mask) ! 59: #define GXorReverse_MASK(src, dst, mask) dst = ((dst) & ~(mask)) | \ ! 60: ((~(dst) | (src)) & mask) ! 61: #define GXinvert_MASK(src, dst, mask) dst = ((dst) & ~(mask)) | \ ! 62: (~(dst) & (mask)) ! 63: #define GXnor_MASK(src, dst, mask) dst = ((dst) & ~(mask)) | \ ! 64: ((~(dst) & ~(src)) & mask) ! 65: #define GXnand_MASK(src, dst, mask) dst = ((dst) & ~(mask)) | \ ! 66: ((~(dst) | ~(src)) & mask) ! 67: #define GXclear_MASK(src, dst, mask) dst = 0 ! 68: #define GXset_MASK(src, dst, mask) dst = 0xFFFF ! 69: #define GXnoop_MASK(src, dst, mask) dst = dst ! 70: ! 71: #ifndef BPL ! 72: #define BPL 32 ! 73: #define LOG2_BPL 5 ! 74: #define MOD_BPL(value) ((value) & (BPL - 1)) ! 75: #define DIV_BPL(value) ((value) >> LOG2_BPL) ! 76: #define MUL_BPL(value) ((value) << LOG2_BPL) ! 77: ! 78: /* ! 79: * Macro to convert Bits to Longs. ! 80: */ ! 81: ! 82: #define BTOL(bits) (DIV_BPL((bits) + (BPL - 1))) ! 83: ! 84: #define MUL_4(n) ((n) << 2) ! 85: #define DIV_4(n) ((n) >> 2) ! 86: #endif BPL ! 87: ! 88: #define SRC ((u_short *)src) ! 89: #define SRCPL ((u_short *)(src + 2)) ! 90: #define DST ((u_short *)dst) ! 91: #define DSTPL ((u_short *)(dst + 2)) ! 92: ! 93: /* ! 94: * Masks for to protect the left portion of a short. That portion that should ! 95: * not be changed. ! 96: */ ! 97: ! 98: static u_short leftmask_lib[] = { ! 99: 0xFFFF,0x7FFF,0x3FFF,0x1FFF, ! 100: 0x0FFF,0x07FF,0x03FF,0x01FF, ! 101: 0x00FF,0x007F,0x003F,0x001F, ! 102: 0x000F,0x0007,0x0003,0x0001, ! 103: 0x0000 ! 104: }; ! 105: ! 106: /* ! 107: * Masks for to protect the right portion of a short. That portion that should ! 108: * not be changed. ! 109: */ ! 110: ! 111: static u_short rightmask_lib[] = { ! 112: 0xFFFF,0x8000,0xC000,0xE000, ! 113: 0xF000,0xF800,0xFC00,0xFE00, ! 114: 0xFF00,0xFF80,0xFFC0,0xFFE0, ! 115: 0xFFF0,0xFFF8,0xFFFC,0xFFFE, ! 116: 0x0000 ! 117: }; ! 118: ! 119: /* ! 120: * This macro is used to copy characters from the fonts character bitmaps ! 121: * to the offscreen bitmap. Later the offscreen bitmap is copied to the screen ! 122: * using the bltter. ! 123: * ! 124: * The CopyText_LOOP is an optimization, of a more general bitblt loop. ! 125: * Because most text characters are less than 16 bits wide the CopyText_LOOP ! 126: * has 2 special inner loops for this size character image. A character ! 127: * image thats less than 16 bits wide can only span at most 2 destination ! 128: * shorts, so the 2 special inner loops are designed for 1 destination and ! 129: * 2 destination shorts changing per line. IF more than 2 destination words ! 130: * are to change then the general purpose loop is used. ! 131: * ! 132: * Some special notes: ! 133: * ! 134: * bitptr - A long integer that "points to" or "indexes into" one offscreen ! 135: * buffer scanline. As if one scanline was an array of bits. ! 136: * ! 137: * src,dst - Are unsigned CHAR pointers and are cast to unsigned shorts ! 138: * when used as pointers. Why? IF src was an unsigned SHORT ! 139: * pointer and src += n was done, the current RT compiler ! 140: * would generate 2 extra assembly language instructions, ! 141: * one to shift n left (multiply by 2) and the other to ! 142: * compute the address. ! 143: * ! 144: * The offscreen buffer is the destination. ! 145: * ! 146: * Here is the algorithm for the CopyText_LOOP: ! 147: * ! 148: * FOREACH character DO ! 149: * IF the character is not printable THEN ! 150: * continue ! 151: * IF the character is wider than zero THEN ! 152: * set start_dst = To the destination short which contains the first ! 153: * bit to be changed. ! 154: * set shift = The first bit within start_dst to be changed. ! 155: * Increment bitptr past the current character. ! 156: * IF bitptr is beyond the last bit in the destination THEN ! 157: * Decrement bitptr back to its previous value. ! 158: * Decrement the character count. ! 159: * Break out of the loop. ! 160: * ENDIF ! 161: * ! 162: * Set the right mask using the right mask library and the NEW bitptr. ! 163: * Calculate the source pointer. ! 164: * Calculate the destination pointer. ! 165: * Calculate the number of shorts changed in the destination. ! 166: * ! 167: * IF no shifting needed THEN ! 168: * IF 1 destination short changed THEN ! 169: * FOREACH scanline DO ! 170: * Use the edge macro (see above) to combine src, dst and ! 171: * mask. ! 172: * Increment the source to the next scanline. ! 173: * Increment the destination to the next scanline. ! 174: * ENDFOR ! 175: * ELSE IF 2 destination shorts changed THEN ! 176: * FOREACH scanline DO ! 177: * Use the macro (see above) to combine src and dst. ! 178: * Use the edge macro (see above) to combine src+2, dst+2 ! 179: * and mask. ! 180: * Increment the source to the next scanline. ! 181: * Increment the destination to the next scanline. ! 182: * ENDFOR ! 183: * ELSE ! 184: * Calculate the amount to decrement the dst to get back ! 185: * to the first scanline next short(the + 2). ! 186: * Calculate the amount to decrement the src to get back ! 187: * to the first scanline next short(the + 2). ! 188: * FOREACH short in the destination DO ! 189: * FOREACH scanline DO ! 190: * Use the macro (see above) to combine src and dst. ! 191: * Increment the source to the next scanline. ! 192: * Increment the destination to the next scanline. ! 193: * ENDFOR ! 194: * Decrement dst back to the first scanline, next short. ! 195: * Decrement src back to the first scanline, next short. ! 196: * Reset the number of scanlines (height). ! 197: * ENDFOR ! 198: * FOREACH scanline DO ! 199: * Use the edge macro to combine src, dst and mask. ! 200: * Increment the source to the next scanline. ! 201: * Increment the destination to the next scanline. ! 202: * ENDFOR ! 203: * ENDIF ! 204: * ELSE ! 205: * Get the left mask from the left mask library using shift. ! 206: * IF 1 destination short changed THEN ! 207: * Combine left and right masks. ! 208: * FOREACH scanline DO ! 209: * Use the edge macro (see above) to combine src shifted, ! 210: * with dst and mask. ! 211: * Increment the source to the next scanline. ! 212: * Increment the destination to the next scanline. ! 213: * ENDFOR ! 214: * ELSE IF 2 destination shorts changed THEN ! 215: * Set the inverse of shift = 16 - shift. ! 216: * IF the src bitmap is only 1 short wide THEN ! 217: * FOREACH scanline DO ! 218: * Use the edge macro (see above) to combine src ! 219: * shifted, with dst and left mask. ! 220: * Use the edge macro (see above) to combine src ! 221: * inversely shifted with dst+2 and right mask. ! 222: * Increment the source to the next scanline. ! 223: * Increment the destination to the next scanline. ! 224: * ENDFOR ! 225: * ELSE # src bitmap is wider than 1 short and the 2nd short ! 226: * # may have useful info in it. ! 227: * FOREACH scanline DO ! 228: * Use the edge macro (see above) to combine src ! 229: * shifted with dst and left mask. ! 230: * Use the edge macro (see above) to combine src ! 231: * shifted, src+2 inversely shifted with ! 232: * dst+2 and right mask. ! 233: * Increment the source to the next scanline. ! 234: * Increment the destination to the next scanline. ! 235: * ENDFOR ! 236: * ELSE ! 237: * Calculate the amount to decrement the dst to get back ! 238: * to the first scanline next short(the + 2). ! 239: * Calculate the amount to decrement the src to get back ! 240: * to the first scanline next short(the + 2). ! 241: * # Deal with the left edge. ! 242: * FOREACH scanline DO ! 243: * Use the edge macro (see above) to combine src shifted ! 244: * with dst and left mask. ! 245: * Increment the source to the next scanline. ! 246: * Increment the destination to the next scanline. ! 247: * ENDFOR ! 248: * # Now deal with the shorts between the left edge and right ! 249: * # edge. ! 250: * FOREACH short in the destination DO ! 251: * FOREACH scanline DO ! 252: * Use the macro (see above) to combine src inversely ! 253: * shifted or'ed with src+2 shifted with dst. ! 254: * Increment the source to the next scanline. ! 255: * Increment the destination to the next scanline. ! 256: * ENDFOR ! 257: * Decrement dst back to the first scanline, next short. ! 258: * Decrement src back to the first scanline, next short. ! 259: * Reset the number of scanlines (height). ! 260: * ENDFOR ! 261: * IF the number of destination shorts == the number of ! 262: * shorts wide the src is THEN ! 263: * # We have incremented to the last short in the src ! 264: * # scanline and should not use src+2. ! 265: * FOREACH scanline DO ! 266: * Use the edge macro to combine src inversely shifted, ! 267: * with dst and right mask. ! 268: * Increment the source to the next scanline. ! 269: * Increment the destination to the next scanline. ! 270: * ENDFOR ! 271: * ELSE ! 272: * FOREACH scanline DO ! 273: * Use the edge macro to combine src inversely shifted ! 274: * or'ed with src+2 shifted, with dst and right ! 275: * mask. ! 276: * Increment the source to the next scanline. ! 277: * Increment the destination to the next scanline. ! 278: * ENDFOR ! 279: * ENDIF ! 280: * ENDIF ! 281: * ENDIF ! 282: * ENDIF ! 283: * ENDFOR ! 284: * ! 285: * NOTE: Make sure ch_pad is not added to the last character copied. ! 286: */ ! 287: ! 288: #define CopyText_LOOP(EDGE_OP, OP) { \ ! 289: for (i = ch_count + 1; --i; ) { \ ! 290: if ((c = (int)(*string++)) < font->first || c > font->last) \ ! 291: continue; /* Character is unprintable. */ \ ! 292: if (char_widths[c] > 0) { \ ! 293: shift = bitptr & 0x0F; \ ! 294: start_dst = DIV_BPW(bitptr); \ ! 295: if (((bitptr += char_widths[c]) + ch_pad) > maxbitptr){ \ ! 296: bitptr -= char_widths[c]; \ ! 297: ch_count -= i; \ ! 298: break; /* Overflow: Get out of the loop */ \ ! 299: } \ ! 300: rtmask = rightmask_lib[bitptr & 0x0F]; \ ! 301: src = (u_char *)(chrs_data) + (shorts_per_char * \ ! 302: (c - font->first)); \ ! 303: dst = (u_char *)buf_bm->data + MUL_2(start_dst); \ ! 304: ndst_shorts = DIV_BPW(bitptr - 1) - start_dst + 1; \ ! 305: height = ht_plus1; \ ! 306: if (shift == 0) { \ ! 307: if (ndst_shorts == 1) { \ ! 308: while (--height) { \ ! 309: EDGE_OP(*SRC, *DST, rtmask); \ ! 310: dst += dst_nextline; \ ! 311: src += src_nextline; \ ! 312: } \ ! 313: } else if (ndst_shorts == 2) { \ ! 314: while (--height) { \ ! 315: OP(*SRC, *DST); \ ! 316: EDGE_OP(*SRCPL, *DSTPL, rtmask); \ ! 317: dst += dst_nextline; \ ! 318: src += src_nextline; \ ! 319: } \ ! 320: } else { \ ! 321: height = font->height; \ ! 322: dst_nextcol = (height*dst_nextline) - 2; \ ! 323: src_nextcol = (height*src_nextline) - 2; \ ! 324: height++; \ ! 325: while (--ndst_shorts > 0) { \ ! 326: while (--height) { \ ! 327: OP(*SRC, *DST); \ ! 328: dst += dst_nextline; \ ! 329: src += src_nextline; \ ! 330: } \ ! 331: dst -= dst_nextcol; \ ! 332: src -= src_nextcol; \ ! 333: height = ht_plus1; \ ! 334: } \ ! 335: while (--height) { \ ! 336: EDGE_OP(*SRC, *DST, rtmask); \ ! 337: dst += dst_nextline; \ ! 338: src += src_nextline; \ ! 339: } \ ! 340: } \ ! 341: } else { \ ! 342: leftmask = leftmask_lib[shift]; \ ! 343: if (ndst_shorts == 1) { \ ! 344: leftmask &= rtmask; \ ! 345: while (--height) { \ ! 346: EDGE_OP((*SRC >> shift), *DST, leftmask); \ ! 347: dst += dst_nextline; \ ! 348: src += src_nextline; \ ! 349: } \ ! 350: } else if (ndst_shorts == 2) { \ ! 351: inv_shift = BPW - shift; \ ! 352: if (chrs_nshorts == 1) { \ ! 353: while (--height) { \ ! 354: EDGE_OP((*SRC >> shift), *DST, leftmask); \ ! 355: EDGE_OP(*(SRC) << inv_shift, *(DSTPL), rtmask); \ ! 356: dst += dst_nextline; \ ! 357: src += src_nextline; \ ! 358: } \ ! 359: } else { \ ! 360: while (--height) { \ ! 361: EDGE_OP((*SRC >> shift), *DST, leftmask); \ ! 362: EDGE_OP((*SRC<<inv_shift)|(*(SRCPL)>>shift), \ ! 363: *(DSTPL), rtmask); \ ! 364: dst += dst_nextline; \ ! 365: src += src_nextline; \ ! 366: } \ ! 367: } \ ! 368: } else { \ ! 369: height = font->height; \ ! 370: dst_nextcol = (height*dst_nextline) - 2; \ ! 371: src_nextcol = (height*src_nextline) - 2; \ ! 372: height++; \ ! 373: while (--height) { \ ! 374: EDGE_OP((*SRC >> shift), *DST, leftmask); \ ! 375: dst += dst_nextline; \ ! 376: src += src_nextline; \ ! 377: } \ ! 378: dst -= dst_nextcol; \ ! 379: src -= (src_nextcol + 2); \ ! 380: inv_shift = BPW - shift; \ ! 381: nsrc_shorts = ndst_shorts - 1; \ ! 382: while (--ndst_shorts > 1) { \ ! 383: height = ht_plus1; \ ! 384: while (--height) { \ ! 385: OP((*SRC<<inv_shift)|(*(SRCPL)>>shift),*DST); \ ! 386: dst += dst_nextline; \ ! 387: src += src_nextline; \ ! 388: } \ ! 389: dst -= dst_nextcol; \ ! 390: src -= src_nextcol; \ ! 391: } \ ! 392: height = ht_plus1; \ ! 393: if (nsrc_shorts == chrs_nshorts) { \ ! 394: while (--height) { \ ! 395: EDGE_OP((*SRC << inv_shift), *DST, rtmask); \ ! 396: dst += dst_nextline; \ ! 397: src += src_nextline; \ ! 398: } \ ! 399: } else { \ ! 400: while (--height) { \ ! 401: EDGE_OP((*SRC << inv_shift) | (*(SRCPL) >> \ ! 402: shift), *DST, rtmask); \ ! 403: dst += dst_nextline; \ ! 404: src += src_nextline; \ ! 405: } \ ! 406: } \ ! 407: } \ ! 408: } \ ! 409: bitptr += ch_pad; \ ! 410: } \ ! 411: if (c == font->space) { \ ! 412: if ((bitptr += sp_pad) > maxbitptr) { \ ! 413: bitptr -= sp_pad; \ ! 414: ch_count -= i; \ ! 415: break; /* Overflow: Get out of the loop. */ \ ! 416: } \ ! 417: } \ ! 418: } \ ! 419: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.