|
|
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.