// Copyright 2000 // College of Computer Science // Northeastern University Boston MA 02115 // This software may be used for educational purposes as long as this copyright // notice is retained at the top of all files // Should this software be modified, the words "Modified from Original" must be // included as a comment below this notice // All publication rights are retained. This software or its documentation may // not be published in any media either in whole or in part. /////////////////////////////////////////////////////////////////////////////// // GraphicsWidget.cpp /////////////////////////////////////////////////////////////////////////////// #include "CoreTools.h" #include "SystemBase.h" #include "GraphicsWidget.h" /////////////////////////////////////////////////////////////////////////////// void PolygonWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: PenSize, PenMode, PenColor, FillColor // changes: if (G.WindowState.PenMode == PM_Normal) { switch(ImageMethod) { case FF_Fill: case FF_FillFrame: DoFill(G); // fill interior with fill color // break if we just want to fill if (ImageMethod == FF_Fill) break; case FF_Frame: DoFrame(G); // fill exterior with pen color break; default: break; } // end switch } else { switch(ImageMethod) { case FF_Fill: DoFill(G); // fill interior break; case FF_Frame: DoFrame(G); // fill exterior break; case FF_FillFrame: DoBoth(G); // fill union of interior and exterior break; default: break; } } } #if defined(CORE_PLATFORM_WIN32) HRGN PolygonWidget::PolygonInterior(GraphicsWindow& G) const { HRGN Region; // poly data const NativePointData* PolygonPointer = (const NativePointData*) Poly.DataPointer(); // poly size int Size = Poly.ValidSize(); // poly fill mode int InternalMode; switch(PolyFillMode) { case PFM_Winding: InternalMode = WINDING; break; case PFM_Regular: default: InternalMode = ALTERNATE; break; } // create poly region Region = CreatePolygonRgn(PolygonPointer, Size, InternalMode); return Region; } HRGN PolygonWidget::PolygonExterior(GraphicsWindow& G) const { int i; int Size = Poly.ValidSize(); HRGN Region = CreateRectRgn(0, 0, 0, 0); HRGN Line; for (i = 1; i < Size; i++) { Line = G.WIN32_Line_Region(Poly.Access(i-1), Poly.Access(i)); CombineRgn(Region, Region, Line, RGN_OR); DeleteObject(Line); } return Region; } HRGN PolygonWidget::CompletePolygon(GraphicsWindow& G) const { HRGN Interior = PolygonInterior(G); HRGN Exterior = PolygonExterior(G); CombineRgn(Interior, Interior, Exterior, RGN_OR); DeleteObject(Exterior); return Interior; } #endif // end WIN32 specific void PolygonWidget::DoFill(GraphicsWindow& G) const { #if defined(CORE_PLATFORM_WIN32) HRGN Region = PolygonInterior(G); if(Region == 0) return; G.WIN32_Show_Region(Region, G.NativeState.FillBrush); DeleteObject(Region); #endif // end WIN32 specific #if defined(CORE_PLATFORM_MACOS) #endif // end MacOS specific } void PolygonWidget::DoFrame(GraphicsWindow& G) const { #if defined(CORE_PLATFORM_WIN32) HRGN Region = PolygonExterior(G); if(Region == 0) return; G.WIN32_Show_Region(Region, G.NativeState.PenBrush); DeleteObject(Region); #endif // end WIN32 specific #if defined(CORE_PLATFORM_MACOS) #endif // end MacOS specific } void PolygonWidget::DoBoth(GraphicsWindow& G) const { #if defined(CORE_PLATFORM_WIN32) HRGN Region = CompletePolygon(G); if(Region == 0) return; G.WIN32_Show_Region(Region, G.NativeState.FillBrush); DeleteObject(Region); #endif // end WIN32 specific #if defined(CORE_PLATFORM_MACOS) #endif // end MacOS specific } /////////////////////////////////////////////////////////////////////////////// void RectWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: PenSize, PenMode, PenColor, FillColor // changes: // find rect bounds in order RectData S = R; S.Order(); short x1, y1, x2, y2; S.Get(x1, y1, x2, y2); // define pen size variables short xpen, ypen; short a1, b1, a2, b2; #if defined(CORE_PLATFORM_WIN32) HRGN Region; HRGN InnerRegion; HRGN OuterRegion; Region = CreateRectRgn(x1, y1, x2, y2); switch (ImageMethod) { case FF_Fill: case FF_FrameFill: G.WIN32_Show_Region(Region, G.NativeState.FillBrush); // break if we just want to fill // or if pen mode is not normal if ((ImageMethod == FF_Fill) || (G.WindowState.PenMode != PM_Normal)) break; case FF_Frame: G.WindowState.PenSize.Get(xpen, ypen); a1 = x1 + xpen; b1 = y1 + ypen; a2 = x2 - xpen; b2 = y2 - ypen; // if pen is very thick then frame might be the same as fill // so just fill with the pen brush and break if ((a1 >= a2) || (b1 >= b2)) { G.WIN32_Show_Region(Region, G.NativeState.PenBrush); break; } // will create doughnut region between two rects InnerRegion = CreateRectRgn(a1, b1, a2, b2); OuterRegion = CreateRectRgn(0, 0, 0, 0); // dummy needed to initialize CombineRgn(OuterRegion, Region, InnerRegion, RGN_DIFF); G.WIN32_Show_Region(OuterRegion, G.NativeState.PenBrush); DeleteObject(InnerRegion); DeleteObject(OuterRegion); break; default: break; } DeleteObject(Region); #endif // end WIN32 specific #if defined(CORE_PLATFORM_MACOS) #endif // end MacOS specific } void OvalWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: PenSize, PenMode, PenColor, FillColor // changes: // find rect bounds in order RectData S = R; S.Order(); short x1, y1, x2, y2; S.Get(x1, y1, x2, y2); // define pen size variables short xpen, ypen; short a1, b1, a2, b2; #if defined(CORE_PLATFORM_WIN32) HRGN Region; HRGN InnerRegion; HRGN OuterRegion; Region = CreateEllipticRgn(x1, y1, x2, y2); switch (ImageMethod) { case FF_Fill: case FF_FrameFill: G.WIN32_Show_Region(Region, G.NativeState.FillBrush); // break if we just want to fill // or if pen mode is not normal if ((ImageMethod == FF_Fill) || (G.WindowState.PenMode != PM_Normal)) break; case FF_Frame: G.WindowState.PenSize.Get(xpen, ypen); a1 = x1 + xpen; b1 = y1 + ypen; a2 = x2 - xpen; b2 = y2 - ypen; // if pen is very thick then frame might be the same as fill // so just fill with the pen brush and break if ((a1 >= a2) || (b1 >= b2)) { G.WIN32_Show_Region(Region, G.NativeState.PenBrush); break; } // will create doughnut region between two ovals InnerRegion = CreateEllipticRgn(a1, b1, a2, b2); OuterRegion = CreateRectRgn(0, 0, 0, 0); // dummy needed to initialize CombineRgn(OuterRegion, Region, InnerRegion, RGN_DIFF); G.WIN32_Show_Region(OuterRegion, G.NativeState.PenBrush); DeleteObject(InnerRegion); DeleteObject(OuterRegion); break; default: break; } DeleteObject(Region); #endif // end WIN32 specific #if defined(CORE_PLATFORM_MACOS) #endif // end MacOS specific } /////////////////////////////////////////////////////////////////////////////// void PixelWidget::DrawDetails(GraphicsWindow& G) const { #if defined(CORE_PLATFORM_WIN32) ::SetPixel(G.hdc, x, y, color.Native()); #endif // end WIN32 specific } PixelWidget& PixelWidget::Peek(GraphicsWindow& G) { if(! G.IsOpen()) return *this; G.PrepareGraphics(); #if defined(CORE_PLATFORM_WIN32) color = ::GetPixel(G.hdc, x, y); #endif // end WIN32 specific G.ReleaseGraphics(); return *this; } PixelWidget& PixelWidget::Peek(int index) { GraphicsWindow* gwp = GraphicsWindowPtr(index); if (gwp) return Peek(*gwp); else return *this; } /////////////////////////////////////////////////////////////////////////////// void MoveToWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: // changes: Location G.WindowState.Location.Set(P); } void LineWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: PenSize, PenMode, PenColor [BackgroundMode, BackgroundColor] // changes: Location #if defined(CORE_PLATFORM_WIN32) HRGN Region; Region = G.WIN32_Line_Region(P, Q); G.WIN32_Show_Region(Region, G.NativeState.PenBrush); DeleteObject(Region); #endif // end WIN32 specific #if defined(CORE_PLATFORM_MACOS) #endif // end MacOS specific // now update the location G.WindowState.Location = Q; } void LineToWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: Location, PenSize, PenMode, PenColor [BackgroundMode, BackgroundColor] // changes: Location LineWidget Widget(G.WindowState.Location, P); // set other widget parameters if (IsPermanent()) Widget.SetPermanent(); else Widget.SetTemporary(); // now draw Widget.Draw(G); } void DeltaLineWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: Location, PenSize, PenMode, PenColor [BackgroundMode, BackgroundColor] // changes: Location PointData P = G.WindowState.Location; PointData Q = P + Delta; LineWidget Widget(P, Q); // set other widget parameters if (IsPermanent()) Widget.SetPermanent(); else Widget.SetTemporary(); // now draw Widget.Draw(G); } void DeltaMoveWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: Location // changes: Location MoveToWidget Widget(G.WindowState.Location + Delta); // set other widget parameters if (IsPermanent()) Widget.SetPermanent(); else Widget.SetTemporary(); // now draw Widget.Draw(G); } /////////////////////////////////////////////////////////////////////////////// void ClipRectWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: // changes: ClipRect, EnableClip [in GraphicsState], internal state #if defined(CORE_PLATFORM_WIN32) // give back current clip region if (G.WindowState.EnableClip) { DeleteObject(G.NativeState.ClipRgn); G.NativeState.ClipRgn = NULL; }; #endif // end WIN32 specific // make sure new clip rect is ordered RectData R = ClipRect; R.Order(); // save clip settings G.WindowState.ClipRect = R; G.WindowState.EnableClip = EnableClip; #if defined(CORE_PLATFORM_WIN32) // if clip is enabled then set up new clip region if (EnableClip) { short x1, y1, x2, y2; R.Get(x1, y1, x2, y2); G.NativeState.ClipRgn = CreateRectRgn(x1, y1, x2, y2); } #endif // end WIN32 specific } /////////////////////////////////////////////////////////////////////////////// void TransformWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: // changes: Transform [in GraphicsState] G.WindowState.Transform = Transform; } /////////////////////////////////////////////////////////////////////////////// void PolygonWidget2D::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: PenSize, PenMode, PenColor, FillColor // changes: // create a pixel poly which is the transform of our polygon PolygonData PixelPoly; G.WindowState.Transform.Apply(Poly, PixelPoly); // use the pixel poly to create a polygon widget PolygonWidget Widget(PixelPoly); // set other widget parameters if (IsPermanent()) Widget.SetPermanent(); else Widget.SetTemporary(); Widget.SetImageMethod(ImageMethod); Widget.SetPolyFillMode(PolyFillMode); // now draw Widget.Draw(G); } /////////////////////////////////////////////////////////////////////////////// void RectWidget2D::DrawDetails(GraphicsWindow& G) const { RectWidget Widget(G.WindowState.Transform(R)); // set other widget parameters if (IsPermanent()) Widget.SetPermanent(); else Widget.SetTemporary(); Widget.SetImageMethod(ImageMethod); // now draw Widget.Draw(G); } void OvalWidget2D::DrawDetails(GraphicsWindow& G) const { OvalWidget Widget(G.WindowState.Transform(R)); // set other widget parameters if (IsPermanent()) Widget.SetPermanent(); else Widget.SetTemporary(); Widget.SetImageMethod(ImageMethod); // now draw Widget.Draw(G); } /////////////////////////////////////////////////////////////////////////////// void LineWidget2D::DrawDetails(GraphicsWindow& G) const { LineWidget Widget(G.WindowState.Transform(P), G.WindowState.Transform(Q)); // set other widget parameters if (IsPermanent()) Widget.SetPermanent(); else Widget.SetTemporary(); // now draw Widget.Draw(G); } void LineToWidget2D::DrawDetails(GraphicsWindow& G) const { LineToWidget Widget(G.WindowState.Transform(P)); // set other widget parameters if (IsPermanent()) Widget.SetPermanent(); else Widget.SetTemporary(); // now draw Widget.Draw(G); } void MoveToWidget2D::DrawDetails(GraphicsWindow& G) const { MoveToWidget Widget(G.WindowState.Transform(P)); // set other widget parameters if (IsPermanent()) Widget.SetPermanent(); else Widget.SetTemporary(); // now draw Widget.Draw(G); } void DeltaLineWidget2D::DrawDetails(GraphicsWindow& G) const { DeltaLineWidget Widget(G.WindowState.Transform(Delta)); // set other widget parameters if (IsPermanent()) Widget.SetPermanent(); else Widget.SetTemporary(); // now draw Widget.Draw(G); } void DeltaMoveWidget2D::DrawDetails(GraphicsWindow& G) const { DeltaMoveWidget Widget(G.WindowState.Transform(Delta)); // set other widget parameters if (IsPermanent()) Widget.SetPermanent(); else Widget.SetTemporary(); // now draw Widget.Draw(G); } /////////////////////////////////////////////////////////////////////////////// void PenSizeWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: // changes: PenSize [in GraphicsState] G.WindowState.PenSize = PenSize; #if defined(CORE_PLATFORM_WIN32) PenSize.Get(G.NativeState.xpen, G.NativeState.ypen); #endif // end WIN32 specific } void PenModeWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: // changes: PenMode [in GraphicsState] G.WindowState.PenMode = PenMode; } void PenColorWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: // changes: PenColor [in GraphicsState] // save pen color G.WindowState.PenColor.Set(color); #if defined(CORE_PLATFORM_WIN32) G.NativeState.SetPenColor(color); #endif // end WIN32 specific } void FillColorWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: // changes: FillColor [in GraphicsState] // save pen color G.WindowState.FillColor.Set(color); #if defined(CORE_PLATFORM_WIN32) G.NativeState.SetFillColor(color); #endif // end WIN32 specific } /////////////////////////////////////////////////////////////////////////////// void TextWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: Location, TextAlign, TextColor, PenMode // BackgroundMode, BackgroundColor // changes: // set system parameters for text draw G.PrepareText(); // use the current location to position text short x, y; G.WindowState.Location.Get(x,y); // get pointer to string data and its length const char* p = text.c_str(); int length = text.length(); #if defined(CORE_PLATFORM_WIN32) TextOut(G.hdc, x, y, p, length); #endif // end WIN32 specific #if defined(CORE_PLATFORM_MACOS) #endif // end MacOS specific } void TextAlignWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: // changes: TextAlign [in GraphicsState] G.WindowState.TextAlign = TextAlign; #if defined(CORE_PLATFORM_WIN32) // extract vertical and horizontal components int valign = TextAlign & VAlign_MASK; int halign = TextAlign & HAlign_MASK; // will follow the convention that drawing text does not // update the current graphics location int WIN32align = TA_NOUPDATECP; switch (valign) { case VAlign_Baseline: WIN32align |= TA_BASELINE; break; case VAlign_Bottom: WIN32align |= TA_BOTTOM; break; // top is default case VAlign_Top: default: WIN32align |= TA_TOP; break; }; switch (halign) { case HAlign_Center: WIN32align |= TA_CENTER; break; case HAlign_Right: WIN32align |= TA_RIGHT; break; // left is default case HAlign_Left: default: WIN32align |= TA_LEFT; break; }; G.NativeState.TextAlign = WIN32align; #endif // end WIN32 specific } TextAlignWidget& TextAlignWidget::Set(int aligncode) { // extract vertical and horizontal components int valign = aligncode & VAlign_MASK; int halign = aligncode & HAlign_MASK; // check for valid v & h align information switch (valign) { case VAlign_Baseline: case VAlign_Bottom: case VAlign_Top: // valid information so break break; default: // no valid information so use stored setting valign = TextAlign & VAlign_MASK; }; switch (halign) { case HAlign_Center: case HAlign_Right: case HAlign_Left: // valid information so break break; default: // no valid information so use stored setting halign = TextAlign & HAlign_MASK; }; TextAlign = valign | halign; return *this; }; void TextColorWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: // changes: TextColor [in GraphicsState] // save pen color G.WindowState.TextColor.Set(color); } /////////////////////////////////////////////////////////////////////////////// void BackgroundModeWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: // changes: BackgroundMode [in GraphicsState] G.WindowState.BackgroundMode = BackgroundMode; } void BackgroundColorWidget::DrawDetails(GraphicsWindow& G) const { // GraphicsState interactions // uses: // changes: BackgroundColor [in GraphicsState] // save pen color G.WindowState.BackgroundColor.Set(color); }