diff options
Diffstat (limited to 'src/libs/graphics/context.c')
-rw-r--r-- | src/libs/graphics/context.c | 404 |
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 */ + |