diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:52 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:52 +0000 |
commit | 9711ac0a780f686806c135045d2db9b99fbe923f (patch) | |
tree | 422a11eba052ec8e1923dcd458943fcdd8d70d04 /Graphics.c |
R6.6 is the Xorg base-lineXORG-MAIN
Diffstat (limited to 'Graphics.c')
-rw-r--r-- | Graphics.c | 1602 |
1 files changed, 1602 insertions, 0 deletions
diff --git a/Graphics.c b/Graphics.c new file mode 100644 index 0000000..918b7c3 --- /dev/null +++ b/Graphics.c @@ -0,0 +1,1602 @@ +/* $Xorg: Graphics.c,v 1.4 2001/02/09 02:05:28 xorgcvs Exp $ */ +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Davor Matic, MIT X Consortium + */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xfuncs.h> +#include "BitmapP.h" + +#include <stdio.h> +#include <math.h> + +#ifndef abs +#define abs(x) (((x) > 0) ? (x) : -(x)) +#endif +#define min(x, y) (((int)(x) < (int)(y)) ? (x) : (y)) +#define max(x, y) (((int)(x) > (int)(y)) ? (x) : (y)) +#ifndef rint +#define rint(x) floor(x + 0.5) +#endif + +/*****************************************************************************\ + * Graphics * +\*****************************************************************************/ + +#define GetBit(image, x, y)\ + ((bit)((*(image->data + (x) / 8 + (y) * image->bytes_per_line) &\ + (1 << ((x) % 8))) ? 1 : 0)) + + +bit BWGetBit(w, x, y) + Widget w; + Position x, y; +{ + BitmapWidget BW = (BitmapWidget) w; + + if (QueryInBitmap(BW, x, y)) + return GetBit(BW->bitmap.image, x, y); + else + return NotSet; +} + + +#define InvertBit(image, x, y)\ + (*(image->data + (x) / 8 + (y) * image->bytes_per_line) ^=\ + (bit) (1 << ((x) % 8))) + + +#define SetBit(image, x, y)\ + (*(image->data + (x) / 8 + (y) * image->bytes_per_line) |=\ + (bit) (1 << ((x) % 8))) + +#define ClearBit(image, x, y)\ + (*(image->data + (x) / 8 + (y) * image->bytes_per_line) &=\ + (bit)~(1 << ((x) % 8))) + + +#define HighlightSquare(BW, x, y)\ + XFillRectangle(XtDisplay(BW), XtWindow(BW),\ + BW->bitmap.highlighting_gc,\ + InWindowX(BW, x), InWindowY(BW, y),\ + BW->bitmap.squareW, BW->bitmap.squareH) +/* +void HighlightSquare(BW, x, y) + BitmapWidget BW; + Position x, y; +{ + XFillRectangle(XtDisplay(BW), XtWindow(BW), + BW->bitmap.highlighting_gc, + InWindowX(BW, x), InWindowY(BW, y), + BW->bitmap.squareW, BW->bitmap.squareH); +} +*/ + +#define DrawSquare(BW, x, y)\ + XFillRectangle(XtDisplay(BW), XtWindow(BW),\ + BW->bitmap.drawing_gc,\ + InWindowX(BW, x), InWindowY(BW, y),\ + BW->bitmap.squareW, BW->bitmap.squareH) + +/* +void DrawSquare(BW, x, y) + BitmapWidget BW; + Position x, y; +{ + XFillRectangle(XtDisplay(BW), XtWindow(BW), + BW->bitmap.drawing_gc, + InWindowX(BW, x), InWindowY(BW, y), + BW->bitmap.squareW, BW->bitmap.squareH); +} +*/ + +#define InvertPoint(BW, x, y)\ + {InvertBit(BW->bitmap.image, x, y); DrawSquare(BW, x, y);} + +#define DrawPoint(BW, x, y, value)\ + if (GetBit(BW->bitmap.image, x, y) != value)\ + InvertPoint(BW, x, y) + +void BWDrawPoint(w, x, y, value) + Widget w; + Position x, y; + bit value; +{ + BitmapWidget BW = (BitmapWidget) w; + + if (QueryInBitmap(BW, x, y)) { + if (value == Highlight) + HighlightSquare(BW, x, y); + else + DrawPoint(BW, x, y, value); + } +} + +XPoint *HotSpotShape(BW, x ,y) + BitmapWidget BW; + Position x, y; +{ + static XPoint points[5]; + + points[0].x = InWindowX(BW, x); + points[0].y = InWindowY(BW, y + 1.0/2); + points[1].x = InWindowX(BW, x + 1.0/2); + points[1].y = InWindowY(BW, y + 1); + points[2].x = InWindowX(BW, x + 1); + points[2].y = InWindowY(BW, y + 1.0/2); + points[3].x = InWindowX(BW, x + 1.0/2); + points[3].y = InWindowY(BW, y); + points[4].x = InWindowX(BW, x); + points[4].y = InWindowY(BW, y + 1.0/2); + + return points; +} + +#define DrawHotSpot(BW, x, y)\ + XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.drawing_gc,\ + HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin) + +#define HighlightHotSpot(BW, x, y)\ + XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,\ + HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin) + +XImage *CreateBitmapImage(); +void DestroyBitmapImage(); + +void BWRedrawHotSpot(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) + DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y); +} + +void BWClearHotSpot(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) { + DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y); + BW->bitmap.hot.x = BW->bitmap.hot.y = NotSet; + } +} + +void BWDrawHotSpot(w, x, y, value) + Widget w; + Position x, y; + int value; +{ + BitmapWidget BW = (BitmapWidget) w; + + if (QueryInBitmap(BW, x, y)) { + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) && + ((BW->bitmap.hot.x == x) && (BW->bitmap.hot.y == y))) { + if ((value == Clear) || (value == Invert)) { + BWClearHotSpot(w); + } + } + else + if ((value == Set) || (value == Invert)) { + BWClearHotSpot(w); + DrawHotSpot(BW, x, y); + BW->bitmap.hot.x = x; + BW->bitmap.hot.y = y; + } + + if (value == Highlight) + HighlightHotSpot(BW, x, y); + } +} + +void BWSetHotSpot(w, x, y) + Widget w; + Position x, y; +{ + if (QuerySet(x, y)) + BWDrawHotSpot(w, x, y, Set); + else + BWClearHotSpot(w); +} + +/* high level procedures */ + +void BWRedrawSquares(w, x, y, width, height) + Widget w; + register Position x, y; + Dimension width, height; +{ + BitmapWidget BW = (BitmapWidget) w; + Position from_x = InBitmapX(BW, x); + Position from_y = InBitmapY(BW, y); + Position to_x = InBitmapX(BW, x + width); + Position to_y = InBitmapY(BW, y + height); + + QuerySwap(from_x, to_x); + QuerySwap(from_y, to_y); + from_x = max(0, from_x); + from_y = max(0, from_y); + to_x = min(BW->bitmap.image->width - 1, to_x); + to_y = min(BW->bitmap.image->height - 1, to_y); + + for (x = from_x; x <= to_x; x++) + for (y = from_y; y <= to_y; y++) + if (GetBit(BW->bitmap.image, x, y)) DrawSquare(BW, x, y); +} + +void BWDrawGrid(w, from_x, from_y, to_x, to_y) + Widget w; + Position from_x, from_y, + to_x, to_y; +{ + BitmapWidget BW = (BitmapWidget) w; + int i; + + QuerySwap(from_x, to_x); + QuerySwap(from_y, to_y); + from_x = max(0, from_x); + from_y = max(0, from_y); + to_x = min(BW->bitmap.image->width - 1, to_x); + to_y = min(BW->bitmap.image->height - 1, to_y); + + for(i = from_x + (from_x == 0); i <= to_x; i++) + XDrawLine(XtDisplay(BW), XtWindow(BW), + BW->bitmap.frame_gc, + InWindowX(BW, i), InWindowY(BW, from_y), + InWindowX(BW, i), InWindowY(BW, to_y + 1)); + + for(i = from_y + (from_y == 0); i <= to_y; i++) + XDrawLine(XtDisplay(BW), XtWindow(BW), + BW->bitmap.frame_gc, + InWindowX(BW, from_x), InWindowY(BW, i), + InWindowX(BW, to_x + 1), InWindowY(BW, i)); +} + + +void BWRedrawGrid(w, x, y, width, height) + Widget w; + Position x, y; + Dimension width, height; +{ + BitmapWidget BW = (BitmapWidget) w; + Position from_x = InBitmapX(BW, x); + Position from_y = InBitmapY(BW, y); + Position to_x = InBitmapX(BW, x + width); + Position to_y = InBitmapY(BW, y + height); + + if (BW->bitmap.grid) + BWDrawGrid(w, from_x, from_y, to_x, to_y); +} + +void BWDrawLine(w, from_x, from_y, to_x, to_y, value) + Widget w; + Position from_x, from_y, + to_x, to_y; + int value; +{ + Position i; + register double x, y; + double dx, dy, delta; + + dx = to_x - from_x; + dy = to_y - from_y; + x = from_x + 0.5; + y = from_y + 0.5; + delta = max(abs(dx), abs(dy)); + if (delta > 0) { + dx /= delta; + dy /= delta; + for(i = 0; i <= delta; i++) { + BWDrawPoint(w, (Position) x, (Position) y, value); + x += dx; + y += dy; + } + } + else + BWDrawPoint(w, from_x, from_y, value); +} + +void BWBlindLine(w, from_x, from_y, to_x, to_y, value) + Widget w; + Position from_x, from_y, + to_x, to_y; + int value; +{ + Position i; + register double x, y; + double dx, dy, delta; + + dx = to_x - from_x; + dy = to_y - from_y; + x = from_x + 0.5; + y = from_y + 0.5; + delta = max(abs(dx), abs(dy)); + if (delta > 0) { + dx /= delta; + dy /= delta; + x += dx; + y += dy; + for(i = 1; i <= delta; i++) { + BWDrawPoint(w, (Position) x, (Position) y, value); + x += dx; + y += dy; + } + } + else + BWDrawPoint(w, from_x, from_y, value); +} + +void BWDrawRectangle(w, from_x, from_y, to_x, to_y, value) + Widget w; + Position from_x, from_y, + to_x, to_y; + int value; +{ + register Position i; + Dimension delta, width, height; + + QuerySwap(from_x, to_x); + QuerySwap(from_y, to_y); + + width = to_x - from_x; + height = to_y - from_y; + + delta = max(width, height); + + if (!QueryZero(width, height)) { + for (i = 0; (int)i < (int)delta; i++) { + if ((int)i < (int)width) { + BWDrawPoint(w, from_x + i, from_y, value); + BWDrawPoint(w, to_x - i, to_y, value); + } + if ((int)i < (int)height) { + BWDrawPoint(w, from_x, to_y - i, value); + BWDrawPoint(w, to_x, from_y + i, value); + } + } + } + else + BWDrawLine(w, + from_x, from_y, + to_x, to_y, value); +} + +void BWDrawFilledRectangle(w, from_x, from_y, to_x, to_y, value) + Widget w; + Position from_x, from_y, + to_x, to_y; + int value; +{ + register Position x, y; + + QuerySwap(from_x, to_x); + QuerySwap(from_y, to_y); + + for (x = from_x; x <= to_x; x++) + for (y = from_y; y <= to_y; y++) + BWDrawPoint(w, x, y, value); +} + +void BWDrawCircle(w, origin_x, origin_y, point_x, point_y, value) + Widget w; + Position origin_x, origin_y, + point_x, point_y; + int value; +{ + register Position i, delta; + Dimension dx, dy, half; + double radius; + + dx = abs(point_x - origin_x); + dy = abs(point_y - origin_y); + radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy)); + if (radius < 1.0) { + BWDrawPoint(w, origin_x, origin_y, value); + } + else { + BWDrawPoint(w, origin_x - (Position) floor(radius), origin_y, value); + BWDrawPoint(w, origin_x + (Position) floor(radius), origin_y, value); + BWDrawPoint(w, origin_x, origin_y - (Position) floor(radius), value); + BWDrawPoint(w, origin_x, origin_y + (Position) floor(radius), value); + } + half = radius / sqrt(2.0); + for(i = 1; (int)i <= (int)half; i++) { + delta = sqrt(radius * radius - i * i); + BWDrawPoint(w, origin_x - delta, origin_y - i, value); + BWDrawPoint(w, origin_x - delta, origin_y + i, value); + BWDrawPoint(w, origin_x + delta, origin_y - i, value); + BWDrawPoint(w, origin_x + delta, origin_y + i, value); + if (i != delta) { + BWDrawPoint(w, origin_x - i, origin_y - delta, value); + BWDrawPoint(w, origin_x - i, origin_y + delta, value); + BWDrawPoint(w, origin_x + i, origin_y - delta, value); + BWDrawPoint(w, origin_x + i, origin_y + delta, value); + } + } +} + +void BWDrawFilledCircle(w, origin_x, origin_y, point_x, point_y, value) + Widget w; + Position origin_x, origin_y, + point_x, point_y; + int value; +{ + register Position i, j, delta; + Dimension dx, dy; + double radius; + + dx = abs(point_x - origin_x); + dy = abs(point_y - origin_y); + radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy)); + for(j = origin_x - (Position) floor(radius); + j <= origin_x + (Position) floor(radius); j++) + BWDrawPoint(w, j, origin_y, value); + for(i = 1; i <= (Position) floor(radius); i++) { + delta = sqrt(radius * radius - i * i); + for(j = origin_x - delta; j <= origin_x + delta; j++) { + BWDrawPoint(w, j, origin_y - i, value); + BWDrawPoint(w, j, origin_y + i, value); + } + } +} + +#define QueryFlood(BW, x, y, value)\ + ((GetBit(BW->bitmap.image, x, y) !=\ + (value & 1)) && QueryInBitmap(BW, x, y)) + +#define Flood(BW, x, y, value)\ + {if (value == Highlight) HighlightSquare(BW, x, y);\ + else InvertPoint(BW, x, y);} + +/* +void FloodLoop(BW, x, y, value) + BitmapWidget BW; + Position x, y; + int value; +{ + if (QueryFlood(BW, x, y, value)) { + Flood(BW, x, y, value); + FloodLoop(BW, x, y - 1, value); + FloodLoop(BW, x - 1, y, value); + FloodLoop(BW, x, y + 1, value); + FloodLoop(BW, x + 1, y, value); + } +} +*/ + +void FloodLoop(BW, x, y, value) + BitmapWidget BW; + Position x, y; + int value; +{ + Position save_x, save_y, x_left, x_right; + + if (QueryFlood(BW, x, y, value)) + Flood(BW, x, y, value) + + + save_x = x; + save_y = y; + + x++; + while (QueryFlood(BW, x, y, value)) { + Flood(BW, x, y, value); + x++; + } + x_right = --x; + + x = save_x; + x--; + while (QueryFlood(BW, x, y, value)) { + Flood(BW, x, y, value); + x--; + } + x_left = ++x; + + + x = x_left; + y = save_y; + y++; + + while (x <= x_right) { + Boolean flag = False; + Position x_enter; + + while (QueryFlood(BW, x, y, value) && (x <= x_right)) { + flag = True; + x++; + } + + if (flag) { + if ((x == x_right) && QueryFlood(BW, x, y, value)) + FloodLoop(BW, x, y, value); + else + FloodLoop(BW, x - 1, y, value); + } + + x_enter = x; + + while (!QueryFlood(BW, x, y, value) && (x < x_right)) + x++; + + if (x == x_enter) x++; + } + + x = x_left; + y = save_y; + y--; + + while (x <= x_right) { + Boolean flag = False; + Position x_enter; + + while (QueryFlood(BW, x, y, value) && (x <= x_right)) { + flag = True; + x++; + } + + if (flag) { + if ((x == x_right) && QueryFlood(BW, x, y, value)) + FloodLoop(BW, x, y, value); + else + FloodLoop(BW, x - 1, y, value); + } + + x_enter = x; + + while (!QueryFlood(BW, x, y, value) && (x < x_right)) + x++; + + if (x == x_enter) x++; + } +} + +void BWFloodFill(w, x, y, value) + Widget w; + Position x, y; + int value; +{ + BitmapWidget BW = (BitmapWidget) w; + int pixel; + + pixel = GetBit(BW->bitmap.image, x, y); + + if (value == Invert) + FloodLoop(BW, x, y, (pixel ? Clear : Set)); + else if (value != pixel) + FloodLoop(BW, x, y, value); +} + +#define QueryHotInMark(BW)\ + ((BW->bitmap.hot.x == max(BW->bitmap.mark.from_x,\ + min(BW->bitmap.hot.x, BW->bitmap.mark.to_x)))\ + &&\ + (BW->bitmap.hot.y == max(BW->bitmap.mark.from_y,\ + min(BW->bitmap.hot.y, BW->bitmap.mark.to_y)))) + +void BWUp(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + register Position x, y; + bit first, up, down; + Position from_x, from_y, to_x, to_y; + + if (BWQueryMarked(w)) { + from_x = BW->bitmap.mark.from_x; + from_y = BW->bitmap.mark.from_y; + to_x = BW->bitmap.mark.to_x; + to_y = BW->bitmap.mark.to_y; + } + else { + from_x = 0; + from_y = 0; + to_x = BW->bitmap.width - 1; + to_y = BW->bitmap.height - 1; + } + + if ((to_y - from_y) == 0) + return; + + for(x = from_x; x <= to_x; x++) { + first = up = GetBit(BW->bitmap.image, x, to_y); + for(y = to_y - 1; y >= from_y; y--) { + down = GetBit(BW->bitmap.image, x, y); + if (up != down) + InvertPoint(BW, x, y); + up =down; + } + if(first != down) + InvertPoint(BW, x, to_y); + } + + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) + && + !BWQueryMarked(w)) + BWSetHotSpot(w, + BW->bitmap.hot.x, + (BW->bitmap.hot.y - 1 + BW->bitmap.image->height) % + BW->bitmap.image->height); + +} + +void BWDown(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + register Position x, y; + bit first, down, up; + Position from_x, from_y, to_x, to_y; + + if (BWQueryMarked(w)) { + from_x = BW->bitmap.mark.from_x; + from_y = BW->bitmap.mark.from_y; + to_x = BW->bitmap.mark.to_x; + to_y = BW->bitmap.mark.to_y; + } + else { + from_x = 0; + from_y = 0; + to_x = BW->bitmap.width - 1; + to_y = BW->bitmap.height - 1; + } + + if ((to_y - from_y) == 0) + return; + + for(x = from_x; x <= to_x; x++) { + first = down = GetBit(BW->bitmap.image, x, from_y); + for(y = from_y + 1; y <= to_y; y++) { + up = GetBit(BW->bitmap.image, x, y); + if (down != up) + InvertPoint(BW, x, y); + down = up; + } + if(first != up) + InvertPoint(BW, x, from_y); + } + + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) + && + !BWQueryMarked(w)) + BWSetHotSpot(w, + BW->bitmap.hot.x, + (BW->bitmap.hot.y + 1) % BW->bitmap.image->height); +} + +void BWLeft(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + register Position x, y; + bit first, left, right; + Position from_x, from_y, to_x, to_y; + + if (BWQueryMarked(w)) { + from_x = BW->bitmap.mark.from_x; + from_y = BW->bitmap.mark.from_y; + to_x = BW->bitmap.mark.to_x; + to_y = BW->bitmap.mark.to_y; + } + else { + from_x = 0; + from_y = 0; + to_x = BW->bitmap.width - 1; + to_y = BW->bitmap.height - 1; + } + + if ((to_x - from_x) == 0) + return; + + for(y = from_y; y <= to_y; y++) { + first = left = GetBit(BW->bitmap.image, to_x, y); + for(x = to_x - 1; x >= from_x; x--) { + right = GetBit(BW->bitmap.image, x, y); + if (left != right) + InvertPoint(BW, x, y); + left = right; + } + if(first != right) + InvertPoint(BW, to_x, y); + } + + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) + && + !BWQueryMarked(w)) + BWSetHotSpot(w, + (BW->bitmap.hot.x - 1 + BW->bitmap.image->width) % + BW->bitmap.image->width, + BW->bitmap.hot.y); +} + +void BWRight(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + register Position x, y; + bit first, right, left; + Position from_x, from_y, to_x, to_y; + + if (BWQueryMarked(w)) { + from_x = BW->bitmap.mark.from_x; + from_y = BW->bitmap.mark.from_y; + to_x = BW->bitmap.mark.to_x; + to_y = BW->bitmap.mark.to_y; + } + else { + from_x = 0; + from_y = 0; + to_x = BW->bitmap.width - 1; + to_y = BW->bitmap.height - 1; + } + + if ((to_x - from_x) == 0) + return; + + for(y = from_y; y <= to_y; y++) { + first = right = GetBit(BW->bitmap.image, from_x, y); + for(x = from_x + 1; x <= to_x; x++) { + left = GetBit(BW->bitmap.image, x, y); + if (right != left) + InvertPoint(BW, x, y); + right = left; + } + if(first != left) + InvertPoint(BW, from_x, y); + } + + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) + && + !BWQueryMarked(w)) + BWSetHotSpot(w, + (BW->bitmap.hot.x + 1) % BW->bitmap.image->width, + BW->bitmap.hot.y); +} + +void TransferImageData(); + +void BWFold(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + Position x, y, new_x, new_y; + Dimension horiz, vert; + char *storage_data; + XImage *storage; + + storage_data = CreateCleanData(Length(BW->bitmap.image->width, + BW->bitmap.image->height)); + + storage = CreateBitmapImage(BW, storage_data, + (Dimension) BW->bitmap.image->width, + (Dimension) BW->bitmap.image->height); + + TransferImageData(BW->bitmap.image, storage); + + BW->bitmap.fold ^= True; + horiz = (BW->bitmap.image->width + BW->bitmap.fold) / 2; + vert = (BW->bitmap.image->height + BW->bitmap.fold) / 2; + + for (x = 0; x < BW->bitmap.image->width; x++) + for (y = 0; y < BW->bitmap.image->height; y++) { + new_x = (int)(x + horiz) % (int)BW->bitmap.image->width; + new_y = (int)(y + vert) % (int)BW->bitmap.image->height; + if(GetBit(BW->bitmap.image, new_x, new_y) != + GetBit(storage, x, y)) + InvertPoint(BW, new_x, new_y); + } + + DestroyBitmapImage(&storage); + + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) + BWSetHotSpot(w, + (Position) + ((int)(BW->bitmap.hot.x+horiz) + %(int)BW->bitmap.image->width), + (Position) + ((int)(BW->bitmap.hot.y+vert) + %(int)BW->bitmap.image->height) + ); +} + + +void BWClear(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + register Position x, y; + int i, length; + + length = Length(BW->bitmap.image->width, BW->bitmap.image->height); + + for (x = 0; x < BW->bitmap.image->width; x++) + for (y = 0; y < BW->bitmap.image->height; y++) + if (GetBit(BW->bitmap.image, x, y)) + DrawSquare(BW, x, y); + + for (i = 0; i < length; i++) + BW->bitmap.image->data[i] = 0; + +} + +void BWSet(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + register Position x, y; + int i, length; + + length = Length(BW->bitmap.image->width, BW->bitmap.image->height); + + for (x = 0; x < BW->bitmap.image->width; x++) + for (y = 0; y < BW->bitmap.image->height; y++) + if (!GetBit(BW->bitmap.image, x, y)) + DrawSquare(BW, x, y); + + for (i = 0; i < length; i++) + BW->bitmap.image->data[i] = 255; + +} + +void BWRedraw(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + + XClearArea(XtDisplay(BW), XtWindow(BW), + 0, 0, BW->core.width, BW->core.height, + True); +} + +void BWInvert(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + int i, length; + + length = Length(BW->bitmap.image->width, BW->bitmap.image->height); + + XFillRectangle(XtDisplay(BW), XtWindow(BW), + BW->bitmap.drawing_gc, + InWindowX(BW, 0), InWindowY(BW, 0), + InWindowX(BW, BW->bitmap.image->width) - InWindowX(BW, 0), + InWindowY(BW, BW->bitmap.image->height) - InWindowY(BW, 0)); + + for (i = 0; i < length; i++) + BW->bitmap.image->data[i] ^= 255; +} + +void BWFlipHoriz(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + register Position x, y; + Position from_x, from_y, to_x, to_y; + float half; + + if (BWQueryMarked(w)) { + from_x = BW->bitmap.mark.from_x; + from_y = BW->bitmap.mark.from_y; + to_x = BW->bitmap.mark.to_x; + to_y = BW->bitmap.mark.to_y; + } + else { + from_x = 0; + from_y = 0; + to_x = BW->bitmap.width - 1; + to_y = BW->bitmap.height - 1; + } + half = (float) (to_y - from_y) / 2.0 + 0.5; + + if (half == 0.0) + return; + + for (x = from_x; x <= to_x; x++) + for (y = 0; y < half; y++) + if (GetBit(BW->bitmap.image, x, from_y + y) != + GetBit(BW->bitmap.image, x, to_y - y)) { + InvertPoint(BW, x, from_y + y); + InvertPoint(BW, x, to_y - y); + } + + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) + && + !BWQueryMarked(w)) + BWSetHotSpot(w, + BW->bitmap.hot.x, + BW->bitmap.image->height - 1 - BW->bitmap.hot.y); +} + +void BWFlipVert(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + register Position x, y; + Position from_x, from_y, to_x, to_y; + float half; + + if (BWQueryMarked(w)) { + from_x = BW->bitmap.mark.from_x; + from_y = BW->bitmap.mark.from_y; + to_x = BW->bitmap.mark.to_x; + to_y = BW->bitmap.mark.to_y; + } + else { + from_x = 0; + from_y = 0; + to_x = BW->bitmap.width - 1; + to_y = BW->bitmap.height - 1; + } + half = (float) (to_x - from_x) / 2.0 + 0.5; + + if (half == 0) + return; + + for (y = from_y; y <= to_y; y++) + for (x = 0; x < half; x++) + if (GetBit(BW->bitmap.image, from_x + x, y) != + GetBit(BW->bitmap.image, to_x - x, y)) { + InvertPoint(BW, from_x + x, y); + InvertPoint(BW, to_x - x, y); + } + + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) + && + !BWQueryMarked(w)) + BWSetHotSpot(w, + BW->bitmap.image->width - 1 - BW->bitmap.hot.x, + BW->bitmap.hot.y); +} + + +void BWRotateRight(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + Position x, y, delta, shift, tmp; + Position half_width, half_height; + XPoint hot; + bit quad1, quad2, quad3, quad4; + Position from_x, from_y, to_x, to_y; + + if (BWQueryMarked(w)) { + from_x = BW->bitmap.mark.from_x; + from_y = BW->bitmap.mark.from_y; + to_x = BW->bitmap.mark.to_x; + to_y = BW->bitmap.mark.to_y; + } + else { + from_x = 0; + from_y = 0; + to_x = BW->bitmap.width - 1; + to_y = BW->bitmap.height - 1; + } + + half_width = floor((to_x - from_x) / 2.0 + 0.5); + half_height = floor((to_y - from_y ) / 2.0 + 0.5); + shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2; + delta = min((Position) half_width, (Position) half_height) - shift; + + for (x = 0; x <= delta; x++) { + for (y = 1 - shift; y <= delta; y++) { + quad1 = GetBit(BW->bitmap.image, + from_x + (Position)half_width + x, + from_y + (Position)half_height + y); + quad2 = GetBit(BW->bitmap.image, + from_x + (Position)half_width + y, + from_y + (Position)half_height - shift - x); + quad3 = GetBit(BW->bitmap.image, + from_x + (Position)half_width - shift - x, + from_y + (Position)half_height - shift - y); + quad4 = GetBit(BW->bitmap.image, + from_x + (Position)half_width - shift - y, + from_y + (Position)half_height + x); + + if (quad1 != quad2) + InvertPoint(BW, + from_x + (Position)half_width + x, + from_y + (Position)half_height + y); + if (quad2 != quad3) + InvertPoint(BW, + from_x + (Position)half_width + y, + from_y + (Position)half_height - shift - x); + if (quad3 != quad4) + InvertPoint(BW, + from_x + (Position)half_width - shift - x, + from_y + (Position)half_height - shift - y); + if (quad4 != quad1) + InvertPoint(BW, + from_x + (Position)half_width - shift - y, + from_y + (Position)half_height + x); + } + } + + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) + && + !BWQueryMarked(w)) { + hot.x = BW->bitmap.hot.x - half_width; + hot.y = BW->bitmap.hot.y - half_height; + if (hot.x >= 0) hot.x += shift; + if (hot.y >= 0) hot.y += shift; + tmp = hot.x; + hot.x = - hot.y; + hot.y = tmp; + if (hot.x > 0) hot.x -= shift; + if (hot.y > 0) hot.y -= shift; + hot.x += half_width; + hot.y += half_height; + if (QueryInBitmap(BW, hot.x, hot.y)) + BWSetHotSpot(w, hot.x, hot.y); + } + +} + +void BWRotateLeft(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + Position x, y,delta, shift, tmp; + Position half_width, half_height; + XPoint hot; + bit quad1, quad2, quad3, quad4; + Position from_x, from_y, to_x, to_y; + + if (BWQueryMarked(w)) { + from_x = BW->bitmap.mark.from_x; + from_y = BW->bitmap.mark.from_y; + to_x = BW->bitmap.mark.to_x; + to_y = BW->bitmap.mark.to_y; + } + else { + from_x = 0; + from_y = 0; + to_x = BW->bitmap.width - 1; + to_y = BW->bitmap.height - 1; + } + + half_width = floor((to_x - from_x) / 2.0 + 0.5); + half_height = floor((to_y - from_y ) / 2.0 + 0.5); + shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2; + delta = min((Position) half_width, (Position) half_height) - shift; + + for (x = 0; x <= delta; x++) { + for (y = 1 - shift; y <= delta; y++) { + quad1 = GetBit(BW->bitmap.image, + from_x + (Position)half_width + x, + from_y + (Position)half_height + y); + quad2 = GetBit(BW->bitmap.image, + from_x + (Position)half_width + y, + from_y + (Position)half_height - shift - x); + quad3 = GetBit(BW->bitmap.image, + from_x + (Position)half_width - shift - x, + from_y + (Position)half_height - shift - y); + quad4 = GetBit(BW->bitmap.image, + from_x + (Position)half_width - shift - y, + from_y + (Position)half_height + x); + + if (quad1 != quad4) + InvertPoint(BW, + from_x + (Position)half_width + x, + from_y + (Position)half_height + y); + if (quad2 != quad1) + InvertPoint(BW, + from_x + (Position)half_width + y, + from_y + (Position)half_height - shift - x); + if (quad3 != quad2) + InvertPoint(BW, + from_x + (Position)half_width - shift - x, + from_y + (Position)half_height - shift - y); + if (quad4 != quad3) + InvertPoint(BW, + from_x + (Position)half_width - shift - y, + from_y + (Position)half_height + x); + } + } + + if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) + && + !BWQueryMarked(w)) { + hot.x = BW->bitmap.hot.x - half_width; + hot.y = BW->bitmap.hot.y - half_height; + if (hot.x >= 0) hot.x += shift; + if (hot.y >= 0) hot.y += shift; + tmp = hot.x; + hot.x = hot.y; + hot.y = - tmp; + if (hot.x > 0) hot.x -= shift; + if (hot.y > 0) hot.y -= shift; + hot.x += half_width; + hot.y += half_height; + if (QueryInBitmap(BW, hot.x, hot.y)) + BWSetHotSpot(w, hot.x, hot.y); + } +} + + +void CopyImageData(source, destination, from_x, from_y, to_x, to_y, at_x, at_y) + XImage *source, *destination; + Position from_x, from_y, to_x, to_y, at_x, at_y; +{ + Position x, y, delta_x, delta_y; + + delta_x = to_x - from_x + 1; + delta_y = to_y - from_y + 1; + + for (x = 0; x < delta_x; x++) + for (y = 0; y < delta_y; y++) + if (GetBit(source, from_x + x, from_y + y)) + SetBit(destination, at_x + x, at_y + y); + else + ClearBit(destination, at_x + x, at_y + y); +} + +XImage *ConvertToBitmapImage(BW, image) + BitmapWidget BW; + XImage *image; +{ + XImage *bitmap_image; + char *data; + Position x, y; + + data = CreateCleanData(Length(image->width, image->height)); + bitmap_image = CreateBitmapImage(BW, data, + (Dimension) image->width, + (Dimension) image->height); + + for (x = 0; x < min(image->width, bitmap_image->width); x++) + for (y = 0; y < min(image->height, bitmap_image->height); y++) + if ((XGetPixel(image, x, y) != 0) != GetBit(bitmap_image, x, y)) + InvertBit(bitmap_image, x, y); + + return bitmap_image; +} + +void TransferImageData(source, destination) + XImage *source, *destination; +{ + Position x, y; + + for (x = 0; x < min(source->width, destination->width); x++) + for (y = 0; y < min(source->height, destination->height); y++) + if (GetBit(source, x, y) != GetBit(destination, x, y)) + InvertBit(destination, x, y); +} + +void BWStore(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + Dimension width, height; + char *storage_data; + + if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { + + DestroyBitmapImage(&BW->bitmap.storage); + + width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1; + height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1; + + storage_data = CreateCleanData(Length(width, height)); + + BW->bitmap.storage = CreateBitmapImage(BW, + storage_data, + width, height); + + CopyImageData(BW->bitmap.image, BW->bitmap.storage, + BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, + BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, + 0, 0); + } +} + +void BWClearMarked(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + + if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) + BWDrawFilledRectangle(w, + BW->bitmap.mark.from_x, + BW->bitmap.mark.from_y, + BW->bitmap.mark.to_x, + BW->bitmap.mark.to_y, + Clear); +} + + +void BWDragMarked(w, at_x, at_y) + Widget w; + Position at_x, at_y; +{ + BitmapWidget BW = (BitmapWidget) w; + + if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) + BWDrawRectangle(w, + at_x, at_y, + at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x, + at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y, + Highlight); +} + +void BWDragStored(w, at_x, at_y) + Widget w; + Position at_x, at_y; +{ + BitmapWidget BW = (BitmapWidget) w; + + if (BW->bitmap.storage) + BWDrawRectangle(w, + at_x, at_y, + at_x + BW->bitmap.storage->width - 1, + at_y + BW->bitmap.storage->height - 1, + Highlight); +} + +void DrawImageData(BW, image, at_x, at_y, value) + BitmapWidget BW; + XImage *image; + Position at_x, at_y; + int value; +{ + Position x, y; + Boolean C, S, I, H; + bit A, B; + + C = value == Clear; + S = value == Set; + I = value == Invert; + H = value == Highlight; + + for (x = 0; x < image->width; x++) + for (y = 0; y < image->height; y++) { + A = GetBit(image, x, y); + B = GetBit(BW->bitmap.image, at_x + x, at_y + y); + if (A & C | (A | B) & S | (A ^ B) & I | (A | B) & H) + value = (A & H) ? Highlight : Set; + else + value = Clear; + BWDrawPoint((Widget) BW, + at_x + x, at_y + y, + value); + } +} + +void BWRestore(w, at_x, at_y, value) + Widget w; + Position at_x, at_y; + int value; +{ + BitmapWidget BW = (BitmapWidget) w; + + if (BW->bitmap.storage) { + DrawImageData(BW, BW->bitmap.storage, at_x, at_y, value); + /*DestroyBitmapImage(&BW->bitmap.storage);*/ + } +} + +void BWCopy(w, at_x, at_y, value) + Widget w; + Position at_x, at_y; + int value; +{ + BitmapWidget BW = (BitmapWidget) w; + XImage *storage; + char *storage_data; + Dimension width, height; + + if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { + + width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1; + height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1; + + storage_data = CreateCleanData(Length(width, height)); + + storage = CreateBitmapImage(BW, storage_data, width, height); + + CopyImageData(BW->bitmap.image, storage, + BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, + BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, + 0, 0); + + DrawImageData(BW, storage, at_x, at_y, value); + + DestroyBitmapImage(&storage); + } +} + +void BWMark(); + +void BWMove(w, at_x, at_y, value) + Widget w; + Position at_x, at_y; + int value; +{ + BitmapWidget BW = (BitmapWidget) w; + XImage *storage; + char *storage_data; + Dimension width, height; + + if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { + + width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1; + height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1; + + storage_data = CreateCleanData(Length(width, height)); + + storage = CreateBitmapImage(BW, storage_data, width, height); + + CopyImageData(BW->bitmap.image, storage, + BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, + BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, + 0, 0); + + BWDrawFilledRectangle(w, + BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, + BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, + Clear); + + DrawImageData(BW, storage, at_x, at_y, value); + + BWMark(w, at_x, at_y, + at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x, + at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y); + + DestroyBitmapImage(&storage); + } +} + +void BWRedrawMark(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + + if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) + XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc, + InWindowX(BW, BW->bitmap.mark.from_x), + InWindowY(BW, BW->bitmap.mark.from_y), + InWindowX(BW, BW->bitmap.mark.to_x + 1) - + InWindowX(BW, BW->bitmap.mark.from_x), + InWindowY(BW, BW->bitmap.mark.to_y + 1) - + InWindowY(BW, BW->bitmap.mark.from_y)); +} + +void BWStoreToBuffer(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + + memmove( BW->bitmap.buffer->data, BW->bitmap.image->data, + Length(BW->bitmap.image->width, BW->bitmap.image->height)); + + BW->bitmap.buffer_hot = BW->bitmap.hot; + BW->bitmap.buffer_mark = BW->bitmap.mark; +} + +void BWUnmark(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + + BW->bitmap.buffer_mark = BW->bitmap.mark; + + if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { + XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc, + InWindowX(BW, BW->bitmap.mark.from_x), + InWindowY(BW, BW->bitmap.mark.from_y), + InWindowX(BW, BW->bitmap.mark.to_x + 1) - + InWindowX(BW, BW->bitmap.mark.from_x), + InWindowY(BW, BW->bitmap.mark.to_y + 1) - + InWindowY(BW, BW->bitmap.mark.from_y)); + + BW->bitmap.mark.from_x = BW->bitmap.mark.from_y = NotSet; + BW->bitmap.mark.to_x = BW->bitmap.mark.to_y = NotSet; + } +} + +void BWMark(w, from_x, from_y, to_x, to_y) + Widget w; + Position from_x, from_y, + to_x, to_y; +{ + BitmapWidget BW = (BitmapWidget) w; + + BWUnmark(w); + + if (QuerySet(from_x, from_y)) { + if ((from_x == to_x) && (from_y == to_y)) { + /* + BW->bitmap.mark.from_x = 0; + BW->bitmap.mark.from_y = 0; + BW->bitmap.mark.to_x = BW->bitmap.image->width - 1; + BW->bitmap.mark.to_y = BW->bitmap.image->height - 1; + */ + return; + } + else { + QuerySwap(from_x, to_x); + QuerySwap(from_y, to_y); + from_x = max(0, from_x); + from_y = max(0, from_y); + to_x = min(BW->bitmap.image->width - 1, to_x); + to_y = min(BW->bitmap.image->height - 1, to_y); + + BW->bitmap.mark.from_x = from_x; + BW->bitmap.mark.from_y = from_y; + BW->bitmap.mark.to_x = to_x; + BW->bitmap.mark.to_y = to_y; + } + + XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc, + InWindowX(BW, BW->bitmap.mark.from_x), + InWindowY(BW, BW->bitmap.mark.from_y), + InWindowX(BW, BW->bitmap.mark.to_x + 1) - + InWindowX(BW, BW->bitmap.mark.from_x), + InWindowY(BW, BW->bitmap.mark.to_y +1) - + InWindowY(BW, BW->bitmap.mark.from_y)); + } +} + +void BWMarkAll(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + + BWMark(w, 0, 0, BW->bitmap.image->width - 1, BW->bitmap.image->height - 1); +} + +void BWUndo(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + Position x, y; + char *tmp_data; + XPoint tmp_hot; + BWArea tmp_mark; + + tmp_data = BW->bitmap.image->data; + BW->bitmap.image->data = BW->bitmap.buffer->data; + BW->bitmap.buffer->data = tmp_data; + + tmp_hot = BW->bitmap.hot; + tmp_mark = BW->bitmap.mark; + + for (x = 0; x < BW->bitmap.image->width; x++) + for (y = 0; y < BW->bitmap.image->height; y++) + if (GetBit(BW->bitmap.image, x, y) != GetBit(BW->bitmap.buffer, x, y)) + DrawSquare(BW, x, y); + + BWSetHotSpot(w, BW->bitmap.buffer_hot.x, BW->bitmap.buffer_hot.y); +/* + BWMark(w, BW->bitmap.buffer_mark.from_x, BW->bitmap.buffer_mark.from_y, + BW->bitmap.buffer_mark.to_x, BW->bitmap.buffer_mark.to_y); +*/ + BW->bitmap.buffer_hot = tmp_hot; + BW->bitmap.buffer_mark= tmp_mark; + +} + +void BWHighlightAxes(w) + Widget w; +{ + BitmapWidget BW = (BitmapWidget) w; + + XDrawLine(XtDisplay(BW), XtWindow(BW), + BW->bitmap.axes_gc, + InWindowX(BW, 0), + InWindowY(BW, 0), + InWindowX(BW, BW->bitmap.width), + InWindowY(BW, BW->bitmap.height)); + XDrawLine(XtDisplay(BW), XtWindow(BW), + BW->bitmap.axes_gc, + InWindowX(BW, BW->bitmap.width), + InWindowY(BW, 0), + InWindowX(BW, 0), + InWindowY(BW, BW->bitmap.height)); + XDrawLine(XtDisplay(BW), XtWindow(BW), + BW->bitmap.axes_gc, + InWindowX(BW, 0), + InWindowY(BW, (float)BW->bitmap.height / 2.0), + InWindowX(BW, BW->bitmap.width), + InWindowY(BW, (float)BW->bitmap.height / 2.0)); + XDrawLine(XtDisplay(BW), XtWindow(BW), + BW->bitmap.axes_gc, + InWindowX(BW, (float)BW->bitmap.width / 2.0), + InWindowY(BW, 0), + InWindowX(BW, (float)BW->bitmap.width / 2.0), + InWindowY(BW, BW->bitmap.height)); +} + +typedef struct { + Position *x, *y; + Dimension *width, *height; +} Table; + +XImage *ScaleBitmapImage(BW, src, scale_x, scale_y) + BitmapWidget BW; + XImage *src; + double scale_x, scale_y; +{ + char *data; + XImage *dst; + Table table; + Position x, y, w, h; + Dimension width, height; + bit pixel; + + width = max(rint(scale_x * src->width), 1); + height = max(rint(scale_y * src->height), 1); + + data = CreateCleanData(Length(width, height)); + dst = CreateBitmapImage(BW, data, width, height); + + /* + * It would be nice to check if width or height < 1.0 and + * average the skipped pixels. But, it is slow as it is now. + */ + if (scale_x == 1.0 && scale_y == 1.0) + memmove( dst->data, src->data, Length(width, height)); + else { + table.x = (Position *) XtMalloc(sizeof(Position) * src->width); + table.y = (Position *) XtMalloc(sizeof(Position) * src->height); + table.width = (Dimension *) XtMalloc(sizeof(Dimension) * src->width); + table.height = (Dimension *) XtMalloc(sizeof(Dimension) * src->height); + + for (x = 0; x < src->width; x++) { + table.x[x] = rint(scale_x * x); + table.width[x] = rint(scale_x * (x + 1)) - rint(scale_x * x); + } + for (y = 0; y < src->height; y++) { + table.y[y] = rint(scale_y * y); + table.height[y] = rint(scale_y * (y + 1)) - rint(scale_y * y); + } + + for (x = 0; x < src->width; x++) + for (y = 0; y < src->height; y++) { + pixel = GetBit(src, x, y); + for (w = 0; (int)w < (int)table.width[x]; w++) + for (h = 0; (int)h < (int)table.height[y]; h++) + if (pixel) SetBit(dst, + table.x[x] + w, + table.y[y] + h); + } + + XtFree((char *)table.x); + XtFree((char *)table.y); + XtFree((char *)table.width); + XtFree((char *)table.height); + } + + return (dst); +} + +/*****************************************************************************/ |