From 10612543aa079b62c4d5a48ecf42e92829878d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Fri, 25 Mar 2005 17:29:20 +0000 Subject: [PATCH] step 3, exracted code from DisplayDriver into DisplayDriverImpl, adjusted the existing implementations to derive from the new class, got rid of some "friend" stuff along the way, essentially I made room for the new Painter based DisplayDriver implementation. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@11986 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/AccelerantDriver.cpp | 15 +- src/servers/app/AccelerantDriver.h | 18 +- src/servers/app/BitmapDriver.cpp | 34 +- src/servers/app/BitmapDriver.h | 21 +- src/servers/app/CursorData.h | 2 + src/servers/app/CursorHandler.cpp | 86 +- src/servers/app/DirectDriver.cpp | 42 +- src/servers/app/DirectDriver.h | 29 +- src/servers/app/DisplayDriver.cpp | 2911 +------------------------ src/servers/app/DisplayDriverImpl.cpp | 2810 ++++++++++++++++++++++++ src/servers/app/Jamfile | 1 + src/servers/app/ViewDriver.cpp | 29 +- src/servers/app/ViewDriver.h | 27 +- 13 files changed, 3052 insertions(+), 2973 deletions(-) create mode 100644 src/servers/app/DisplayDriverImpl.cpp diff --git a/src/servers/app/AccelerantDriver.cpp b/src/servers/app/AccelerantDriver.cpp index b371e0a2db..3fa6be8ba4 100644 --- a/src/servers/app/AccelerantDriver.cpp +++ b/src/servers/app/AccelerantDriver.cpp @@ -47,7 +47,8 @@ \brief Sets up internal variables needed by AccelerantDriver */ -AccelerantDriver::AccelerantDriver(void) : DisplayDriver() +AccelerantDriver::AccelerantDriver() + : DisplayDriverImpl() { cursor=NULL; under_cursor=NULL; @@ -63,7 +64,7 @@ AccelerantDriver::AccelerantDriver(void) : DisplayDriver() \brief Deletes the heap memory used by the AccelerantDriver */ -AccelerantDriver::~AccelerantDriver(void) +AccelerantDriver::~AccelerantDriver() { if (cursor) delete cursor; @@ -80,7 +81,7 @@ AccelerantDriver::~AccelerantDriver(void) Initialize sets up the driver for display, including the initial clearing of the screen. If things do not go as they should, false should be returned. */ -bool AccelerantDriver::Initialize(void) +bool AccelerantDriver::Initialize() { int i; char signature[1024]; @@ -181,8 +182,8 @@ bool AccelerantDriver::Initialize(void) RGBColor blue(0,0,255,0); FillRect(BRect(0,0,1024,768),blue); #endif - - return true; + + return DisplayDriver::Initialize(); } /*! @@ -191,8 +192,10 @@ bool AccelerantDriver::Initialize(void) Any work done by Initialize() should be undone here. Note that Shutdown() is called even if Initialize() was unsuccessful. */ -void AccelerantDriver::Shutdown(void) +void AccelerantDriver::Shutdown() { + DisplayDriver::Shutdown(); + #ifdef RUN_UNDER_R5 set_display_mode SetDisplayMode = (set_display_mode)accelerant_hook(B_SET_DISPLAY_MODE, NULL); if ( SetDisplayMode ) diff --git a/src/servers/app/AccelerantDriver.h b/src/servers/app/AccelerantDriver.h index dba570293c..f30894f70c 100644 --- a/src/servers/app/AccelerantDriver.h +++ b/src/servers/app/AccelerantDriver.h @@ -29,22 +29,24 @@ #define _ACCELERANTDRIVER_H_ #include -#include "DisplayDriver.h" + #include "PatternHandler.h" #include "FontServer.h" #include "LayerData.h" +#include "DisplayDriverImpl.h" + class ServerBitmap; class ServerCursor; -class AccelerantDriver : public DisplayDriver +class AccelerantDriver : public DisplayDriverImpl { public: - AccelerantDriver(void); - ~AccelerantDriver(void); + AccelerantDriver(); + ~AccelerantDriver(); - bool Initialize(void); - void Shutdown(void); + bool Initialize(); + void Shutdown(); virtual void InvertRect(const BRect &r); virtual void SetMode(const int32 &mode); @@ -54,8 +56,8 @@ public: /* virtual status_t SetDPMSMode(const uint32 &state); - virtual uint32 DPMSMode(void) const; - virtual uint32 DPMSCapabilities(void) const; + virtual uint32 DPMSMode() const; + virtual uint32 DPMSCapabilities() const; virtual status_t GetDeviceInfo(accelerant_device_info *info); virtual status_t GetModeList(display_mode **mode_list, uint32 *count); virtual status_t GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high); diff --git a/src/servers/app/BitmapDriver.cpp b/src/servers/app/BitmapDriver.cpp index 25c19c8af5..a499dcb3b3 100644 --- a/src/servers/app/BitmapDriver.cpp +++ b/src/servers/app/BitmapDriver.cpp @@ -52,7 +52,11 @@ extern RGBColor workspace_default_color; // defined in AppServer.cpp Subclasses should follow DisplayDriver's lead and use this function mostly for initializing data members. */ -BitmapDriver::BitmapDriver(void) : DisplayDriver() +BitmapDriver::BitmapDriver() + : DisplayDriverImpl(), + // NOTE: fLineThickness appeared to be never + // initialized in DisplayDriver + fLineThickness(1) { fTarget=NULL; fGraphicsBuffer=NULL; @@ -64,34 +68,10 @@ BitmapDriver::BitmapDriver(void) : DisplayDriver() Subclasses should use the destructor mostly for freeing allocated heap space. */ -BitmapDriver::~BitmapDriver(void) +BitmapDriver::~BitmapDriver() { } -/*! - \brief Initializes the driver object. - \return true if successful, false if not - - Initialize sets up the driver for display, including the initial clearing - of the screen. If things do not go as they should, false should be returned. -*/ -bool BitmapDriver::Initialize(void) -{ - // Nothing is needed because of SetTarget taking care of the work for us. - return true; -} - -/*! - \brief Shuts down the driver's video subsystem - - Any work done by Initialize() should be undone here. Note that Shutdown() is - called even if Initialize() was unsuccessful. -*/ -void BitmapDriver::Shutdown(void) -{ - // Nothing is needed here -} - void BitmapDriver::SetTarget(ServerBitmap *target) { Lock(); @@ -669,7 +649,7 @@ bool BitmapDriver::AcquireBuffer(FBBitmap *fbmp) return true; } -void BitmapDriver::ReleaseBuffer(void) +void BitmapDriver::ReleaseBuffer() { } diff --git a/src/servers/app/BitmapDriver.h b/src/servers/app/BitmapDriver.h index 5dcac58462..05b7f5fb62 100644 --- a/src/servers/app/BitmapDriver.h +++ b/src/servers/app/BitmapDriver.h @@ -37,11 +37,13 @@ #include // for clipping_rect definition #include #include -#include "DisplayDriver.h" + #include "FontServer.h" #include "GraphicsBuffer.h" #include "PixelRenderer.h" +#include "DisplayDriverImpl.h" + class ServerCursor; class ServerBitmap; class RGBColor; @@ -60,17 +62,14 @@ class PatternHandler; Usage: Allocate and call SetTarget on the desired ServerBitmap and start calling graphics methods. All ServerBitmap memory belongs to the BitmapManager. */ -class BitmapDriver : public DisplayDriver +class BitmapDriver : public DisplayDriverImpl { public: - BitmapDriver(void); - ~BitmapDriver(void); - - bool Initialize(void); - void Shutdown(void); + BitmapDriver(); + ~BitmapDriver(); void SetTarget(ServerBitmap *target); - ServerBitmap *GetTarget(void) const { return fTarget; } + ServerBitmap *GetTarget() const { return fTarget; } // Settings functions // virtual void DrawBitmap(ServerBitmap *bmp, const BRect &src, const BRect &dest, const DrawData *d); @@ -80,7 +79,7 @@ public: virtual void InvertRect(const BRect &rect); protected: virtual bool AcquireBuffer(FBBitmap *bmp); - virtual void ReleaseBuffer(void); + virtual void ReleaseBuffer(); virtual void Blit(const BRect &src, const BRect &dest, const DrawData *d); virtual void FillSolidRect(const BRect &rect, const RGBColor &color); @@ -102,6 +101,10 @@ protected: ServerBitmap *fTarget; GraphicsBuffer *fGraphicsBuffer; PixelRenderer *fPixelRenderer; + + // NOTE: completely outdated? + int fLineThickness; + PatternHandler fDrawPattern; }; #endif diff --git a/src/servers/app/CursorData.h b/src/servers/app/CursorData.h index f367b61cd3..dde23fcdd6 100644 --- a/src/servers/app/CursorData.h +++ b/src/servers/app/CursorData.h @@ -1,6 +1,8 @@ #ifndef CURSORDATA_H_ #define CURSORDATA_H_ +#include + extern int8 default_cursor_data[]; extern int8 default_text_data[]; extern int8 default_move_data[]; diff --git a/src/servers/app/CursorHandler.cpp b/src/servers/app/CursorHandler.cpp index a9b6e79489..4ced7f740c 100644 --- a/src/servers/app/CursorHandler.cpp +++ b/src/servers/app/CursorHandler.cpp @@ -36,6 +36,7 @@ CursorHandler::CursorHandler(DisplayDriver *driver) fSavedData(NULL), fCursor(NULL), fHideLevel(0), + fDrawData(), fDriverHidden(false), fIsObscured(false), fValidSaveData(false) @@ -92,28 +93,34 @@ void CursorHandler::SetCursor(ServerCursor *cursor) This function fails if asked to move the cursor outside the screen boundaries */ -void CursorHandler::MoveTo(const BPoint &pt) +void CursorHandler::MoveTo(BPoint pt) { - if(pt.x<0 || pt.y<0 || (pt.x>fDriver->fDisplayMode.virtual_width-1) || - (pt.y>fDriver->fDisplayMode.virtual_height-1)) - return; + pt.x = max_c(pt.x, 0.0); + pt.y = max_c(pt.y, 0.0); + pt.x = min_c(pt.x, fDriver->DisplayMode()->virtual_width - 1); + pt.y = min_c(pt.y, fDriver->DisplayMode()->virtual_height - 1); + + if (fCursorPos != pt) { - fCursorPos=pt; -if (!fSavedData) - debugger("NULL savedata\n"); - fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&(fDriver->fDrawData)); - fPosition.OffsetTo(fCursorPos.x-fCursor->GetHotSpot().x, - fCursorPos.y-fCursor->GetHotSpot().y); - fDriver->CopyToBitmap(fSavedData,fPosition); - - fDriver->fDrawData.draw_mode=B_OP_ALPHA; - fDriver->CopyBitmap(fCursor,fCursor->Bounds(),fPosition,&(fDriver->fDrawData)); - fDriver->fDrawData.draw_mode=B_OP_COPY; - - fDriver->Invalidate(fOldPosition); - fOldPosition=fPosition; - - fDriver->Invalidate(fPosition); + fCursorPos=pt; + + if (!fSavedData) + debugger("NULL savedata\n"); + + fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&fDrawData); + fPosition.OffsetTo(fCursorPos.x-fCursor->GetHotSpot().x, + fCursorPos.y-fCursor->GetHotSpot().y); + fDriver->CopyToBitmap(fSavedData,fPosition); + + fDrawData.draw_mode=B_OP_ALPHA; + fDriver->CopyBitmap(fCursor,fCursor->Bounds(),fPosition,&fDrawData); + fDrawData.draw_mode=B_OP_COPY; + + fDriver->Invalidate(fOldPosition); + fOldPosition=fPosition; + + fDriver->Invalidate(fPosition); + } } //! Shows the cursor. Unlike BView, calls are not cumulative @@ -121,31 +128,32 @@ void CursorHandler::Show(void) { // This call is pretty simple -- save the area underneath the cursor and draw the thing - if(fHideLevel==0) + if (fHideLevel == 0) return; - fIsObscured=false; + fIsObscured = false; fHideLevel--; - if(fHideLevel>0) + if (fHideLevel > 0) return; - fOldPosition=fPosition; + fOldPosition = fPosition; - if(!fCursor) + if (!fCursor) return; - fValidSaveData=true; + fValidSaveData = true; - if(!fSavedData) - fSavedData=new UtilityBitmap(fCursor->Bounds(),(color_space)fDriver->fDisplayMode.space,0); + if (!fSavedData) + fSavedData = new UtilityBitmap(fCursor->Bounds(), + (color_space)fDriver->DisplayMode()->space, 0); - fDriver->CopyToBitmap(fSavedData,fPosition); + fDriver->CopyToBitmap(fSavedData, fPosition); // Draw the data to the buffer - fDriver->fDrawData.draw_mode=B_OP_ALPHA; - fDriver->CopyBitmap(fCursor,fCursor->Bounds(),fPosition,&(fDriver->fDrawData)); - fDriver->fDrawData.draw_mode=B_OP_COPY; + fDrawData.draw_mode = B_OP_ALPHA; + fDriver->CopyBitmap(fCursor, fCursor->Bounds(), fPosition, &fDrawData); + fDrawData.draw_mode = B_OP_COPY; fDriver->Invalidate(fPosition); } @@ -172,7 +180,7 @@ void CursorHandler::Hide(void) if(!fSavedData) fSavedData=new UtilityBitmap(fCursor); - fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&(fDriver->fDrawData)); + fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&fDrawData); fDriver->Invalidate(fPosition); } @@ -193,7 +201,7 @@ void CursorHandler::Obscure(void) return; } - fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&(fDriver->fDrawData)); + fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&fDrawData); fDriver->Invalidate(fPosition); } @@ -210,7 +218,7 @@ void CursorHandler::DriverHide(void) if(!fSavedData) fSavedData=new UtilityBitmap(fCursor); - fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&(fDriver->fDrawData)); + fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&fDrawData); fDriver->Invalidate(fPosition); } @@ -229,13 +237,13 @@ void CursorHandler::DriverShow(void) fValidSaveData=true; if(!fSavedData) - fSavedData=new UtilityBitmap(fCursor->Bounds(),(color_space)fDriver->fDisplayMode.space,0); + fSavedData=new UtilityBitmap(fCursor->Bounds(),(color_space)fDriver->DisplayMode()->space,0); fDriver->CopyToBitmap(fSavedData,fPosition); // Draw the data to the buffer - fDriver->fDrawData.draw_mode=B_OP_ALPHA; - fDriver->CopyBitmap(fCursor,fCursor->Bounds(),fPosition,&(fDriver->fDrawData)); - fDriver->fDrawData.draw_mode=B_OP_COPY; + fDrawData.draw_mode=B_OP_ALPHA; + fDriver->CopyBitmap(fCursor,fCursor->Bounds(),fPosition,&fDrawData); + fDrawData.draw_mode=B_OP_COPY; fDriver->Invalidate(fPosition); } diff --git a/src/servers/app/DirectDriver.cpp b/src/servers/app/DirectDriver.cpp index 2a8c41d700..6a981cfca9 100644 --- a/src/servers/app/DirectDriver.cpp +++ b/src/servers/app/DirectDriver.cpp @@ -102,7 +102,8 @@ extern RGBColor workspace_default_color; by a couple orders of magnitude --------------------------------------------------------------------------------------- */ -DirectDriver::DirectDriver(void) +DirectDriver::DirectDriver() + : DisplayDriverImpl() { ATRACE(("DirectDriver::DirectDriver\n")); @@ -133,7 +134,7 @@ DirectDriver::DirectDriver(void) #endif } -DirectDriver::~DirectDriver(void) +DirectDriver::~DirectDriver() { ATRACE(("DirectDriver::~DirectDriver\n")); Lock(); @@ -143,20 +144,25 @@ DirectDriver::~DirectDriver(void) Unlock(); } -bool DirectDriver::Initialize(void) +bool DirectDriver::Initialize() { - ATRACE(("DirectDriver::Initialize\n")); - screenwin=new DDWindow(640,480,B_RGB32,this); - while(find_thread("drawing_thread")==B_NAME_NOT_FOUND) - { - ATRACE(("\tWaiting for the drawing thread to spawn\n")); - snooze(100); + if (DisplayDriver::Initialize()) { + ATRACE(("DirectDriver::Initialize\n")); + screenwin=new DDWindow(640,480,B_RGB32,this); + while(find_thread("drawing_thread")==B_NAME_NOT_FOUND) + { + ATRACE(("\tWaiting for the drawing thread to spawn\n")); + snooze(100); + } + return true; } - return true; + return false; } -void DirectDriver::Shutdown(void) +void DirectDriver::Shutdown() { + DisplayDriver::Shutdown(); + ATRACE(("DirectDriver::Shutdown\n")); screenwin->PostMessage(B_QUIT_REQUESTED); @@ -433,14 +439,14 @@ status_t DirectDriver::SetDPMSMode(const uint32 &state) return BScreen().SetDPMS(state); } -uint32 DirectDriver::DPMSMode(void) const +uint32 DirectDriver::DPMSMode() const { STRACE(("DirectDriver::DPMSMode\n")); // This is a hack, but should do enough to be ok for our purposes return BScreen().DPMSState(); } -uint32 DirectDriver::DPMSCapabilities(void) const +uint32 DirectDriver::DPMSCapabilities() const { STRACE(("DirectDriver::DPMSCapabilities\n")); @@ -1039,7 +1045,7 @@ DDWindow::DDWindow(uint16 width, uint16 height, color_space space, DirectDriver Show(); } -DDWindow::~DDWindow(void) +DDWindow::~DDWindow() { int32 result; @@ -1097,7 +1103,7 @@ void DDWindow::DirectConnected(direct_buffer_info *info) locker.Unlock(); } -bool DDWindow::QuitRequested(void) +bool DDWindow::QuitRequested() { port_id serverport=find_port(SERVER_PORT_NAME); @@ -1296,12 +1302,12 @@ int32 DDWindow::DrawingThread(void *data) return 0; } -RectPipe::RectPipe(void) +RectPipe::RectPipe() { list.MakeEmpty(); } -RectPipe::~RectPipe(void) +RectPipe::~RectPipe() { lock.Lock(); clipping_rect *rect; @@ -1357,7 +1363,7 @@ bool RectPipe::GetRect(clipping_rect *rect) return false; } -bool RectPipe::HasRects(void) +bool RectPipe::HasRects() { lock.Lock(); bool value=has_rects; diff --git a/src/servers/app/DirectDriver.h b/src/servers/app/DirectDriver.h index 56696154e2..47890e717a 100644 --- a/src/servers/app/DirectDriver.h +++ b/src/servers/app/DirectDriver.h @@ -34,11 +34,12 @@ #include // for clipping_rect definition #include #include -#include "DisplayDriver.h" #include "PortLink.h" #include #include "PatternHandler.h" +#include "DisplayDriverImpl.h" + class UtilityBitmap; class SDWindow; class LayerData; @@ -51,14 +52,14 @@ class DirectDriver; class RectPipe { public: - RectPipe(void); - ~RectPipe(void); + RectPipe(); + ~RectPipe(); void PutRect(const BRect &rect); void PutRect(const clipping_rect &rect); bool GetRect(clipping_rect *rect); - bool HasRects(void); - int32 CountRects(void) const { return list.CountItems(); } + bool HasRects(); + int32 CountRects() const { return list.CountItems(); } protected: BList list; BLocker lock; @@ -81,9 +82,9 @@ class DDWindow : public BDirectWindow { public: DDWindow(uint16 width, uint16 height, color_space space, DirectDriver *owner); - ~DDWindow(void); + ~DDWindow(); - virtual bool QuitRequested(void); + virtual bool QuitRequested(); virtual void DirectConnected(direct_buffer_info *info); virtual void WindowActivated(bool active); static int32 DrawingThread(void *data); @@ -114,14 +115,14 @@ public: the video display. An updater thread simply locks access to this bitmap, copies data to the framebuffer, and releases access. Derived DisplayDriver functions operate on this bitmap. */ -class DirectDriver : public DisplayDriver +class DirectDriver : public DisplayDriverImpl { public: - DirectDriver(void); - ~DirectDriver(void); + DirectDriver(); + ~DirectDriver(); - virtual bool Initialize(void); - virtual void Shutdown(void); + virtual bool Initialize(); + virtual void Shutdown(); // void DrawBitmap(ServerBitmap *bmp, const BRect &src, const BRect &dest, const DrawData *d); @@ -134,8 +135,8 @@ public: virtual bool DumpToFile(const char *path); virtual status_t SetDPMSMode(const uint32 &state); - virtual uint32 DPMSMode(void) const; - virtual uint32 DPMSCapabilities(void) const; + virtual uint32 DPMSMode() const; + virtual uint32 DPMSCapabilities() const; virtual status_t GetDeviceInfo(accelerant_device_info *info); virtual status_t GetModeList(display_mode **mode_list, uint32 *count); virtual status_t GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high); diff --git a/src/servers/app/DisplayDriver.cpp b/src/servers/app/DisplayDriver.cpp index 4578fb77b8..3fd63cc782 100644 --- a/src/servers/app/DisplayDriver.cpp +++ b/src/servers/app/DisplayDriver.cpp @@ -26,2323 +26,32 @@ // for the server // //------------------------------------------------------------------------------ -#include -#include "Angle.h" -#include "FontFamily.h" #include -#include "DisplayDriver.h" -#include "RectUtils.h" -#include "Utils.h" -#include "ServerCursor.h" +#include + #include "CursorData.h" +#include "ServerCursor.h" -// TODO: Implement all functions. Bounds checking needs to be -// handled by the public drawing functions. -// Add clipping and make sure public functions have Lock & Unlock. - -static Blitter blitter; +#include "DisplayDriver.h" /*! \brief Sets up internal variables needed by all DisplayDriver subclasses - - Subclasses should follow DisplayDriver's lead and use this function mostly - for initializing data members. */ -DisplayDriver::DisplayDriver(void) : - fCursorHandler(this) +DisplayDriver::DisplayDriver() + : fLocker("DisplayDriver lock"), + fCursorHandler(this), + fDPMSState(B_DPMS_ON), + fDPMSCaps(B_DPMS_ON) { - _locker=new BLocker(); - fCursorHandler.SetCursor(new ServerCursor(default_cursor_data)); - fDPMSCaps=B_DPMS_ON; - fDPMSState=B_DPMS_ON; + // TODO: somehow init fDisplayMode } /*! - \brief Deletes the locking semaphore - - Subclasses should use the destructor mostly for freeing allocated heap space. + \brief Does nothing */ -DisplayDriver::~DisplayDriver(void) +DisplayDriver::~DisplayDriver() { - delete _locker; -} - -/*! - \brief Initializes the driver object. - \return true if successful, false if not - - Initialize sets up the driver for display, including the initial clearing - of the screen. If things do not go as they should, false should be returned. -*/ -bool DisplayDriver::Initialize(void) -{ - return false; -} - -/*! - \brief Shuts down the driver's video subsystem - - Any work done by Initialize() should be undone here. Note that Shutdown() is - called even if Initialize() was unsuccessful. -*/ -void DisplayDriver::Shutdown(void) -{ -} - -/*! - \brief Called for all BView::CopyBits calls - \param src Source rectangle. - \param dest Destination rectangle. - - If the destination is not the same size as the source, the source should be scaled to fit. -*/ -void DisplayDriver::CopyBits(const BRect &src, const BRect &dest, const DrawData *d) -{ - if(!d) - return; - - Lock(); - - if(fCursorHandler.IntersectsCursor(dest)) - fCursorHandler.DriverHide(); - Blit(src,dest,d); - fCursorHandler.DriverShow(); - Unlock(); -} - -/*! - \brief A screen-to-screen blit (of sorts) which copies a BRegion - \param src Source region - \param lefttop Offset to which the region will be copied -*/ -void -DisplayDriver::CopyRegion(BRegion *src, const BPoint &lefttop) -{ - // TODO: Implement DisplayDriver;:CopyRegion -} - -/*! - \brief Inverts the colors in the rectangle. - \param r Rectangle of the area to be inverted. Guaranteed to be within bounds. -*/ -void DisplayDriver::InvertRect(const BRect &r) -{ -} - -/*! - \brief Called for all BView::DrawBitmap calls - \param region Destination rects in screen coordinates - \param bmp Bitmap to be drawn. It will always be non-NULL and valid. The color - space is not guaranteed to match. - \param src Source rectangle - \param dest Destination rectangle. Source will be scaled to fit if not the same size. - \param d Data structure containing any other data necessary for the call. Always non-NULL. -*/ -void -DisplayDriver::DrawBitmap(BRegion *region, ServerBitmap *bitmap, - const BRect &source, const BRect &dest, - const DrawData *d) -{ - // TODO: make sure we all mean the same region -> see PicturePlayer line 257 - if (!region) - return; - - Lock(); - - FBBitmap frameBuffer; - FBBitmap *bmp = &frameBuffer; - - blitter.Select(32, 32); - - if(!AcquireBuffer(&frameBuffer)) - { - debugger("ERROR: Couldn't acquire framebuffer in DrawBitmap()\n"); - Unlock(); - return; - } - - if(fCursorHandler.IntersectsCursor(dest)) - fCursorHandler.DriverHide(); - - uint8 colorspace_size = (bitmap->BitsPerPixel() + 7) / 8; - - int32 count = region->CountRects(); - - BRect bitmaprect(bitmap->Bounds()); - BRect sourcerect(source); - - BRect destrect(dest); - destrect.right *= d->scale; - destrect.bottom *= d->scale; - - if(sourcerect.left < 0) sourcerect.left = 0; - if(sourcerect.top < 0) sourcerect.top = 0; - - if(sourcerect.Width() > bitmaprect.Width()) - sourcerect.right = bitmaprect.left + bitmaprect.Width(); - - if(sourcerect.Height() > bitmaprect.Height()) - sourcerect.bottom = bitmaprect.top + bitmaprect.Height(); - - int32 sourcewidth = (int32)sourcerect.Width() + 1; - int32 sourceheight = (int32)sourcerect.Height() + 1; - - int32 destwidth = (int32)destrect.Width() + 1; - int32 destheight = (int32)destrect.Height() + 1; - - int32 xscale_factor = (sourcewidth << 16) / destwidth; - int32 yscale_factor = (sourceheight << 16) / destheight; - - uint8 *src_bits = (uint8 *)bitmap->Bits(); - uint8 *dest_bits = (uint8*)bmp->Bits(); - - int32 src_row = bitmap->BytesPerRow(); - int32 dest_row = bmp->BytesPerRow(); - - src_bits += uint32((sourcerect.top * src_row) + (sourcerect.left * colorspace_size)); - - integer_rect src_integer_rectangle = BRect_to_integer_rect(sourcerect); - integer_rect dst_integer_rectangle = BRect_to_integer_rect(destrect); - - int32 xscale_position = 0, yscale_position = 0, clipped_xscale_position = 0; - - for(int32 c = 0; c < count; c++) - { - integer_rect screen_integer_rect = BRect_to_integer_rect(region->RectAt(c)); - integer_rect src_integer_rect = src_integer_rectangle; - integer_rect dst_integer_rect = dst_integer_rectangle; - - xscale_position = 0, yscale_position = 0, clipped_xscale_position = 0; - - if(dst_integer_rect.x < screen_integer_rect.x) - { - dst_integer_rect.x -= screen_integer_rect.x; - dst_integer_rect.w += dst_integer_rect.x; - src_integer_rect.x -= dst_integer_rect.x; - dst_integer_rect.x = screen_integer_rect.x; - } - - if(dst_integer_rect.y < screen_integer_rect.y) - { - dst_integer_rect.y -= screen_integer_rect.y; - dst_integer_rect.h += dst_integer_rect.y; - src_integer_rect.y -= dst_integer_rect.y; - dst_integer_rect.y = screen_integer_rect.y; - } - - if(dst_integer_rect.w > screen_integer_rect.w) - dst_integer_rect.w = screen_integer_rect.w; - - if(dst_integer_rect.h > screen_integer_rect.h) - dst_integer_rect.h = screen_integer_rect.h; - - if(src_integer_rect.x > src_integer_rectangle.x) - { - int32 x_scale_pixel_multiply = src_integer_rect.x - src_integer_rectangle.x; - clipped_xscale_position = xscale_factor * x_scale_pixel_multiply; - } - - if(src_integer_rect.y > src_integer_rectangle.y) - { - int32 y_scale_pixel_multiply = src_integer_rect.y - src_integer_rectangle.y; - yscale_position = yscale_factor * y_scale_pixel_multiply; - } - - if(dst_integer_rect.w > 0 && dst_integer_rect.h > 0) - { - uint8 *src_data = src_bits; - uint8 *dst_data = (uint8 *)dest_bits + dst_integer_rect.y * dest_row + dst_integer_rect.x * colorspace_size; - - while(dst_integer_rect.h--) - { - xscale_position = clipped_xscale_position; - uint8 *s = (uint8 *)((uint8 *)src_data + (yscale_position >> 16) * src_row); - uint8 *d = (uint8 *)((uint8 *)dst_data); - - blitter.Draw(s, d, dst_integer_rect.w, xscale_position, xscale_factor); - #if 0 - for(int32 x = 0; x < dst_integer_rect.w; x++) - { - *d++ = s[xscale_position >> 16]; - xscale_position += xscale_factor; - } - #endif - dst_data += dest_row; - yscale_position += yscale_factor; - } - } - } - - fCursorHandler.DriverShow(); - ReleaseBuffer(); - Unlock(); - Invalidate(destrect); -} - -void DisplayDriver::CopyRegionList(BList* list, BList* pList, int32 rCount, BRegion* clipReg) -{ - Lock(); - - FBBitmap frameBuffer; - FBBitmap *bmp = &frameBuffer; - - if(!AcquireBuffer(&frameBuffer)) - { - debugger("ERROR: Couldn't acquire framebuffer in CopyRegionList()\n"); - Unlock(); - return; - } - - fCursorHandler.DriverHide(); - - - uint32 bytesPerPixel = bmp->BytesPerRow() / bmp->Bounds().IntegerWidth(); - BList rectList; - int32 i, k; - uint8 *bitmapBits = (uint8*)bmp->Bits(); - int32 Bwidth = bmp->Bounds().IntegerWidth() + 1; - int32 Bheight = bmp->Bounds().IntegerHeight() + 1; - - for(k=0; k < rCount; k++) - { - BRegion *reg = (BRegion*)list->ItemAt(k); - - int32 rectCount = reg->CountRects(); - for(i=0; i < rectCount; i++) - { - BRect r = reg->RectAt(i); - uint8 *rectCopy; - uint8 *srcAddress; - uint8 *destAddress; - int32 firstRow, lastRow; - int32 firstCol, lastCol; - int32 copyLength; - int32 copyRows; - - firstRow = (int32)(r.top < 0? 0: r.top); - lastRow = (int32)(r.bottom > (Bheight-1)? (Bheight-1): r.bottom); - firstCol = (int32)(r.left < 0? 0: r.left); - lastCol = (int32)(r.right > (Bwidth-1)? (Bwidth-1): r.right); - copyLength = (lastCol - firstCol + 1) < 0? 0: (lastCol - firstCol + 1); - copyRows = (lastRow - firstRow + 1) < 0? 0: (lastRow - firstRow + 1); - - rectCopy = (uint8*)malloc(copyLength * copyRows * bytesPerPixel); - - srcAddress = bitmapBits + (((firstRow) * Bwidth + firstCol) * bytesPerPixel); - destAddress = rectCopy; - - for (int32 j = 0; j < copyRows; j++) - { - uint8 *destRowAddress = destAddress + (j * copyLength * bytesPerPixel); - uint8 *srcRowAddress = srcAddress + (j * Bwidth * bytesPerPixel); - memcpy(destRowAddress, srcRowAddress, copyLength * bytesPerPixel ); - } - - rectList.AddItem(rectCopy); - } - } - - int32 item = 0; - for(k=0; k < rCount; k++) - { - BRegion *reg = (BRegion*)list->ItemAt(k); - - int32 rectCount = reg->CountRects(); - for(i=0; i < rectCount; i++) - { - BRect r = reg->RectAt(i); - uint8 *rectCopy; - uint8 *srcAddress; - uint8 *destAddress; - int32 firstRow, lastRow; - int32 firstCol, lastCol; - int32 copyLength, copyLength2; - int32 copyRows, copyRows2; - - firstRow = (int32)(r.top < 0? 0: r.top); - lastRow = (int32)(r.bottom > (Bheight-1)? (Bheight-1): r.bottom); - firstCol = (int32)(r.left < 0? 0: r.left); - lastCol = (int32)(r.right > (Bwidth-1)? (Bwidth-1): r.right); - copyLength = (lastCol - firstCol + 1) < 0? 0: (lastCol - firstCol + 1); - copyRows = (lastRow - firstRow + 1) < 0? 0: (lastRow - firstRow + 1); - - rectCopy = (uint8*)rectList.ItemAt(item++); - - srcAddress = rectCopy; - - r.Set(firstCol, firstRow, lastCol, lastRow); - r.OffsetBy( *((BPoint*)pList->ItemAt(k%rCount)) ); - firstRow = (int32)(r.top < 0? 0: r.top); - lastRow = (int32)(r.bottom > (Bheight-1)? (Bheight-1): r.bottom); - firstCol = (int32)(r.left < 0? 0: r.left); - lastCol = (int32)(r.right > (Bwidth-1)? (Bwidth-1): r.right); - copyLength2 = (lastCol - firstCol + 1) < 0? 0: (lastCol - firstCol + 1); - copyRows2 = (lastRow - firstRow + 1) < 0? 0: (lastRow - firstRow + 1); - - destAddress = bitmapBits + (((firstRow) * Bwidth + firstCol) * bytesPerPixel); - - int32 minLength = copyLength < copyLength2? copyLength: copyLength2; - int32 minRows = copyRows < copyRows2? copyRows: copyRows2; - - for (int32 j = 0; j < minRows; j++) - { - uint8 *destRowAddress = destAddress + (j * Bwidth * bytesPerPixel); - uint8 *srcRowAddress = srcAddress + (j * copyLength * bytesPerPixel); - memcpy(destRowAddress, srcRowAddress, minLength * bytesPerPixel ); - } - } - } - - for(i=0; i < rectList.CountItems(); i++) - { - void *rectCopy; - rectCopy = rectList.ItemAt(i); - if (rectCopy) - free(rectCopy); - } - rectList.MakeEmpty(); - - fCursorHandler.DriverShow(); - - BRect inval(bmp->Bounds()); - ReleaseBuffer(); - Unlock(); - -// ConstrainClippingRegion(clipReg); - Invalidate(inval); -// ConstrainClippingRegion(NULL); -} - -/*! - \brief Called for all BView::FillArc calls - \param r Rectangle enclosing the entire arc - \param angle Starting angle for the arc in degrees - \param span Span of the arc in degrees. Ending angle = angle+span. - \param d Object holding the bazillion other options -*/ -void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &span, const DrawData *d) -{ - if(fCursorHandler.IntersectsCursor(r)) - fCursorHandler.DriverHide(); - - float xc = (r.left+r.right)/2; - float yc = (r.top+r.bottom)/2; - float rx = r.Width()/2; - float ry = r.Height()/2; - int Rx2 = ROUND(rx*rx); - int Ry2 = ROUND(ry*ry); - int twoRx2 = 2*Rx2; - int twoRy2 = 2*Ry2; - int p; - int x=0; - int y = (int)ry; - int px = 0; - int py = twoRx2 * y; - int startx, endx; - int starty, endy; - int xclip, startclip, endclip; - int startQuad, endQuad; - bool useQuad1, useQuad2, useQuad3, useQuad4; - bool shortspan = false; - DrawData data; - - // Watch out for bozos giving us whacko spans - if ( (span >= 360) || (span <= -360) ) - { - FillEllipse(r,d); - fCursorHandler.DriverShow(); - return; - } - - Lock(); - - data = *d; - data.pensize = 1; - - if ( span > 0 ) - { - startQuad = (int)(angle/90)%4+1; - endQuad = (int)((angle+span)/90)%4+1; - startx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); - endx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); - } - else - { - endQuad = (int)(angle/90)%4+1; - startQuad = (int)((angle+span)/90)%4+1; - endx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); - startx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); - } - - starty = ROUND(ry*sqrt(1-(double)startx*startx/(rx*rx))); - endy = ROUND(ry*sqrt(1-(double)endx*endx/(rx*rx))); - - if ( startQuad != endQuad ) - { - useQuad1 = (endQuad > 1) && (startQuad > endQuad); - useQuad2 = ((startQuad == 1) && (endQuad > 2)) || ((startQuad > endQuad) && (endQuad > 2)); - useQuad3 = ((startQuad < 3) && (endQuad == 4)) || ((startQuad < 3) && (endQuad < startQuad)); - useQuad4 = (startQuad < 4) && (startQuad > endQuad); - } - else - { - if ( (span < 90) && (span > -90) ) - { - useQuad1 = false; - useQuad2 = false; - useQuad3 = false; - useQuad4 = false; - shortspan = true; - } - else - { - useQuad1 = (startQuad != 1); - useQuad2 = (startQuad != 2); - useQuad3 = (startQuad != 3); - useQuad4 = (startQuad != 4); - } - } - - if ( useQuad1 ) - StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); - if ( useQuad2 ) - StrokeLine(BPoint(xc,yc-y),BPoint(xc-x,yc-y),&data); - if ( useQuad3 ) - StrokeLine(BPoint(xc,yc+y),BPoint(xc-x,yc+y),&data); - if ( useQuad4 ) - StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); - - p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); - while (px < py) - { - x++; - px += twoRy2; - if ( p < 0 ) - p += Ry2 + px; - else - { - y--; - py -= twoRx2; - p += Ry2 + px - py; - } - - if ( useQuad1 ) - StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); - if ( useQuad2 ) - StrokeLine(BPoint(xc,yc-y),BPoint(xc-x,yc-y),&data); - if ( useQuad3 ) - StrokeLine(BPoint(xc,yc+y),BPoint(xc-x,yc+y),&data); - if ( useQuad4 ) - StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); - if ( !shortspan ) - { - if ( startQuad == 1 ) - { - if ( x <= startx ) - StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); - else - { - xclip = ROUND(y*startx/(double)starty); - StrokeLine(BPoint(xc,yc-y),BPoint(xc+xclip,yc-y),&data); - } - } - else if ( startQuad == 2 ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-xclip,yc-y),&data); - } - } - else if ( startQuad == 3 ) - { - if ( x <= startx ) - StrokeLine(BPoint(xc-x,yc+y),BPoint(xc,yc+y),&data); - else - { - xclip = ROUND(y*startx/(double)starty); - StrokeLine(BPoint(xc-xclip,yc+y),BPoint(xc,yc+y),&data); - } - } - else if ( startQuad == 4 ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - StrokeLine(BPoint(xc+xclip,yc+y),BPoint(xc+x,yc+y),&data); - } - } - - if ( endQuad == 1 ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - StrokeLine(BPoint(xc+xclip,yc-y),BPoint(xc+x,yc-y),&data); - } - } - else if ( endQuad == 2 ) - { - if ( x <= endx ) - StrokeLine(BPoint(xc-x,yc-y),BPoint(xc,yc-y),&data); - else - { - xclip = ROUND(y*endx/(double)endy); - StrokeLine(BPoint(xc-xclip,yc-y),BPoint(xc,yc-y),&data); - } - } - else if ( endQuad == 3 ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-xclip,yc+y),&data); - } - } - else if ( endQuad == 4 ) - { - if ( x <= endx ) - StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); - else - { - xclip = ROUND(y*endx/(double)endy); - StrokeLine(BPoint(xc,yc+y),BPoint(xc+xclip,yc+y),&data); - } - } - } - else - { - startclip = ROUND(y*startx/(double)starty); - endclip = ROUND(y*endx/(double)endy); - if ( startQuad == 1 ) - { - if ( (x <= startx) && (x >= endx) ) - StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+x,yc-y),&data); - else - StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+startclip,yc-y),&data); - } - else if ( startQuad == 2 ) - { - if ( (x <= startx) && (x >= endx) ) - StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-startclip,yc-y),&data); - else - StrokeLine(BPoint(xc-endclip,yc-y),BPoint(xc-startclip,yc-y),&data); - } - else if ( startQuad == 3 ) - { - if ( (x <= startx) && (x >= endx) ) - StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-endclip,yc+y),&data); - else - StrokeLine(BPoint(xc-startclip,yc+y),BPoint(xc-endclip,yc+y),&data); - } - else if ( startQuad == 4 ) - { - if ( (x <= startx) && (x >= endx) ) - StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+x,yc+y),&data); - else - StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+endclip,yc+y),&data); - } - } - } - - p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); - while (y>0) - { - y--; - py -= twoRx2; - if (p>0) - p += Rx2 - py; - else - { - x++; - px += twoRy2; - p += Rx2 - py +px; - } - - if ( useQuad1 ) - StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); - if ( useQuad2 ) - StrokeLine(BPoint(xc,yc-y),BPoint(xc-x,yc-y),&data); - if ( useQuad3 ) - StrokeLine(BPoint(xc,yc+y),BPoint(xc-x,yc+y),&data); - if ( useQuad4 ) - StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); - if ( !shortspan ) - { - if ( startQuad == 1 ) - { - if ( x <= startx ) - StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); - else - { - xclip = ROUND(y*startx/(double)starty); - StrokeLine(BPoint(xc,yc-y),BPoint(xc+xclip,yc-y),&data); - } - } - else if ( startQuad == 2 ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-xclip,yc-y),&data); - } - } - else if ( startQuad == 3 ) - { - if ( x <= startx ) - StrokeLine(BPoint(xc-x,yc+y),BPoint(xc,yc+y),&data); - else - { - xclip = ROUND(y*startx/(double)starty); - StrokeLine(BPoint(xc-xclip,yc+y),BPoint(xc,yc+y),&data); - } - } - else if ( startQuad == 4 ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - StrokeLine(BPoint(xc+xclip,yc+y),BPoint(xc+x,yc+y),&data); - } - } - - if ( endQuad == 1 ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - StrokeLine(BPoint(xc+xclip,yc-y),BPoint(xc+x,yc-y),&data); - } - } - else if ( endQuad == 2 ) - { - if ( x <= endx ) - StrokeLine(BPoint(xc-x,yc-y),BPoint(xc,yc-y),&data); - else - { - xclip = ROUND(y*endx/(double)endy); - StrokeLine(BPoint(xc-xclip,yc-y),BPoint(xc,yc-y),&data); - } - } - else if ( endQuad == 3 ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-xclip,yc+y),&data); - } - } - else if ( endQuad == 4 ) - { - if ( x <= endx ) - StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); - else - { - xclip = ROUND(y*endx/(double)endy); - StrokeLine(BPoint(xc,yc+y),BPoint(xc+xclip,yc+y),&data); - } - } - } - else - { - startclip = ROUND(y*startx/(double)starty); - endclip = ROUND(y*endx/(double)endy); - if ( startQuad == 1 ) - { - if ( (x <= startx) && (x >= endx) ) - StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+x,yc-y),&data); - else - StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+startclip,yc-y),&data); - } - else if ( startQuad == 2 ) - { - if ( (x <= startx) && (x >= endx) ) - StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-startclip,yc-y),&data); - else - StrokeLine(BPoint(xc-endclip,yc-y),BPoint(xc-startclip,yc-y),&data); - } - else if ( startQuad == 3 ) - { - if ( (x <= startx) && (x >= endx) ) - StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-endclip,yc+y),&data); - else - StrokeLine(BPoint(xc-startclip,yc+y),BPoint(xc-endclip,yc+y),&data); - } - else if ( startQuad == 4 ) - { - if ( (x <= startx) && (x >= endx) ) - StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+x,yc+y),&data); - else - StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+endclip,yc+y),&data); - } - } - } - fCursorHandler.DriverShow(); - Invalidate(r); - Unlock(); -} - -/*! - \brief Called for all BView::FillBezier calls. - \param pts 4-element array of BPoints in the order of start, end, and then the two control - points. - \param d draw data -*/ -void DisplayDriver::FillBezier(BPoint *pts, const DrawData *d) -{ - Lock(); - - BezierCurve curve(pts); - - if(fCursorHandler.IntersectsCursor(curve.Frame())) - fCursorHandler.DriverHide(); - - FillPolygon(curve.GetPointArray(), curve.points.CountItems(), curve.Frame(), d); - - fCursorHandler.DriverShow(); - Unlock(); -} - -/*! - \brief Called for all BView::FillEllipse calls - \param r BRect enclosing the ellipse to be drawn. - \param d DrawData containing the endless options -*/ -void DisplayDriver::FillEllipse(const BRect &r, const DrawData *d) -{ - float xc = (r.left+r.right)/2; - float yc = (r.top+r.bottom)/2; - float rx = r.Width()/2; - float ry = r.Height()/2; - int Rx2 = ROUND(rx*rx); - int Ry2 = ROUND(ry*ry); - int twoRx2 = 2*Rx2; - int twoRy2 = 2*Ry2; - int p; - int x=0; - int y = (int)ry; - int px = 0; - int py = twoRx2 * y; - DrawData data; - - Lock(); - - if(fCursorHandler.IntersectsCursor(r)) - fCursorHandler.DriverHide(); - - data = *d; - data.pensize = 1; - - StrokeLine(BPoint(xc,yc-y),BPoint(xc,yc-y),&data); - StrokeLine(BPoint(xc,yc+y),BPoint(xc,yc+y),&data); - - p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); - while (px < py) - { - x++; - px += twoRy2; - if ( p < 0 ) - p += Ry2 + px; - else - { - y--; - py -= twoRx2; - p += Ry2 + px - py; - } - - StrokeLine(BPoint(xc-x,yc-y),BPoint(xc+x,yc-y),&data); - StrokeLine(BPoint(xc-x,yc+y),BPoint(xc+x,yc+y),&data); - } - - p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); - while (y>0) - { - y--; - py -= twoRx2; - if (p>0) - p += Rx2 - py; - else - { - x++; - px += twoRy2; - p += Rx2 - py +px; - } - - StrokeLine(BPoint(xc-x,yc-y),BPoint(xc+x,yc-y),&data); - StrokeLine(BPoint(xc-x,yc+y),BPoint(xc+x,yc+y),&data); - } - fCursorHandler.DriverShow(); - Invalidate(r); - Unlock(); -} - -/*! - \brief Called for all BView::FillPolygon calls - \param ptlist Array of BPoints defining the polygon. - \param numpts Number of points in the BPoint array. - \param d The 50 bazillion drawing options (inluding clip region) -*/ -void DisplayDriver::FillPolygon(BPoint *ptlist, int32 numpts, const BRect &bounds, const DrawData *d) -{ - // Here's the plan. Record all line segments in polygon. If a line segments crosses - // the y-value of a point not in the segment, split the segment into 2 segments. - // Once we have gone through all of the segments, sort them primarily on y-value - // and secondarily on x-value. Step through each y-value in the bounding rectangle - // and look for intersections with line segments. First intersection is start of - // horizontal line, second intersection is end of horizontal line. Continue for - // all pairs of intersections. Watch out for horizontal line segments. - if ( !ptlist || (numpts < 3) ) - return; - - Lock(); - - if(fCursorHandler.IntersectsCursor(bounds)) - fCursorHandler.DriverHide(); - - BPoint *currentPoint, *nextPoint; - BPoint tempNextPoint; - BPoint tempCurrentPoint; - int currentIndex, bestIndex, i, j, y; - LineCalc *segmentArray = new LineCalc[2*numpts]; - int numSegments = 0; - int minX, minY, maxX, maxY; - - minX = ROUND(ptlist[0].x); - maxX = ROUND(ptlist[0].x); - minY = ROUND(ptlist[0].y); - maxY = ROUND(ptlist[0].y); - - // Generate the segment list - currentPoint = ptlist; - currentIndex = 0; - nextPoint = &ptlist[1]; - while (currentPoint) - { - if ( numSegments >= 2*numpts ) - { - printf("ERROR: Insufficient memory allocated to segment array\n"); - delete[] segmentArray; - fCursorHandler.DriverShow(); - Unlock(); - return; - } - - if ( ROUND(currentPoint->x) < minX ) - minX = ROUND(currentPoint->x); - if ( ROUND(currentPoint->x) > maxX ) - maxX = ROUND(currentPoint->x); - if ( ROUND(currentPoint->y) < minY ) - minY = ROUND(currentPoint->y); - if ( ROUND(currentPoint->y) > maxY ) - maxY = ROUND(currentPoint->y); - - for (i=0; i currentPoint->y) && (ptlist[i].y < nextPoint->y)) || - ((ptlist[i].y < currentPoint->y) && (ptlist[i].y > nextPoint->y)) ) - { - segmentArray[numSegments].SetPoints(*currentPoint,*nextPoint); - tempNextPoint.x = segmentArray[numSegments].GetX(ptlist[i].y); - tempNextPoint.y = ptlist[i].y; - nextPoint = &tempNextPoint; - } - } - - segmentArray[numSegments].SetPoints(*currentPoint,*nextPoint); - numSegments++; - if ( nextPoint == &tempNextPoint ) - { - tempCurrentPoint = tempNextPoint; - currentPoint = &tempCurrentPoint; - nextPoint = &ptlist[(currentIndex+1)%numpts]; - } - else if ( nextPoint == ptlist ) - { - currentPoint = NULL; - } - else - { - currentPoint = nextPoint; - currentIndex++; - nextPoint = &ptlist[(currentIndex+1)%numpts]; - } - } - - // Selection sort the segments. Probably should replace this later. - for (i=0; iclipReg ) - { - // Draw the lines - for (y=minY; y<=maxY; y++) - { - i = 0; - while (i y) - break; - if (segmentArray[i].MaxY() < y) - { - i++; - continue; - } - if (segmentArray[i].MinY() == segmentArray[i].MaxY()) - { - if ( (segmentArray[i].MinX() < fDisplayMode.virtual_width) && - (segmentArray[i].MaxX() >= 0) ) - StrokePatternLine(ROUND(segmentArray[i].MinX()), y, - ROUND(segmentArray[i].MaxX()), y, d); - i++; - } - else - { - if ( (segmentArray[i+1].GetX(y) < fDisplayMode.virtual_width) && - (segmentArray[i].GetX(y) >= 0) ) - StrokePatternLine(ROUND(segmentArray[i].GetX(y)), y, - ROUND(segmentArray[i+1].GetX(y)), y, d); - i+=2; - } - } - } - } - else - { - int numRects, rectIndex; - int yStart, yEnd; - BRect clipRect; - numRects = d->clipReg->CountRects(); - for (rectIndex = 0; rectIndex < numRects; rectIndex++) - { - clipRect = d->clipReg->RectAt(rectIndex); - if ( clipRect.bottom < minY ) - continue; - if ( clipRect.top > maxY ) - continue; - if ( clipRect.left < minX ) - continue; - if ( clipRect.right > maxX ) - continue; - yStart = MAX(minY,ROUND(clipRect.top)); - yEnd = MIN(maxY,ROUND(clipRect.bottom)); - - // Draw the lines - for (y=yStart; y<=yEnd; y++) - { - i = 0; - while (i y) - break; - if (segmentArray[i].MaxY() < y) - { - i++; - continue; - } - if (segmentArray[i].MinY() == segmentArray[i].MaxY()) - { - if (segmentArray[i].MinX() > clipRect.right) - { - i++; - continue; - } - if (segmentArray[i].MaxX() < clipRect.left) - { - i++; - continue; - } - StrokePatternLine(ROUND(MAX(segmentArray[i].MinX(),clipRect.left)), y, - ROUND(MIN(segmentArray[i].MaxX(),clipRect.right)), y, d); - i++; - } - else - { - if (segmentArray[i].GetX(y) > clipRect.right) - { - i+=2; - continue; - } - if (segmentArray[i+1].GetX(y) < clipRect.left) - { - i+=2; - continue; - } - StrokePatternLine(ROUND(MAX(segmentArray[i].GetX(y),clipRect.left)), y, - ROUND(MIN(segmentArray[i+1].GetX(y),clipRect.right)), y, d); - i+=2; - } - } - } - } - } - delete[] segmentArray; - fCursorHandler.DriverShow(); - Invalidate(bounds); - Unlock(); -} - -/*! - \brief Called for all BView::FillRect calls - \param r BRect to be filled. Guaranteed to be in the frame buffer's coordinate space - \param color The color used to fill the rectangle -*/ -void DisplayDriver::FillRect(const BRect &r, const RGBColor &color) -{ - Lock(); - if(fCursorHandler.IntersectsCursor(r)) - fCursorHandler.DriverHide(); - - FillSolidRect(r,color); - fCursorHandler.DriverShow(); - Unlock(); -} - -/*! - \brief Called for all BView::FillRect calls - \param r BRect to be filled. Guaranteed to be in the frame buffer's coordinate space - \param pattern The pattern used to fill the rectangle - \param high_color The high color of the pattern - \param low_color The low color of the pattern -*/ -void DisplayDriver::FillRect(const BRect &r, const DrawData *d) -{ - if(!d) - return; - - Lock(); - if(fCursorHandler.IntersectsCursor(r)) - fCursorHandler.DriverHide(); - if ( d->clipReg ) - { - if ( d->clipReg->Intersects(r) ) - { - BRegion reg(r); - reg.IntersectWith(d->clipReg); - int numRects = reg.CountRects(); - - for(int32 i=0; iclipReg ) - { - BRegion drawReg = r; - - drawReg.IntersectWith(d->clipReg); - numRects = drawReg.CountRects(); - - for(int32 i=0; iclipReg ) - { - int numRects, rectIndex; - BRect clipRect; - int left, right, y1, y2; - int rectTop, rectBottom, rectLeft, rectRight; - - numRects = d->clipReg->CountRects(); - for (rectIndex=0; rectIndexclipReg->RectAt(rectIndex); - rectTop = ROUND(clipRect.top); - rectBottom = ROUND(clipRect.bottom); - rectLeft = ROUND(clipRect.left); - rectRight = ROUND(clipRect.right); - for (i=0; i<=(int)yrad; i++) - { - arc_x = xrad*sqrt(1-i*i/yrad2); - left = ROUND(r.left + xrad - arc_x); - right = ROUND(r.right - xrad + arc_x); - if ( (left > rectRight) || (right < rectLeft) ) - continue; - y1 = ROUND(r.top + yrad - i); - y2 = ROUND(r.bottom - yrad + i); - if ( (y1 >= rectTop) && (y1 <= rectBottom) ) - StrokePatternLine(MAX(left,rectLeft), y1, MIN(right,rectRight), y1,d); - if ( (y2 >= rectTop) && (y2 <= rectBottom) ) - StrokePatternLine(MAX(left,rectLeft), y2, MIN(right,rectRight), y2,d); - } - } - } - else - { - for (i=0; i<=(int)yrad; i++) - { - arc_x = xrad*sqrt(1-i*i/yrad2); - StrokePatternLine(ROUND(r.left+xrad-arc_x), ROUND(r.top+yrad-i), ROUND(r.right-xrad+arc_x), ROUND(r.top+yrad-i),d); - StrokePatternLine(ROUND(r.left+xrad-arc_x), ROUND(r.bottom-yrad+i), ROUND(r.right-xrad+arc_x), ROUND(r.bottom-yrad+i),d); - } - } - FillPatternRect(BRect(r.left,r.top+yrad,r.right,r.bottom-yrad),d); - fCursorHandler.DriverShow(); - Invalidate(r); - Unlock(); -} - -void DisplayDriver::FillShape(const BRect &bounds, const int32 &opcount, const int32 *oplist, - const int32 &ptcount, const BPoint *ptlist, const DrawData *d) -{ - // TODO: Implement DisplayDriver::FillShape. How, though? AGG backend? - printf("DisplayDriver::FillShape unimplemented\n"); -} - -/*! - \brief Called for all BView::FillTriangle calls - \param pts Array of 3 BPoints. Always non-NULL. - \param setLine Horizontal line drawing routine which handles things like color and pattern. -*/ -void DisplayDriver::FillTriangle(BPoint *pts, const BRect &bounds, const DrawData *d) -{ - if ( !pts ) - return; - - Lock(); - - if(fCursorHandler.IntersectsCursor(bounds)) - fCursorHandler.DriverHide(); - - if ( d->clipReg ) - { - // For now, cop out and use FillPolygon - // Need to investigate if Triangle specific code would save processing time - FillPolygon(pts,3,bounds,d); - fCursorHandler.DriverShow(); - } - else - { - BPoint first, second, third; - - // Sort points according to their y values and x values (y is primary) - if ( (pts[0].y < pts[1].y) || - ((pts[0].y == pts[1].y) && (pts[0].x <= pts[1].x)) ) - { - first=pts[0]; - second=pts[1]; - } - else - { - first=pts[1]; - second=pts[0]; - } - - if ( (second.y= 360) || (span <= -360) ) - { - StrokeEllipse(r,d); - fCursorHandler.DriverShow(); - Unlock(); - return; - } - - if ( span > 0 ) - { - startQuad = (int)(angle/90)%4+1; - endQuad = (int)((angle+span)/90)%4+1; - startx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); - endx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); - } - else - { - endQuad = (int)(angle/90)%4+1; - startQuad = (int)((angle+span)/90)%4+1; - endx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); - startx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); - } - - if ( startQuad != endQuad ) - { - useQuad1 = (endQuad > 1) && (startQuad > endQuad); - useQuad2 = ((startQuad == 1) && (endQuad > 2)) || ((startQuad > endQuad) && (endQuad > 2)); - useQuad3 = ((startQuad < 3) && (endQuad == 4)) || ((startQuad < 3) && (endQuad < startQuad)); - useQuad4 = (startQuad < 4) && (startQuad > endQuad); - } - else - { - if ( (span < 90) && (span > -90) ) - { - useQuad1 = false; - useQuad2 = false; - useQuad3 = false; - useQuad4 = false; - shortspan = true; - } - else - { - useQuad1 = (startQuad != 1); - useQuad2 = (startQuad != 2); - useQuad3 = (startQuad != 3); - useQuad4 = (startQuad != 4); - } - } - - if ( useQuad1 || - (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || - (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - StrokePoint(BPoint(xc+x,yc-y),d); - if ( useQuad2 || - (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || - (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - StrokePoint(BPoint(xc-x,yc-y),d); - if ( useQuad3 || - (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || - (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - StrokePoint(BPoint(xc-x,yc+y),d); - if ( useQuad4 || - (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || - (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - StrokePoint(BPoint(xc+x,yc+y),d); - - p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); - while (px < py) - { - x++; - px += twoRy2; - if ( p < 0 ) - p += Ry2 + px; - else - { - y--; - py -= twoRx2; - p += Ry2 + px - py; - } - - if ( useQuad1 || - (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || - (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - StrokePoint(BPoint(xc+x,yc-y),d); - if ( useQuad2 || - (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || - (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - StrokePoint(BPoint(xc-x,yc-y),d); - if ( useQuad3 || - (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || - (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - StrokePoint(BPoint(xc-x,yc+y),d); - if ( useQuad4 || - (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || - (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - StrokePoint(BPoint(xc+x,yc+y),d); - } - - p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); - while (y>0) - { - y--; - py -= twoRx2; - if (p>0) - p += Rx2 - py; - else - { - x++; - px += twoRy2; - p += Rx2 - py +px; - } - - if ( useQuad1 || - (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || - (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - StrokePoint(BPoint(xc+x,yc-y),d); - if ( useQuad2 || - (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || - (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - StrokePoint(BPoint(xc-x,yc-y),d); - if ( useQuad3 || - (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || - (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - StrokePoint(BPoint(xc-x,yc+y),d); - if ( useQuad4 || - (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || - (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - StrokePoint(BPoint(xc+x,yc+y),d); - } - fCursorHandler.DriverShow(); - Invalidate(r); - Unlock(); -} - -/*! - \brief Called for all BView::StrokeBezier calls. - \param pts 4-element array of BPoints in the order of start, end, and then the two control points. - \param d draw data -*/ -void DisplayDriver::StrokeBezier(BPoint *pts, const DrawData *d) -{ - int i, numLines; - - Lock(); - BezierCurve curve(pts); - - if(fCursorHandler.IntersectsCursor(curve.Frame())) - fCursorHandler.DriverHide(); - - numLines = curve.points.CountItems()-1; - for (i=0; i0) - { - lastx = x; - lasty = y; - y--; - py -= twoRx2; - if (p>0) - p += Rx2 - py; - else - { - x++; - px += twoRy2; - p += Rx2 - py +px; - } - - StrokeLine(BPoint(xc+lastx,yc-lasty),BPoint(xc+x,yc-y),d); - StrokeLine(BPoint(xc-lastx,yc-lasty),BPoint(xc-x,yc-y),d); - StrokeLine(BPoint(xc-lastx,yc+lasty),BPoint(xc-x,yc+y),d); - StrokeLine(BPoint(xc+lastx,yc+lasty),BPoint(xc+x,yc+y),d); - } - fCursorHandler.DriverShow(); - Invalidate(r); - Unlock(); -} - -/*! - \brief Draws a line. Really. - \param start Starting point - \param end Ending point - \param c The color of the line -*/ -void DisplayDriver::StrokeLine(const BPoint &start, const BPoint &end, const RGBColor &color) -{ - Lock(); - if(fCursorHandler.IntersectsCursor(BRect(start,end))) - fCursorHandler.DriverHide(); - StrokeSolidLine(ROUND(start.x),ROUND(start.y),ROUND(end.x),ROUND(end.y),color); - - fCursorHandler.DriverShow(); - Invalidate(BRect(start,end)); - Unlock(); -} - -/*! - \brief Draws a line. Really. - \param start Starting point - \param end Ending point - \param d The relevant drawing data for this line -*/ -void DisplayDriver::StrokeLine(const BPoint &start, const BPoint &end, const DrawData *d) -{ - Lock(); - - if(fCursorHandler.IntersectsCursor(BRect(start,end))) - fCursorHandler.DriverHide(); - - if ( d->pensize == 1 ) - { - if ( d->clipReg ) - { - int i, numRects; - double left, right, y1, y2; - BRect clipRect; - LineCalc line(start,end); - numRects = d->clipReg->CountRects(); - for (i=0; iclipReg->RectAt(i); - left = MAX(line.MinX(), clipRect.left); - right = MIN(line.MaxX(), clipRect.right); - if ( right < left ) - continue; - y1 = line.GetY(left); - y2 = line.GetY(right); - if ( MAX(y1,y2) < clipRect.top ) - continue; - if ( MIN(y1,y2) > clipRect.bottom ) - continue; - if ( y1 < clipRect.top ) - { - y1 = clipRect.top; - left = line.GetX(y1); - } - if ( y1 > clipRect.bottom ) - { - y1 = clipRect.bottom; - left = line.GetX(y1); - } - if ( y2 < clipRect.top ) - { - y2 = clipRect.top; - right = line.GetX(y2); - } - if ( y2 > clipRect.bottom ) - { - y2 = clipRect.bottom; - right = line.GetX(y2); - } - StrokePatternLine(ROUND(left),ROUND(y1),ROUND(right),ROUND(y2),d); - } - } - else - StrokePatternLine(ROUND(start.x),ROUND(start.y),ROUND(end.x),ROUND(end.y),d); - } - else - { - BPoint corners[4]; - double halfWidth = .5*d->pensize; - corners[0] = start; - corners[1] = start; - corners[2] = end; - corners[3] = end; - if ( (start.x == end.x) && (start.y == end.y) ) - { - FillRect(BRect(start.x-halfWidth,start.y-halfWidth,start.x+halfWidth,start.y+halfWidth),d); - } - else - { - if ( start.x == end.x ) - { - corners[0].x += halfWidth; - corners[1].x -= halfWidth; - corners[2].x -= halfWidth; - corners[3].x += halfWidth; - } - else if ( start.y == end.y ) - { - corners[0].y -= halfWidth; - corners[1].y += halfWidth; - corners[2].y += halfWidth; - corners[3].y -= halfWidth; - } - else - { - double angle, xoffset, yoffset; - // TODO try to find a way to avoid atan2, sin, and cos - angle = atan2(end.y-start.y, end.x-start.x) + M_PI/4; - xoffset = halfWidth*cos(angle); - yoffset = halfWidth*sin(angle); - corners[0].x += xoffset; - corners[0].y += yoffset; - corners[1].x -= xoffset; - corners[1].y -= yoffset; - corners[2].x -= xoffset; - corners[2].y -= yoffset; - corners[3].x += xoffset; - corners[3].y += yoffset; - } - FillPolygon(corners,4,BRect(start,end),d); - } - } - fCursorHandler.DriverShow(); - Invalidate(BRect(start,end)); - Unlock(); -} - -void DisplayDriver::StrokePoint(const BPoint& pt, const RGBColor &color) -{ - StrokeLine(pt, pt, color); - Invalidate(BRect(pt,pt)); -} - -void DisplayDriver::StrokePoint(const BPoint& pt, const DrawData *d) -{ - StrokeLine(pt, pt, d); - Invalidate(BRect(pt,pt)); -} - -/*! - \brief Called for all BView::StrokePolygon calls - \param ptlist Array of BPoints defining the polygon. - \param numpts Number of points in the BPoint array. - \param d DrawData containing all of the other options -*/ -void DisplayDriver::StrokePolygon(BPoint *ptlist, int32 numpts, const BRect &bounds, const DrawData *d, bool is_closed) -{ - if(!ptlist) - return; - - Lock(); - if(fCursorHandler.IntersectsCursor(bounds)) - fCursorHandler.DriverHide(); - - for(int32 i=0; i<(numpts-1); i++) - StrokeLine(ptlist[i],ptlist[i+1],d); - if(is_closed) - StrokeLine(ptlist[numpts-1],ptlist[0],d); - - fCursorHandler.DriverShow(); - Invalidate(bounds); - Unlock(); -} - -/*! - \brief Called by Decorator - \param r BRect to be drawn - \param color Color in which to draw -*/ -void DisplayDriver::StrokeRect(const BRect &r, const RGBColor &color) -{ - Lock(); - - if(fCursorHandler.IntersectsCursor(r)) - fCursorHandler.DriverHide(); - StrokeSolidRect(r,color); - - fCursorHandler.DriverShow(); - Invalidate(r); - Unlock(); -} - -/*! - \brief Called for all BView::StrokeRect calls - \param r BRect to be drawn - \param d DrawData containing all of the other options -*/ -void DisplayDriver::StrokeRect(const BRect &r, const DrawData *d) -{ - Lock(); - if(fCursorHandler.IntersectsCursor(r)) - fCursorHandler.DriverHide(); - StrokeLine(r.LeftTop(),r.RightTop(),d); - StrokeLine(r.LeftTop(),r.LeftBottom(),d); - StrokeLine(r.RightTop(),r.RightBottom(),d); - StrokeLine(r.LeftBottom(),r.RightBottom(),d); - - fCursorHandler.DriverShow(); - Invalidate(r); - Unlock(); -} - -/*! - \brief Convenience function for server use - \param r BRegion to be stroked - \param d Data structure containing any other data necessary for the call. Always non-NULL. - -*/ -void DisplayDriver::StrokeRegion(BRegion& r, const DrawData *d) -{ - Lock(); - - if(fCursorHandler.IntersectsCursor(r.Frame())) - fCursorHandler.DriverHide(); - - for(int32 i=0; ifont.Size()*1.5; - intersection.right+=d->font.Size()*1.5*length; - if(fCursorHandler.IntersectsCursor(intersection)) - fCursorHandler.DriverHide(); - - BPoint point(pt); - - const ServerFont *font=&(d->font); - - FT_Face face; - FT_GlyphSlot slot; - FT_Matrix rmatrix,smatrix; - FT_UInt glyph_index=0, previous=0; - FT_Vector pen,delta,space,nonspace; - int16 error=0; - int32 strlength,i; - Angle rotation(font->Rotation()), shear(font->Shear()); - - bool antialias=true; - - if(font->Size()<18 && (font->Flags()& B_DISABLE_ANTIALIASING==1)) - antialias=false; - - // Originally, I thought to do this shear checking here, but it really should be - // done in BFont::SetShear() - float shearangle=shear.Value(); - if(shearangle>135) - shearangle=135; - if(shearangle<45) - shearangle=45; - - if(shearangle>90) - shear=90+((180-shearangle)*2); - else - shear=90-(90-shearangle)*2; - - error=FT_New_Face(ftlib, font->GetPath(), 0, &face); - if(error) - { - Unlock(); - return; - } - - slot=face->glyph; - - bool use_kerning=FT_HAS_KERNING(face) && font->Spacing()==B_STRING_SPACING; - - error=FT_Set_Char_Size(face, 0,int32(font->Size())*64,72,72); - if(error) - { - Unlock(); - return; - } - - // if we do any transformation, we do a call to FT_Set_Transform() here - - // First, rotate - rmatrix.xx = (FT_Fixed)( rotation.Cosine()*0x10000); - rmatrix.xy = (FT_Fixed)(-rotation.Sine()*0x10000); - rmatrix.yx = (FT_Fixed)( rotation.Sine()*0x10000); - rmatrix.yy = (FT_Fixed)( rotation.Cosine()*0x10000); - - // Next, shear - smatrix.xx = (FT_Fixed)(0x10000); - smatrix.xy = (FT_Fixed)(-shear.Cosine()*0x10000); - smatrix.yx = (FT_Fixed)(0); - smatrix.yy = (FT_Fixed)(0x10000); - - FT_Matrix_Multiply(&rmatrix,&smatrix); - - // Set up the increment value for escapement padding - space.x=int32(d->edelta.space * rotation.Cosine()*64); - space.y=int32(d->edelta.space * rotation.Sine()*64); - nonspace.x=int32(d->edelta.nonspace * rotation.Cosine()*64); - nonspace.y=int32(d->edelta.nonspace * rotation.Sine()*64); - - // set the pen position in 26.6 cartesian space coordinates - pen.x=(int32)point.x * 64; - pen.y=(int32)point.y * 64; - - slot=face->glyph; - - - strlength=strlen(string); - if(lengthbitmap, - BPoint(slot->bitmap_left,point.y-(slot->bitmap_top-point.y)), d); - else - BlitMono2RGB32(&slot->bitmap, - BPoint(slot->bitmap_left,point.y-(slot->bitmap_top-point.y)), d); - } - - // increment pen position - pen.x+=slot->advance.x; - pen.y+=slot->advance.y; - previous=glyph_index; - } - - // TODO: implement calculation of invalid rectangle in DisplayDriver::DrawString properly - BRect r; - r.left=MIN(point.x,pen.x>>6); - r.right=MAX(point.x,pen.x>>6); - r.top=point.y-face->height; - r.bottom=point.y+face->height; - - fCursorHandler.DriverShow(); - Invalidate(r); - - // Update the caller's pen position - d->penlocation.x=pen.x / 64; - d->penlocation.y=pen.y / 64; - - FT_Done_Face(face); - - Unlock(); - -} - -/*! - \brief Gets the width of a string in pixels - \param string Source null-terminated string - \param length Number of characters in the string - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \return Width of the string in pixels - - This corresponds to BView::StringWidth. -*/ -float DisplayDriver::StringWidth(const char *string, int32 length, const DrawData *d) -{ - if(!string || !d) - return 0.0; - Lock(); - - const ServerFont *font=&(d->font); - - FT_Face face; - FT_GlyphSlot slot; - FT_UInt glyph_index=0, previous=0; - FT_Vector pen,delta; - int16 error=0; - int32 strlength,i; - float returnval; - - error=FT_New_Face(ftlib, font->GetPath(), 0, &face); - if(error) - { - Unlock(); - return 0.0; - } - - slot=face->glyph; - - bool use_kerning=FT_HAS_KERNING(face) && font->Spacing()==B_STRING_SPACING; - - error=FT_Set_Char_Size(face, 0,int32(font->Size())*64,72,72); - if(error) - { - Unlock(); - return 0.0; - } - - // set the pen position in 26.6 cartesian space coordinates - pen.x=0; - - slot=face->glyph; - - strlength=strlen(string); - if(lengthadvance.x; - previous=glyph_index; - } - - FT_Done_Face(face); - Unlock(); - - returnval=pen.x>>6; - return returnval; -} - -/*! - \brief Gets the height of a string in pixels - \param string Source null-terminated string - \param length Number of characters in the string - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \return Height of the string in pixels - - The height calculated in this function does not include any padding - just the - precise maximum height of the characters within and does not necessarily equate - with a font's height, i.e. the strings 'case' and 'alps' will have different values - even when called with all other values equal. -*/ -float DisplayDriver::StringHeight(const char *string, int32 length, const DrawData *d) -{ - if(!string || !d) - return 0.0; - Lock(); - - const ServerFont *font=&(d->font); - - FT_Face face; - FT_GlyphSlot slot; - int16 error=0; - int32 strlength,i; - float returnval=0.0,ascent=0.0,descent=0.0; - - error=FT_New_Face(ftlib, font->GetPath(), 0, &face); - if(error) - { - Unlock(); - return 0.0; - } - - slot=face->glyph; - - error=FT_Set_Char_Size(face, 0,int32(font->Size())*64,72,72); - if(error) - { - Unlock(); - return 0.0; - } - - slot=face->glyph; - - strlength=strlen(string); - if(lengthmetrics.horiBearingYmetrics.height) - descent=MAX((slot->metrics.height-slot->metrics.horiBearingY)>>6,descent); - else - ascent=MAX(slot->bitmap.rows,ascent); - } - - FT_Done_Face(face); - - Unlock(); - returnval=ascent+descent; - return returnval; -} - -/*! - \brief Retrieves the bounding box each character in the string - \param string Source null-terminated string - \param count Number of characters in the string - \param mode Metrics mode for either screen or printing - \param delta Optional glyph padding. This value may be NULL. - \param rectarray Array of BRect objects which will have at least count elements - \param d Data structure containing any other data necessary for the call. Always non-NULL. - - See BFont::GetBoundingBoxes for more details on this function. -*/ -void DisplayDriver::GetBoundingBoxes(const char *string, int32 count, - font_metric_mode mode, escapement_delta *delta, BRect *rectarray, const DrawData *d) -{ - // TODO: Implement DisplayDriver::GetBoundingBoxes -} - -/*! - \brief Retrieves the escapements for each character in the string - \param string Source null-terminated string - \param charcount Number of characters in the string - \param delta Optional glyph padding. This value may be NULL. - \param escapements Array of escapement_delta objects which will have at least charcount elements - \param offsets Actual offset values when iterating over the string. This array will also - have at least charcount elements and the values placed therein will reflect - the current kerning/spacing mode. - \param d Data structure containing any other data necessary for the call. Always non-NULL. - - See BFont::GetEscapements for more details on this function. -*/ -void DisplayDriver::GetEscapements(const char *string, int32 charcount, - escapement_delta *delta, escapement_delta *escapements, escapement_delta *offsets, const DrawData *d) -{ - // TODO: Implement DisplayDriver::GetEscapements -} - -/*! - \brief Retrieves the inset values of each glyph from its escapement values - \param string Source null-terminated string - \param charcount Number of characters in the string - \param edgearray Array of edge_info objects which will have at least charcount elements - \param d Data structure containing any other data necessary for the call. Always non-NULL. - - See BFont::GetEdges for more details on this function. -*/ -void DisplayDriver::GetEdges(const char *string, int32 charcount, edge_info *edgearray, const DrawData *d) -{ - // TODO: Implement DisplayDriver::GetEdges -} - -/*! - \brief Determines whether a font contains a certain string of characters - \param string Source null-terminated string - \param charcount Number of characters in the string - \param hasarray Array of booleans which will have at least charcount elements - - See BFont::GetHasGlyphs for more details on this function. -*/ -void DisplayDriver::GetHasGlyphs(const char *string, int32 charcount, bool *hasarray) -{ - // TODO: Implement DisplayDriver::GetHasGlyphs -} - -/*! - \brief Truncates an array of strings to a certain width - \param instrings Array of null-terminated strings - \param stringcount Number of strings passed to the function - \param mode Truncation mode - \param maxwidth Maximum width for all strings - \param outstrings String array provided by the caller into which the truncated strings are - to be placed. - - See BFont::GetTruncatedStrings for more details on this function. -*/ -void DisplayDriver::GetTruncatedStrings(const char **instrings,const int32 &stringcount, - const uint32 &mode, const float &maxwidth, char **outstrings) -{ - // TODO: Implement DisplayDriver::GetTruncatedStrings } /*! @@ -2353,7 +62,8 @@ void DisplayDriver::GetTruncatedStrings(const char **instrings,const int32 &stri maintained accurately. Subclasses must include a call to DisplayDriver::HideCursor for proper state tracking. */ -void DisplayDriver::HideCursor(void) +void +DisplayDriver::HideCursor() { Lock(); fCursorHandler.Hide(); @@ -2365,10 +75,11 @@ void DisplayDriver::HideCursor(void) \return true if hidden or obscured, false if not. */ -bool DisplayDriver::IsCursorHidden(void) +bool +DisplayDriver::IsCursorHidden() { Lock(); - bool value=fCursorHandler.IsHidden(); + bool value = fCursorHandler.IsHidden(); Unlock(); return value; @@ -2382,10 +93,11 @@ bool DisplayDriver::IsCursorHidden(void) cursor is obscured should be made and if so, a call to _SetCursorObscured(false) should be made the cursor in addition to displaying at the passed coordinates. */ -void DisplayDriver::MoveCursorTo(const float &x, const float &y) +void +DisplayDriver::MoveCursorTo(const float &x, const float &y) { Lock(); - fCursorHandler.MoveTo(BPoint(x,y)); + fCursorHandler.MoveTo(BPoint(x, y)); Unlock(); } @@ -2397,7 +109,8 @@ void DisplayDriver::MoveCursorTo(const float &x, const float &y) maintained accurately. Subclasses must call DisplayDriver::ShowCursor at some point to ensure proper state tracking. */ -void DisplayDriver::ShowCursor(void) +void +DisplayDriver::ShowCursor() { Lock(); fCursorHandler.Show(); @@ -2412,7 +125,8 @@ void DisplayDriver::ShowCursor(void) will be made by the system before the next MoveCursorTo call to show the cursor if it is obscured. */ -void DisplayDriver::ObscureCursor(void) +void +DisplayDriver::ObscureCursor() { Lock(); fCursorHandler.Obscure(); @@ -2428,7 +142,8 @@ void DisplayDriver::ObscureCursor(void) a copy of the cursor passed to it. The default version of this function hides the cursory, replaces it, and shows the cursor if previously visible. */ -void DisplayDriver::SetCursor(ServerCursor *cursor) +void +DisplayDriver::SetCursor(ServerCursor *cursor) { Lock(); fCursorHandler.SetCursor(cursor); @@ -2436,29 +151,54 @@ void DisplayDriver::SetCursor(ServerCursor *cursor) } //! Returns the cursor's current position -BPoint DisplayDriver::GetCursorPosition(void) +BPoint +DisplayDriver::GetCursorPosition() { Lock(); - BPoint value=fCursorHandler.GetPosition(); + BPoint pos = fCursorHandler.GetPosition(); Unlock(); - return value; + return pos; } /*! \brief Returns whether or not the cursor is currently obscured \return True if obscured, false if not. */ -bool DisplayDriver::IsCursorObscured(bool state) +bool +DisplayDriver::IsCursorObscured(bool state) { Lock(); - bool value=fCursorHandler.IsObscured(); + bool obscured = fCursorHandler.IsObscured(); Unlock(); - return value; + return obscured; } -// Protected Internal Functions +/*! + \brief Initializes the driver object. + \return true if successful, false if not + + Initialize sets up the driver for display, including the initial clearing + of the screen. If things do not go as they should, false should be returned. +*/ +bool +DisplayDriver::Initialize() +{ + fCursorHandler.SetCursor(new ServerCursor(default_cursor_data)); + return true; +} + +/*! + \brief Shuts down the driver's video subsystem + + Any work done by Initialize() should be undone here. Note that Shutdown() is + called even if Initialize() was unsuccessful. +*/ +void +DisplayDriver::Shutdown() +{ +} /*! \brief Locks the driver @@ -2469,22 +209,25 @@ bool DisplayDriver::IsCursorObscured(bool state) member function should lock the driver before doing anything else. Functions internal to the driver (protected/private) need not do this. */ -bool DisplayDriver::Lock(bigtime_t timeout) +bool +DisplayDriver::Lock(bigtime_t timeout) { - if(timeout==B_INFINITE_TIMEOUT) - return _locker->Lock(); + if (timeout == B_INFINITE_TIMEOUT) + return fLocker.Lock(); - return (_locker->LockWithTimeout(timeout)==B_OK)?true:false; + return (fLocker.LockWithTimeout(timeout) == B_OK) ? true : false; } /*! \brief Unlocks the driver */ -void DisplayDriver::Unlock(void) +void +DisplayDriver::Unlock() { - _locker->Unlock(); + fLocker.Unlock(); } +// Protected Internal Functions /* \brief Sets the screen mode to specified resolution and color depth. \param mode Data structure as defined in Screen.h @@ -2492,103 +235,24 @@ void DisplayDriver::Unlock(void) Subclasses must include calls to _SetDepth, _SetHeight, _SetWidth, and _SetMode to update the state variables kept internally by the DisplayDriver class. */ -void DisplayDriver::SetMode(const display_mode &mode) +void +DisplayDriver::SetMode(const display_mode &mode) { + fDisplayMode = mode; } -/*! - \brief Sets the attributes in mode to reflect the current display mode - \param mode Structure to receive the current display mode's status -*/ -void DisplayDriver::GetMode(display_mode *mode) +// GetMode +void +DisplayDriver::GetMode(display_mode *mode) { - if(!mode) + if (!mode) return; Lock(); - *mode=fDisplayMode; + *mode = fDisplayMode; Unlock(); } -/*! - \brief Dumps the contents of the frame buffer to a file. - \param path Path and leaf of the file to be created without an extension - \return False if unimplemented or unsuccessful. True if otherwise. - - Subclasses should add an extension based on what kind of file is saved -*/ -bool DisplayDriver::DumpToFile(const char *path) -{ - return false; -} - -/*! - \brief Returns a new ServerBitmap containing the contents of the frame buffer - \return A new ServerBitmap containing the contents of the frame buffer or NULL if unsuccessful -*/ -ServerBitmap *DisplayDriver::DumpToBitmap(void) -{ - return NULL; -} - -/*! - \brief Draws a series of lines - optimized for speed - \param numlines Number of lines to be drawn - \param linedata Array of LineArrayData objects - \param d current DrawData settings -*/ -void DisplayDriver::StrokeLineArray(const int32 &numlines, const LineArrayData *linedata,const DrawData *d) -{ - if(!d || !linedata) - return; - - const LineArrayData *dataindex=linedata; - BRect r(0,0,0,0); - DrawData drawdata; - - Lock(); - - fCursorHandler.DriverHide(); - - drawdata = *d; - - r.Set(linedata->pt1.x,linedata->pt1.y,linedata->pt1.x,linedata->pt1.y); - - for (int32 i=0; icolor; - - // Keep track of the invalid region - if (dataindex->pt1.x < r.left) - r.left = dataindex->pt1.x; - if (dataindex->pt1.y < r.top) - r.top = dataindex->pt1.y; - if (dataindex->pt1.x > r.right) - r.right = dataindex->pt1.x; - if (dataindex->pt1.y > r.bottom) - r.bottom = dataindex->pt1.y; - - if (dataindex->pt2.x < r.left) - r.left = dataindex->pt2.x; - if (dataindex->pt2.y < r.top) - r.top = dataindex->pt2.y; - if (dataindex->pt2.x > r.right) - r.right = dataindex->pt2.x; - if (dataindex->pt2.y > r.bottom) - r.bottom = dataindex->pt2.y; - - StrokeLine(dataindex->pt1,dataindex->pt2,&drawdata); - } - - Invalidate(r); - - fCursorHandler.DriverShow(); - - Unlock(); -} - - /*! \brief Sets the driver's Display Power Management System state \param state The state which the driver should enter @@ -2598,11 +262,14 @@ void DisplayDriver::StrokeLineArray(const int32 &numlines, const LineArrayData * particular DPMS state. Use DPMSCapabilities to find out the supported states. The default implementation supports only B_DPMS_ON. */ -status_t DisplayDriver::SetDPMSMode(const uint32 &state) +status_t +DisplayDriver::SetDPMSMode(const uint32 &state) { - if(state!=B_DPMS_ON) + if (state != B_DPMS_ON) return B_ERROR; + fDPMSState = state; + return B_OK; } @@ -2610,7 +277,8 @@ status_t DisplayDriver::SetDPMSMode(const uint32 &state) \brief Returns the driver's current DPMS state \return The driver's current DPMS state */ -uint32 DisplayDriver::DPMSMode(void) const +uint32 +DisplayDriver::DPMSMode() const { return fDPMSState; } @@ -2622,420 +290,9 @@ uint32 DisplayDriver::DPMSMode(void) const The capabilities are the modes supported by the driver. The default implementation allows only B_DPMS_ON. Other possible states are B_DPMS_STANDBY, SUSPEND, and OFF. */ -uint32 DisplayDriver::DPMSCapabilities(void) const +uint32 +DisplayDriver::DPMSCapabilities() const { return fDPMSCaps; } -/*! - \brief Returns data about the rendering device - \param info Pointer to an object to receive the device info - \return B_OK if this function is supported, B_UNSUPPORTED if not - - The default implementation of this returns B_UNSUPPORTED and does nothing. - - From Accelerant.h: - - uint32 version; // structure version number - char name[32]; // a name the user will recognize the device by - char chipset[32]; // the chipset used by the device - char serial_no[32]; // serial number for the device - uint32 memory; // amount of memory on the device, in bytes - uint32 dac_speed; // nominal DAC speed, in MHz - -*/ -status_t DisplayDriver::GetDeviceInfo(accelerant_device_info *info) -{ - return B_ERROR; -} - -/*! - \brief Returns data about the rendering device - \param mode_list Pointer to receive a list of modes. - \param count The number of modes in mode_list - \return B_OK if this function is supported, B_UNSUPPORTED if not - - The default implementation of this returns B_UNSUPPORTED and does nothing. -*/ -status_t DisplayDriver::GetModeList(display_mode **mode_list, uint32 *count) -{ - return B_UNSUPPORTED; -} - -/*! - \brief Obtains the minimum and maximum pixel throughput - \param mode Structure to receive the data for the given mode - \param low Recipient of the minimum clock rate - \param high Recipient of the maximum clock rate - \return - - \c B_OK: Everything is kosher - - \c B_UNSUPPORTED: The function is unsupported - - \c B_ERROR: No known pixel clock limits - - - This function returns the minimum and maximum "pixel clock" rates, in - thousands-of-pixels per second, that are possible for the given mode. See - BScreen::GetPixelClockLimits() for more information. - - The default implementation of this returns B_UNSUPPORTED and does nothing. -*/ -status_t DisplayDriver::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high) -{ - return B_UNSUPPORTED; -} - -/*! - \brief Obtains the timing constraints of the current display mode. - \param dtc Object to receive the constraints - \return - - \c B_OK: Everything is kosher - - \c B_UNSUPPORTED: The function is unsupported - - \c B_ERROR: No known timing constraints - - The default implementation of this returns B_UNSUPPORTED and does nothing. -*/ -status_t DisplayDriver::GetTimingConstraints(display_timing_constraints *dtc) -{ - return B_UNSUPPORTED; -} - -/*! - \brief Obtains the timing constraints of the current display mode. - \param dtc Object to receive the constraints - \return - - \c B_OK: Everything is kosher - - \c B_UNSUPPORTED: The function is unsupported - - The default implementation of this returns B_UNSUPPORTED and does nothing. - This is mostly the responsible of the hardware driver if the DisplayDriver - interfaces with actual hardware. -*/ -status_t DisplayDriver::ProposeMode(display_mode *candidate, const display_mode *low, const display_mode *high) -{ - return B_UNSUPPORTED; -} - -/*! - \brief Waits for the device's vertical retrace - \param timeout Amount of time to wait until retrace. Default is B_INFINITE_TIMEOUT - \return - - \c B_OK: Everything is kosher - - \c B_ERROR: The function timed out before retrace - - \c B_UNSUPPORTED: The function is unsupported - - The default implementation of this returns B_UNSUPPORTED and does nothing. -*/ -status_t DisplayDriver::WaitForRetrace(bigtime_t timeout) -{ - return B_UNSUPPORTED; -} - - -/*! - \brief Obtains the current cursor for the driver. - \return Pointer to the current cursor object. - - Do NOT delete this pointer - change pointers via SetCursor. This call will be - necessary for blitting the cursor to the screen and other such tasks. -*/ -ServerCursor *DisplayDriver::_GetCursor(void) -{ - Lock(); - ServerCursor *c=fCursorHandler.GetCursor(); - Unlock(); - - return c; -} - -void DisplayDriver::HLinePatternThick(int32 x1, int32 x2, int32 y) -{ -} - -void DisplayDriver::VLinePatternThick(int32 x1, int32 x2, int32 y) -{ -} - -/*! - \brief Draws a point of a specified thickness - \param x The x coordinate (not guaranteed to be in bounds) - \param y The y coordinate (not guaranteed to be in bounds) - \param thick The thickness of the point - \param pat The PatternHandler which detemines pixel colors - Must be implemented in subclasses -*/ -void DisplayDriver::SetThickPatternPixel(int x, int y) -{ -} - -/*! - \brief Draws a horizontal line - \param x1 The first x coordinate (guaranteed to be in bounds) - \param x2 The second x coordinate (guaranteed to be in bounds) - \param y The y coordinate (guaranteed to be in bounds) - \param pat The PatternHandler which detemines pixel colors - Must be implemented in subclasses -*/ - -void DisplayDriver::BlitMono2RGB32(FT_Bitmap *src, const BPoint &pt, const DrawData *d) -{ - rgb_color color=d->highcolor.GetColor32(); - - // pointers to the top left corner of the area to be copied in each bitmap - uint8 *srcbuffer, *destbuffer; - FBBitmap framebuffer; - - if(!AcquireBuffer(&framebuffer)) - { - printf("ERROR: Couldn't acquire framebuffer in BlitMono2RGB32\n"); - return; - } - - // index pointers which are incremented during the course of the blit - uint8 *srcindex, *destindex, *rowptr, value; - - // increment values for the index pointers - int32 srcinc=src->pitch, destinc=framebuffer.BytesPerRow(); - - int16 i,j,k, srcwidth=src->pitch, srcheight=src->rows; - int32 x=(int32)pt.x,y=(int32)pt.y; - - // starting point in source bitmap - srcbuffer=(uint8*)src->buffer; - - if(y<0) - { - if(yframebuffer.Bounds().IntegerHeight()) - { - if(y>pt.y) - y--; - srcheight-=(y+srcheight-1)-framebuffer.Bounds().IntegerHeight(); - } - - if(x+srcwidth>framebuffer.Bounds().IntegerWidth()) - { - if(x>pt.x) - x--; - srcwidth-=(x+srcwidth-1)-framebuffer.Bounds().IntegerWidth(); - } - - if(x<0) - { - if(x>3; - srcwidth-=0-x; - destbuffer+=(0-x)*4; - } - - // starting point in destination bitmap - destbuffer=(uint8*)framebuffer.Bits()+int32( (pt.y*framebuffer.BytesPerRow())+(pt.x*4) ); - - srcindex=srcbuffer; - destindex=destbuffer; - - for(i=0; ihighcolor.GetColor32(), lowcolor=d->lowcolor.GetColor32(); float rstep,gstep,bstep,astep; - - rstep=float(highcolor.red-lowcolor.red)/255.0; - gstep=float(highcolor.green-lowcolor.green)/255.0; - bstep=float(highcolor.blue-lowcolor.blue)/255.0; - astep=float(highcolor.alpha-lowcolor.alpha)/255.0; - - // increment values for the index pointers - int32 x=(int32)pt.x, - y=(int32)pt.y, - srcinc=src->pitch, -// destinc=dest->BytesPerRow(), - destinc=framebuffer.BytesPerRow(), - srcwidth=src->width, - srcheight=src->rows, - incval=0; - - int16 i,j; - - // starting point in source bitmap - srcbuffer=(uint8*)src->buffer; - - // starting point in destination bitmap - destbuffer=(uint8*)framebuffer.Bits()+(y*framebuffer.BytesPerRow()+(x*4)); - - - if(y<0) - { - if(yframebuffer.Bounds().IntegerHeight()) - { - if(y>pt.y) - y--; - srcheight-=(y+srcheight-1)-framebuffer.Bounds().IntegerHeight(); - } - - if(x+srcwidth>framebuffer.Bounds().IntegerWidth()) - { - if(x>pt.x) - x--; - srcwidth-=(x+srcwidth-1)-framebuffer.Bounds().IntegerWidth(); - } - - if(x<0) - { - if(xdraw_mode==B_OP_COPY) - { - rowptr[0]=uint8(highcolor.blue-(value*bstep)); - rowptr[1]=uint8(highcolor.green-(value*gstep)); - rowptr[2]=uint8(highcolor.red-(value*rstep)); - rowptr[3]=255; - } - else - if(d->draw_mode==B_OP_OVER) - { - if(highcolor.alpha>127) - { - rowptr[0]=uint8(highcolor.blue-(value*(float(highcolor.blue-rowptr[0])/255.0))); - rowptr[1]=uint8(highcolor.green-(value*(float(highcolor.green-rowptr[1])/255.0))); - rowptr[2]=uint8(highcolor.red-(value*(float(highcolor.red-rowptr[2])/255.0))); - rowptr[3]=255; - } - } - } - rowptr+=4; - - } - - srcindex+=srcinc; - destindex+=destinc; - } - ReleaseBuffer(); -} - -bool DisplayDriver::AcquireBuffer(FBBitmap *bmp) -{ - return false; -} - -void DisplayDriver::ReleaseBuffer(void) -{ -} - -void DisplayDriver::Invalidate(const BRect &r) -{ -} - -void DisplayDriver::Blit(const BRect &src, const BRect &dest, const DrawData *d) -{ -} - -void DisplayDriver::FillSolidRect(const BRect &rect, const RGBColor &color) -{ -} - -void DisplayDriver::FillPatternRect(const BRect &rect, const DrawData *d) -{ -} - -/* Draws a line with pensize 1. Coordinates are guarenteed to be in bounds */ -void DisplayDriver::StrokeSolidLine(int32 x1, int32 y1, int32 x2, int32 y2, const RGBColor &color) -{ -} - -// Draws a line with pensize 1. Coordinates are guarenteed to be in bounds -void DisplayDriver::StrokePatternLine(int32 x1, int32 y1, int32 x2, int32 y2, const DrawData *d) -{ -} - -void DisplayDriver::StrokeSolidRect(const BRect &rect, const RGBColor &color) -{ -} - -void DisplayDriver::CopyBitmap(ServerBitmap *bitmap, const BRect &source, const BRect &dest, const DrawData *d) -{ -} - -void DisplayDriver::CopyToBitmap(ServerBitmap *target, const BRect &source) -{ -} - -void DisplayDriver::ConstrainClippingRegion(BRegion *reg) -{ -} diff --git a/src/servers/app/DisplayDriverImpl.cpp b/src/servers/app/DisplayDriverImpl.cpp new file mode 100644 index 0000000000..76814a69c8 --- /dev/null +++ b/src/servers/app/DisplayDriverImpl.cpp @@ -0,0 +1,2810 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2005, Haiku, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// 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 +// AUTHORS OR COPYRIGHT HOLDERS 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. +// +// File Name: DisplayDriverImpl.cpp +// Authors: DarkWyrm +// Gabe Yoder +// Stephan Aßmus +// Description: Mostly abstract class which handles all graphics output +// for the server +// +//------------------------------------------------------------------------------ +#include + +#include + +#include "Angle.h" +#include "CursorData.h" +#include "FontFamily.h" +#include "RectUtils.h" +#include "ServerCursor.h" +#include "Utils.h" + +#include "DisplayDriverImpl.h" + +// TODO: Implement all functions. Bounds checking needs to be +// handled by the public drawing functions. +// Add clipping and make sure public functions have Lock & Unlock. + +static Blitter blitter; + +/*! + \brief Sets up internal variables needed by all DisplayDriverImpl subclasses +*/ +DisplayDriverImpl::DisplayDriverImpl() + : DisplayDriver() +{ +} + + +/*! + \brief Does nothing +*/ +DisplayDriverImpl::~DisplayDriverImpl() +{ +} + +/*! + \brief Called for all BView::CopyBits calls + \param src Source rectangle. + \param dest Destination rectangle. + + If the destination is not the same size as the source, the source should be scaled to fit. +*/ +void DisplayDriverImpl::CopyBits(const BRect &src, const BRect &dest, const DrawData *d) +{ + if(!d) + return; + + Lock(); + + if(fCursorHandler.IntersectsCursor(dest)) + fCursorHandler.DriverHide(); + Blit(src,dest,d); + fCursorHandler.DriverShow(); + Unlock(); +} + +/*! + \brief A screen-to-screen blit (of sorts) which copies a BRegion + \param src Source region + \param lefttop Offset to which the region will be copied +*/ +void +DisplayDriverImpl::CopyRegion(BRegion *src, const BPoint &lefttop) +{ + // TODO: Implement DisplayDriverImpl::CopyRegion +} + +/*! + \brief Inverts the colors in the rectangle. + \param r Rectangle of the area to be inverted. Guaranteed to be within bounds. +*/ +void DisplayDriverImpl::InvertRect(const BRect &r) +{ +} + +/*! + \brief Called for all BView::DrawBitmap calls + \param region Destination rects in screen coordinates + \param bmp Bitmap to be drawn. It will always be non-NULL and valid. The color + space is not guaranteed to match. + \param src Source rectangle + \param dest Destination rectangle. Source will be scaled to fit if not the same size. + \param d Data structure containing any other data necessary for the call. Always non-NULL. +*/ +void +DisplayDriverImpl::DrawBitmap(BRegion *region, ServerBitmap *bitmap, + const BRect &source, const BRect &dest, + const DrawData *d) +{ + // TODO: make sure we all mean the same region -> see PicturePlayer line 257 + if (!region) + return; + + Lock(); + + FBBitmap frameBuffer; + FBBitmap *bmp = &frameBuffer; + + blitter.Select(32, 32); + + if(!AcquireBuffer(&frameBuffer)) + { + debugger("ERROR: Couldn't acquire framebuffer in DrawBitmap()\n"); + Unlock(); + return; + } + + if(fCursorHandler.IntersectsCursor(dest)) + fCursorHandler.DriverHide(); + + uint8 colorspace_size = (bitmap->BitsPerPixel() + 7) / 8; + + int32 count = region->CountRects(); + + BRect bitmaprect(bitmap->Bounds()); + BRect sourcerect(source); + + BRect destrect(dest); + destrect.right *= d->scale; + destrect.bottom *= d->scale; + + if(sourcerect.left < 0) sourcerect.left = 0; + if(sourcerect.top < 0) sourcerect.top = 0; + + if(sourcerect.Width() > bitmaprect.Width()) + sourcerect.right = bitmaprect.left + bitmaprect.Width(); + + if(sourcerect.Height() > bitmaprect.Height()) + sourcerect.bottom = bitmaprect.top + bitmaprect.Height(); + + int32 sourcewidth = (int32)sourcerect.Width() + 1; + int32 sourceheight = (int32)sourcerect.Height() + 1; + + int32 destwidth = (int32)destrect.Width() + 1; + int32 destheight = (int32)destrect.Height() + 1; + + int32 xscale_factor = (sourcewidth << 16) / destwidth; + int32 yscale_factor = (sourceheight << 16) / destheight; + + uint8 *src_bits = (uint8 *)bitmap->Bits(); + uint8 *dest_bits = (uint8*)bmp->Bits(); + + int32 src_row = bitmap->BytesPerRow(); + int32 dest_row = bmp->BytesPerRow(); + + src_bits += uint32((sourcerect.top * src_row) + (sourcerect.left * colorspace_size)); + + integer_rect src_integer_rectangle = BRect_to_integer_rect(sourcerect); + integer_rect dst_integer_rectangle = BRect_to_integer_rect(destrect); + + int32 xscale_position = 0, yscale_position = 0, clipped_xscale_position = 0; + + for(int32 c = 0; c < count; c++) + { + integer_rect screen_integer_rect = BRect_to_integer_rect(region->RectAt(c)); + integer_rect src_integer_rect = src_integer_rectangle; + integer_rect dst_integer_rect = dst_integer_rectangle; + + xscale_position = 0, yscale_position = 0, clipped_xscale_position = 0; + + if(dst_integer_rect.x < screen_integer_rect.x) + { + dst_integer_rect.x -= screen_integer_rect.x; + dst_integer_rect.w += dst_integer_rect.x; + src_integer_rect.x -= dst_integer_rect.x; + dst_integer_rect.x = screen_integer_rect.x; + } + + if(dst_integer_rect.y < screen_integer_rect.y) + { + dst_integer_rect.y -= screen_integer_rect.y; + dst_integer_rect.h += dst_integer_rect.y; + src_integer_rect.y -= dst_integer_rect.y; + dst_integer_rect.y = screen_integer_rect.y; + } + + if(dst_integer_rect.w > screen_integer_rect.w) + dst_integer_rect.w = screen_integer_rect.w; + + if(dst_integer_rect.h > screen_integer_rect.h) + dst_integer_rect.h = screen_integer_rect.h; + + if(src_integer_rect.x > src_integer_rectangle.x) + { + int32 x_scale_pixel_multiply = src_integer_rect.x - src_integer_rectangle.x; + clipped_xscale_position = xscale_factor * x_scale_pixel_multiply; + } + + if(src_integer_rect.y > src_integer_rectangle.y) + { + int32 y_scale_pixel_multiply = src_integer_rect.y - src_integer_rectangle.y; + yscale_position = yscale_factor * y_scale_pixel_multiply; + } + + if(dst_integer_rect.w > 0 && dst_integer_rect.h > 0) + { + uint8 *src_data = src_bits; + uint8 *dst_data = (uint8 *)dest_bits + dst_integer_rect.y * dest_row + dst_integer_rect.x * colorspace_size; + + while(dst_integer_rect.h--) + { + xscale_position = clipped_xscale_position; + uint8 *s = (uint8 *)((uint8 *)src_data + (yscale_position >> 16) * src_row); + uint8 *d = (uint8 *)((uint8 *)dst_data); + + blitter.Draw(s, d, dst_integer_rect.w, xscale_position, xscale_factor); + #if 0 + for(int32 x = 0; x < dst_integer_rect.w; x++) + { + *d++ = s[xscale_position >> 16]; + xscale_position += xscale_factor; + } + #endif + dst_data += dest_row; + yscale_position += yscale_factor; + } + } + } + + fCursorHandler.DriverShow(); + ReleaseBuffer(); + Unlock(); + Invalidate(destrect); +} + +void DisplayDriverImpl::CopyRegionList(BList* list, BList* pList, int32 rCount, BRegion* clipReg) +{ + Lock(); + + FBBitmap frameBuffer; + FBBitmap *bmp = &frameBuffer; + + if(!AcquireBuffer(&frameBuffer)) + { + debugger("ERROR: Couldn't acquire framebuffer in CopyRegionList()\n"); + Unlock(); + return; + } + + fCursorHandler.DriverHide(); + + + uint32 bytesPerPixel = bmp->BytesPerRow() / bmp->Bounds().IntegerWidth(); + BList rectList; + int32 i, k; + uint8 *bitmapBits = (uint8*)bmp->Bits(); + int32 Bwidth = bmp->Bounds().IntegerWidth() + 1; + int32 Bheight = bmp->Bounds().IntegerHeight() + 1; + + for(k=0; k < rCount; k++) + { + BRegion *reg = (BRegion*)list->ItemAt(k); + + int32 rectCount = reg->CountRects(); + for(i=0; i < rectCount; i++) + { + BRect r = reg->RectAt(i); + uint8 *rectCopy; + uint8 *srcAddress; + uint8 *destAddress; + int32 firstRow, lastRow; + int32 firstCol, lastCol; + int32 copyLength; + int32 copyRows; + + firstRow = (int32)(r.top < 0? 0: r.top); + lastRow = (int32)(r.bottom > (Bheight-1)? (Bheight-1): r.bottom); + firstCol = (int32)(r.left < 0? 0: r.left); + lastCol = (int32)(r.right > (Bwidth-1)? (Bwidth-1): r.right); + copyLength = (lastCol - firstCol + 1) < 0? 0: (lastCol - firstCol + 1); + copyRows = (lastRow - firstRow + 1) < 0? 0: (lastRow - firstRow + 1); + + rectCopy = (uint8*)malloc(copyLength * copyRows * bytesPerPixel); + + srcAddress = bitmapBits + (((firstRow) * Bwidth + firstCol) * bytesPerPixel); + destAddress = rectCopy; + + for (int32 j = 0; j < copyRows; j++) + { + uint8 *destRowAddress = destAddress + (j * copyLength * bytesPerPixel); + uint8 *srcRowAddress = srcAddress + (j * Bwidth * bytesPerPixel); + memcpy(destRowAddress, srcRowAddress, copyLength * bytesPerPixel ); + } + + rectList.AddItem(rectCopy); + } + } + + int32 item = 0; + for(k=0; k < rCount; k++) + { + BRegion *reg = (BRegion*)list->ItemAt(k); + + int32 rectCount = reg->CountRects(); + for(i=0; i < rectCount; i++) + { + BRect r = reg->RectAt(i); + uint8 *rectCopy; + uint8 *srcAddress; + uint8 *destAddress; + int32 firstRow, lastRow; + int32 firstCol, lastCol; + int32 copyLength, copyLength2; + int32 copyRows, copyRows2; + + firstRow = (int32)(r.top < 0? 0: r.top); + lastRow = (int32)(r.bottom > (Bheight-1)? (Bheight-1): r.bottom); + firstCol = (int32)(r.left < 0? 0: r.left); + lastCol = (int32)(r.right > (Bwidth-1)? (Bwidth-1): r.right); + copyLength = (lastCol - firstCol + 1) < 0? 0: (lastCol - firstCol + 1); + copyRows = (lastRow - firstRow + 1) < 0? 0: (lastRow - firstRow + 1); + + rectCopy = (uint8*)rectList.ItemAt(item++); + + srcAddress = rectCopy; + + r.Set(firstCol, firstRow, lastCol, lastRow); + r.OffsetBy( *((BPoint*)pList->ItemAt(k%rCount)) ); + firstRow = (int32)(r.top < 0? 0: r.top); + lastRow = (int32)(r.bottom > (Bheight-1)? (Bheight-1): r.bottom); + firstCol = (int32)(r.left < 0? 0: r.left); + lastCol = (int32)(r.right > (Bwidth-1)? (Bwidth-1): r.right); + copyLength2 = (lastCol - firstCol + 1) < 0? 0: (lastCol - firstCol + 1); + copyRows2 = (lastRow - firstRow + 1) < 0? 0: (lastRow - firstRow + 1); + + destAddress = bitmapBits + (((firstRow) * Bwidth + firstCol) * bytesPerPixel); + + int32 minLength = copyLength < copyLength2? copyLength: copyLength2; + int32 minRows = copyRows < copyRows2? copyRows: copyRows2; + + for (int32 j = 0; j < minRows; j++) + { + uint8 *destRowAddress = destAddress + (j * Bwidth * bytesPerPixel); + uint8 *srcRowAddress = srcAddress + (j * copyLength * bytesPerPixel); + memcpy(destRowAddress, srcRowAddress, minLength * bytesPerPixel ); + } + } + } + + for(i=0; i < rectList.CountItems(); i++) + { + void *rectCopy; + rectCopy = rectList.ItemAt(i); + if (rectCopy) + free(rectCopy); + } + rectList.MakeEmpty(); + + fCursorHandler.DriverShow(); + + BRect inval(bmp->Bounds()); + ReleaseBuffer(); + Unlock(); + +// ConstrainClippingRegion(clipReg); + Invalidate(inval); +// ConstrainClippingRegion(NULL); +} + +/*! + \brief Called for all BView::FillArc calls + \param r Rectangle enclosing the entire arc + \param angle Starting angle for the arc in degrees + \param span Span of the arc in degrees. Ending angle = angle+span. + \param d Object holding the bazillion other options +*/ +void DisplayDriverImpl::FillArc(const BRect &r, const float &angle, const float &span, const DrawData *d) +{ + if(fCursorHandler.IntersectsCursor(r)) + fCursorHandler.DriverHide(); + + float xc = (r.left+r.right)/2; + float yc = (r.top+r.bottom)/2; + float rx = r.Width()/2; + float ry = r.Height()/2; + int Rx2 = ROUND(rx*rx); + int Ry2 = ROUND(ry*ry); + int twoRx2 = 2*Rx2; + int twoRy2 = 2*Ry2; + int p; + int x=0; + int y = (int)ry; + int px = 0; + int py = twoRx2 * y; + int startx, endx; + int starty, endy; + int xclip, startclip, endclip; + int startQuad, endQuad; + bool useQuad1, useQuad2, useQuad3, useQuad4; + bool shortspan = false; + DrawData data; + + // Watch out for bozos giving us whacko spans + if ( (span >= 360) || (span <= -360) ) + { + FillEllipse(r,d); + fCursorHandler.DriverShow(); + return; + } + + Lock(); + + data = *d; + data.pensize = 1; + + if ( span > 0 ) + { + startQuad = (int)(angle/90)%4+1; + endQuad = (int)((angle+span)/90)%4+1; + startx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); + endx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); + } + else + { + endQuad = (int)(angle/90)%4+1; + startQuad = (int)((angle+span)/90)%4+1; + endx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); + startx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); + } + + starty = ROUND(ry*sqrt(1-(double)startx*startx/(rx*rx))); + endy = ROUND(ry*sqrt(1-(double)endx*endx/(rx*rx))); + + if ( startQuad != endQuad ) + { + useQuad1 = (endQuad > 1) && (startQuad > endQuad); + useQuad2 = ((startQuad == 1) && (endQuad > 2)) || ((startQuad > endQuad) && (endQuad > 2)); + useQuad3 = ((startQuad < 3) && (endQuad == 4)) || ((startQuad < 3) && (endQuad < startQuad)); + useQuad4 = (startQuad < 4) && (startQuad > endQuad); + } + else + { + if ( (span < 90) && (span > -90) ) + { + useQuad1 = false; + useQuad2 = false; + useQuad3 = false; + useQuad4 = false; + shortspan = true; + } + else + { + useQuad1 = (startQuad != 1); + useQuad2 = (startQuad != 2); + useQuad3 = (startQuad != 3); + useQuad4 = (startQuad != 4); + } + } + + if ( useQuad1 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); + if ( useQuad2 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc-x,yc-y),&data); + if ( useQuad3 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc-x,yc+y),&data); + if ( useQuad4 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); + + p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); + while (px < py) + { + x++; + px += twoRy2; + if ( p < 0 ) + p += Ry2 + px; + else + { + y--; + py -= twoRx2; + p += Ry2 + px - py; + } + + if ( useQuad1 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); + if ( useQuad2 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc-x,yc-y),&data); + if ( useQuad3 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc-x,yc+y),&data); + if ( useQuad4 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); + if ( !shortspan ) + { + if ( startQuad == 1 ) + { + if ( x <= startx ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); + else + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc,yc-y),BPoint(xc+xclip,yc-y),&data); + } + } + else if ( startQuad == 2 ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-xclip,yc-y),&data); + } + } + else if ( startQuad == 3 ) + { + if ( x <= startx ) + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc,yc+y),&data); + else + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc-xclip,yc+y),BPoint(xc,yc+y),&data); + } + } + else if ( startQuad == 4 ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc+xclip,yc+y),BPoint(xc+x,yc+y),&data); + } + } + + if ( endQuad == 1 ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc+xclip,yc-y),BPoint(xc+x,yc-y),&data); + } + } + else if ( endQuad == 2 ) + { + if ( x <= endx ) + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc,yc-y),&data); + else + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc-xclip,yc-y),BPoint(xc,yc-y),&data); + } + } + else if ( endQuad == 3 ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-xclip,yc+y),&data); + } + } + else if ( endQuad == 4 ) + { + if ( x <= endx ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); + else + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc,yc+y),BPoint(xc+xclip,yc+y),&data); + } + } + } + else + { + startclip = ROUND(y*startx/(double)starty); + endclip = ROUND(y*endx/(double)endy); + if ( startQuad == 1 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+x,yc-y),&data); + else + StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+startclip,yc-y),&data); + } + else if ( startQuad == 2 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-startclip,yc-y),&data); + else + StrokeLine(BPoint(xc-endclip,yc-y),BPoint(xc-startclip,yc-y),&data); + } + else if ( startQuad == 3 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-endclip,yc+y),&data); + else + StrokeLine(BPoint(xc-startclip,yc+y),BPoint(xc-endclip,yc+y),&data); + } + else if ( startQuad == 4 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+x,yc+y),&data); + else + StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+endclip,yc+y),&data); + } + } + } + + p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); + while (y>0) + { + y--; + py -= twoRx2; + if (p>0) + p += Rx2 - py; + else + { + x++; + px += twoRy2; + p += Rx2 - py +px; + } + + if ( useQuad1 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); + if ( useQuad2 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc-x,yc-y),&data); + if ( useQuad3 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc-x,yc+y),&data); + if ( useQuad4 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); + if ( !shortspan ) + { + if ( startQuad == 1 ) + { + if ( x <= startx ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); + else + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc,yc-y),BPoint(xc+xclip,yc-y),&data); + } + } + else if ( startQuad == 2 ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-xclip,yc-y),&data); + } + } + else if ( startQuad == 3 ) + { + if ( x <= startx ) + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc,yc+y),&data); + else + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc-xclip,yc+y),BPoint(xc,yc+y),&data); + } + } + else if ( startQuad == 4 ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc+xclip,yc+y),BPoint(xc+x,yc+y),&data); + } + } + + if ( endQuad == 1 ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc+xclip,yc-y),BPoint(xc+x,yc-y),&data); + } + } + else if ( endQuad == 2 ) + { + if ( x <= endx ) + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc,yc-y),&data); + else + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc-xclip,yc-y),BPoint(xc,yc-y),&data); + } + } + else if ( endQuad == 3 ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-xclip,yc+y),&data); + } + } + else if ( endQuad == 4 ) + { + if ( x <= endx ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); + else + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc,yc+y),BPoint(xc+xclip,yc+y),&data); + } + } + } + else + { + startclip = ROUND(y*startx/(double)starty); + endclip = ROUND(y*endx/(double)endy); + if ( startQuad == 1 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+x,yc-y),&data); + else + StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+startclip,yc-y),&data); + } + else if ( startQuad == 2 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-startclip,yc-y),&data); + else + StrokeLine(BPoint(xc-endclip,yc-y),BPoint(xc-startclip,yc-y),&data); + } + else if ( startQuad == 3 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-endclip,yc+y),&data); + else + StrokeLine(BPoint(xc-startclip,yc+y),BPoint(xc-endclip,yc+y),&data); + } + else if ( startQuad == 4 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+x,yc+y),&data); + else + StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+endclip,yc+y),&data); + } + } + } + fCursorHandler.DriverShow(); + Invalidate(r); + Unlock(); +} + +/*! + \brief Called for all BView::FillBezier calls. + \param pts 4-element array of BPoints in the order of start, end, and then the two control + points. + \param d draw data +*/ +void DisplayDriverImpl::FillBezier(BPoint *pts, const DrawData *d) +{ + Lock(); + + BezierCurve curve(pts); + + if(fCursorHandler.IntersectsCursor(curve.Frame())) + fCursorHandler.DriverHide(); + + FillPolygon(curve.GetPointArray(), curve.points.CountItems(), curve.Frame(), d); + + fCursorHandler.DriverShow(); + Unlock(); +} + +/*! + \brief Called for all BView::FillEllipse calls + \param r BRect enclosing the ellipse to be drawn. + \param d DrawData containing the endless options +*/ +void DisplayDriverImpl::FillEllipse(const BRect &r, const DrawData *d) +{ + float xc = (r.left+r.right)/2; + float yc = (r.top+r.bottom)/2; + float rx = r.Width()/2; + float ry = r.Height()/2; + int Rx2 = ROUND(rx*rx); + int Ry2 = ROUND(ry*ry); + int twoRx2 = 2*Rx2; + int twoRy2 = 2*Ry2; + int p; + int x=0; + int y = (int)ry; + int px = 0; + int py = twoRx2 * y; + DrawData data; + + Lock(); + + if(fCursorHandler.IntersectsCursor(r)) + fCursorHandler.DriverHide(); + + data = *d; + data.pensize = 1; + + StrokeLine(BPoint(xc,yc-y),BPoint(xc,yc-y),&data); + StrokeLine(BPoint(xc,yc+y),BPoint(xc,yc+y),&data); + + p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); + while (px < py) + { + x++; + px += twoRy2; + if ( p < 0 ) + p += Ry2 + px; + else + { + y--; + py -= twoRx2; + p += Ry2 + px - py; + } + + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc+x,yc-y),&data); + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc+x,yc+y),&data); + } + + p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); + while (y>0) + { + y--; + py -= twoRx2; + if (p>0) + p += Rx2 - py; + else + { + x++; + px += twoRy2; + p += Rx2 - py +px; + } + + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc+x,yc-y),&data); + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc+x,yc+y),&data); + } + fCursorHandler.DriverShow(); + Invalidate(r); + Unlock(); +} + +/*! + \brief Called for all BView::FillPolygon calls + \param ptlist Array of BPoints defining the polygon. + \param numpts Number of points in the BPoint array. + \param d The 50 bazillion drawing options (inluding clip region) +*/ +void DisplayDriverImpl::FillPolygon(BPoint *ptlist, int32 numpts, const BRect &bounds, const DrawData *d) +{ + // Here's the plan. Record all line segments in polygon. If a line segments crosses + // the y-value of a point not in the segment, split the segment into 2 segments. + // Once we have gone through all of the segments, sort them primarily on y-value + // and secondarily on x-value. Step through each y-value in the bounding rectangle + // and look for intersections with line segments. First intersection is start of + // horizontal line, second intersection is end of horizontal line. Continue for + // all pairs of intersections. Watch out for horizontal line segments. + if ( !ptlist || (numpts < 3) ) + return; + + Lock(); + + if(fCursorHandler.IntersectsCursor(bounds)) + fCursorHandler.DriverHide(); + + BPoint *currentPoint, *nextPoint; + BPoint tempNextPoint; + BPoint tempCurrentPoint; + int currentIndex, bestIndex, i, j, y; + LineCalc *segmentArray = new LineCalc[2*numpts]; + int numSegments = 0; + int minX, minY, maxX, maxY; + + minX = ROUND(ptlist[0].x); + maxX = ROUND(ptlist[0].x); + minY = ROUND(ptlist[0].y); + maxY = ROUND(ptlist[0].y); + + // Generate the segment list + currentPoint = ptlist; + currentIndex = 0; + nextPoint = &ptlist[1]; + while (currentPoint) + { + if ( numSegments >= 2*numpts ) + { + printf("ERROR: Insufficient memory allocated to segment array\n"); + delete[] segmentArray; + fCursorHandler.DriverShow(); + Unlock(); + return; + } + + if ( ROUND(currentPoint->x) < minX ) + minX = ROUND(currentPoint->x); + if ( ROUND(currentPoint->x) > maxX ) + maxX = ROUND(currentPoint->x); + if ( ROUND(currentPoint->y) < minY ) + minY = ROUND(currentPoint->y); + if ( ROUND(currentPoint->y) > maxY ) + maxY = ROUND(currentPoint->y); + + for (i=0; i currentPoint->y) && (ptlist[i].y < nextPoint->y)) || + ((ptlist[i].y < currentPoint->y) && (ptlist[i].y > nextPoint->y)) ) + { + segmentArray[numSegments].SetPoints(*currentPoint,*nextPoint); + tempNextPoint.x = segmentArray[numSegments].GetX(ptlist[i].y); + tempNextPoint.y = ptlist[i].y; + nextPoint = &tempNextPoint; + } + } + + segmentArray[numSegments].SetPoints(*currentPoint,*nextPoint); + numSegments++; + if ( nextPoint == &tempNextPoint ) + { + tempCurrentPoint = tempNextPoint; + currentPoint = &tempCurrentPoint; + nextPoint = &ptlist[(currentIndex+1)%numpts]; + } + else if ( nextPoint == ptlist ) + { + currentPoint = NULL; + } + else + { + currentPoint = nextPoint; + currentIndex++; + nextPoint = &ptlist[(currentIndex+1)%numpts]; + } + } + + // Selection sort the segments. Probably should replace this later. + for (i=0; iclipReg ) + { + // Draw the lines + for (y=minY; y<=maxY; y++) + { + i = 0; + while (i y) + break; + if (segmentArray[i].MaxY() < y) + { + i++; + continue; + } + if (segmentArray[i].MinY() == segmentArray[i].MaxY()) + { + if ( (segmentArray[i].MinX() < fDisplayMode.virtual_width) && + (segmentArray[i].MaxX() >= 0) ) + StrokePatternLine(ROUND(segmentArray[i].MinX()), y, + ROUND(segmentArray[i].MaxX()), y, d); + i++; + } + else + { + if ( (segmentArray[i+1].GetX(y) < fDisplayMode.virtual_width) && + (segmentArray[i].GetX(y) >= 0) ) + StrokePatternLine(ROUND(segmentArray[i].GetX(y)), y, + ROUND(segmentArray[i+1].GetX(y)), y, d); + i+=2; + } + } + } + } + else + { + int numRects, rectIndex; + int yStart, yEnd; + BRect clipRect; + numRects = d->clipReg->CountRects(); + for (rectIndex = 0; rectIndex < numRects; rectIndex++) + { + clipRect = d->clipReg->RectAt(rectIndex); + if ( clipRect.bottom < minY ) + continue; + if ( clipRect.top > maxY ) + continue; + if ( clipRect.left < minX ) + continue; + if ( clipRect.right > maxX ) + continue; + yStart = MAX(minY,ROUND(clipRect.top)); + yEnd = MIN(maxY,ROUND(clipRect.bottom)); + + // Draw the lines + for (y=yStart; y<=yEnd; y++) + { + i = 0; + while (i y) + break; + if (segmentArray[i].MaxY() < y) + { + i++; + continue; + } + if (segmentArray[i].MinY() == segmentArray[i].MaxY()) + { + if (segmentArray[i].MinX() > clipRect.right) + { + i++; + continue; + } + if (segmentArray[i].MaxX() < clipRect.left) + { + i++; + continue; + } + StrokePatternLine(ROUND(MAX(segmentArray[i].MinX(),clipRect.left)), y, + ROUND(MIN(segmentArray[i].MaxX(),clipRect.right)), y, d); + i++; + } + else + { + if (segmentArray[i].GetX(y) > clipRect.right) + { + i+=2; + continue; + } + if (segmentArray[i+1].GetX(y) < clipRect.left) + { + i+=2; + continue; + } + StrokePatternLine(ROUND(MAX(segmentArray[i].GetX(y),clipRect.left)), y, + ROUND(MIN(segmentArray[i+1].GetX(y),clipRect.right)), y, d); + i+=2; + } + } + } + } + } + delete[] segmentArray; + fCursorHandler.DriverShow(); + Invalidate(bounds); + Unlock(); +} + +/*! + \brief Called for all BView::FillRect calls + \param r BRect to be filled. Guaranteed to be in the frame buffer's coordinate space + \param color The color used to fill the rectangle +*/ +void DisplayDriverImpl::FillRect(const BRect &r, const RGBColor &color) +{ + Lock(); + if(fCursorHandler.IntersectsCursor(r)) + fCursorHandler.DriverHide(); + + FillSolidRect(r,color); + fCursorHandler.DriverShow(); + Unlock(); +} + +/*! + \brief Called for all BView::FillRect calls + \param r BRect to be filled. Guaranteed to be in the frame buffer's coordinate space + \param pattern The pattern used to fill the rectangle + \param high_color The high color of the pattern + \param low_color The low color of the pattern +*/ +void DisplayDriverImpl::FillRect(const BRect &r, const DrawData *d) +{ + if(!d) + return; + + Lock(); + if(fCursorHandler.IntersectsCursor(r)) + fCursorHandler.DriverHide(); + if ( d->clipReg ) + { + if ( d->clipReg->Intersects(r) ) + { + BRegion reg(r); + reg.IntersectWith(d->clipReg); + int numRects = reg.CountRects(); + + for(int32 i=0; iclipReg ) + { + BRegion drawReg = r; + + drawReg.IntersectWith(d->clipReg); + numRects = drawReg.CountRects(); + + for(int32 i=0; iclipReg ) + { + int numRects, rectIndex; + BRect clipRect; + int left, right, y1, y2; + int rectTop, rectBottom, rectLeft, rectRight; + + numRects = d->clipReg->CountRects(); + for (rectIndex=0; rectIndexclipReg->RectAt(rectIndex); + rectTop = ROUND(clipRect.top); + rectBottom = ROUND(clipRect.bottom); + rectLeft = ROUND(clipRect.left); + rectRight = ROUND(clipRect.right); + for (i=0; i<=(int)yrad; i++) + { + arc_x = xrad*sqrt(1-i*i/yrad2); + left = ROUND(r.left + xrad - arc_x); + right = ROUND(r.right - xrad + arc_x); + if ( (left > rectRight) || (right < rectLeft) ) + continue; + y1 = ROUND(r.top + yrad - i); + y2 = ROUND(r.bottom - yrad + i); + if ( (y1 >= rectTop) && (y1 <= rectBottom) ) + StrokePatternLine(MAX(left,rectLeft), y1, MIN(right,rectRight), y1,d); + if ( (y2 >= rectTop) && (y2 <= rectBottom) ) + StrokePatternLine(MAX(left,rectLeft), y2, MIN(right,rectRight), y2,d); + } + } + } + else + { + for (i=0; i<=(int)yrad; i++) + { + arc_x = xrad*sqrt(1-i*i/yrad2); + StrokePatternLine(ROUND(r.left+xrad-arc_x), ROUND(r.top+yrad-i), ROUND(r.right-xrad+arc_x), ROUND(r.top+yrad-i),d); + StrokePatternLine(ROUND(r.left+xrad-arc_x), ROUND(r.bottom-yrad+i), ROUND(r.right-xrad+arc_x), ROUND(r.bottom-yrad+i),d); + } + } + FillPatternRect(BRect(r.left,r.top+yrad,r.right,r.bottom-yrad),d); + fCursorHandler.DriverShow(); + Invalidate(r); + Unlock(); +} + +void DisplayDriverImpl::FillShape(const BRect &bounds, const int32 &opcount, const int32 *oplist, + const int32 &ptcount, const BPoint *ptlist, const DrawData *d) +{ + // TODO: Implement DisplayDriverImpl::FillShape. How, though? AGG backend? + printf("DisplayDriverImpl::FillShape unimplemented\n"); +} + +/*! + \brief Called for all BView::FillTriangle calls + \param pts Array of 3 BPoints. Always non-NULL. + \param setLine Horizontal line drawing routine which handles things like color and pattern. +*/ +void DisplayDriverImpl::FillTriangle(BPoint *pts, const BRect &bounds, const DrawData *d) +{ + if ( !pts ) + return; + + Lock(); + + if(fCursorHandler.IntersectsCursor(bounds)) + fCursorHandler.DriverHide(); + + if ( d->clipReg ) + { + // For now, cop out and use FillPolygon + // Need to investigate if Triangle specific code would save processing time + FillPolygon(pts,3,bounds,d); + fCursorHandler.DriverShow(); + } + else + { + BPoint first, second, third; + + // Sort points according to their y values and x values (y is primary) + if ( (pts[0].y < pts[1].y) || + ((pts[0].y == pts[1].y) && (pts[0].x <= pts[1].x)) ) + { + first=pts[0]; + second=pts[1]; + } + else + { + first=pts[1]; + second=pts[0]; + } + + if ( (second.y= 360) || (span <= -360) ) + { + StrokeEllipse(r,d); + fCursorHandler.DriverShow(); + Unlock(); + return; + } + + if ( span > 0 ) + { + startQuad = (int)(angle/90)%4+1; + endQuad = (int)((angle+span)/90)%4+1; + startx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); + endx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); + } + else + { + endQuad = (int)(angle/90)%4+1; + startQuad = (int)((angle+span)/90)%4+1; + endx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); + startx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); + } + + if ( startQuad != endQuad ) + { + useQuad1 = (endQuad > 1) && (startQuad > endQuad); + useQuad2 = ((startQuad == 1) && (endQuad > 2)) || ((startQuad > endQuad) && (endQuad > 2)); + useQuad3 = ((startQuad < 3) && (endQuad == 4)) || ((startQuad < 3) && (endQuad < startQuad)); + useQuad4 = (startQuad < 4) && (startQuad > endQuad); + } + else + { + if ( (span < 90) && (span > -90) ) + { + useQuad1 = false; + useQuad2 = false; + useQuad3 = false; + useQuad4 = false; + shortspan = true; + } + else + { + useQuad1 = (startQuad != 1); + useQuad2 = (startQuad != 2); + useQuad3 = (startQuad != 3); + useQuad4 = (startQuad != 4); + } + } + + if ( useQuad1 || + (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || + (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc+x,yc-y),d); + if ( useQuad2 || + (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || + (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc-x,yc-y),d); + if ( useQuad3 || + (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || + (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc-x,yc+y),d); + if ( useQuad4 || + (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || + (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc+x,yc+y),d); + + p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); + while (px < py) + { + x++; + px += twoRy2; + if ( p < 0 ) + p += Ry2 + px; + else + { + y--; + py -= twoRx2; + p += Ry2 + px - py; + } + + if ( useQuad1 || + (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || + (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc+x,yc-y),d); + if ( useQuad2 || + (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || + (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc-x,yc-y),d); + if ( useQuad3 || + (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || + (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc-x,yc+y),d); + if ( useQuad4 || + (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || + (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc+x,yc+y),d); + } + + p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); + while (y>0) + { + y--; + py -= twoRx2; + if (p>0) + p += Rx2 - py; + else + { + x++; + px += twoRy2; + p += Rx2 - py +px; + } + + if ( useQuad1 || + (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || + (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc+x,yc-y),d); + if ( useQuad2 || + (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || + (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc-x,yc-y),d); + if ( useQuad3 || + (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || + (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc-x,yc+y),d); + if ( useQuad4 || + (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || + (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc+x,yc+y),d); + } + fCursorHandler.DriverShow(); + Invalidate(r); + Unlock(); +} + +/*! + \brief Called for all BView::StrokeBezier calls. + \param pts 4-element array of BPoints in the order of start, end, and then the two control points. + \param d draw data +*/ +void DisplayDriverImpl::StrokeBezier(BPoint *pts, const DrawData *d) +{ + int i, numLines; + + Lock(); + BezierCurve curve(pts); + + if(fCursorHandler.IntersectsCursor(curve.Frame())) + fCursorHandler.DriverHide(); + + numLines = curve.points.CountItems()-1; + for (i=0; i0) + { + lastx = x; + lasty = y; + y--; + py -= twoRx2; + if (p>0) + p += Rx2 - py; + else + { + x++; + px += twoRy2; + p += Rx2 - py +px; + } + + StrokeLine(BPoint(xc+lastx,yc-lasty),BPoint(xc+x,yc-y),d); + StrokeLine(BPoint(xc-lastx,yc-lasty),BPoint(xc-x,yc-y),d); + StrokeLine(BPoint(xc-lastx,yc+lasty),BPoint(xc-x,yc+y),d); + StrokeLine(BPoint(xc+lastx,yc+lasty),BPoint(xc+x,yc+y),d); + } + fCursorHandler.DriverShow(); + Invalidate(r); + Unlock(); +} + +/*! + \brief Draws a line. Really. + \param start Starting point + \param end Ending point + \param c The color of the line +*/ +void DisplayDriverImpl::StrokeLine(const BPoint &start, const BPoint &end, const RGBColor &color) +{ + Lock(); + if(fCursorHandler.IntersectsCursor(BRect(start,end))) + fCursorHandler.DriverHide(); + StrokeSolidLine(ROUND(start.x),ROUND(start.y),ROUND(end.x),ROUND(end.y),color); + + fCursorHandler.DriverShow(); + Invalidate(BRect(start,end)); + Unlock(); +} + +/*! + \brief Draws a line. Really. + \param start Starting point + \param end Ending point + \param d The relevant drawing data for this line +*/ +void DisplayDriverImpl::StrokeLine(const BPoint &start, const BPoint &end, const DrawData *d) +{ + Lock(); + + if(fCursorHandler.IntersectsCursor(BRect(start,end))) + fCursorHandler.DriverHide(); + + if ( d->pensize == 1 ) + { + if ( d->clipReg ) + { + int i, numRects; + double left, right, y1, y2; + BRect clipRect; + LineCalc line(start,end); + numRects = d->clipReg->CountRects(); + for (i=0; iclipReg->RectAt(i); + left = MAX(line.MinX(), clipRect.left); + right = MIN(line.MaxX(), clipRect.right); + if ( right < left ) + continue; + y1 = line.GetY(left); + y2 = line.GetY(right); + if ( MAX(y1,y2) < clipRect.top ) + continue; + if ( MIN(y1,y2) > clipRect.bottom ) + continue; + if ( y1 < clipRect.top ) + { + y1 = clipRect.top; + left = line.GetX(y1); + } + if ( y1 > clipRect.bottom ) + { + y1 = clipRect.bottom; + left = line.GetX(y1); + } + if ( y2 < clipRect.top ) + { + y2 = clipRect.top; + right = line.GetX(y2); + } + if ( y2 > clipRect.bottom ) + { + y2 = clipRect.bottom; + right = line.GetX(y2); + } + StrokePatternLine(ROUND(left),ROUND(y1),ROUND(right),ROUND(y2),d); + } + } + else + StrokePatternLine(ROUND(start.x),ROUND(start.y),ROUND(end.x),ROUND(end.y),d); + } + else + { + BPoint corners[4]; + double halfWidth = .5*d->pensize; + corners[0] = start; + corners[1] = start; + corners[2] = end; + corners[3] = end; + if ( (start.x == end.x) && (start.y == end.y) ) + { + FillRect(BRect(start.x-halfWidth,start.y-halfWidth,start.x+halfWidth,start.y+halfWidth),d); + } + else + { + if ( start.x == end.x ) + { + corners[0].x += halfWidth; + corners[1].x -= halfWidth; + corners[2].x -= halfWidth; + corners[3].x += halfWidth; + } + else if ( start.y == end.y ) + { + corners[0].y -= halfWidth; + corners[1].y += halfWidth; + corners[2].y += halfWidth; + corners[3].y -= halfWidth; + } + else + { + double angle, xoffset, yoffset; + // TODO try to find a way to avoid atan2, sin, and cos + angle = atan2(end.y-start.y, end.x-start.x) + M_PI/4; + xoffset = halfWidth*cos(angle); + yoffset = halfWidth*sin(angle); + corners[0].x += xoffset; + corners[0].y += yoffset; + corners[1].x -= xoffset; + corners[1].y -= yoffset; + corners[2].x -= xoffset; + corners[2].y -= yoffset; + corners[3].x += xoffset; + corners[3].y += yoffset; + } + FillPolygon(corners,4,BRect(start,end),d); + } + } + fCursorHandler.DriverShow(); + Invalidate(BRect(start,end)); + Unlock(); +} + +void DisplayDriverImpl::StrokePoint(const BPoint& pt, const RGBColor &color) +{ + StrokeLine(pt, pt, color); + Invalidate(BRect(pt,pt)); +} + +void DisplayDriverImpl::StrokePoint(const BPoint& pt, const DrawData *d) +{ + StrokeLine(pt, pt, d); + Invalidate(BRect(pt,pt)); +} + +/*! + \brief Called for all BView::StrokePolygon calls + \param ptlist Array of BPoints defining the polygon. + \param numpts Number of points in the BPoint array. + \param d DrawData containing all of the other options +*/ +void DisplayDriverImpl::StrokePolygon(BPoint *ptlist, int32 numpts, const BRect &bounds, const DrawData *d, bool is_closed) +{ + if(!ptlist) + return; + + Lock(); + if(fCursorHandler.IntersectsCursor(bounds)) + fCursorHandler.DriverHide(); + + for(int32 i=0; i<(numpts-1); i++) + StrokeLine(ptlist[i],ptlist[i+1],d); + if(is_closed) + StrokeLine(ptlist[numpts-1],ptlist[0],d); + + fCursorHandler.DriverShow(); + Invalidate(bounds); + Unlock(); +} + +/*! + \brief Called by Decorator + \param r BRect to be drawn + \param color Color in which to draw +*/ +void DisplayDriverImpl::StrokeRect(const BRect &r, const RGBColor &color) +{ + Lock(); + + if(fCursorHandler.IntersectsCursor(r)) + fCursorHandler.DriverHide(); + StrokeSolidRect(r,color); + + fCursorHandler.DriverShow(); + Invalidate(r); + Unlock(); +} + +/*! + \brief Called for all BView::StrokeRect calls + \param r BRect to be drawn + \param d DrawData containing all of the other options +*/ +void DisplayDriverImpl::StrokeRect(const BRect &r, const DrawData *d) +{ + Lock(); + if(fCursorHandler.IntersectsCursor(r)) + fCursorHandler.DriverHide(); + StrokeLine(r.LeftTop(),r.RightTop(),d); + StrokeLine(r.LeftTop(),r.LeftBottom(),d); + StrokeLine(r.RightTop(),r.RightBottom(),d); + StrokeLine(r.LeftBottom(),r.RightBottom(),d); + + fCursorHandler.DriverShow(); + Invalidate(r); + Unlock(); +} + +/*! + \brief Convenience function for server use + \param r BRegion to be stroked + \param d Data structure containing any other data necessary for the call. Always non-NULL. + +*/ +void DisplayDriverImpl::StrokeRegion(BRegion& r, const DrawData *d) +{ + Lock(); + + if(fCursorHandler.IntersectsCursor(r.Frame())) + fCursorHandler.DriverHide(); + + for(int32 i=0; ifont.Size()*1.5; + intersection.right+=d->font.Size()*1.5*length; + if(fCursorHandler.IntersectsCursor(intersection)) + fCursorHandler.DriverHide(); + + BPoint point(pt); + + const ServerFont *font=&(d->font); + + FT_Face face; + FT_GlyphSlot slot; + FT_Matrix rmatrix,smatrix; + FT_UInt glyph_index=0, previous=0; + FT_Vector pen,delta,space,nonspace; + int16 error=0; + int32 strlength,i; + Angle rotation(font->Rotation()), shear(font->Shear()); + + bool antialias=true; + + if(font->Size()<18 && (font->Flags()& B_DISABLE_ANTIALIASING==1)) + antialias=false; + + // Originally, I thought to do this shear checking here, but it really should be + // done in BFont::SetShear() + float shearangle=shear.Value(); + if(shearangle>135) + shearangle=135; + if(shearangle<45) + shearangle=45; + + if(shearangle>90) + shear=90+((180-shearangle)*2); + else + shear=90-(90-shearangle)*2; + + error=FT_New_Face(ftlib, font->GetPath(), 0, &face); + if(error) + { + Unlock(); + return; + } + + slot=face->glyph; + + bool use_kerning=FT_HAS_KERNING(face) && font->Spacing()==B_STRING_SPACING; + + error=FT_Set_Char_Size(face, 0,int32(font->Size())*64,72,72); + if(error) + { + Unlock(); + return; + } + + // if we do any transformation, we do a call to FT_Set_Transform() here + + // First, rotate + rmatrix.xx = (FT_Fixed)( rotation.Cosine()*0x10000); + rmatrix.xy = (FT_Fixed)(-rotation.Sine()*0x10000); + rmatrix.yx = (FT_Fixed)( rotation.Sine()*0x10000); + rmatrix.yy = (FT_Fixed)( rotation.Cosine()*0x10000); + + // Next, shear + smatrix.xx = (FT_Fixed)(0x10000); + smatrix.xy = (FT_Fixed)(-shear.Cosine()*0x10000); + smatrix.yx = (FT_Fixed)(0); + smatrix.yy = (FT_Fixed)(0x10000); + + FT_Matrix_Multiply(&rmatrix,&smatrix); + + // Set up the increment value for escapement padding + space.x=int32(d->edelta.space * rotation.Cosine()*64); + space.y=int32(d->edelta.space * rotation.Sine()*64); + nonspace.x=int32(d->edelta.nonspace * rotation.Cosine()*64); + nonspace.y=int32(d->edelta.nonspace * rotation.Sine()*64); + + // set the pen position in 26.6 cartesian space coordinates + pen.x=(int32)point.x * 64; + pen.y=(int32)point.y * 64; + + slot=face->glyph; + + + strlength=strlen(string); + if(lengthbitmap, + BPoint(slot->bitmap_left,point.y-(slot->bitmap_top-point.y)), d); + else + BlitMono2RGB32(&slot->bitmap, + BPoint(slot->bitmap_left,point.y-(slot->bitmap_top-point.y)), d); + } + + // increment pen position + pen.x+=slot->advance.x; + pen.y+=slot->advance.y; + previous=glyph_index; + } + + // TODO: implement calculation of invalid rectangle in DisplayDriverImpl::DrawString properly + BRect r; + r.left=MIN(point.x,pen.x>>6); + r.right=MAX(point.x,pen.x>>6); + r.top=point.y-face->height; + r.bottom=point.y+face->height; + + fCursorHandler.DriverShow(); + Invalidate(r); + + // Update the caller's pen position + d->penlocation.x=pen.x / 64; + d->penlocation.y=pen.y / 64; + + FT_Done_Face(face); + + Unlock(); + +} + +/*! + \brief Gets the width of a string in pixels + \param string Source null-terminated string + \param length Number of characters in the string + \param d Data structure containing any other data necessary for the call. Always non-NULL. + \return Width of the string in pixels + + This corresponds to BView::StringWidth. +*/ +float DisplayDriverImpl::StringWidth(const char *string, int32 length, const DrawData *d) +{ + if(!string || !d) + return 0.0; + Lock(); + + const ServerFont *font=&(d->font); + + FT_Face face; + FT_GlyphSlot slot; + FT_UInt glyph_index=0, previous=0; + FT_Vector pen,delta; + int16 error=0; + int32 strlength,i; + float returnval; + + error=FT_New_Face(ftlib, font->GetPath(), 0, &face); + if(error) + { + Unlock(); + return 0.0; + } + + slot=face->glyph; + + bool use_kerning=FT_HAS_KERNING(face) && font->Spacing()==B_STRING_SPACING; + + error=FT_Set_Char_Size(face, 0,int32(font->Size())*64,72,72); + if(error) + { + Unlock(); + return 0.0; + } + + // set the pen position in 26.6 cartesian space coordinates + pen.x=0; + + slot=face->glyph; + + strlength=strlen(string); + if(lengthadvance.x; + previous=glyph_index; + } + + FT_Done_Face(face); + Unlock(); + + returnval=pen.x>>6; + return returnval; +} + +/*! + \brief Gets the height of a string in pixels + \param string Source null-terminated string + \param length Number of characters in the string + \param d Data structure containing any other data necessary for the call. Always non-NULL. + \return Height of the string in pixels + + The height calculated in this function does not include any padding - just the + precise maximum height of the characters within and does not necessarily equate + with a font's height, i.e. the strings 'case' and 'alps' will have different values + even when called with all other values equal. +*/ +float DisplayDriverImpl::StringHeight(const char *string, int32 length, const DrawData *d) +{ + if(!string || !d) + return 0.0; + Lock(); + + const ServerFont *font=&(d->font); + + FT_Face face; + FT_GlyphSlot slot; + int16 error=0; + int32 strlength,i; + float returnval=0.0,ascent=0.0,descent=0.0; + + error=FT_New_Face(ftlib, font->GetPath(), 0, &face); + if(error) + { + Unlock(); + return 0.0; + } + + slot=face->glyph; + + error=FT_Set_Char_Size(face, 0,int32(font->Size())*64,72,72); + if(error) + { + Unlock(); + return 0.0; + } + + slot=face->glyph; + + strlength=strlen(string); + if(lengthmetrics.horiBearingYmetrics.height) + descent=MAX((slot->metrics.height-slot->metrics.horiBearingY)>>6,descent); + else + ascent=MAX(slot->bitmap.rows,ascent); + } + + FT_Done_Face(face); + + Unlock(); + returnval=ascent+descent; + return returnval; +} + +/*! + \brief Retrieves the bounding box each character in the string + \param string Source null-terminated string + \param count Number of characters in the string + \param mode Metrics mode for either screen or printing + \param delta Optional glyph padding. This value may be NULL. + \param rectarray Array of BRect objects which will have at least count elements + \param d Data structure containing any other data necessary for the call. Always non-NULL. + + See BFont::GetBoundingBoxes for more details on this function. +*/ +void DisplayDriverImpl::GetBoundingBoxes(const char *string, int32 count, + font_metric_mode mode, escapement_delta *delta, BRect *rectarray, const DrawData *d) +{ + // TODO: Implement DisplayDriverImpl::GetBoundingBoxes +} + +/*! + \brief Retrieves the escapements for each character in the string + \param string Source null-terminated string + \param charcount Number of characters in the string + \param delta Optional glyph padding. This value may be NULL. + \param escapements Array of escapement_delta objects which will have at least charcount elements + \param offsets Actual offset values when iterating over the string. This array will also + have at least charcount elements and the values placed therein will reflect + the current kerning/spacing mode. + \param d Data structure containing any other data necessary for the call. Always non-NULL. + + See BFont::GetEscapements for more details on this function. +*/ +void DisplayDriverImpl::GetEscapements(const char *string, int32 charcount, + escapement_delta *delta, escapement_delta *escapements, escapement_delta *offsets, const DrawData *d) +{ + // TODO: Implement DisplayDriverImpl::GetEscapements +} + +/*! + \brief Retrieves the inset values of each glyph from its escapement values + \param string Source null-terminated string + \param charcount Number of characters in the string + \param edgearray Array of edge_info objects which will have at least charcount elements + \param d Data structure containing any other data necessary for the call. Always non-NULL. + + See BFont::GetEdges for more details on this function. +*/ +void DisplayDriverImpl::GetEdges(const char *string, int32 charcount, edge_info *edgearray, const DrawData *d) +{ + // TODO: Implement DisplayDriverImpl::GetEdges +} + +/*! + \brief Determines whether a font contains a certain string of characters + \param string Source null-terminated string + \param charcount Number of characters in the string + \param hasarray Array of booleans which will have at least charcount elements + + See BFont::GetHasGlyphs for more details on this function. +*/ +void DisplayDriverImpl::GetHasGlyphs(const char *string, int32 charcount, bool *hasarray) +{ + // TODO: Implement DisplayDriverImpl::GetHasGlyphs +} + +/*! + \brief Truncates an array of strings to a certain width + \param instrings Array of null-terminated strings + \param stringcount Number of strings passed to the function + \param mode Truncation mode + \param maxwidth Maximum width for all strings + \param outstrings String array provided by the caller into which the truncated strings are + to be placed. + + See BFont::GetTruncatedStrings for more details on this function. +*/ +void DisplayDriverImpl::GetTruncatedStrings(const char **instrings,const int32 &stringcount, + const uint32 &mode, const float &maxwidth, char **outstrings) +{ + // TODO: Implement DisplayDriverImpl::GetTruncatedStrings +} + +/*! + \brief Dumps the contents of the frame buffer to a file. + \param path Path and leaf of the file to be created without an extension + \return False if unimplemented or unsuccessful. True if otherwise. + + Subclasses should add an extension based on what kind of file is saved +*/ +bool DisplayDriverImpl::DumpToFile(const char *path) +{ + return false; +} + +/*! + \brief Returns a new ServerBitmap containing the contents of the frame buffer + \return A new ServerBitmap containing the contents of the frame buffer or NULL if unsuccessful +*/ +ServerBitmap *DisplayDriverImpl::DumpToBitmap() +{ + return NULL; +} + +/*! + \brief Draws a series of lines - optimized for speed + \param numlines Number of lines to be drawn + \param linedata Array of LineArrayData objects + \param d current DrawData settings +*/ +void DisplayDriverImpl::StrokeLineArray(const int32 &numlines, const LineArrayData *linedata,const DrawData *d) +{ + if(!d || !linedata) + return; + + const LineArrayData *dataindex=linedata; + BRect r(0,0,0,0); + DrawData drawdata; + + Lock(); + + fCursorHandler.DriverHide(); + + drawdata = *d; + + r.Set(linedata->pt1.x,linedata->pt1.y,linedata->pt1.x,linedata->pt1.y); + + for (int32 i=0; icolor; + + // Keep track of the invalid region + if (dataindex->pt1.x < r.left) + r.left = dataindex->pt1.x; + if (dataindex->pt1.y < r.top) + r.top = dataindex->pt1.y; + if (dataindex->pt1.x > r.right) + r.right = dataindex->pt1.x; + if (dataindex->pt1.y > r.bottom) + r.bottom = dataindex->pt1.y; + + if (dataindex->pt2.x < r.left) + r.left = dataindex->pt2.x; + if (dataindex->pt2.y < r.top) + r.top = dataindex->pt2.y; + if (dataindex->pt2.x > r.right) + r.right = dataindex->pt2.x; + if (dataindex->pt2.y > r.bottom) + r.bottom = dataindex->pt2.y; + + StrokeLine(dataindex->pt1,dataindex->pt2,&drawdata); + } + + Invalidate(r); + + fCursorHandler.DriverShow(); + + Unlock(); +} + + +/*! + \brief Returns data about the rendering device + \param info Pointer to an object to receive the device info + \return B_OK if this function is supported, B_UNSUPPORTED if not + + The default implementation of this returns B_UNSUPPORTED and does nothing. + + From Accelerant.h: + + uint32 version; // structure version number + char name[32]; // a name the user will recognize the device by + char chipset[32]; // the chipset used by the device + char serial_no[32]; // serial number for the device + uint32 memory; // amount of memory on the device, in bytes + uint32 dac_speed; // nominal DAC speed, in MHz + +*/ +status_t DisplayDriverImpl::GetDeviceInfo(accelerant_device_info *info) +{ + return B_ERROR; +} + +/*! + \brief Returns data about the rendering device + \param mode_list Pointer to receive a list of modes. + \param count The number of modes in mode_list + \return B_OK if this function is supported, B_UNSUPPORTED if not + + The default implementation of this returns B_UNSUPPORTED and does nothing. +*/ +status_t DisplayDriverImpl::GetModeList(display_mode **mode_list, uint32 *count) +{ + return B_UNSUPPORTED; +} + +/*! + \brief Obtains the minimum and maximum pixel throughput + \param mode Structure to receive the data for the given mode + \param low Recipient of the minimum clock rate + \param high Recipient of the maximum clock rate + \return + - \c B_OK: Everything is kosher + - \c B_UNSUPPORTED: The function is unsupported + - \c B_ERROR: No known pixel clock limits + + + This function returns the minimum and maximum "pixel clock" rates, in + thousands-of-pixels per second, that are possible for the given mode. See + BScreen::GetPixelClockLimits() for more information. + + The default implementation of this returns B_UNSUPPORTED and does nothing. +*/ +status_t DisplayDriverImpl::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high) +{ + return B_UNSUPPORTED; +} + +/*! + \brief Obtains the timing constraints of the current display mode. + \param dtc Object to receive the constraints + \return + - \c B_OK: Everything is kosher + - \c B_UNSUPPORTED: The function is unsupported + - \c B_ERROR: No known timing constraints + + The default implementation of this returns B_UNSUPPORTED and does nothing. +*/ +status_t DisplayDriverImpl::GetTimingConstraints(display_timing_constraints *dtc) +{ + return B_UNSUPPORTED; +} + +/*! + \brief Obtains the timing constraints of the current display mode. + \param dtc Object to receive the constraints + \return + - \c B_OK: Everything is kosher + - \c B_UNSUPPORTED: The function is unsupported + + The default implementation of this returns B_UNSUPPORTED and does nothing. + This is mostly the responsible of the hardware driver if the DisplayDriverImpl + interfaces with actual hardware. +*/ +status_t DisplayDriverImpl::ProposeMode(display_mode *candidate, const display_mode *low, const display_mode *high) +{ + return B_UNSUPPORTED; +} + +/*! + \brief Waits for the device's vertical retrace + \param timeout Amount of time to wait until retrace. Default is B_INFINITE_TIMEOUT + \return + - \c B_OK: Everything is kosher + - \c B_ERROR: The function timed out before retrace + - \c B_UNSUPPORTED: The function is unsupported + + The default implementation of this returns B_UNSUPPORTED and does nothing. +*/ +status_t DisplayDriverImpl::WaitForRetrace(bigtime_t timeout) +{ + return B_UNSUPPORTED; +} + + +/*! + \brief Obtains the current cursor for the driver. + \return Pointer to the current cursor object. + + Do NOT delete this pointer - change pointers via SetCursor. This call will be + necessary for blitting the cursor to the screen and other such tasks. +*/ +ServerCursor *DisplayDriverImpl::_GetCursor() +{ + Lock(); + ServerCursor *c=fCursorHandler.GetCursor(); + Unlock(); + + return c; +} + +void DisplayDriverImpl::HLinePatternThick(int32 x1, int32 x2, int32 y) +{ +} + +void DisplayDriverImpl::VLinePatternThick(int32 x1, int32 x2, int32 y) +{ +} + +/*! + \brief Draws a point of a specified thickness + \param x The x coordinate (not guaranteed to be in bounds) + \param y The y coordinate (not guaranteed to be in bounds) + \param thick The thickness of the point + \param pat The PatternHandler which detemines pixel colors + Must be implemented in subclasses +*/ +void DisplayDriverImpl::SetThickPatternPixel(int x, int y) +{ +} + +/*! + \brief Draws a horizontal line + \param x1 The first x coordinate (guaranteed to be in bounds) + \param x2 The second x coordinate (guaranteed to be in bounds) + \param y The y coordinate (guaranteed to be in bounds) + \param pat The PatternHandler which detemines pixel colors + Must be implemented in subclasses +*/ + +void DisplayDriverImpl::BlitMono2RGB32(FT_Bitmap *src, const BPoint &pt, const DrawData *d) +{ + rgb_color color=d->highcolor.GetColor32(); + + // pointers to the top left corner of the area to be copied in each bitmap + uint8 *srcbuffer, *destbuffer; + FBBitmap framebuffer; + + if(!AcquireBuffer(&framebuffer)) + { + printf("ERROR: Couldn't acquire framebuffer in BlitMono2RGB32\n"); + return; + } + + // index pointers which are incremented during the course of the blit + uint8 *srcindex, *destindex, *rowptr, value; + + // increment values for the index pointers + int32 srcinc=src->pitch, destinc=framebuffer.BytesPerRow(); + + int16 i,j,k, srcwidth=src->pitch, srcheight=src->rows; + int32 x=(int32)pt.x,y=(int32)pt.y; + + // starting point in source bitmap + srcbuffer=(uint8*)src->buffer; + + if(y<0) + { + if(yframebuffer.Bounds().IntegerHeight()) + { + if(y>pt.y) + y--; + srcheight-=(y+srcheight-1)-framebuffer.Bounds().IntegerHeight(); + } + + if(x+srcwidth>framebuffer.Bounds().IntegerWidth()) + { + if(x>pt.x) + x--; + srcwidth-=(x+srcwidth-1)-framebuffer.Bounds().IntegerWidth(); + } + + if(x<0) + { + if(x>3; + srcwidth-=0-x; + destbuffer+=(0-x)*4; + } + + // starting point in destination bitmap + destbuffer=(uint8*)framebuffer.Bits()+int32( (pt.y*framebuffer.BytesPerRow())+(pt.x*4) ); + + srcindex=srcbuffer; + destindex=destbuffer; + + for(i=0; ihighcolor.GetColor32(), lowcolor=d->lowcolor.GetColor32(); float rstep,gstep,bstep,astep; + + rstep=float(highcolor.red-lowcolor.red)/255.0; + gstep=float(highcolor.green-lowcolor.green)/255.0; + bstep=float(highcolor.blue-lowcolor.blue)/255.0; + astep=float(highcolor.alpha-lowcolor.alpha)/255.0; + + // increment values for the index pointers + int32 x=(int32)pt.x, + y=(int32)pt.y, + srcinc=src->pitch, +// destinc=dest->BytesPerRow(), + destinc=framebuffer.BytesPerRow(), + srcwidth=src->width, + srcheight=src->rows, + incval=0; + + int16 i,j; + + // starting point in source bitmap + srcbuffer=(uint8*)src->buffer; + + // starting point in destination bitmap + destbuffer=(uint8*)framebuffer.Bits()+(y*framebuffer.BytesPerRow()+(x*4)); + + + if(y<0) + { + if(yframebuffer.Bounds().IntegerHeight()) + { + if(y>pt.y) + y--; + srcheight-=(y+srcheight-1)-framebuffer.Bounds().IntegerHeight(); + } + + if(x+srcwidth>framebuffer.Bounds().IntegerWidth()) + { + if(x>pt.x) + x--; + srcwidth-=(x+srcwidth-1)-framebuffer.Bounds().IntegerWidth(); + } + + if(x<0) + { + if(xdraw_mode==B_OP_COPY) + { + rowptr[0]=uint8(highcolor.blue-(value*bstep)); + rowptr[1]=uint8(highcolor.green-(value*gstep)); + rowptr[2]=uint8(highcolor.red-(value*rstep)); + rowptr[3]=255; + } + else + if(d->draw_mode==B_OP_OVER) + { + if(highcolor.alpha>127) + { + rowptr[0]=uint8(highcolor.blue-(value*(float(highcolor.blue-rowptr[0])/255.0))); + rowptr[1]=uint8(highcolor.green-(value*(float(highcolor.green-rowptr[1])/255.0))); + rowptr[2]=uint8(highcolor.red-(value*(float(highcolor.red-rowptr[2])/255.0))); + rowptr[3]=255; + } + } + } + rowptr+=4; + + } + + srcindex+=srcinc; + destindex+=destinc; + } + ReleaseBuffer(); +} + +bool DisplayDriverImpl::AcquireBuffer(FBBitmap *bmp) +{ + return false; +} + +void DisplayDriverImpl::ReleaseBuffer() +{ +} + +void DisplayDriverImpl::Blit(const BRect &src, const BRect &dest, const DrawData *d) +{ +} + +void DisplayDriverImpl::FillSolidRect(const BRect &rect, const RGBColor &color) +{ +} + +void DisplayDriverImpl::FillPatternRect(const BRect &rect, const DrawData *d) +{ +} + +/* Draws a line with pensize 1. Coordinates are guarenteed to be in bounds */ +void DisplayDriverImpl::StrokeSolidLine(int32 x1, int32 y1, int32 x2, int32 y2, const RGBColor &color) +{ +} + +// Draws a line with pensize 1. Coordinates are guarenteed to be in bounds +void DisplayDriverImpl::StrokePatternLine(int32 x1, int32 y1, int32 x2, int32 y2, const DrawData *d) +{ +} + +void DisplayDriverImpl::StrokeSolidRect(const BRect &rect, const RGBColor &color) +{ +} + +void DisplayDriverImpl::CopyBitmap(ServerBitmap *bitmap, const BRect &source, const BRect &dest, const DrawData *d) +{ +} + +void DisplayDriverImpl::CopyToBitmap(ServerBitmap *target, const BRect &source) +{ +} + +void DisplayDriverImpl::Invalidate(const BRect &r) +{ +} + +void DisplayDriverImpl::ConstrainClippingRegion(BRegion *reg) +{ +} diff --git a/src/servers/app/Jamfile b/src/servers/app/Jamfile index 0d9cb2f2e0..1968cb262b 100644 --- a/src/servers/app/Jamfile +++ b/src/servers/app/Jamfile @@ -17,6 +17,7 @@ SharedLibrary appserver : CursorHandler.cpp Decorator.cpp DisplayDriver.cpp + DisplayDriverImpl.cpp DisplaySupport.cpp FontFamily.cpp GraphicsBuffer.cpp diff --git a/src/servers/app/ViewDriver.cpp b/src/servers/app/ViewDriver.cpp index d79a754d83..08006d4552 100644 --- a/src/servers/app/ViewDriver.cpp +++ b/src/servers/app/ViewDriver.cpp @@ -110,7 +110,7 @@ VDView::VDView(BRect bounds) oldcursorframe=cursor->Bounds(); } -VDView::~VDView(void) +VDView::~VDView() { delete serverlink; delete cursor; @@ -119,7 +119,7 @@ VDView::~VDView(void) delete viewbmp; } -void VDView::AttachedToWindow(void) +void VDView::AttachedToWindow() { } @@ -243,7 +243,7 @@ VDWindow::VDWindow(BRect frame) AddChild(view); } -VDWindow::~VDWindow(void) +VDWindow::~VDWindow() { } @@ -441,7 +441,7 @@ void VDWindow::MessageReceived(BMessage *msg) } } -bool VDWindow::QuitRequested(void) +bool VDWindow::QuitRequested() { port_id serverport=find_port(SERVER_PORT_NAME); @@ -483,7 +483,8 @@ void VDWindow::WindowActivated(bool active) //----------------------------------------------------------------------- //----------------------------------------------------------------------- -ViewDriver::ViewDriver(void) +ViewDriver::ViewDriver() + : DisplayDriverImpl() { fDisplayMode.virtual_width=640; fDisplayMode.virtual_height=480; @@ -500,7 +501,7 @@ ViewDriver::ViewDriver(void) framebuffer->Unlock(); } -ViewDriver::~ViewDriver(void) +ViewDriver::~ViewDriver() { if(is_initialized) { @@ -510,7 +511,8 @@ ViewDriver::~ViewDriver(void) } } -bool ViewDriver::Initialize(void) +bool +ViewDriver::Initialize() { Lock(); @@ -531,11 +533,14 @@ bool ViewDriver::Initialize(void) // because the window is locked until Show() is first called screenwin->Show(); Unlock(); - return true; + + return DisplayDriver::Initialize(); } -void ViewDriver::Shutdown(void) +void ViewDriver::Shutdown() { + DisplayDriver::Shutdown(); + Lock(); is_initialized=false; Unlock(); @@ -916,13 +921,13 @@ status_t ViewDriver::SetDPMSMode(const uint32 &state) return BScreen().SetDPMS(state); } -uint32 ViewDriver::DPMSMode(void) const +uint32 ViewDriver::DPMSMode() const { // See note for SetDPMSMode if there are questions return BScreen().DPMSState(); } -uint32 ViewDriver::DPMSCapabilities(void) const +uint32 ViewDriver::DPMSCapabilities() const { // See note for SetDPMSMode if there are questions return BScreen().DPMSCapabilites(); @@ -1205,7 +1210,7 @@ bool ViewDriver::AcquireBuffer(FBBitmap *bmp) return true; } -void ViewDriver::ReleaseBuffer(void) +void ViewDriver::ReleaseBuffer() { if(!is_initialized) return; diff --git a/src/servers/app/ViewDriver.h b/src/servers/app/ViewDriver.h index e6c257381d..8ab7e3b8b2 100644 --- a/src/servers/app/ViewDriver.h +++ b/src/servers/app/ViewDriver.h @@ -36,9 +36,10 @@ #include #include #include -#include "DisplayDriver.h" #include "FontServer.h" +#include "DisplayDriverImpl.h" + class BBitmap; class BPortLink; class VDWindow; @@ -48,8 +49,8 @@ class VDView : public BView { public: VDView(BRect bounds); - ~VDView(void); - void AttachedToWindow(void); + ~VDView(); + void AttachedToWindow(); void Draw(BRect rect); void MouseDown(BPoint pt); void MouseMoved(BPoint pt, uint32 transit, const BMessage *msg); @@ -70,9 +71,9 @@ class VDWindow : public BWindow { public: VDWindow(BRect frame); - ~VDWindow(void); + ~VDWindow(); void MessageReceived(BMessage *msg); - bool QuitRequested(void); + bool QuitRequested(); void WindowActivated(bool active); VDView *view; @@ -96,14 +97,14 @@ public: VDWindow - does most of the work. VDView - doesn't do all that much except display the rendered bitmap */ -class ViewDriver : public DisplayDriver +class ViewDriver : public DisplayDriverImpl { public: - ViewDriver(void); - ~ViewDriver(void); + ViewDriver(); + ~ViewDriver(); - virtual bool Initialize(void); // Sets the driver - virtual void Shutdown(void); // You never know when you'll need this + virtual bool Initialize(); // Sets the driver + virtual void Shutdown(); // You never know when you'll need this // Drawing functions // void DrawBitmap(ServerBitmap *bmp, const BRect &src, const BRect &dest, const DrawData *d); @@ -120,8 +121,8 @@ public: VDWindow *screenwin; virtual status_t SetDPMSMode(const uint32 &state); - virtual uint32 DPMSMode(void) const; - virtual uint32 DPMSCapabilities(void) const; + virtual uint32 DPMSMode() const; + virtual uint32 DPMSCapabilities() const; virtual status_t GetDeviceInfo(accelerant_device_info *info); virtual status_t GetModeList(display_mode **mode_list, uint32 *count); virtual status_t GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high); @@ -146,7 +147,7 @@ protected: virtual bool AcquireBuffer(FBBitmap *bmp); - virtual void ReleaseBuffer(void); + virtual void ReleaseBuffer(); virtual void Invalidate(const BRect &r); // void BlitMono2RGB32(FT_Bitmap *src, BPoint pt, DrawData *d);