home *** CD-ROM | disk | FTP | other *** search
- /*
- * GRAPH, Version 1.00 - 4 August 1989
- *
- * Copyright 1989, David Gay. All Rights Reserved.
- * This software is freely redistrubatable.
- */
-
- /* Various graphic extensions */
- #include <exec/types.h>
- #include <graphics/rastport.h>
- #include <math.h>
- #include <string.h>
-
- #include "graphics.h"
-
- #include <proto/graphics.h>
-
- /* Size limit for std routines */
- #define MAXPIXELS 1007
-
- /* Draws very long lines */
- void BigDraw(struct RastPort *rp, long x1, long y1)
- {
- short x0 = rp->cp_x;
- short y0 = rp->cp_y;
- short dx = x1 - x0;
- short dy = y1 - y0;
-
- if (rp->PenWidth > 1 || rp->PenHeight > 1)
- ThickDraw(rp, x1, y1);
- else
- {
- if (dx < 0) dx = -dx;
- if (dy < 0) dy = -dy;
-
- /* Use std routine if possible. It's 10 (or is it 100) x faster ! */
- if (dx <= MAXPIXELS && dy <= MAXPIXELS ||
- rp->BitMap->BytesPerRow <= (MAXPIXELS >> 3) && rp->BitMap->Rows <=
- MAXPIXELS)
- Draw(rp, x1, y1);
-
- else if (dx == 0) /* Vertical line */
- {
- if (y0 < y1)
- do Draw(rp, x1, y0 = min(y0 + MAXPIXELS, y1)); while (y0 != y1)
- ;
- else
- do Draw(rp, x1, y0 = max(y0 - MAXPIXELS, y1)); while (y0 != y1)
- ;
- }
- else if (dy == 0) /* Horizontal line */
- {
- if (x0 < x1)
- do Draw(rp, x0 = min(x0 + MAXPIXELS, x1), y1); while (x0 != x1)
- ;
- else
- do Draw(rp, x0 = max(x0 - MAXPIXELS, x1), y1); while (x0 != x1)
- ;
- }
- else /* "Standard" line drawing routine, with shifts. Could be recoded
- in assembly, but as most time is spent in WritePixel, this
- wouldn't help much. Probably faster to work out where to
- break the line to be able to use the std draw routine (even
- using real arithmetic). However, is rarely used, so ... */
- {
- register short x, y;
- register short a;
- register short add1;
- register short upadd;
- short end, oend, inc;
-
- if (dx > dy) /* --> 1 pixel for each x */
- {
- /* We want to start at the lowest value of x */
- if (x0 > x1)
- {
- x = x1;
- y = y1;
- end = x0;
- oend = y0;
- }
- else
- {
- x = x0;
- y = y0;
- end = x1;
- oend = y1;
- }
-
- inc = (oend < y) ? -1 : 1; /* y direction */
- a = 2 * dy - dx; /* initial "error" */
- add1 = 2 * dy; /* Standard increment */
- upadd = 2 * dy - 2 * dx; /* Pixel increment */
-
- while (x <= end)
- {
- WritePixel(rp, x, y);
-
- if (a > 0) /* A y shift ! */
- {
- a += upadd;
- y += inc;
- }
- else
- a += add1;
-
- x += 1;
- }
- }
- else /* 1 pixel for each y */
- {
- if (y0 > y1)
- {
- y = y1;
- x = x1;
- end = y0;
- oend = x0;
- }
- else
- {
- y = y0;
- x = x0;
- end = y1;
- oend = x1;
- }
-
- inc = (oend < x) ? -1 : 1;
- a = 2 * dx - dy;
- add1 = 2 * dx;
- upadd = 2 * dx - 2 * dy;
-
- while (y <= end)
- {
- WritePixel(rp, x, y);
-
- if (a > 0)
- {
- a += upadd;
- x += inc;
- }
- else
- a += add1;
-
- y += 1;
- }
- }
- rp->cp_x = x1;
- rp->cp_y = y1;
- }
- }
- }
-
- /* Only for RastPort's with no clipping ! */
- void BigSetRast(struct RastPort *rp, long colour)
- {
- struct BitMap *bm = rp->BitMap;
- int i;
-
- for (i = 0; i < bm->Depth; i++, colour = colour >> 1)
- memset(bm->Planes[i], colour & 1 ? 255 : 0, bm->BytesPerRow * bm->Rows)
- ;
- }
-
- /* Determine real text extent, if written in font font */
- void TextExtent(char *text, struct TextFont *font, struct TextExtent *ext)
- {
- static struct IntuiText it = {
- 1, 0, JAM1, 0, 0
- };
- struct TextAttr ta;
-
- ta.ta_Name = font->tf_Message.mn_Node.ln_Name;
- ta.ta_YSize = font->tf_YSize;
- ta.ta_Style = font->tf_Style;
- ta.ta_Flags = font->tf_Flags;
-
- it.ITextFont = &ta;
- it.IText = text;
-
- ext->te_Extent.MaxX = ext->te_Width = IntuiTextLength(&it) - 1;
- ext->te_Height = font->tf_YSize;
- ext->te_Extent.MinY = - font->tf_Baseline;
- ext->te_Extent.MaxY = font->tf_YSize - font->tf_Baseline - 1;
- /* The tricky part: in a proportional font, with kerning, a letter may
- start gto the left of the current position. */
- ext->te_Extent.MinX =
- (font->tf_CharKern && (UBYTE)(text[0]) >= font->tf_LoChar && (UBYTE)(tex
- t[0]) <= font->tf_HiChar)
- ? ((WORD *)(font->tf_CharKern))[text[0] - font->tf_LoChar]
- : 0;
- }
-
- /* Assumes w,h not too big ( < MAXPIXELS ) ..., w and h odd */
- void ThickDraw(struct RastPort *rp, long _x1, long _y1)
- {
- short x0 = rp->cp_x;
- short y0 = rp->cp_y;
- short x1 = _x1;
- short y1 = _y1;
- short dx = x1 - x0;
- short dy = y1 - y0;
- short w = rp->PenWidth;
- short h = rp->PenHeight;
-
- if (dx < 0) dx = -dx;
- if (dy < 0) dy = -dy;
-
- if (dx == 0) /* Vertical line -> easy */
- {
- short x00 = x0 - w / 2;
- short x01 = x0 + w / 2;;
-
- if (y0 < y1)
- {
- y0 -= h / 2;
- y1 += h / 2;
- do {
- short ny = min(y0 + MAXPIXELS, y1);
- RectFill(rp, x00, y0, x01, ny);
- y0 = ny;
- } while (y0 != y1);
- }
- else
- {
- y1 -= h / 2;
- y0 += h / 2;
- do {
- short ny = max(y0 - MAXPIXELS, y1);
- RectFill(rp, x00, ny, x01, y0);
- y0 = ny;
- } while (y0 != y1);
- }
- }
- else if (dy == 0) /* Horizontal line */
- {
- short y00 = y0 - h / 2;
- short y01 = y0 + h / 2;
-
- if (x0 < x1)
- {
- x0 -= w / 2;
- x1 += w / 2;
- do {
- short nx = min(x0 + MAXPIXELS, x1);
- RectFill(rp, x0, y00, nx, y01);
- x0 = nx;
- } while (x0 != x1);
- }
- else
- {
- x0 += w / 2;
- x1 -= w / 2;
- do {
- short nx = max(x0 - MAXPIXELS, x1);
- RectFill(rp, nx, y00, x0, y01);
- x0 = nx;
- } while (x0 != x1);
- }
- }
- else /* Same algorithme as in BigDraw, the thickness is done by drawing
- horiz. (or vert.) lines for each value of y (x) */
- {
- register short x, y;
- register short a;
- register short add1;
- register short upadd;
- short end, oend, inc;
-
- if (dx > dy) /* 1 pixel for each x */
- {
- short barh, bary0, bary1, sx;
-
- barh = (w * dy);
- barh = barh / dx + h;
-
- if (x0 > x1)
- {
- x = x1;
- y = y1;
- end = x0;
- oend = y0;
- }
- else
- {
- x = x0;
- y = y0;
- end = x1;
- oend = y1;
- }
-
- inc = (oend < y) ? -1 : 1;
- a = 2 * dy - dx;
- add1 = 2 * dy;
- upadd = 2 * dy - 2 * dx;
-
- x -= w / 2;
- end += w / 2;
- if (inc > 0)
- {
- bary0 = y - h / 2;
- bary1 = oend + h / 2;
- y += h / 2 - barh + 1;
- oend -= h / 2;
- }
- else
- {
- bary0 = y + h / 2;
- bary1 = oend - h / 2;
- y -= h / 2;
- oend += h / 2 - barh + 1;
- }
- sx = x;
- while (x <= end)
- {
- short y00 = y, y01 = y + barh - 1;
-
- if (inc < 0)
- {
- if (x < sx + w) y01 = bary0;
- if (x > end - w) y00 = bary1;
- }
- else
- {
- if (x < sx + w) y00 = bary0;
- if (x > end - w) y01 = bary1;
- }
- Move(rp, x, y00);
- Draw(rp, x, y01);
-
- if (a > 0)
- {
- a += upadd;
- y += inc;
- }
- else
- a += add1;
-
- x += 1;
- }
- }
- else /* 1 pixel for each y */
- {
- short barw, barx0, barx1, sy;
-
- barw = h * dx;
- barw = w + barw / dy;
-
- if (y0 > y1)
- {
- y = y1;
- x = x1;
- end = y0;
- oend = x0;
- }
- else
- {
- y = y0;
- x = x0;
- end = y1;
- oend = x1;
- }
-
- inc = (oend < x) ? -1 : 1;
- a = 2 * dx - dy;
- add1 = 2 * dx;
- upadd = 2 * dx - 2 * dy;
-
- y -= h / 2;
- end += h / 2;
- if (inc > 0)
- {
- barx0 = x - w / 2;
- barx1 = oend + w / 2;
- x += w / 2 - barw + 1;
- oend -= w / 2;
- }
- else
- {
- barx0 = x + w / 2;
- barx1 = oend - w / 2;
- x -= w / 2;
- oend += w / 2 - barw + 1;
- }
- sy = y;
- while (y <= end)
- {
- short x00 = x, x01 = x + barw - 1;
-
- if (inc > 0)
- {
- if (y < sy + h) x00 = barx0;
- if (y > end - h) x01 = barx1;
- }
- else
- {
- if (y < sy + h) x01 = barx0;
- if (y > end - h) x00 = barx1;
- }
- Move(rp, x00, y);
- Draw(rp, x01, y);
-
- if (a > 0)
- {
- a += upadd;
- x += inc;
- }
- else
- a += add1;
-
- y += 1;
- }
- }
- }
- rp->cp_x = _x1;
- rp->cp_y = _y1;
- }
-
-