summaryrefslogtreecommitdiff
path: root/src/libs/graphics/context.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/graphics/context.c')
-rw-r--r--src/libs/graphics/context.c404
1 files changed, 404 insertions, 0 deletions
diff --git a/src/libs/graphics/context.c b/src/libs/graphics/context.c
new file mode 100644
index 0000000..d609ded
--- /dev/null
+++ b/src/libs/graphics/context.c
@@ -0,0 +1,404 @@
+//Copyright Paul Reiche, Fred Ford. 1992-2002
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "gfxintrn.h"
+
+GRAPHICS_STATUS _GraphicsStatusFlags;
+CONTEXT _pCurContext;
+
+#ifdef DEBUG
+// We keep track of all contexts
+CONTEXT firstContext;
+ // The first one in the list.
+CONTEXT *contextEnd = &firstContext;
+ // Where to put the next context.
+#endif
+
+PRIMITIVE _locPrim;
+
+FONT _CurFontPtr;
+
+#define DEFAULT_FORE_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)
+#define DEFAULT_BACK_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)
+
+#define DEFAULT_DRAW_MODE MAKE_DRAW_MODE (DRAW_DEFAULT, 255)
+
+CONTEXT
+SetContext (CONTEXT Context)
+{
+ CONTEXT LastContext;
+
+ LastContext = _pCurContext;
+ if (Context != LastContext)
+ {
+ if (LastContext)
+ {
+ UnsetContextFlags (
+ MAKE_WORD (0, GRAPHICS_ACTIVE | DRAWABLE_ACTIVE));
+ SetContextFlags (
+ MAKE_WORD (0, _GraphicsStatusFlags
+ & (GRAPHICS_ACTIVE | DRAWABLE_ACTIVE)));
+
+ DeactivateContext ();
+ }
+
+ _pCurContext = Context;
+ if (_pCurContext)
+ {
+ ActivateContext ();
+
+ _GraphicsStatusFlags &= ~(GRAPHICS_ACTIVE | DRAWABLE_ACTIVE);
+ _GraphicsStatusFlags |= HIBYTE (_get_context_flags ());
+
+ SetPrimColor (&_locPrim, _get_context_fg_color ());
+
+ _CurFramePtr = _get_context_fg_frame ();
+ _CurFontPtr = _get_context_font ();
+ }
+ }
+
+ return (LastContext);
+}
+
+#ifdef DEBUG
+CONTEXT
+CreateContextAux (const char *name)
+#else /* if !defined(DEBUG) */
+CONTEXT
+CreateContextAux (void)
+#endif /* !defined(DEBUG) */
+{
+ CONTEXT NewContext;
+
+ NewContext = AllocContext ();
+ if (NewContext)
+ {
+ /* initialize context */
+#ifdef DEBUG
+ NewContext->name = name;
+ NewContext->next = NULL;
+ *contextEnd = NewContext;
+ contextEnd = &NewContext->next;
+#endif /* DEBUG */
+
+ NewContext->Mode = DEFAULT_DRAW_MODE;
+ NewContext->ForeGroundColor = DEFAULT_FORE_COLOR;
+ NewContext->BackGroundColor = DEFAULT_BACK_COLOR;
+ }
+
+ return NewContext;
+}
+
+#ifdef DEBUG
+// Loop through the list of context to the pointer which points to the
+// specified context. This is either 'firstContext' or the address of
+// the 'next' field of some other context.
+static CONTEXT *
+FindContextPtr (CONTEXT context) {
+ CONTEXT *ptr;
+
+ for (ptr = &firstContext; *ptr != NULL; ptr = &(*ptr)->next) {
+ if (*ptr == context)
+ break;
+ }
+ return ptr;
+}
+#endif /* DEBUG */
+
+BOOLEAN
+DestroyContext (CONTEXT ContextRef)
+{
+ TFB_Image *img;
+
+ if (ContextRef == 0)
+ return (FALSE);
+
+ if (_pCurContext && _pCurContext == ContextRef)
+ SetContext ((CONTEXT)0);
+
+#ifdef DEBUG
+ // Unlink the context.
+ {
+ CONTEXT *contextPtr = FindContextPtr (ContextRef);
+ if (contextEnd == &ContextRef->next)
+ contextEnd = contextPtr;
+ *contextPtr = ContextRef->next;
+ }
+#endif /* DEBUG */
+
+ img = ContextRef->FontBacking;
+ if (img)
+ TFB_DrawImage_Delete (img);
+
+ FreeContext (ContextRef);
+ return TRUE;
+}
+
+Color
+SetContextForeGroundColor (Color color)
+{
+ Color oldColor;
+
+ if (!ContextActive ())
+ return DEFAULT_FORE_COLOR;
+
+ oldColor = _get_context_fg_color ();
+ if (!sameColor(oldColor, color))
+ {
+ SwitchContextForeGroundColor (color);
+
+ if (!(_get_context_fbk_flags () & FBK_IMAGE))
+ {
+ SetContextFBkFlags (FBK_DIRTY);
+ }
+ }
+ SetPrimColor (&_locPrim, color);
+
+ return (oldColor);
+}
+
+Color
+GetContextForeGroundColor (void)
+{
+ if (!ContextActive ())
+ return DEFAULT_FORE_COLOR;
+
+ return _get_context_fg_color ();
+}
+
+Color
+SetContextBackGroundColor (Color color)
+{
+ Color oldColor;
+
+ if (!ContextActive ())
+ return DEFAULT_BACK_COLOR;
+
+ oldColor = _get_context_bg_color ();
+ if (!sameColor(oldColor, color))
+ SwitchContextBackGroundColor (color);
+
+ return oldColor;
+}
+
+Color
+GetContextBackGroundColor (void)
+{
+ if (!ContextActive ())
+ return DEFAULT_BACK_COLOR;
+
+ return _get_context_bg_color ();
+}
+
+DrawMode
+SetContextDrawMode (DrawMode mode)
+{
+ DrawMode oldMode;
+
+ if (!ContextActive ())
+ return DEFAULT_DRAW_MODE;
+
+ oldMode = _get_context_draw_mode ();
+ SwitchContextDrawMode (mode);
+
+ return oldMode;
+}
+
+DrawMode
+GetContextDrawMode (void)
+{
+ if (!ContextActive ())
+ return DEFAULT_DRAW_MODE;
+
+ return _get_context_draw_mode ();
+}
+
+// Returns a rect based at 0,0 and the size of context foreground frame
+static inline RECT
+_get_context_fg_rect (void)
+{
+ RECT r = { {0, 0}, {0, 0} };
+ if (_CurFramePtr)
+ r.extent = GetFrameBounds (_CurFramePtr);
+ return r;
+}
+
+BOOLEAN
+SetContextClipRect (RECT *lpRect)
+{
+ if (!ContextActive ())
+ return (FALSE);
+
+ if (lpRect)
+ {
+ if (rectsEqual (*lpRect, _get_context_fg_rect ()))
+ { // Cliprect is undefined to mirror GetContextClipRect()
+ _pCurContext->ClipRect.extent.width = 0;
+ }
+ else
+ { // We have a cliprect
+ _pCurContext->ClipRect = *lpRect;
+ }
+ }
+ else
+ { // Set cliprect as undefined
+ _pCurContext->ClipRect.extent.width = 0;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+GetContextClipRect (RECT *lpRect)
+{
+ if (!ContextActive ())
+ return (FALSE);
+
+ *lpRect = _pCurContext->ClipRect;
+ if (!_pCurContext->ClipRect.extent.width)
+ { // Though the cliprect is undefined, drawing will be clipped
+ // to the extent of the foreground frame
+ *lpRect = _get_context_fg_rect ();
+ }
+
+ return (_pCurContext->ClipRect.extent.width != 0);
+}
+
+POINT
+SetContextOrigin (POINT orgOffset)
+{
+ // XXX: This is a hack, kind of. But that's what the original did.
+ return SetFrameHot (_CurFramePtr, orgOffset);
+}
+
+FRAME
+SetContextFontEffect (FRAME EffectFrame)
+{
+ FRAME LastEffect;
+
+ if (!ContextActive ())
+ return (NULL);
+
+ LastEffect = _get_context_fonteff ();
+ if (EffectFrame != LastEffect)
+ {
+ SwitchContextFontEffect (EffectFrame);
+
+ if (EffectFrame != 0)
+ {
+ SetContextFBkFlags (FBK_IMAGE);
+ }
+ else
+ {
+ UnsetContextFBkFlags (FBK_IMAGE);
+ }
+ }
+
+ return LastEffect;
+}
+
+void
+FixContextFontEffect (void)
+{
+ SIZE w, h;
+ TFB_Image* img;
+
+ if (!ContextActive () || (_get_context_font_backing () != 0
+ && !(_get_context_fbk_flags () & FBK_DIRTY)))
+ return;
+
+ if (!GetContextFontLeading (&h) || !GetContextFontLeadingWidth (&w))
+ return;
+
+ img = _pCurContext->FontBacking;
+ if (img)
+ TFB_DrawScreen_DeleteImage (img);
+
+ img = TFB_DrawImage_CreateForScreen (w, h, TRUE);
+ if (_get_context_fbk_flags () & FBK_IMAGE)
+ { // image pattern backing
+ FRAME EffectFrame = _get_context_fonteff ();
+
+ TFB_DrawImage_Image (EffectFrame->image,
+ -EffectFrame->HotSpot.x, -EffectFrame->HotSpot.y,
+ 0, 0, NULL, DRAW_REPLACE_MODE, img);
+ }
+ else
+ { // solid color backing
+ RECT r = { {0, 0}, {w, h} };
+ Color color = _get_context_fg_color ();
+
+ TFB_DrawImage_Rect (&r, color, DRAW_REPLACE_MODE, img);
+ }
+
+ _pCurContext->FontBacking = img;
+ UnsetContextFBkFlags (FBK_DIRTY);
+}
+
+// 'area' may be NULL to copy the entire CONTEXT cliprect
+// 'area' is relative to the CONTEXT cliprect
+DRAWABLE
+CopyContextRect (const RECT* area)
+{
+ RECT clipRect;
+ RECT fgRect;
+ RECT r;
+
+ if (!ContextActive () || !_CurFramePtr)
+ return NULL;
+
+ fgRect = _get_context_fg_rect ();
+ GetContextClipRect (&clipRect);
+ r = clipRect;
+ if (area)
+ { // a portion of the context
+ r.corner.x += area->corner.x;
+ r.corner.y += area->corner.y;
+ r.extent = area->extent;
+ }
+ // TODO: Should this take CONTEXT origin into account too?
+ // validate the rect
+ if (!BoxIntersect (&r, &fgRect, &r))
+ return NULL;
+
+ if (_CurFramePtr->Type == SCREEN_DRAWABLE)
+ return LoadDisplayPixmap (&r, NULL);
+ else
+ return CopyFrameRect (_CurFramePtr, &r);
+}
+
+#ifdef DEBUG
+const char *
+GetContextName (CONTEXT context)
+{
+ return context->name;
+}
+
+CONTEXT
+GetFirstContext (void)
+{
+ return firstContext;
+}
+
+CONTEXT
+GetNextContext (CONTEXT context)
+{
+ return context->next;
+}
+#endif /* DEBUG */
+