|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T b ┃
Length: 25046 (0x61d6) Types: TextFile Names: »bitblt.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z« └─⟦2109abc41⟧ └─ ⟦this⟧ »./X.V10R4/libibm/bitblt/bitblt.c«
#ifndef lint static char *rcsid_bitblt_c = "$Header: bitblt.c,v 10.1 86/11/19 10:50:19 jg Exp $"; #endif lint /* * Copyright (c) 1986 Brown University * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies, and that both * that copyright notice and this permission notice appear in supporting * documentation, and that the name of Brown University not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Brown University makes no * representations about the suitability of this software for any purpose. * It is provided "as-is" without express or implied warranty. * * Written by Daniel Stone, Brown University/IRIS November 21, 1985 and * "enhanced" a number of times since. * * ABOUT BITBLT.C: This program and related 'C' files (bitblt_int.h, * bitblt_subr.c, bitblt_apa16.c, bitblt_apa16.h) were originally written to go * into the Unix 4.2 kernel as a "bitblt" driver. Later we were able * to put in some ifdef's and use it for Smalltalk and X. Whatever * version you have, there may be some strange ifdef's that may not * make any sense at all. We tried to remove all ifdef's not relevant * to the system being compiled but then no one's perfect. * Also some strange things are done to support the APA8, APA8C and the AED * (viking). You will encounter ifdef's for all these things. if you define * all the screens (-DAED -DAPA8 -DAPA16 ... on the compile line) the bitblt * routine will work on every screen. */ #include "bitblt_int.h" #ifdef USE_APA16_HDWR #include "bitblt_apa16.h" #endif #ifdef BLT_DEBUG int blt_debug = 0; #endif #define MSK_SKEW 0x01 #define SRC_SKEW 0x02 Blt_sysdata blt_info; /* internal variables used by bitblt() */ Blt_Rectangle changed_rect; /* describes the area changed by the bltter */ /* * Array of short masks used to compute the masks to mask out the edges * of the destination that should not be affected. A one means that bit * in the destination can be changed. The values in leftMasks are set up * to be used with the left edge and the values in rightMasks are to be used * in right edge. */ static unsigned short leftMasks[] = { 0xffff,0x7fff,0x3fff,0x1fff,0x0fff,0x07ff,0x03ff,0x01ff, 0x00ff,0x007f,0x003f,0x001f,0x000f,0x0007,0x0003,0x0001, 0x0000 }; static unsigned short rightMasks[] = { 0xffff,0x8000,0xc000,0xe000,0xf000,0xf800,0xfc00,0xfe00, 0xff00,0xff80,0xffc0,0xffe0,0xfff0,0xfff8,0xfffc,0xfffe, 0x0000 }; static Blt_Tile white = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static Blt_Tile black = { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }; /* * Defines used to indicate whether 1 or 2 source words are needed to make * the first destination word. * NOTE: Changing the value of MUST_PRIME may have bad side effects because * the variable "preload_src" is added to something in calculateOffsets. * THIS IS SEMI-HOOKY BUT IT WORKS. */ #define MUST_PRIME 1 #define DONT_PRIME 0 #define SAVE_LOCATOR() { \ if (blt_cur_screen.cursortype & SOFT_CURSOR) { \ saved_loc = 0; \ if (IS_SCREEN(u_info->dst_bitmap)) { \ if (sys_info->is_src && IS_SCREEN(u_info->src_bitmap)){\ saved_loc = 1; \ save_cursor(MIN(sys_info->dst.rect.origin_x, \ sys_info->src.rect.origin_x), \ MIN(sys_info->dst.rect.origin_y, \ sys_info->src.rect.origin_y), \ MAX(sys_info->dst.rect.corner_x, \ sys_info->src.rect.corner_x)+1,\ MAX(sys_info->dst.rect.corner_y, \ sys_info->src.rect.corner_y)+1);\ } \ else { \ saved_loc = 1; \ save_cursor(sys_info->dst.rect.origin_x, \ sys_info->dst.rect.origin_y, \ sys_info->dst.rect.corner_x + 1, \ sys_info->dst.rect.corner_y + 1);\ } \ } \ else if (sys_info->is_src && IS_SCREEN(u_info->src_bitmap)) { \ saved_loc = 1; \ save_cursor(sys_info->src.rect.origin_x, \ sys_info->src.rect.origin_y, \ sys_info->src.rect.corner_x + 1, \ sys_info->src.rect.corner_y + 1); \ } \ } \ } #define RESTORE_LOCATOR() { \ if ((blt_cur_screen.cursortype & SOFT_CURSOR) && saved_loc) { \ restore_cursor(); \ } \ } /* * Macros to calculate the skew and preload flag depending on the direction * of the blt. */ #define computeSkewPos(SI) { \ if ((MOD_BPW(SI->dst.rect.origin_x))<(MOD_BPW(SI->src.rect.origin_x))){\ SI->skew_src = MOD_BPW(SI->src.rect.origin_x) - \ MOD_BPW(SI->dst.rect.origin_x); \ SI->preload_src = MUST_PRIME; \ } \ else { \ SI->skew_src = BPW - (MOD_BPW(SI->dst.rect.origin_x) - \ MOD_BPW(SI->src.rect.origin_x)); \ SI->preload_src = DONT_PRIME; \ } \ } #define computeSkewMskPos(SI) { \ if ((MOD_BPW(SI->dst.rect.origin_x))<(MOD_BPW(SI->msk.rect.origin_x))){\ SI->skew_msk = MOD_BPW(SI->msk.rect.origin_x) - \ MOD_BPW(SI->dst.rect.origin_x); \ SI->preload_msk = MUST_PRIME; \ } \ else { \ SI->skew_msk = BPW - (MOD_BPW(SI->dst.rect.origin_x) - \ MOD_BPW(SI->msk.rect.origin_x)); \ SI->preload_msk = DONT_PRIME; \ } \ } #define computeSkewNeg(SI) { \ if ((MOD_BPW(SI->dst.rect.corner_x))>(MOD_BPW(SI->src.rect.corner_x))){\ SI->skew_src = MOD_BPW(SI->dst.rect.corner_x) - \ MOD_BPW(SI->src.rect.corner_x); \ SI->preload_src = MUST_PRIME; \ } \ else { \ SI->skew_src = BPW - (MOD_BPW(SI->src.rect.corner_x) - \ MOD_BPW(SI->dst.rect.corner_x)); \ SI->preload_src = DONT_PRIME; \ } \ } #define computeSkewMskNeg(SI) { \ if ((MOD_BPW(SI->dst.rect.corner_x))>(MOD_BPW(SI->msk.rect.corner_x))){\ SI->skew_msk = MOD_BPW(SI->dst.rect.corner_x) - \ MOD_BPW(SI->msk.rect.corner_x); \ SI->preload_msk = MUST_PRIME; \ } \ else { \ SI->skew_msk = BPW - (MOD_BPW(SI->msk.rect.corner_x) - \ MOD_BPW(SI->dst.rect.corner_x)); \ SI->preload_msk = DONT_PRIME; \ } \ } /* * Make a mask for the first and last destination word in each scanline. * 1's mean those bits can be changed in the destination. * Combine the masks if only one destination word is effected and set * BOTH masks equal to it so as not to screw up copyBitNeg. * * NOTE: The +1 with dst.rect.corner_x. This is because dst.rect.corner_x was * set to the rectangle size -1. (see blt_setup()) */ #define computeMasks(SI) { \ if (SI->nshorts == 1) { \ SI->right_mask = SI->left_mask = \ leftMasks[MOD_BPW(SI->dst.rect.origin_x)] &\ rightMasks[MOD_BPW(SI->dst.rect.corner_x+1)];\ } \ else { \ SI->left_mask = leftMasks[MOD_BPW(SI->dst.rect.origin_x)];\ SI->right_mask = rightMasks[MOD_BPW(SI->dst.rect.corner_x+1)];\ } \ } /* * CheckOverlap checks for overlapping source and destination. * (See checkOverlap in Smalltalk-80) It set SI->top_to_bot to * non-zero if we must copy from bottom to top, right to left * instead of top to bottom, left to right. * * NOTE: The +1 for both src.rect.corner_y and src.rect.corner_x this is because * these local variables have "closed" corners. (See blt_setup()) * * IF the destination and source have the same bitmap * AND * TEST AREA 1 OR TEST AREA 2 * THEN * (We must copy from right to left bottom to top) * * TEST AREA 1: The destination top is GREATER than or EQUAL to the * source top and its less than the source bottom * (src.rect.origin_y <= dst.rect.origin_y < src.rect.corner_y+1) AND * the destination left is greater than or equal to * the source left and its less than the source right. * (src.rect.origin_x <= dst.rect.origin_x < src.rect.corner_x+1) * IN OTHER WORDS, the top left corner of the destination * is in the source area. * * TEST AREA 2: The destination top is GREATER than the source top * and its less than the source bottom: * (src.rect.origin_y < dst.rect.origin_y < src.rect.corner_y+1) * AND the source left is greater than the destination left * and its less than the destination right. * (dst.rect.origin_x < src.rect.origin_x < dst.rect.corner_x+1) * IN OTHER WORDS, the top horizontal line of the destination * intersects the left vertical line of the source, causing * the right top corner of the destination to be in the * source. * * src.rect.origin_x * src.rect.origin_y +---------------------------- * src.rect.origin_y - 1 -----------------------| * | * TEST AREA 2 | TEST AREA 1 * | * | * src.rect.corner_y+1 ------------------------------------------------ */ #define checkOverlap(UI,SI) \ SI->top_to_bot = ((UI->src_bitmap.base == UI->dst_bitmap.base) \ && (((SI->src.rect.origin_y <= SI->dst.rect.origin_y &&\ SI->dst.rect.origin_y < (SI->src.rect.corner_y+1))\ && (SI->src.rect.origin_x <= SI->dst.rect.origin_x && \ SI->dst.rect.origin_x < (SI->src.rect.corner_x+1)))\ || ((SI->src.rect.origin_y < SI->dst.rect.origin_y && \ SI->dst.rect.origin_y < (SI->src.rect.corner_y+1))\ && (SI->dst.rect.origin_x < SI->src.rect.origin_x && \ SI->src.rect.origin_x < (SI->dst.rect.corner_x+1))))) /* * CalculateOffsetDst sets up pointers to a word in the destination and * possibly to the mask bitmap using the dst_x,dst_y points given. * It calculates the increment for each pointer from the end of one * rectangle scanline to the beginning of the next. */ calculateOffsetDst(u_info,s_info,dst_x,dst_y) register Blt_userdata *u_info; register Blt_sysdata *s_info; short dst_x,dst_y; /* top,left or bottom,right */ { /* * Set up the destination pointer and increment. * NOTE that (dst_y * u_info->dst_bitmap.nshorts) + DIV_BPW(dst_x) * gives the WORD offset to base. Since we need the byte address * this quantity must be multiplied by 2 (MUL_2). * * Set up destination to point to a word offset from the base address. */ #if (APA8 || APA8C) if (IS_APA8orAPA8C(u_info->dst_bitmap)) { s_info->dst_plus = 4; s_info->dst.data = (unsigned short *)( (long)u_info->dst_bitmap.base + MUL_4((dst_y * u_info->dst_bitmap.nshorts) + DIV_BPW(dst_x))); s_info->dst.nextline = MUL_4(u_info->dst_bitmap.nshorts - s_info->nshorts + 1); } else { s_info->dst_plus = 2; s_info->dst.data = (unsigned short *)( (long)u_info->dst_bitmap.base + MUL_2((dst_y * u_info->dst_bitmap.nshorts) + DIV_BPW(dst_x))); s_info->dst.nextline = MUL_2(u_info->dst_bitmap.nshorts - s_info->nshorts + 1); } #else no APA8 stuff s_info->dst.data = (unsigned short *)((long)u_info->dst_bitmap.base + MUL_2((dst_y * u_info->dst_bitmap.nshorts) + DIV_BPW(dst_x))); /* * NOTE: This increment shows the increment for the number of BYTES. */ s_info->dst.nextline = MUL_2(u_info->dst_bitmap.nshorts - s_info->nshorts + 1); #endif APA8 /* * Set up the masking bitmap (if given) to point to a word * offset from the base address. */ if (u_info->blt_flags & BLT_MASKON) { /* * Calculate the shift amount (skew) that is needed * to align a word in the mask bitmap with a word * in the destination. */ if (s_info->top_to_bot) { computeSkewMskNeg(s_info); /* * Calculate the mask pointer. */ s_info->msk.data = (unsigned short *)( (long)(u_info->msk_bitmap.base) + MUL_2((s_info->msk.rect.corner_y * u_info->msk_bitmap.nshorts) + DIV_BPW(s_info->msk.rect.corner_x))); } else { computeSkewMskPos(s_info); /* * Calculate the mask pointer. */ s_info->msk.data = (unsigned short *)( (long)(u_info->msk_bitmap.base) + MUL_2((s_info->msk.rect.origin_y * u_info->msk_bitmap.nshorts) + DIV_BPW(s_info->msk.rect.origin_x))); } /* * Calculate the mask increment. */ s_info->msk.nextline = MUL_2( u_info->msk_bitmap.nshorts - (s_info->nshorts + s_info->preload_msk) + 1); } else { s_info->msk.data = (unsigned short *)0; s_info->msk.nextline = 0; } } /* * CalculateOffsetSrcNeg sets up pointers to the last word in the * source. It also determines if "priming" must be done. * (i.e. 2 words of source are needed for the first word of the destination.) * When going from right to left this happens when for example you have * 3 bits in the source (at the end of the line) (0-2) and 5 bits to fill * in the destination (0-4). One must take those 3 bits from the source * and put them in 2-4 in the destination and increment the source. * * It then calculates the increment for the source. */ #if (APA8 || APA8C) #define calculateOffsetSrcNeg(UI,SI) { \ if (IS_APA8orAPA8C(UI->src_bitmap)) { \ SI->src_plus = 4; \ SI->src.data = (unsigned short *)((long)(UI->src_bitmap.base) +\ MUL_4((SI->src.rect.corner_y * \ UI->src_bitmap.nshorts) + \ DIV_BPW(SI->src.rect.corner_x)));\ SI->src.nextline = MUL_4(UI->src_bitmap.nshorts - \ (SI->nshorts+SI->preload_src) + 1);\ } \ else { \ SI->src_plus = 2; \ SI->src.data = (unsigned short *)((long)(UI->src_bitmap.base) +\ MUL_2((SI->src.rect.corner_y * \ UI->src_bitmap.nshorts) + \ DIV_BPW(SI->src.rect.corner_x))); \ SI->src.nextline = MUL_2(UI->src_bitmap.nshorts - \ (SI->nshorts + SI->preload_src) + 1);\ } \ } #else no APA8 stuff #define calculateOffsetSrcNeg(UI,SI) { \ SI->src.data = (unsigned short *)((long)(UI->src_bitmap.base) + \ MUL_2((SI->src.rect.corner_y * UI->src_bitmap.nshorts) +\ DIV_BPW(SI->src.rect.corner_x))); \ SI->src.nextline = MUL_2(UI->src_bitmap.nshorts - \ (SI->nshorts+SI->preload_src) + 1); \ } #endif /* * CalculateOffsetSrcPos sets up pointers to the first word in the * source. It also determines if "priming" must be done. (i.e. 2 words * of source are needed for the first word of the destination.) * When going from left to right this happens when for example you have * 3 bits in the source (13-15) and 5 bits to fill in the destination (11-15). * One must take those 3 bits from the source and put them in 11-13 * and then increment the source. * * It then calculates the increment for the source. */ #if (APA8 || APA8C) #define calculateOffsetSrcPos(UI,SI) { \ if (IS_APA8orAPA8C(UI->src_bitmap)) { \ SI->src_plus = 4; \ SI->src.data = (unsigned short *)((long)UI->src_bitmap.base + \ MUL_4((SI->src.rect.origin_y * \ UI->src_bitmap.nshorts) + \ DIV_BPW(SI->src.rect.origin_x)));\ SI->src.nextline = MUL_4(UI->src_bitmap.nshorts - \ (SI->nshorts + SI->preload_src) + 1);\ } \ else { \ SI->src_plus = 2; \ SI->src.data = (unsigned short *)((long)UI->src_bitmap.base +\ MUL_2((SI->src.rect.origin_y * \ UI->src_bitmap.nshorts) + \ DIV_BPW(SI->src.rect.origin_x))); \ SI->src.nextline = MUL_2(UI->src_bitmap.nshorts - \ (SI->nshorts+SI->preload_src) + 1); \ } \ } #else no APA8 stuff #define calculateOffsetSrcPos(UI,SI) { \ SI->src.data = (unsigned short *)((long)UI->src_bitmap.base + \ MUL_2((SI->src.rect.origin_y * UI->src_bitmap.nshorts) +\ DIV_BPW(SI->src.rect.origin_x))); \ SI->src.nextline = MUL_2(UI->src_bitmap.nshorts - \ (SI->nshorts+SI->preload_src) + 1); \ } #endif /* * Set up destination offsets. */ #define calculateOffsetDstNeg(UI,SI) calculateOffsetDst(UI,SI, \ SI->dst.rect.corner_x,\ SI->dst.rect.corner_y) #define calculateOffsetDstPos(UI,SI) calculateOffsetDst(UI,SI, \ SI->dst.rect.origin_x, \ SI->dst.rect.origin_y) /* * If a rule specifies the type of tile to be used then set tile_ptr. * If tile_ptr has already been set then don't change it. */ #define calculateOffsetTile(UI,SI) { \ if (SI->rule == DstClear || SI->rule == TileDstClear) { \ SI->tile_ptr = &white.tile[0]; \ } \ else if (SI->rule == DstSet || SI->rule == TileDstSet \ || SI->rule == NotDstCopy) { \ SI->tile_ptr = &black.tile[0]; \ } \ else if (SI->tile_ptr == (unsigned short *)0){ \ SI->tile_ptr = (unsigned short *)UI->tile_ptr; \ } \ } /* * Do the bit block transfer using the information in u_info. Return -1 if * bad pointers are given, 0 if the area clipped down to a null blt and 1 if * the "bitblt" was done. */ bitblt(u_info) register Blt_userdata *u_info; { register Blt_sysdata *sys_info = &blt_info; register tmp; register saved_loc; int blt_status; DEBUGF((blt_debug > 1),printf("Enter bitblt.\r\n")); /* * Set up to do this blt. blt_setup does clipping if necessary, sets * up either the source or tile (depending on the combination rule * being used) and sets the width and height of the blt. It returns * zero if the blt is to be done. */ if ((blt_status = blt_setup(u_info,sys_info)) != 1) { /* * Bad pointers or the combination rule was such that nothing * has to be done. */ return(blt_status); } else if (sys_info->width <= 0 || sys_info->height <= 0) { /* * Nothing to do. */ return(0); } #ifdef USE_APA16_HDWR /* * Are we using hardware?? This is for debugging purposes, we * know the software works so to test the hardware stuff we have this * flag in blt_flags. However if we are using a mask bitmap then * the hardware can not be used. */ if ((u_info->blt_flags & BLT_MASKON) == 0) { register int ret_flag; /* Hardware return flag */ /* * One can only use the hardware assist if the destination * bitmap is the screen. */ ret_flag = 1; if (IS_APA16(u_info->dst_bitmap)) { extern unsigned short execute_cmd[]; /* * Check and see if there is a hardware function * (execute command) for this rule. */ if (execute_cmd[sys_info->rule]) { if (sys_info->is_src) { if (IS_APA16(u_info->src_bitmap)) { /* * Pass in the pointers to * the screen because if they * are greater than the first * byte address in the APA16 * buffer things will not * work. */ sys_info->dst.data = u_info->dst_bitmap.base; sys_info->src.data = u_info->src_bitmap.base; ret_flag = apa16_StoS(sys_info); } else { /* * The APA-16 does memory to * screen stuff. But first * The source address and * and the source "nextline" * field must also be * calculated. * * NOT IMPLEMENTED YET. * * computeSkewPos(sys_info); * calculateOffsetSrcPos(u_info, * sys_info); * ret_flag = * apa16_MtoS(sys_info); */ } } else { /* * The tile ptr has not been set up yet. */ sys_info->tile_ptr = (unsigned short *) u_info->tile_ptr; ret_flag = apa16_copyTile(sys_info); } /* * Check the status of the hardware blt, if * its 0 then everything was done successfully. */ if (ret_flag == 0) { /* * Indicate that a blt was done. */ return(1); } } } } /* * Regardless of the hardware flag, if we get here it means * that we are going to use the software to blt. If the screen * is to be changed then we must wait for the rasterop engine to finish * with the screen if it is still using the screen. */ if (*QUE_COUNT_R != 0) { if (IS_APA16(u_info->dst_bitmap) || (IS_APA16(u_info->src_bitmap))) { WAIT_QUE(tmp,0); } } #endif USE_APA16_HDWR #ifdef AED /* * If this is a screen to screen blt on the AED have the microcode * make the screen changes while the bltter alters the * offscreen bitmap. */ if (IS_AED(u_info->src_bitmap) && IS_AED(u_info->dst_bitmap) && (u_info->blt_flags & BLT_ECHO)) { aed_screen_copy(sys_info->src.rect.origin_x, sys_info->src.rect.origin_y, sys_info->dst.rect.origin_x, sys_info->dst.rect.origin_y, (short) sys_info->width, (short) sys_info->height, sys_info->rule); blt_status = 0; } #endif AED /* * Remove the locator from the screen if it is a software locator that * is actually in (on) the source or destination bitmap. Hardware * locators (as in the APA-16) are not removed. */ SAVE_LOCATOR(); /* * Calculate the edge masks for the destination. (See computeMasks * in Smalltalk-80) */ computeMasks(sys_info); /* * If the source is to be used then things will be done differently * than if a tile is used. */ if (sys_info->is_src) { /* * Check for overlapping source and destination. (See * checkOverlap in Smalltalk-80) Sets sys_info->top_to_bot * non-zero if we must copy from bottom to top, right to * left instead of top to bottom, left to right. */ checkOverlap(u_info,sys_info); if (sys_info->top_to_bot) { /* * Calculate the shift amount (skew) that is needed * to align a word in the source with a word in the * destination. */ computeSkewNeg(sys_info); /* * Set up pointers to the source, destination * and possibly to the mask bitmap. Also set up * shift amounts (skews) for the mask bitmap if needed. * Calculate the increment for each pointer from * the end of one rectangle scanline to the beginning * of the next. */ calculateOffsetSrcNeg(u_info,sys_info); calculateOffsetDstNeg(u_info,sys_info); /* * Do the blt from bottom to top, right to left!! */ if (u_info->blt_flags & BLT_MASKON) { maskBitNeg(sys_info); } else { /* * Just copy from source to destination * going bottom to top, right to left. * No mask bitmap to worry about. */ copyBitNeg(sys_info); } } else { /* * Calculate the shift amount (skew) that is needed * to align a word in the source with a word in the * destination. */ computeSkewPos(sys_info); /* * Set up pointers to the source, destination * and possibly to the mask bitmap. * Also set up shift amounts (skews) for the mask * bitmap if needed. Calculate the increment for * each pointer from the end of one rectangle * scanline to the beginning of the next. */ calculateOffsetSrcPos(u_info,sys_info); calculateOffsetDstPos(u_info,sys_info); /* * Do the blt from top to bottom, left to right!! */ if (u_info->blt_flags & BLT_MASKON) { /* * Copy from source to destination going * top to bottom, left to right. Use the * mask bitmap. */ maskBitPos(sys_info); } else { /* * Just copy from source to destination * going top to bottom, left to right. */ if (sys_info->nshorts < 3) { /* * Optimize this very important routine * for one and two shorts in the dst * changed. */ smallcopyBitPos(sys_info); } else { copyBitPos(sys_info); } } } } else { /* * We have a TILE rule. */ sys_info->top_to_bot = 0; /* * Set up pointers to the tile and destination and possibly * to the mask bitmap. Calculate the increment for * each pointer from the end of one rectangle scanline to * the beginning of the next. * NOTE: The pointer to the tile may have been set in * blt_setup. */ calculateOffsetTile(u_info,sys_info); calculateOffsetDstPos(u_info,sys_info); /* * Do the tile blt! */ if (u_info->blt_flags & BLT_MASKON) { maskTile(sys_info); } else { copyTile(sys_info); } } /* * Restore the locator if the screen was dealt with. */ RESTORE_LOCATOR(); #ifdef AED /* * If we are echoing to AED, keep track of bounding * rectangle of the updated screen area. */ if (IS_AED(u_info->dst_bitmap) && blt_status && (u_info->blt_flags & BLT_ECHO)) { aed_echo_rect(&changed_rect); } #endif AED /* * Indicate that a blt was done. */ return(1); }