diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 8b8631b521..a32c4d9f36 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -66,7 +66,7 @@ BEOS_PREFERENCES = Appearance Backgrounds DataTranslations E-mail ; BEOS_DEMOS = BSnow Chart Clock $(X86_ONLY)Cortex FontDemo $(X86_ONLY)GLDirectMode $(X86_ONLY)GLTeapot Mandelbrot Pairs - Playground Pulse Sudoku + Playground Pulse Sudoku Gradients ; BEOS_SYSTEM_LIBS = libbe.so $(HAIKU_LIBSTDC++) libmedia.so libtracker.so libtranslation.so libbnetapi.so libnetwork.so libdebug.so libbsd.so diff --git a/headers/build/private/app/PortLink.h b/headers/build/private/app/PortLink.h index e2943130f3..38084f1339 100644 --- a/headers/build/private/app/PortLink.h +++ b/headers/build/private/app/PortLink.h @@ -50,6 +50,7 @@ class ServerLink { status_t AttachString(const char *string, int32 length = -1); status_t AttachRegion(const BRegion ®ion); status_t AttachShape(BShape &shape); + status_t AttachGradient(const BGradient &gradient); template status_t Attach(const Type& data); // receive methods @@ -63,6 +64,7 @@ class ServerLink { status_t ReadString(char **string); status_t ReadRegion(BRegion *region); status_t ReadShape(BShape *shape); + status_t ReadGradient(BGradient *gradient); template status_t Read(Type *data); // convenience methods diff --git a/headers/build/private/app/ServerProtocol.h b/headers/build/private/app/ServerProtocol.h index 7d3566545d..76c263a8ba 100644 --- a/headers/build/private/app/ServerProtocol.h +++ b/headers/build/private/app/ServerProtocol.h @@ -219,14 +219,23 @@ enum { AS_STROKE_TRIANGLE, AS_FILL_ARC, + AS_FILL_ARC_GRADIENT, AS_FILL_BEZIER, + AS_FILL_BEZIER_GRADIENT, AS_FILL_ELLIPSE, + AS_FILL_ELLIPSE_GRADIENT, AS_FILL_POLYGON, + AS_FILL_POLYGON_GRADIENT, AS_FILL_RECT, + AS_FILL_RECT_GRADIENT, AS_FILL_REGION, + AS_FILL_REGION_GRADIENT, AS_FILL_ROUNDRECT, + AS_FILL_ROUNDRECT_GRADIENT, AS_FILL_SHAPE, + AS_FILL_SHAPE_GRADIENT, AS_FILL_TRIANGLE, + AS_FILL_TRIANGLE_GRADIENT, AS_MOVEPENBY, AS_MOVEPENTO, diff --git a/headers/os/interface/Gradient.h b/headers/os/interface/Gradient.h new file mode 100644 index 0000000000..331be06f8c --- /dev/null +++ b/headers/os/interface/Gradient.h @@ -0,0 +1,110 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + * Artur Wyszynski + */ + +#ifndef GRADIENT_H +#define GRADIENT_H + +#include +#include +#include + + +class BMessage; +class BRect; + + +enum gradient_type { + B_GRADIENT_LINEAR = 0, + B_GRADIENT_RADIAL, + B_GRADIENT_RADIAL_FOCUS, + B_GRADIENT_DIAMOND, + B_GRADIENT_CONIC, + B_GRADIENT_NONE +}; + + +struct color_step { + color_step(const rgb_color c, float o); + color_step(uint8 r, uint8 g, uint8 b, uint8 a, float o); + color_step(const color_step& other); + color_step(); + + bool operator!=(const color_step& other) const; + + rgb_color color; + float offset; +}; + + +class BGradient : public BArchivable { +public: + BGradient(); + BGradient(BMessage* archive); + virtual ~BGradient(); + + status_t Archive(BMessage* into, bool deep = true) const; + + BGradient& operator=(const BGradient& other); + + bool operator==(const BGradient& other) const; + bool operator!=(const BGradient& other) const; + bool ColorStepsAreEqual(const BGradient& other) const; + + void SetColors(const BGradient& other); + + int32 AddColor(const rgb_color& color, float offset); + bool AddColor(const color_step& color, int32 index); + + bool RemoveColor(int32 index); + + bool SetColor(int32 index, const color_step& step); + bool SetColor(int32 index, const rgb_color& color); + bool SetOffset(int32 index, float offset); + + int32 CountColors() const; + color_step* ColorAt(int32 index) const; + color_step* ColorAtFast(int32 index) const; + color_step* Colors() const; + void SortColorStepsByOffset(); + + gradient_type Type() const + { return fType; } + + void MakeEmpty(); + +private: + friend class BGradientLinear; + friend class BGradientRadial; + friend class BGradientRadialFocus; + friend class BGradientDiamond; + friend class BGradientConic; + + union { + struct { + float x1, y1, x2, y2; + } linear; + struct { + float cx, cy, radius; + } radial; + struct { + float cx, cy, fx, fy, radius; + } radial_focus; + struct { + float cx, cy; + } diamond; + struct { + float cx, cy, angle; + } conic; + } fData; + + BList fColors; + gradient_type fType; +}; + +#endif // GRADIENT_H diff --git a/headers/os/interface/GradientConic.h b/headers/os/interface/GradientConic.h new file mode 100644 index 0000000000..5111e1535a --- /dev/null +++ b/headers/os/interface/GradientConic.h @@ -0,0 +1,30 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Artur Wyszynski + */ + +#ifndef GRADIENT_CONIC_H +#define GRADIENT_CONIC_H + +#include + +class BPoint; + +class BGradientConic : public BGradient { +public: + BGradientConic(); + BGradientConic(const BPoint& center, float angle); + BGradientConic(float cx, float cy, float angle); + + BPoint Center() const; + void SetCenter(const BPoint& center); + void SetCenter(float cx, float cy); + + float Angle() const; + void SetAngle(float angle); +}; + +#endif // GRADIENT_CONIC_H diff --git a/headers/os/interface/GradientDiamond.h b/headers/os/interface/GradientDiamond.h new file mode 100644 index 0000000000..56689fa396 --- /dev/null +++ b/headers/os/interface/GradientDiamond.h @@ -0,0 +1,27 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Artur Wyszynski + */ + +#ifndef GRADIENT_DIAMOND_H +#define GRADIENT_DIAMOND_H + +#include + +class BPoint; + +class BGradientDiamond : public BGradient { +public: + BGradientDiamond(); + BGradientDiamond(const BPoint& center); + BGradientDiamond(float cx, float cy); + + BPoint Center() const; + void SetCenter(const BPoint& center); + void SetCenter(float cx, float cy); +}; + +#endif // GRADIENT_DIAMOND_H diff --git a/headers/os/interface/GradientLinear.h b/headers/os/interface/GradientLinear.h new file mode 100644 index 0000000000..6c596c8274 --- /dev/null +++ b/headers/os/interface/GradientLinear.h @@ -0,0 +1,31 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Artur Wyszynski + */ + +#ifndef GRADIENT_LINEAR_H +#define GRADIENT_LINEAR_H + +#include + +class BPoint; + +class BGradientLinear : public BGradient { +public: + BGradientLinear(); + BGradientLinear(const BPoint& start, const BPoint& end); + BGradientLinear(float x1, float y1, float x2, float y2); + + BPoint Start() const; + void SetStart(const BPoint& start); + void SetStart(float x1, float y1); + + BPoint End() const; + void SetEnd(const BPoint& end); + void SetEnd(float x2, float y2); +}; + +#endif // GRADIENT_LINEAR_H diff --git a/headers/os/interface/GradientRadial.h b/headers/os/interface/GradientRadial.h new file mode 100644 index 0000000000..34f4ee8da1 --- /dev/null +++ b/headers/os/interface/GradientRadial.h @@ -0,0 +1,30 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Artur Wyszynski + */ + +#ifndef GRADIENT_RADIAL_H +#define GRADIENT_RADIAL_H + +#include + +class BPoint; + +class BGradientRadial : public BGradient { +public: + BGradientRadial(); + BGradientRadial(const BPoint& center, float radius); + BGradientRadial(float cx, float cy, float radius); + + BPoint Center() const; + void SetCenter(const BPoint& center); + void SetCenter(float cx, float cy); + + float Radius() const; + void SetRadius(float radius); +}; + +#endif // GRADIENT_RADIAL_H diff --git a/headers/os/interface/GradientRadialFocus.h b/headers/os/interface/GradientRadialFocus.h new file mode 100644 index 0000000000..b920e1b5a7 --- /dev/null +++ b/headers/os/interface/GradientRadialFocus.h @@ -0,0 +1,35 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Artur Wyszynski + */ + +#ifndef GRADIENT_RADIAL_FOCUS_H +#define GRADIENT_RADIAL_FOCUS_H + +#include + +class BPoint; + +class BGradientRadialFocus : public BGradient { +public: + BGradientRadialFocus(); + BGradientRadialFocus(const BPoint& center, float radius, + const BPoint& focal); + BGradientRadialFocus(float cx, float cy, float radius, float fx, float fy); + + BPoint Center() const; + void SetCenter(const BPoint& center); + void SetCenter(float cx, float cy); + + BPoint Focal() const; + void SetFocal(const BPoint& focal); + void SetFocal(float fx, float fy); + + float Radius() const; + void SetRadius(float radius); +}; + +#endif // GRADIENT_RADIAL_FOCUS_H diff --git a/headers/os/interface/View.h b/headers/os/interface/View.h index 2f88339b8e..eb7dff9125 100644 --- a/headers/os/interface/View.h +++ b/headers/os/interface/View.h @@ -16,6 +16,7 @@ #include #include #include +#include // mouse button @@ -317,7 +318,13 @@ public: pattern p = B_SOLID_HIGH); void FillPolygon(const BPoint* ptArray, int32 numPts, BRect bounds, pattern p = B_SOLID_HIGH); - + void FillPolygon(const BPolygon* polygon, + const BGradient& gradient); + void FillPolygon(const BPoint* ptArray, int32 numPts, + const BGradient& gradient); + void FillPolygon(const BPoint* ptArray, int32 numPts, + BRect bounds, const BGradient& gradient); + void StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, BRect bounds, pattern p = B_SOLID_HIGH); void StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, @@ -326,17 +333,26 @@ public: pattern p = B_SOLID_HIGH); void FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, BRect bounds, pattern p = B_SOLID_HIGH); + void FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, + const BGradient& gradient); + void FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, + BRect bounds, const BGradient& gradient); void StrokeRect(BRect r, pattern p = B_SOLID_HIGH); void FillRect(BRect r, pattern p = B_SOLID_HIGH); + void FillRect(BRect r, const BGradient& gradient); void FillRegion(BRegion* region, pattern p = B_SOLID_HIGH); + void FillRegion(BRegion* region, + const BGradient& gradient); void InvertRect(BRect r); void StrokeRoundRect(BRect r, float xRadius, float yRadius, pattern p = B_SOLID_HIGH); void FillRoundRect(BRect r, float xRadius, float yRadius, pattern p = B_SOLID_HIGH); + void FillRoundRect(BRect r, float xRadius, float yRadius, + const BGradient& gradient); void StrokeEllipse(BPoint center, float xRadius, float yRadius, pattern p = B_SOLID_HIGH); @@ -344,7 +360,10 @@ public: void FillEllipse(BPoint center, float xRadius, float yRadius, pattern p = B_SOLID_HIGH); void FillEllipse(BRect r, pattern p = B_SOLID_HIGH); - + void FillEllipse(BPoint center, float xRadius, + float yRadius, const BGradient& gradient); + void FillEllipse(BRect r, const BGradient& gradient); + void StrokeArc(BPoint center, float xRadius, float yRadius, float startAngle, float arcAngle, pattern p = B_SOLID_HIGH); @@ -355,15 +374,23 @@ public: pattern p = B_SOLID_HIGH); void FillArc(BRect r, float startAngle, float arcAngle, pattern p = B_SOLID_HIGH); - + void FillArc(BPoint center, float xRadius, float yRadius, + float startAngle, float arcAngle, + const BGradient& gradient); + void FillArc(BRect r, float startAngle, float arcAngle, + const BGradient& gradient); + void StrokeBezier(BPoint* controlPoints, pattern p = B_SOLID_HIGH); void FillBezier(BPoint* controlPoints, pattern p = B_SOLID_HIGH); + void FillBezier(BPoint* controlPoints, + const BGradient& gradient); void StrokeShape(BShape* shape, pattern p = B_SOLID_HIGH); void FillShape(BShape* shape, pattern p = B_SOLID_HIGH); + void FillShape(BShape* shape, const BGradient& gradient); void CopyBits(BRect src, BRect dst); diff --git a/headers/private/app/LinkReceiver.h b/headers/private/app/LinkReceiver.h index 748a52b4f7..3d1f9ffb11 100644 --- a/headers/private/app/LinkReceiver.h +++ b/headers/private/app/LinkReceiver.h @@ -15,6 +15,7 @@ class BString; class BRegion; +class BGradient; namespace BPrivate { @@ -37,6 +38,7 @@ class LinkReceiver { status_t ReadString(BString& string, size_t* _length = NULL); status_t ReadString(char* buffer, size_t bufferSize); status_t ReadRegion(BRegion* region); + status_t ReadGradient(BGradient *gradient); template status_t Read(Type *data) { return Read(data, sizeof(Type)); } diff --git a/headers/private/app/ServerLink.h b/headers/private/app/ServerLink.h index aabc843b5b..514e42630f 100644 --- a/headers/private/app/ServerLink.h +++ b/headers/private/app/ServerLink.h @@ -17,6 +17,7 @@ class BShape; class BString; +class BGradient; /* * Error checking rules: (for if you don't want to check every return code) @@ -49,6 +50,7 @@ class ServerLink { status_t AttachString(const char *string, int32 length = -1); status_t AttachRegion(const BRegion ®ion); status_t AttachShape(BShape &shape); + status_t AttachGradient(const BGradient &gradient); template status_t Attach(const Type& data); // receive methods @@ -64,6 +66,7 @@ class ServerLink { status_t ReadString(char** _string, size_t* _length = NULL); status_t ReadRegion(BRegion *region); status_t ReadShape(BShape *shape); + status_t ReadGradient(BGradient *gradient); template status_t Read(Type *data); // convenience methods diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index 860d8ba5a3..f6808f1981 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -218,14 +218,23 @@ enum { AS_STROKE_TRIANGLE, AS_FILL_ARC, + AS_FILL_ARC_GRADIENT, AS_FILL_BEZIER, + AS_FILL_BEZIER_GRADIENT, AS_FILL_ELLIPSE, + AS_FILL_ELLIPSE_GRADIENT, AS_FILL_POLYGON, + AS_FILL_POLYGON_GRADIENT, AS_FILL_RECT, + AS_FILL_RECT_GRADIENT, AS_FILL_REGION, + AS_FILL_REGION_GRADIENT, AS_FILL_ROUNDRECT, + AS_FILL_ROUNDRECT_GRADIENT, AS_FILL_SHAPE, + AS_FILL_SHAPE_GRADIENT, AS_FILL_TRIANGLE, + AS_FILL_TRIANGLE_GRADIENT, AS_DRAW_STRING, AS_DRAW_STRING_WITH_DELTA, diff --git a/src/apps/Jamfile b/src/apps/Jamfile index 6b7cb37039..66b7364ecd 100644 --- a/src/apps/Jamfile +++ b/src/apps/Jamfile @@ -18,6 +18,7 @@ SubInclude HAIKU_TOP src apps drivesetup ; SubInclude HAIKU_TOP src apps expander ; SubInclude HAIKU_TOP src apps fontdemo ; SubInclude HAIKU_TOP src apps glteapot ; +SubInclude HAIKU_TOP src apps gradients ; SubInclude HAIKU_TOP src apps icon-o-matic ; SubInclude HAIKU_TOP src apps installedpackages ; SubInclude HAIKU_TOP src apps installer ; diff --git a/src/apps/gradients/Gradients.cpp b/src/apps/gradients/Gradients.cpp new file mode 100644 index 0000000000..97925dad38 --- /dev/null +++ b/src/apps/gradients/Gradients.cpp @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2008, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Artur Wyszynski + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define MSG_LINEAR 'gtli' +#define MSG_RADIAL 'gtra' +#define MSG_RADIAL_FOCUS 'gtrf' +#define MSG_DIAMOND 'gtdi' +#define MSG_CONIC 'gtco' + +class GradientsApp : public BApplication { +public: + GradientsApp(void); +}; + + +class GradientsView : public BView { +public: + GradientsView(const BRect &r); + virtual ~GradientsView(void); + + virtual void Draw(BRect update); + void DrawLinear(BRect update); + void DrawRadial(BRect update); + void DrawRadialFocus(BRect update); + void DrawDiamond(BRect update); + void DrawConic(BRect update); + void SetType(gradient_type type); + +private: + gradient_type fType; +}; + + +class GradientsWindow : public BWindow { +public: + GradientsWindow(void); + + bool QuitRequested(void); + virtual void MessageReceived(BMessage *msg); + +private: + BPopUpMenu* fGradientsMenu; + BMenuItem* fLinearItem; + BMenuItem* fRadialItem; + BMenuItem* fRadialFocusItem; + BMenuItem* fDiamondItem; + BMenuItem* fConicItem; + BMenuField* fGradientsTypeField; + GradientsView* fGradientsView; +}; + + +// #pragma mark - + + +GradientsApp::GradientsApp(void) + : BApplication("application/x-vnd.Haiku-Gradients") +{ + GradientsWindow *window = new GradientsWindow(); + window->Show(); +} + + +// #pragma mark - + + +GradientsWindow::GradientsWindow() + : BWindow(BRect(0, 0, 230, 490), "Gradients Test", B_TITLED_WINDOW, + B_NOT_RESIZABLE | B_NOT_ZOOMABLE) +{ + BRect field(10, 10, Bounds().Width() - 10, 30); + fGradientsMenu = new BPopUpMenu("gradientsType"); + fLinearItem = new BMenuItem("Linear", new BMessage(MSG_LINEAR)); + fRadialItem = new BMenuItem("Radial", new BMessage(MSG_RADIAL)); + fRadialFocusItem = new BMenuItem("Radial Focus", + new BMessage(MSG_RADIAL_FOCUS)); + fDiamondItem = new BMenuItem("Diamond", new BMessage(MSG_DIAMOND)); + fConicItem = new BMenuItem("Conic", new BMessage(MSG_CONIC)); + fGradientsMenu->AddItem(fLinearItem); + fGradientsMenu->AddItem(fRadialItem); + fGradientsMenu->AddItem(fRadialFocusItem); + fGradientsMenu->AddItem(fDiamondItem); + fGradientsMenu->AddItem(fConicItem); + fLinearItem->SetMarked(true); + fGradientsTypeField = new BMenuField(field, "gradientsField", + "Gradient type:", + fGradientsMenu, + B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, + B_WILL_DRAW | B_NAVIGABLE + | B_FRAME_EVENTS); + fGradientsTypeField->SetViewColor(255, 255, 255); + fGradientsTypeField->SetDivider(110); + AddChild(fGradientsTypeField); + + BRect bounds = Bounds(); + bounds.top = 40; + fGradientsView = new GradientsView(bounds); + AddChild(fGradientsView); + + MoveTo((BScreen().Frame().Width() - Bounds().Width()) / 2, + (BScreen().Frame().Height() - Bounds().Height()) / 2 ); +} + + +bool +GradientsWindow::QuitRequested() +{ + be_app->PostMessage(B_QUIT_REQUESTED); + return true; +} + + +void +GradientsWindow::MessageReceived(BMessage *msg) +{ + switch (msg->what) { + case MSG_LINEAR: + fGradientsView->SetType(B_GRADIENT_LINEAR); + break; + case MSG_RADIAL: + fGradientsView->SetType(B_GRADIENT_RADIAL); + break; + case MSG_RADIAL_FOCUS: + fGradientsView->SetType(B_GRADIENT_RADIAL_FOCUS); + break; + case MSG_DIAMOND: + fGradientsView->SetType(B_GRADIENT_DIAMOND); + break; + case MSG_CONIC: + fGradientsView->SetType(B_GRADIENT_CONIC); + break; + default: + BWindow::MessageReceived(msg); + break; + } +} + + +// #pragma mark - + + +GradientsView::GradientsView(const BRect &rect) + : BView(rect, "gradientsview", B_FOLLOW_ALL, B_WILL_DRAW | B_PULSE_NEEDED), + fType(B_GRADIENT_LINEAR) +{ +} + + +GradientsView::~GradientsView() +{ +} + + +void +GradientsView::Draw(BRect update) +{ + switch (fType) { + case B_GRADIENT_LINEAR: { + DrawLinear(update); + break; + } + case B_GRADIENT_RADIAL: { + DrawRadial(update); + break; + } + case B_GRADIENT_RADIAL_FOCUS: { + DrawRadialFocus(update); + break; + } + case B_GRADIENT_DIAMOND: { + DrawDiamond(update); + break; + } + case B_GRADIENT_CONIC: { + DrawConic(update); + break; + } + case B_GRADIENT_NONE: + default: { + break; + } + } +} + +void +GradientsView::DrawLinear(BRect update) +{ + BGradientLinear gradient; + rgb_color c; + c.red = 255; + c.green = 0; + c.blue = 0; + gradient.AddColor(c, 0); + c.red = 0; + c.green = 255; + c.blue = 0; + gradient.AddColor(c, 127); + c.red = 0; + c.green = 0; + c.blue = 255; + gradient.AddColor(c, 255); + + // RoundRect + SetHighColor(0, 0, 0); + FillRoundRect(BRect(10, 10, 110, 110), 5, 5); + gradient.SetStart(BPoint(120, 10)); + gradient.SetEnd(BPoint(220, 110)); + FillRoundRect(BRect(120, 10, 220, 110), 5, 5, gradient); + + // Rect + SetHighColor(0, 0, 0); + FillRect(BRect(10, 120, 110, 220)); + gradient.SetStart(BPoint(120, 120)); + gradient.SetEnd(BPoint(220, 220)); + FillRect(BRect(120, 120, 220, 220), gradient); + + // Triangle + SetHighColor(0, 0, 0); + FillTriangle(BPoint(60, 230), BPoint(10, 330), BPoint(110, 330)); + gradient.SetStart(BPoint(60, 230)); + gradient.SetEnd(BPoint(60, 330)); + FillTriangle(BPoint(170, 230), BPoint(120, 330), BPoint(220, 330), gradient); + + // Ellipse + SetHighColor(0, 0, 0); + FillEllipse(BPoint(60, 390), 50, 50); + gradient.SetStart(BPoint(60, 340)); + gradient.SetEnd(BPoint(60, 440)); + FillEllipse(BPoint(170, 390), 50, 50, gradient); +} + + +void +GradientsView::DrawRadial(BRect update) +{ + BGradientRadial gradient; + rgb_color c; + c.red = 255; + c.green = 0; + c.blue = 0; + gradient.AddColor(c, 0); + c.red = 0; + c.green = 255; + c.blue = 0; + gradient.AddColor(c, 127); + c.red = 0; + c.green = 0; + c.blue = 255; + gradient.AddColor(c, 255); + + // RoundRect + SetHighColor(0, 0, 0); + FillRoundRect(BRect(10, 10, 110, 110), 5, 5); + gradient.SetCenter(BPoint(170, 60)); + FillRoundRect(BRect(120, 10, 220, 110), 5, 5, gradient); + + // Rect + SetHighColor(0, 0, 0); + FillRect(BRect(10, 120, 110, 220)); + gradient.SetCenter(BPoint(170, 170)); + FillRect(BRect(120, 120, 220, 220), gradient); + + // Triangle + SetHighColor(0, 0, 0); + FillTriangle(BPoint(60, 230), BPoint(10, 330), BPoint(110, 330)); + gradient.SetCenter(BPoint(170, 280)); + FillTriangle(BPoint(170, 230), BPoint(120, 330), BPoint(220, 330), gradient); + + // Ellipse + SetHighColor(0, 0, 0); + FillEllipse(BPoint(60, 390), 50, 50); + gradient.SetCenter(BPoint(170, 390)); + FillEllipse(BPoint(170, 390), 50, 50, gradient); +} + + +void +GradientsView::DrawRadialFocus(BRect update) +{ + BGradientRadialFocus gradient; + rgb_color c; + c.red = 255; + c.green = 0; + c.blue = 0; + gradient.AddColor(c, 0); + c.red = 0; + c.green = 255; + c.blue = 0; + gradient.AddColor(c, 127); + c.red = 0; + c.green = 0; + c.blue = 255; + gradient.AddColor(c, 255); + + // RoundRect + SetHighColor(0, 0, 0); + FillRoundRect(BRect(10, 10, 110, 110), 5, 5); + gradient.SetCenter(BPoint(170, 60)); + FillRoundRect(BRect(120, 10, 220, 110), 5, 5, gradient); + + // Rect + SetHighColor(0, 0, 0); + FillRect(BRect(10, 120, 110, 220)); + gradient.SetCenter(BPoint(170, 170)); + FillRect(BRect(120, 120, 220, 220), gradient); + + // Triangle + SetHighColor(0, 0, 0); + FillTriangle(BPoint(60, 230), BPoint(10, 330), BPoint(110, 330)); + gradient.SetCenter(BPoint(170, 280)); + FillTriangle(BPoint(170, 230), BPoint(120, 330), BPoint(220, 330), gradient); + + // Ellipse + SetHighColor(0, 0, 0); + FillEllipse(BPoint(60, 390), 50, 50); + gradient.SetCenter(BPoint(170, 390)); + FillEllipse(BPoint(170, 390), 50, 50, gradient); +} + + +void +GradientsView::DrawDiamond(BRect update) +{ + BGradientDiamond gradient; + rgb_color c; + c.red = 255; + c.green = 0; + c.blue = 0; + gradient.AddColor(c, 0); + c.red = 0; + c.green = 255; + c.blue = 0; + gradient.AddColor(c, 127); + c.red = 0; + c.green = 0; + c.blue = 255; + gradient.AddColor(c, 255); + + // RoundRect + SetHighColor(0, 0, 0); + FillRoundRect(BRect(10, 10, 110, 110), 5, 5); + gradient.SetCenter(BPoint(170, 60)); + FillRoundRect(BRect(120, 10, 220, 110), 5, 5, gradient); + + // Rect + SetHighColor(0, 0, 0); + FillRect(BRect(10, 120, 110, 220)); + gradient.SetCenter(BPoint(170, 170)); + FillRect(BRect(120, 120, 220, 220), gradient); + + // Triangle + SetHighColor(0, 0, 0); + FillTriangle(BPoint(60, 230), BPoint(10, 330), BPoint(110, 330)); + gradient.SetCenter(BPoint(170, 280)); + FillTriangle(BPoint(170, 230), BPoint(120, 330), BPoint(220, 330), gradient); + + // Ellipse + SetHighColor(0, 0, 0); + FillEllipse(BPoint(60, 390), 50, 50); + gradient.SetCenter(BPoint(170, 390)); + FillEllipse(BPoint(170, 390), 50, 50, gradient); +} + + +void +GradientsView::DrawConic(BRect update) +{ + BGradientConic gradient; + rgb_color c; + c.red = 255; + c.green = 0; + c.blue = 0; + gradient.AddColor(c, 0); + c.red = 0; + c.green = 255; + c.blue = 0; + gradient.AddColor(c, 127); + c.red = 0; + c.green = 0; + c.blue = 255; + gradient.AddColor(c, 255); + + // RoundRect + SetHighColor(0, 0, 0); + FillRoundRect(BRect(10, 10, 110, 110), 5, 5); + gradient.SetCenter(BPoint(170, 60)); + FillRoundRect(BRect(120, 10, 220, 110), 5, 5, gradient); + + // Rect + SetHighColor(0, 0, 0); + FillRect(BRect(10, 120, 110, 220)); + gradient.SetCenter(BPoint(170, 170)); + FillRect(BRect(120, 120, 220, 220), gradient); + + // Triangle + SetHighColor(0, 0, 0); + FillTriangle(BPoint(60, 230), BPoint(10, 330), BPoint(110, 330)); + gradient.SetCenter(BPoint(170, 280)); + FillTriangle(BPoint(170, 230), BPoint(120, 330), BPoint(220, 330), gradient); + + // Ellipse + SetHighColor(0, 0, 0); + FillEllipse(BPoint(60, 390), 50, 50); + gradient.SetCenter(BPoint(170, 390)); + FillEllipse(BPoint(170, 390), 50, 50, gradient); +} + + +void +GradientsView::SetType(gradient_type type) +{ + fType = type; + Invalidate(); +} + + +// #pragma mark - + + +int +main() +{ + GradientsApp app; + app.Run(); + return 0; +} diff --git a/src/apps/gradients/Gradients.rdef b/src/apps/gradients/Gradients.rdef new file mode 100644 index 0000000000..1006d58141 --- /dev/null +++ b/src/apps/gradients/Gradients.rdef @@ -0,0 +1,27 @@ + +resource app_signature "application/x-vnd.Haiku-Gradients"; + +resource app_version { + major = 1, + middle = 0, + minor = 0, + + variety = B_APPV_BETA, + + internal = 0, + + short_info = "Gradients", + long_info = "Gradients ©2008 Haiku, Inc." +}; + +resource app_flags B_SINGLE_LAUNCH; + +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + +resource vector_icon { + $"6E636966020200040269FF0000D000FF000200040308FF0000C700FF00FF0000" + $"FF020A0420204020406020600A044020602060604060020A000100000A010101" + $"00" +}; + +#endif // HAIKU_TARGET_PLATFORM_HAIKU diff --git a/src/apps/gradients/Jamfile b/src/apps/gradients/Jamfile new file mode 100644 index 0000000000..eaaaae9002 --- /dev/null +++ b/src/apps/gradients/Jamfile @@ -0,0 +1,7 @@ +SubDir HAIKU_TOP src apps gradients ; + +Application Gradients : + Gradients.cpp + : be + : Gradients.rdef +; diff --git a/src/apps/icon-o-matic/Jamfile b/src/apps/icon-o-matic/Jamfile index 4496a39cf6..424cae3555 100644 --- a/src/apps/icon-o-matic/Jamfile +++ b/src/apps/icon-o-matic/Jamfile @@ -85,7 +85,7 @@ Application Icon-O-Matic : VectorPath.cpp # icon/style - Gradient.cpp + GradientTransformable.cpp Style.cpp StyleContainer.cpp diff --git a/src/apps/icon-o-matic/MainWindow.cpp b/src/apps/icon-o-matic/MainWindow.cpp index 6e8739650c..deb1962817 100644 --- a/src/apps/icon-o-matic/MainWindow.cpp +++ b/src/apps/icon-o-matic/MainWindow.cpp @@ -52,7 +52,7 @@ // TODO: just for testing #include "AffineTransformer.h" -#include "Gradient.h" +#include "GradientTransformable.h" #include "Icon.h" #include "MultipleManipulatorState.h" #include "PathManipulator.h" diff --git a/src/apps/icon-o-matic/gui/GradientControl.cpp b/src/apps/icon-o-matic/gui/GradientControl.cpp index 634c605be9..515c9c6bec 100644 --- a/src/apps/icon-o-matic/gui/GradientControl.cpp +++ b/src/apps/icon-o-matic/gui/GradientControl.cpp @@ -18,7 +18,7 @@ #include "ui_defines.h" #include "support_ui.h" -#include "Gradient.h" +#include "GradientTransformable.h" // constructor GradientControl::GradientControl(BMessage* message, BHandler* target) diff --git a/src/apps/icon-o-matic/gui/StyleListView.cpp b/src/apps/icon-o-matic/gui/StyleListView.cpp index 9d3b2e01b5..fce48e1f3e 100644 --- a/src/apps/icon-o-matic/gui/StyleListView.cpp +++ b/src/apps/icon-o-matic/gui/StyleListView.cpp @@ -22,7 +22,7 @@ #include "AssignStyleCommand.h" #include "CurrentColor.h" #include "CommandStack.h" -#include "Gradient.h" +#include "GradientTransformable.h" #include "MoveStylesCommand.h" #include "RemoveStylesCommand.h" #include "Style.h" diff --git a/src/apps/icon-o-matic/gui/StyleView.cpp b/src/apps/icon-o-matic/gui/StyleView.cpp index 5e6269bcf1..fab4a938ac 100644 --- a/src/apps/icon-o-matic/gui/StyleView.cpp +++ b/src/apps/icon-o-matic/gui/StyleView.cpp @@ -23,7 +23,7 @@ #include "CommandStack.h" #include "CurrentColor.h" -#include "Gradient.h" +#include "GradientTransformable.h" #include "GradientControl.h" #include "SetColorCommand.h" #include "SetGradientCommand.h" @@ -438,7 +438,7 @@ StyleView::_SetStyleType(int32 type) void StyleView::_SetGradientType(int32 type) { - fGradientControl->Gradient()->SetType((gradient_type)type); + fGradientControl->Gradient()->SetType((gradients_type)type); } // _AdoptCurrentColor diff --git a/src/apps/icon-o-matic/import_export/flat_icon/FlatIconExporter.cpp b/src/apps/icon-o-matic/import_export/flat_icon/FlatIconExporter.cpp index 1481d3952b..63c7dc3bfc 100644 --- a/src/apps/icon-o-matic/import_export/flat_icon/FlatIconExporter.cpp +++ b/src/apps/icon-o-matic/import_export/flat_icon/FlatIconExporter.cpp @@ -19,7 +19,7 @@ #include "AffineTransformer.h" #include "ContourTransformer.h" #include "FlatIconFormat.h" -#include "Gradient.h" +#include "GradientTransformable.h" #include "Icon.h" #include "LittleEndianBuffer.h" #include "PathCommandQueue.h" diff --git a/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp b/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp index bec9eea3a6..28f4d2ea6b 100644 --- a/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp +++ b/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp @@ -31,7 +31,7 @@ #include #include "AutoDeleter.h" -#include "Gradient.h" +#include "GradientTransformable.h" #include "Icon.h" #include "PathContainer.h" #include "Shape.h" diff --git a/src/apps/icon-o-matic/import_export/svg/SVGExporter.cpp b/src/apps/icon-o-matic/import_export/svg/SVGExporter.cpp index fe8e521f8a..9eab4804ea 100644 --- a/src/apps/icon-o-matic/import_export/svg/SVGExporter.cpp +++ b/src/apps/icon-o-matic/import_export/svg/SVGExporter.cpp @@ -16,7 +16,7 @@ #include "support.h" #include "Icon.h" -#include "Gradient.h" +#include "GradientTransformable.h" #include "Shape.h" #include "StrokeTransformer.h" #include "Style.h" diff --git a/src/apps/icon-o-matic/import_export/svg/SVGGradients.cpp b/src/apps/icon-o-matic/import_export/svg/SVGGradients.cpp index 1885bc16da..43a9509480 100644 --- a/src/apps/icon-o-matic/import_export/svg/SVGGradients.cpp +++ b/src/apps/icon-o-matic/import_export/svg/SVGGradients.cpp @@ -10,7 +10,7 @@ #include #include -#include "Gradient.h" +#include "GradientTransformable.h" #include "SVGGradients.h" diff --git a/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.cpp b/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.cpp index 6afa8f1430..526c9f4580 100644 --- a/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.cpp +++ b/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.cpp @@ -12,7 +12,7 @@ #include #include -#include "Gradient.h" +#include "GradientTransformable.h" #include "Shape.h" #include "Style.h" #include "VectorPath.h" diff --git a/src/apps/icon-o-matic/style/SetColorCommand.cpp b/src/apps/icon-o-matic/style/SetColorCommand.cpp index 8b5b7d4e40..614e6728b5 100644 --- a/src/apps/icon-o-matic/style/SetColorCommand.cpp +++ b/src/apps/icon-o-matic/style/SetColorCommand.cpp @@ -11,7 +11,7 @@ #include #include -#include "Gradient.h" +#include "GradientTransformable.h" #include "Style.h" using std::nothrow; diff --git a/src/apps/icon-o-matic/style/SetGradientCommand.cpp b/src/apps/icon-o-matic/style/SetGradientCommand.cpp index 326e1ebce8..e3addaa3df 100644 --- a/src/apps/icon-o-matic/style/SetGradientCommand.cpp +++ b/src/apps/icon-o-matic/style/SetGradientCommand.cpp @@ -11,7 +11,7 @@ #include #include -#include "Gradient.h" +#include "GradientTransformable.h" #include "Style.h" using std::nothrow; diff --git a/src/apps/icon-o-matic/transformable/TransformGradientBox.cpp b/src/apps/icon-o-matic/transformable/TransformGradientBox.cpp index 3c208b2c92..c9ac0d3a8f 100644 --- a/src/apps/icon-o-matic/transformable/TransformGradientBox.cpp +++ b/src/apps/icon-o-matic/transformable/TransformGradientBox.cpp @@ -13,7 +13,7 @@ #include #include "CanvasView.h" -#include "Gradient.h" +#include "GradientTransformable.h" #include "Shape.h" #include "StateView.h" #include "TransformObjectsCommand.h" diff --git a/src/kits/app/LinkReceiver.cpp b/src/kits/app/LinkReceiver.cpp index a695a30de9..2ab6de8858 100644 --- a/src/kits/app/LinkReceiver.cpp +++ b/src/kits/app/LinkReceiver.cpp @@ -19,6 +19,11 @@ #include #include #include +#include +#include +#include +#include +#include #include "link_message.h" #include "syscalls.h" @@ -31,6 +36,15 @@ # define STRACE(x) ; #endif +//#define TRACE_LINK_RECEIVER_GRADIENTS +#ifdef TRACE_LINK_RECEIVER_GRADIENTS +# include +# define GTRACE(x) debug_printf x +#else +# define GTRACE(x) ; +#endif + + namespace BPrivate { LinkReceiver::LinkReceiver(port_id port) @@ -455,6 +469,87 @@ LinkReceiver::ReadRegion(BRegion* region) } +status_t +LinkReceiver::ReadGradient(BGradient *gradient) +{ + GTRACE(("LinkReceiver::ReadGradient\n")); + gradient_type gradientType; + int32 colorsCount; + Read(&gradientType, sizeof(gradient_type)); + Read(&colorsCount, sizeof(int32)); + + if (colorsCount > 0) { + color_step step; + for (int i = 0; i < colorsCount; i++) { + Read(&step, sizeof(color_step)); + gradient->AddColor(step, i); + } + } + + switch(gradientType) { + case B_GRADIENT_LINEAR: { + GTRACE(("LinkReceiver::ReadGradient> type == B_GRADIENT_LINEAR\n")); + BGradientLinear* linear = (BGradientLinear*) gradient; + BPoint start; + BPoint end; + Read(&start, sizeof(BPoint)); + Read(&end, sizeof(BPoint)); + linear->SetStart(start); + linear->SetEnd(end); + break; + } + case B_GRADIENT_RADIAL: { + GTRACE(("LinkReceiver::ReadGradient> type == B_GRADIENT_RADIAL\n")); + BGradientRadial* radial = (BGradientRadial*) gradient; + BPoint center; + float radius; + Read(¢er, sizeof(BPoint)); + Read(&radius, sizeof(float)); + radial->SetCenter(center); + radial->SetRadius(radius); + break; + } + case B_GRADIENT_RADIAL_FOCUS: { + GTRACE(("LinkReceiver::ReadGradient> type == B_GRADIENT_RADIAL_FOCUS\n")); + BGradientRadialFocus* radialFocus = + (BGradientRadialFocus*) gradient; + BPoint center; + BPoint focal; + float radius; + Read(¢er, sizeof(BPoint)); + Read(&focal, sizeof(BPoint)); + Read(&radius, sizeof(float)); + radialFocus->SetCenter(center); + radialFocus->SetFocal(focal); + radialFocus->SetRadius(radius); + break; + } + case B_GRADIENT_DIAMOND: { + GTRACE(("LinkReceiver::ReadGradient> type == B_GRADIENT_DIAMOND\n")); + BGradientDiamond* diamond = (BGradientDiamond*) gradient; + BPoint center; + Read(¢er, sizeof(BPoint)); + diamond->SetCenter(center); + break; + } + case B_GRADIENT_CONIC: { + GTRACE(("LinkReceiver::ReadGradient> type == B_GRADIENT_CONIC\n")); + BGradientConic* conic = (BGradientConic*) gradient; + BPoint center; + float angle; + Read(¢er, sizeof(BPoint)); + Read(&angle, sizeof(float)); + conic->SetCenter(center); + conic->SetAngle(angle); + break; + } + case B_GRADIENT_NONE: { + GTRACE(("LinkReceiver::ReadGradient> type == B_GRADIENT_NONE\n")); + break; + } + } + + return B_OK; +} + } // namespace BPrivate - - diff --git a/src/kits/app/ServerLink.cpp b/src/kits/app/ServerLink.cpp index 976edd0113..b0c635e672 100644 --- a/src/kits/app/ServerLink.cpp +++ b/src/kits/app/ServerLink.cpp @@ -12,12 +12,26 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include #include #include +//#define TRACE_SERVER_LINK_GRADIENTS +#ifdef TRACE_SERVER_LINK_GRADIENTS +# include +# define GTRACE(x) debug_printf x +#else +# define GTRACE(x) ; +#endif + namespace BPrivate { @@ -100,6 +114,163 @@ ServerLink::AttachShape(BShape &shape) } +status_t +ServerLink::ReadGradient(BGradient *gradient) +{ + GTRACE(("ServerLink::ReadGradient\n")); + fReceiver->ReadGradient(gradient); +/* gradient_type gradientType; + int32 colorsCount; + fReceiver->Read(&gradientType, sizeof(gradient_type)); + fReceiver->Read(&colorsCount, sizeof(int32)); + + if (colorsCount > 0) { + color_step step; + for (int i = 0; i < colorsCount; i++) { + fReceiver->Read(&step, sizeof(color_step)); + gradient->AddColor(step, i); + } + } + + switch(gradientType) { + case B_GRADIENT_LINEAR: { + GTRACE(("ServerLink::ReadGradient> type == B_GRADIENT_LINEAR\n")); + BGradientLinear* linear = (BGradientLinear*) gradient; + BPoint start; + BPoint end; + fReceiver->Read(&start, sizeof(BPoint)); + fReceiver->Read(&end, sizeof(BPoint)); + linear->SetStart(start); + linear->SetEnd(end); + break; + } + case B_GRADIENT_RADIAL: { + GTRACE(("ServerLink::ReadGradient> type == B_GRADIENT_RADIAL\n")); + BGradientRadial* radial = (BGradientRadial*) gradient; + BPoint center; + float radius; + fReceiver->Read(¢er, sizeof(BPoint)); + fReceiver->Read(&radius, sizeof(float)); + radial->SetCenter(center); + radial->SetRadius(radius); + break; + } + case B_GRADIENT_RADIAL_FOCUS: { + GTRACE(("ServerLink::ReadGradient> type == B_GRADIENT_RADIAL_FOCUS\n")); + BGradientRadialFocus* radialFocus = + (BGradientRadialFocus*) gradient; + BPoint center; + BPoint focal; + float radius; + fReceiver->Read(¢er, sizeof(BPoint)); + fReceiver->Read(&focal, sizeof(BPoint)); + fReceiver->Read(&radius, sizeof(float)); + radialFocus->SetCenter(center); + radialFocus->SetFocal(focal); + radialFocus->SetRadius(radius); + break; + } + case B_GRADIENT_DIAMOND: { + GTRACE(("ServerLink::ReadGradient> type == B_GRADIENT_DIAMOND\n")); + BGradientDiamond* diamond = (BGradientDiamond*) gradient; + BPoint center; + fReceiver->Read(¢er, sizeof(BPoint)); + diamond->SetCenter(center); + break; + } + case B_GRADIENT_CONIC: { + GTRACE(("ServerLink::ReadGradient> type == B_GRADIENT_CONIC\n")); + BGradientConic* conic = (BGradientConic*) gradient; + BPoint center; + float angle; + fReceiver->Read(¢er, sizeof(BPoint)); + fReceiver->Read(&angle, sizeof(float)); + conic->SetCenter(center); + conic->SetAngle(angle); + break; + } + case B_GRADIENT_NONE: { + GTRACE(("ServerLink::ReadGradient> type == B_GRADIENT_NONE\n")); + break; + } + } +*/ + return B_OK; +} + + +status_t +ServerLink::AttachGradient(const BGradient &gradient) +{ + GTRACE(("ServerLink::AttachGradient\n")); + gradient_type gradientType = gradient.Type(); + int32 colorsCount = gradient.CountColors(); + GTRACE(("ServerLink::AttachGradient> colors count == %d\n", (int)colorsCount)); + fSender->Attach(&gradientType, sizeof(gradient_type)); + fSender->Attach(&colorsCount, sizeof(int32)); + if (colorsCount > 0) { + for (int i = 0; i < colorsCount; i++) { + fSender->Attach((color_step*) gradient.ColorAtFast(i), + sizeof(color_step)); + } + } + + switch(gradientType) { + case B_GRADIENT_LINEAR: { + GTRACE(("ServerLink::AttachGradient> type == B_GRADIENT_LINEAR\n")); + const BGradientLinear* linear = (BGradientLinear*) &gradient; + BPoint start = linear->Start(); + BPoint end = linear->End(); + fSender->Attach(&start, sizeof(BPoint)); + fSender->Attach(&end, sizeof(BPoint)); + break; + } + case B_GRADIENT_RADIAL: { + GTRACE(("ServerLink::AttachGradient> type == B_GRADIENT_RADIAL\n")); + const BGradientRadial* radial = (BGradientRadial*) &gradient; + BPoint center = radial->Center(); + float radius = radial->Radius(); + fSender->Attach(¢er, sizeof(BPoint)); + fSender->Attach(&radius, sizeof(float)); + break; + } + case B_GRADIENT_RADIAL_FOCUS: { + GTRACE(("ServerLink::AttachGradient> type == B_GRADIENT_RADIAL_FOCUS\n")); + const BGradientRadialFocus* radialFocus = + (BGradientRadialFocus*) &gradient; + BPoint center = radialFocus->Center(); + BPoint focal = radialFocus->Focal(); + float radius = radialFocus->Radius(); + fSender->Attach(¢er, sizeof(BPoint)); + fSender->Attach(&focal, sizeof(BPoint)); + fSender->Attach(&radius, sizeof(float)); + break; + } + case B_GRADIENT_DIAMOND: { + GTRACE(("ServerLink::AttachGradient> type == B_GRADIENT_DIAMOND\n")); + const BGradientDiamond* diamond = (BGradientDiamond*) &gradient; + BPoint center = diamond->Center(); + fSender->Attach(¢er, sizeof(BPoint)); + break; + } + case B_GRADIENT_CONIC: { + GTRACE(("ServerLink::AttachGradient> type == B_GRADIENT_CONIC\n")); + const BGradientConic* conic = (BGradientConic*) &gradient; + BPoint center = conic->Center(); + float angle = conic->Angle(); + fSender->Attach(¢er, sizeof(BPoint)); + fSender->Attach(&angle, sizeof(float)); + break; + } + case B_GRADIENT_NONE: { + GTRACE(("ServerLink::AttachGradient> type == B_GRADIENT_NONE\n")); + break; + } + } + return B_OK; +} + + status_t ServerLink::FlushWithReply(int32 &code) { diff --git a/src/kits/interface/Gradient.cpp b/src/kits/interface/Gradient.cpp new file mode 100644 index 0000000000..6709e1252c --- /dev/null +++ b/src/kits/interface/Gradient.cpp @@ -0,0 +1,448 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + * Artur Wyszynski + */ + +#include "Gradient.h" + +#include +#include + +#include + + +// constructor +color_step::color_step(const rgb_color c, float o) +{ + color.red = c.red; + color.green = c.green; + color.blue = c.blue; + color.alpha = c.alpha; + offset = o; +} + + +// constructor +color_step::color_step(uint8 r, uint8 g, uint8 b, uint8 a, float o) +{ + color.red = r; + color.green = g; + color.blue = b; + color.alpha = a; + offset = o; +} + + +// constructor +color_step::color_step(const color_step& other) +{ + color.red = other.color.red; + color.green = other.color.green; + color.blue = other.color.blue; + color.alpha = other.color.alpha; + offset = other.offset; +} + + +// constructor +color_step::color_step() +{ + color.red = 0; + color.green = 0; + color.blue = 0; + color.alpha = 255; + offset = 0; +} + + +// operator!= +bool +color_step::operator!=(const color_step& other) const +{ + return color.red != other.color.red || + color.green != other.color.green || + color.blue != other.color.blue || + color.alpha != other.color.alpha || + offset != other.offset; +} + + +static int +sort_color_steps_by_offset(const void* left, const void* right) +{ + const color_step **firstStep((const color_step**) left), + **secondStep((const color_step**) right); + int ret = 0; + if ((*firstStep)->offset > (*secondStep)->offset) { + ret = 1; + } if ((*firstStep)->offset < (*secondStep)->offset) { + ret = -1; + } if ((*firstStep)->offset == (*secondStep)->offset) { + ret = 0; + } + return ret; +} + + +// #pragma mark - + + +// constructor +BGradient::BGradient() + : BArchivable(), + fColors(4), + fType(B_GRADIENT_NONE) +{ +} + + +// constructor +BGradient::BGradient(BMessage* archive) + : BArchivable(archive), + fColors(4), + fType(B_GRADIENT_NONE) +{ + if (!archive) + return; + + // color steps + color_step step; + for (int32 i = 0; archive->FindFloat("offset", i, &step.offset) >= B_OK; i++) { + if (archive->FindInt32("color", i, (int32*)&step.color) >= B_OK) + AddColor(step, i); + else + break; + } + if (archive->FindInt32("type", (int32*)&fType) < B_OK) + fType = B_GRADIENT_LINEAR; + + // linear + if (archive->FindFloat("linear_x1", (float*)&fData.linear.x1) < B_OK) + fData.linear.x1 = 0.0f; + if (archive->FindFloat("linear_y1", (float*)&fData.linear.y1) < B_OK) + fData.linear.y1 = 0.0f; + if (archive->FindFloat("linear_x2", (float*)&fData.linear.x2) < B_OK) + fData.linear.x2 = 0.0f; + if (archive->FindFloat("linear_y2", (float*)&fData.linear.y2) < B_OK) + fData.linear.x2 = 0.0f; + + // radial + if (archive->FindFloat("radial_cx", (float*)&fData.radial.cx) < B_OK) + fData.radial.cx = 0.0f; + if (archive->FindFloat("radial_cy", (float*)&fData.radial.cy) < B_OK) + fData.radial.cy = 0.0f; + if (archive->FindFloat("radial_radius", (float*)&fData.radial.radius) < B_OK) + fData.radial.radius = 0.0f; + + // radial focus + if (archive->FindFloat("radial_f_cx", (float*)&fData.radial_focus.cx) < B_OK) + fData.radial_focus.cx = 0.0f; + if (archive->FindFloat("radial_f_cy", (float*)&fData.radial_focus.cy) < B_OK) + fData.radial_focus.cy = 0.0f; + if (archive->FindFloat("radial_f_fx", (float*)&fData.radial_focus.fx) < B_OK) + fData.radial_focus.fx = 0.0f; + if (archive->FindFloat("radial_f_fy", (float*)&fData.radial_focus.fy) < B_OK) + fData.radial_focus.fy = 0.0f; + if (archive->FindFloat("radial_f_radius", (float*)&fData.radial.radius) < B_OK) + fData.radial.radius = 0.0f; + + // diamond + if (archive->FindFloat("diamond_cx", (float*)&fData.diamond.cx) < B_OK) + fData.diamond.cx = 0.0f; + if (archive->FindFloat("diamond_cy", (float*)&fData.diamond.cy) < B_OK) + fData.diamond.cy = 0.0f; + + // conic + if (archive->FindFloat("conic_cx", (float*)&fData.conic.cx) < B_OK) + fData.conic.cx = 0.0f; + if (archive->FindFloat("conic_cy", (float*)&fData.conic.cy) < B_OK) + fData.conic.cy = 0.0f; + if (archive->FindFloat("conic_angle", (float*)&fData.conic.angle) < B_OK) + fData.conic.angle = 0.0f; +} + + +// destructor +BGradient::~BGradient() +{ + MakeEmpty(); +} + + +// Archive +status_t +BGradient::Archive(BMessage* into, bool deep) const +{ + status_t ret = BArchivable::Archive(into, deep); + + // color steps + if (ret >= B_OK) { + for (int32 i = 0; color_step* step = ColorAt(i); i++) { + ret = into->AddInt32("color", (const uint32&)step->color); + if (ret < B_OK) + break; + ret = into->AddFloat("offset", step->offset); + if (ret < B_OK) + break; + } + } + // gradient type + if (ret >= B_OK) + ret = into->AddInt32("type", (int32)fType); + + // linear + if (ret >= B_OK) + ret = into->AddFloat("linear_x1", (float)fData.linear.x1); + if (ret >= B_OK) + ret = into->AddFloat("linear_y1", (float)fData.linear.y1); + if (ret >= B_OK) + ret = into->AddFloat("linear_x2", (float)fData.linear.x2); + if (ret >= B_OK) + ret = into->AddFloat("linear_y2", (float)fData.linear.y2); + + // radial + if (ret >= B_OK) + ret = into->AddFloat("radial_cx", (float)fData.radial.cx); + if (ret >= B_OK) + ret = into->AddFloat("radial_cy", (float)fData.radial.cy); + if (ret >= B_OK) + ret = into->AddFloat("radial_radius", (float)fData.radial.radius); + + // radial focus + if (ret >= B_OK) + ret = into->AddFloat("radial_f_cx", (float)fData.radial_focus.cx); + if (ret >= B_OK) + ret = into->AddFloat("radial_f_cy", (float)fData.radial_focus.cy); + if (ret >= B_OK) + ret = into->AddFloat("radial_f_fx", (float)fData.radial_focus.fx); + if (ret >= B_OK) + ret = into->AddFloat("radial_f_fy", (float)fData.radial_focus.fy); + if (ret >= B_OK) + ret = into->AddFloat("radial_radius", (float)fData.radial.radius); + + // diamond + if (ret >= B_OK) + ret = into->AddFloat("diamond_cx", (float)fData.diamond.cx); + if (ret >= B_OK) + ret = into->AddFloat("diamond_cy", (float)fData.diamond.cy); + + // conic + if (ret >= B_OK) + ret = into->AddFloat("conic_cx", (float)fData.conic.cx); + if (ret >= B_OK) + ret = into->AddFloat("conic_cy", (float)fData.conic.cy); + if (ret >= B_OK) + ret = into->AddFloat("conic_angle", (float)fData.conic.angle); + + // finish off + if (ret >= B_OK) + ret = into->AddString("class", "BGradient"); + + return ret; +} + + +// operator= +BGradient& +BGradient::operator=(const BGradient& other) +{ + SetColors(other); + fType = other.fType; + return *this; +} + + +// operator== +bool +BGradient::operator==(const BGradient& other) const +{ + return ((other.Type() == Type()) && ColorStepsAreEqual(other)); +} + + +// operator!= +bool +BGradient::operator!=(const BGradient& other) const +{ + return !(*this == other); +} + + +// ColorStepsAreEqual +bool +BGradient::ColorStepsAreEqual(const BGradient& other) const +{ + int32 count = CountColors(); + if (count == other.CountColors() && + fType == other.fType) { + + bool equal = true; + for (int32 i = 0; i < count; i++) { + color_step* ourStep = ColorAtFast(i); + color_step* otherStep = other.ColorAtFast(i); + if (*ourStep != *otherStep) { + equal = false; + break; + } + } + return equal; + } + return false; +} + + +// SetColors +void +BGradient::SetColors(const BGradient& other) +{ + MakeEmpty(); + for (int32 i = 0; color_step* step = other.ColorAt(i); i++) + AddColor(*step, i); +} + + +// AddColor +int32 +BGradient::AddColor(const rgb_color& color, float offset) +{ + // find the correct index (sorted by offset) + color_step* step = new color_step(color, offset); + int32 index = 0; + int32 count = CountColors(); + for (; index < count; index++) { + color_step* s = ColorAtFast(index); + if (s->offset > step->offset) + break; + } + if (!fColors.AddItem((void*)step, index)) { + delete step; + return -1; + } + return index; +} + + +// AddColor +bool +BGradient::AddColor(const color_step& color, int32 index) +{ + color_step* step = new color_step(color); + if (!fColors.AddItem((void*)step, index)) { + delete step; + return false; + } + return true; +} + + +// RemoveColor +bool +BGradient::RemoveColor(int32 index) +{ + color_step* step = (color_step*)fColors.RemoveItem(index); + if (!step) { + return false; + } + delete step; + return true; +} + + +// SetColor +bool +BGradient::SetColor(int32 index, const color_step& color) +{ + if (color_step* step = ColorAt(index)) { + if (*step != color) { + step->color = color.color; + step->offset = color.offset; + return true; + } + } + return false; +} + + +// SetColor +bool +BGradient::SetColor(int32 index, const rgb_color& color) +{ + if (color_step* step = ColorAt(index)) { + if ((uint32&)step->color != (uint32&)color) { + step->color = color; + return true; + } + } + return false; +} + + +// SetOffset +bool +BGradient::SetOffset(int32 index, float offset) +{ + color_step* step = ColorAt(index); + if (step && step->offset != offset) { + step->offset = offset; + return true; + } + return false; +} + + +// CountColors +int32 +BGradient::CountColors() const +{ + return fColors.CountItems(); +} + + +// ColorAt +color_step* +BGradient::ColorAt(int32 index) const +{ + return (color_step*)fColors.ItemAt(index); +} + + +// ColorAtFast +color_step* +BGradient::ColorAtFast(int32 index) const +{ + return (color_step*)fColors.ItemAtFast(index); +} + + +// Colors +color_step* +BGradient::Colors() const +{ + if (CountColors() > 0) { + return (color_step*) fColors.Items(); + } + return NULL; +} + + +// SortColorStepsByOffset +void +BGradient::SortColorStepsByOffset() +{ + fColors.SortItems(sort_color_steps_by_offset); +} + + +// MakeEmpty +void +BGradient::MakeEmpty() +{ + int32 count = CountColors(); + for (int32 i = 0; i < count; i++) + delete ColorAtFast(i); + fColors.MakeEmpty(); +} diff --git a/src/kits/interface/GradientConic.cpp b/src/kits/interface/GradientConic.cpp new file mode 100644 index 0000000000..e978aa1aee --- /dev/null +++ b/src/kits/interface/GradientConic.cpp @@ -0,0 +1,83 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Artur Wyszynski + */ + +#include +#include +#include + + +// constructor +BGradientConic::BGradientConic() +{ + fData.conic.cx = 0.0f; + fData.conic.cy = 0.0f; + fData.conic.angle = 0.0f; + fType = B_GRADIENT_CONIC; +} + + +// constructor +BGradientConic::BGradientConic(const BPoint& center, float angle) +{ + fData.conic.cx = center.x; + fData.conic.cy = center.y; + fData.conic.angle = angle; + fType = B_GRADIENT_CONIC; +} + + +// constructor +BGradientConic::BGradientConic(float cx, float cy, float angle) +{ + fData.conic.cx = cx; + fData.conic.cy = cy; + fData.conic.angle = angle; + fType = B_GRADIENT_CONIC; +} + + +// Center +BPoint +BGradientConic::Center() const +{ + return BPoint(fData.conic.cx, fData.conic.cy); +} + + +// SetCenter +void +BGradientConic::SetCenter(const BPoint& center) +{ + fData.conic.cx = center.x; + fData.conic.cy = center.y; +} + + +// SetCenter +void +BGradientConic::SetCenter(float cx, float cy) +{ + fData.conic.cx = cx; + fData.conic.cy = cy; +} + + +// Angle +float +BGradientConic::Angle() const +{ + return fData.conic.angle; +} + + +// SetAngle +void +BGradientConic::SetAngle(float angle) +{ + fData.conic.angle = angle; +} diff --git a/src/kits/interface/GradientDiamond.cpp b/src/kits/interface/GradientDiamond.cpp new file mode 100644 index 0000000000..8db4809378 --- /dev/null +++ b/src/kits/interface/GradientDiamond.cpp @@ -0,0 +1,64 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Artur Wyszynski + */ + +#include +#include +#include + + +// constructor +BGradientDiamond::BGradientDiamond() +{ + fData.diamond.cx = 0.0f; + fData.diamond.cy = 0.0f; + fType = B_GRADIENT_DIAMOND; +} + + +// constructor +BGradientDiamond::BGradientDiamond(const BPoint& center) +{ + fData.diamond.cx = center.x; + fData.diamond.cy = center.y; + fType = B_GRADIENT_DIAMOND; +} + + +// constructor +BGradientDiamond::BGradientDiamond(float cx, float cy) +{ + fData.diamond.cx = cx; + fData.diamond.cy = cy; + fType = B_GRADIENT_DIAMOND; +} + + +// Center +BPoint +BGradientDiamond::Center() const +{ + return BPoint(fData.diamond.cx, fData.diamond.cy); +} + + +// SetCenter +void +BGradientDiamond::SetCenter(const BPoint& center) +{ + fData.diamond.cx = center.x; + fData.diamond.cy = center.y; +} + + +// SetCenter +void +BGradientDiamond::SetCenter(float cx, float cy) +{ + fData.diamond.cx = cx; + fData.diamond.cy = cy; +} diff --git a/src/kits/interface/GradientLinear.cpp b/src/kits/interface/GradientLinear.cpp new file mode 100644 index 0000000000..e4f41ef80d --- /dev/null +++ b/src/kits/interface/GradientLinear.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Artur Wyszynski + */ + +#include +#include +#include + + +// constructor +BGradientLinear::BGradientLinear() +{ + fData.linear.x1 = 0.0f; + fData.linear.y1 = 0.0f; + fData.linear.x2 = 0.0f; + fData.linear.y2 = 0.0f; + fType = B_GRADIENT_LINEAR; +} + + +// constructor +BGradientLinear::BGradientLinear(const BPoint& start, const BPoint& end) +{ + fData.linear.x1 = start.x; + fData.linear.y1 = start.y; + fData.linear.x2 = end.x; + fData.linear.y2 = end.y; + fType = B_GRADIENT_LINEAR; +} + + +// constructor +BGradientLinear::BGradientLinear(float x1, float y1, float x2, float y2) +{ + fData.linear.x1 = x1; + fData.linear.y1 = y1; + fData.linear.x2 = x2; + fData.linear.y2 = y2; + fType = B_GRADIENT_LINEAR; +} + + +// Start +BPoint +BGradientLinear::Start() const +{ + return BPoint(fData.linear.x1, fData.linear.y1); +} + + +// SetStart +void +BGradientLinear::SetStart(const BPoint& start) +{ + fData.linear.x1 = start.x; + fData.linear.y1 = start.y; +} + + +// SetStart +void +BGradientLinear::SetStart(float x, float y) +{ + fData.linear.x1 = x; + fData.linear.y1 = y; +} + + +// End +BPoint +BGradientLinear::End() const +{ + return BPoint(fData.linear.x2, fData.linear.y2); +} + + +// SetEnd +void +BGradientLinear::SetEnd(const BPoint& end) +{ + fData.linear.x2 = end.x; + fData.linear.y2 = end.y; +} + + +// SetEnd +void +BGradientLinear::SetEnd(float x, float y) +{ + fData.linear.x2 = x; + fData.linear.y2 = y; +} diff --git a/src/kits/interface/GradientRadial.cpp b/src/kits/interface/GradientRadial.cpp new file mode 100644 index 0000000000..ebcfc4aceb --- /dev/null +++ b/src/kits/interface/GradientRadial.cpp @@ -0,0 +1,83 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Artur Wyszynski + */ + +#include +#include +#include + + +// constructor +BGradientRadial::BGradientRadial() +{ + fData.radial.cx = 0.0f; + fData.radial.cy = 0.0f; + fData.radial.radius = 0.0f; + fType = B_GRADIENT_RADIAL; +} + + +// constructor +BGradientRadial::BGradientRadial(const BPoint& center, float radius) +{ + fData.radial.cx = center.x; + fData.radial.cy = center.y; + fData.radial.radius = radius; + fType = B_GRADIENT_RADIAL; +} + + +// constructor +BGradientRadial::BGradientRadial(float cx, float cy, float radius) +{ + fData.radial.cx = cx; + fData.radial.cy = cy; + fData.radial.radius = radius; + fType = B_GRADIENT_RADIAL; +} + + +// Center +BPoint +BGradientRadial::Center() const +{ + return BPoint(fData.radial.cx, fData.radial.cy); +} + + +// SetCenter +void +BGradientRadial::SetCenter(const BPoint& center) +{ + fData.radial.cx = center.x; + fData.radial.cy = center.y; +} + + +// SetCenter +void +BGradientRadial::SetCenter(float cx, float cy) +{ + fData.radial.cx = cx; + fData.radial.cy = cy; +} + + +// Radius +float +BGradientRadial::Radius() const +{ + return fData.radial.radius; +} + + +// SetRadius +void +BGradientRadial::SetRadius(float radius) +{ + fData.radial.radius = radius; +} diff --git a/src/kits/interface/GradientRadialFocus.cpp b/src/kits/interface/GradientRadialFocus.cpp new file mode 100644 index 0000000000..a12ab118aa --- /dev/null +++ b/src/kits/interface/GradientRadialFocus.cpp @@ -0,0 +1,117 @@ +/* + * Copyright 2006-2008, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Artur Wyszynski + */ + +#include +#include +#include + + +// constructor +BGradientRadialFocus::BGradientRadialFocus() +{ + fData.radial_focus.cx = 0.0f; + fData.radial_focus.cy = 0.0f; + fData.radial_focus.fx = 0.0f; + fData.radial_focus.fy = 0.0f; + fData.radial_focus.radius = 0.0f; + fType = B_GRADIENT_RADIAL_FOCUS; +} + + +// constructor +BGradientRadialFocus::BGradientRadialFocus(const BPoint& center, float radius, + const BPoint& focal) +{ + fData.radial_focus.cx = center.x; + fData.radial_focus.cy = center.y; + fData.radial_focus.fx = focal.x; + fData.radial_focus.fy = focal.y; + fData.radial_focus.radius = radius; + fType = B_GRADIENT_RADIAL_FOCUS; +} + + +// constructor +BGradientRadialFocus::BGradientRadialFocus(float cx, float cy, float radius, + float fx, float fy) +{ + fData.radial_focus.cx = cx; + fData.radial_focus.cy = cy; + fData.radial_focus.fx = fx; + fData.radial_focus.fy = fy; + fData.radial_focus.radius = radius; + fType = B_GRADIENT_RADIAL_FOCUS; +} + + +// Center +BPoint +BGradientRadialFocus::Center() const +{ + return BPoint(fData.radial_focus.cx, fData.radial_focus.cy); +} + + +// SetCenter +void +BGradientRadialFocus::SetCenter(const BPoint& center) +{ + fData.radial_focus.cx = center.x; + fData.radial_focus.cy = center.y; +} + + +// SetCenter +void +BGradientRadialFocus::SetCenter(float cx, float cy) +{ + fData.radial_focus.cx = cx; + fData.radial_focus.cy = cy; +} + + +// Focal +BPoint +BGradientRadialFocus::Focal() const +{ + return BPoint(fData.radial_focus.fx, fData.radial_focus.fy); +} + + +// SetFocal +void +BGradientRadialFocus::SetFocal(const BPoint& focal) +{ + fData.radial_focus.fx = focal.x; + fData.radial_focus.fy = focal.y; +} + + +// SetFocal +void +BGradientRadialFocus::SetFocal(float fx, float fy) +{ + fData.radial_focus.fx = fx; + fData.radial_focus.fy = fy; +} + + +// Radius +float +BGradientRadialFocus::Radius() const +{ + return fData.radial_focus.radius; +} + + +// SetRadius +void +BGradientRadialFocus::SetRadius(float radius) +{ + fData.radial_focus.radius = radius; +} diff --git a/src/kits/interface/Jamfile b/src/kits/interface/Jamfile index dbb2bf077a..69496da05c 100644 --- a/src/kits/interface/Jamfile +++ b/src/kits/interface/Jamfile @@ -57,6 +57,12 @@ MergeObject interface_kit.o : Deskbar.cpp Dragger.cpp Font.cpp + Gradient.cpp + GradientLinear.cpp + GradientRadial.cpp + GradientRadialFocus.cpp + GradientDiamond.cpp + GradientConic.cpp GraphicsDefs.cpp GridLayout.cpp GridLayoutBuilder.cpp diff --git a/src/kits/interface/View.cpp b/src/kits/interface/View.cpp index cfda88b38f..13e585df0f 100644 --- a/src/kits/interface/View.cpp +++ b/src/kits/interface/View.cpp @@ -44,6 +44,12 @@ #include #include +#include +#include +#include +#include +#include + #include #include #include @@ -2573,6 +2579,15 @@ BView::FillEllipse(BPoint center, float xRadius, float yRadius, } +void +BView::FillEllipse(BPoint center, float xRadius, float yRadius, + const BGradient& gradient) +{ + FillEllipse(BRect(center.x - xRadius, center.y - yRadius, + center.x + xRadius, center.y + yRadius), gradient); +} + + void BView::FillEllipse(BRect rect, ::pattern pattern) { @@ -2589,6 +2604,23 @@ BView::FillEllipse(BRect rect, ::pattern pattern) } +void +BView::FillEllipse(BRect rect, const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_FILL_ELLIPSE_GRADIENT); + fOwner->fLink->Attach(rect); + fOwner->fLink->Attach(gradient.Type()); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::StrokeArc(BPoint center, float xRadius, float yRadius, float startAngle, float arcAngle, ::pattern pattern) @@ -2626,6 +2658,15 @@ BView::FillArc(BPoint center,float xRadius, float yRadius, float startAngle, } +void +BView::FillArc(BPoint center,float xRadius, float yRadius, float startAngle, + float arcAngle, const BGradient& gradient) +{ + FillArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius, + center.y + yRadius), startAngle, arcAngle, gradient); +} + + void BView::FillArc(BRect rect, float startAngle, float arcAngle, ::pattern pattern) @@ -2645,6 +2686,26 @@ BView::FillArc(BRect rect, float startAngle, float arcAngle, } +void +BView::FillArc(BRect rect, float startAngle, float arcAngle, + const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_FILL_ARC_GRADIENT); + fOwner->fLink->Attach(rect); + fOwner->fLink->Attach(startAngle); + fOwner->fLink->Attach(arcAngle); + fOwner->fLink->Attach(gradient.Type()); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::StrokeBezier(BPoint *controlPoints, ::pattern pattern) { @@ -2683,6 +2744,26 @@ BView::FillBezier(BPoint *controlPoints, ::pattern pattern) } +void +BView::FillBezier(BPoint *controlPoints, const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_FILL_BEZIER_GRADIENT); + fOwner->fLink->Attach(controlPoints[0]); + fOwner->fLink->Attach(controlPoints[1]); + fOwner->fLink->Attach(controlPoints[2]); + fOwner->fLink->Attach(controlPoints[3]); + fOwner->fLink->Attach(gradient.Type()); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::StrokePolygon(const BPolygon *polygon, bool closed, ::pattern pattern) { @@ -2761,6 +2842,33 @@ BView::FillPolygon(const BPolygon *polygon, ::pattern pattern) } +void +BView::FillPolygon(const BPolygon *polygon, const BGradient& gradient) +{ + if (polygon == NULL + || polygon->fCount <= 2 + || fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + if (fOwner->fLink->StartMessage(AS_FILL_POLYGON_GRADIENT, + polygon->fCount * sizeof(BPoint) + + sizeof(BRect) + sizeof(int32)) == B_OK) { + fOwner->fLink->Attach(polygon->Frame()); + fOwner->fLink->Attach(polygon->fCount); + fOwner->fLink->Attach(polygon->fPoints, + polygon->fCount * sizeof(BPoint)); + fOwner->fLink->Attach(gradient.Type()); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); + } else { + fprintf(stderr, "ERROR: Can't send polygon to app_server!\n"); + } +} + + void BView::FillPolygon(const BPoint *ptArray, int32 numPts, ::pattern pattern) { @@ -2772,6 +2880,18 @@ BView::FillPolygon(const BPoint *ptArray, int32 numPts, ::pattern pattern) } +void +BView::FillPolygon(const BPoint *ptArray, int32 numPts, + const BGradient& gradient) +{ + if (!ptArray) + return; + + BPolygon polygon(ptArray, numPts); + FillPolygon(&polygon, gradient); +} + + void BView::FillPolygon(const BPoint *ptArray, int32 numPts, BRect bounds, pattern p) @@ -2786,6 +2906,20 @@ BView::FillPolygon(const BPoint *ptArray, int32 numPts, BRect bounds, } +void +BView::FillPolygon(const BPoint *ptArray, int32 numPts, BRect bounds, + const BGradient& gradient) +{ + if (!ptArray) + return; + + BPolygon polygon(ptArray, numPts); + + polygon.MapTo(polygon.Frame(), bounds); + FillPolygon(&polygon, gradient); +} + + void BView::StrokeRect(BRect rect, ::pattern pattern) { @@ -2823,6 +2957,28 @@ BView::FillRect(BRect rect, ::pattern pattern) } +void +BView::FillRect(BRect rect, const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + // NOTE: ensuring compatibility with R5, + // invalid rects are not filled, they are stroked though! + if (!rect.IsValid()) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_FILL_RECT_GRADIENT); + fOwner->fLink->Attach(rect); + fOwner->fLink->Attach(gradient.Type()); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::StrokeRoundRect(BRect rect, float xRadius, float yRadius, ::pattern pattern) @@ -2862,6 +3018,26 @@ BView::FillRoundRect(BRect rect, float xRadius, float yRadius, } +void +BView::FillRoundRect(BRect rect, float xRadius, float yRadius, + const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_FILL_ROUNDRECT_GRADIENT); + fOwner->fLink->Attach(rect); + fOwner->fLink->Attach(xRadius); + fOwner->fLink->Attach(yRadius); + fOwner->fLink->Attach(gradient.Type()); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::FillRegion(BRegion *region, ::pattern pattern) { @@ -2879,6 +3055,23 @@ BView::FillRegion(BRegion *region, ::pattern pattern) } +void +BView::FillRegion(BRegion *region, const BGradient& gradient) +{ + if (region == NULL || fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_FILL_REGION_GRADIENT); + fOwner->fLink->AttachRegion(*region); + fOwner->fLink->Attach(gradient.Type()); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, BRect bounds, ::pattern pattern) @@ -2978,6 +3171,46 @@ BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, pattern p) } +void +BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, + const BGradient& gradient) +{ + if (fOwner) { + // we construct the smallest rectangle that contains the 3 points + // for the 1st point + BRect bounds(pt1, pt1); + + // for the 2nd point + if (pt2.x < bounds.left) + bounds.left = pt2.x; + + if (pt2.y < bounds.top) + bounds.top = pt2.y; + + if (pt2.x > bounds.right) + bounds.right = pt2.x; + + if (pt2.y > bounds.bottom) + bounds.bottom = pt2.y; + + // for the 3rd point + if (pt3.x < bounds.left) + bounds.left = pt3.x; + + if (pt3.y < bounds.top) + bounds.top = pt3.y; + + if (pt3.x > bounds.right) + bounds.right = pt3.x; + + if (pt3.y > bounds.bottom) + bounds.bottom = pt3.y; + + FillTriangle(pt1, pt2, pt3, bounds, gradient); + } +} + + void BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, BRect bounds, ::pattern pattern) @@ -2998,6 +3231,26 @@ BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, } +void +BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, + BRect bounds, const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + fOwner->fLink->StartMessage(AS_FILL_TRIANGLE_GRADIENT); + fOwner->fLink->Attach(pt1); + fOwner->fLink->Attach(pt2); + fOwner->fLink->Attach(pt3); + fOwner->fLink->Attach(bounds); + fOwner->fLink->Attach(gradient.Type()); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::StrokeLine(BPoint toPt, pattern p) { @@ -3073,6 +3326,31 @@ BView::FillShape(BShape *shape, ::pattern pattern) } +void +BView::FillShape(BShape *shape, const BGradient& gradient) +{ + if (shape == NULL || fOwner == NULL) + return; + + shape_data *sd = (shape_data *)(shape->fPrivateData); + if (sd->opCount == 0 || sd->ptCount == 0) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_FILL_SHAPE_GRADIENT); + fOwner->fLink->Attach(shape->Bounds()); + fOwner->fLink->Attach(sd->opCount); + fOwner->fLink->Attach(sd->ptCount); + fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(int32)); + fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint)); + fOwner->fLink->Attach(gradient.Type()); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::BeginLineArray(int32 count) { @@ -5170,5 +5448,3 @@ BView::_PrintTree() } } } - - diff --git a/src/libs/icon/IconRenderer.cpp b/src/libs/icon/IconRenderer.cpp index b63d3b2dda..4e097e979e 100644 --- a/src/libs/icon/IconRenderer.cpp +++ b/src/libs/icon/IconRenderer.cpp @@ -17,7 +17,7 @@ #include #include -#include "Gradient.h" +#include "GradientTransformable.h" #include "Icon.h" #include "Shape.h" #include "ShapeContainer.h" diff --git a/src/libs/icon/Jamfile b/src/libs/icon/Jamfile index eb5c5a24b9..15c775568d 100644 --- a/src/libs/icon/Jamfile +++ b/src/libs/icon/Jamfile @@ -36,7 +36,7 @@ StaticLibrary libicon.a : VectorPath.cpp # style - Gradient.cpp + GradientTransformable.cpp Style.cpp StyleContainer.cpp diff --git a/src/libs/icon/flat_icon/FlatIconImporter.cpp b/src/libs/icon/flat_icon/FlatIconImporter.cpp index 42639062cf..08aced4f48 100644 --- a/src/libs/icon/flat_icon/FlatIconImporter.cpp +++ b/src/libs/icon/flat_icon/FlatIconImporter.cpp @@ -19,7 +19,7 @@ #include "AutoDeleter.h" #include "ContourTransformer.h" #include "FlatIconFormat.h" -#include "Gradient.h" +#include "GradientTransformable.h" #include "Icon.h" #include "LittleEndianBuffer.h" #include "PathCommandQueue.h" @@ -221,7 +221,7 @@ _ReadGradientStyle(LittleEndianBuffer& buffer) Gradient gradient(true); // empty gradient - gradient.SetType((gradient_type)gradientType); + gradient.SetType((gradients_type)gradientType); // TODO: support more stuff with flags // ("inherits transformation" and so on) if (gradientFlags & GRADIENT_FLAG_TRANSFORM) { diff --git a/src/libs/icon/style/Gradient.cpp b/src/libs/icon/style/GradientTransformable.cpp similarity index 92% rename from src/libs/icon/style/Gradient.cpp rename to src/libs/icon/style/GradientTransformable.cpp index 8983165789..f9b2c43399 100644 --- a/src/libs/icon/style/Gradient.cpp +++ b/src/libs/icon/style/GradientTransformable.cpp @@ -6,7 +6,7 @@ * Stephan Aßmus */ -#include "Gradient.h" +#include "GradientTransformable.h" #include #include @@ -17,59 +17,6 @@ # include "support.h" #endif -// constructor -color_step::color_step(const rgb_color c, float o) -{ - color.red = c.red; - color.green = c.green; - color.blue = c.blue; - color.alpha = c.alpha; - offset = o; -} - -// constructor -color_step::color_step(uint8 r, uint8 g, uint8 b, uint8 a, float o) -{ - color.red = r; - color.green = g; - color.blue = b; - color.alpha = a; - offset = o; -} - -// constructor -color_step::color_step(const color_step& other) -{ - color.red = other.color.red; - color.green = other.color.green; - color.blue = other.color.blue; - color.alpha = other.color.alpha; - offset = other.offset; -} - -// constructor -color_step::color_step() -{ - color.red = 0; - color.green = 0; - color.blue = 0; - color.alpha = 255; - offset = 0; -} - -// operator!= -bool -color_step::operator!=(const color_step& other) const -{ - return color.red != other.color.red || - color.green != other.color.green || - color.blue != other.color.blue || - color.alpha != other.color.alpha || - offset != other.offset; -} - -// #pragma mark - - // constructor Gradient::Gradient(bool empty) #ifdef ICON_O_MATIC @@ -398,7 +345,7 @@ Gradient::ColorAtFast(int32 index) const // SetType void -Gradient::SetType(gradient_type type) +Gradient::SetType(gradients_type type) { if (fType != type) { fType = type; @@ -575,7 +522,7 @@ Gradient::FitToBounds(const BRect& bounds) // string_for_type static const char* -string_for_type(gradient_type type) +string_for_type(gradients_type type) { switch (type) { case GRADIENT_LINEAR: diff --git a/src/libs/icon/style/Gradient.h b/src/libs/icon/style/GradientTransformable.h similarity index 82% rename from src/libs/icon/style/Gradient.h rename to src/libs/icon/style/GradientTransformable.h index 5a7c422e95..e3ba19552f 100644 --- a/src/libs/icon/style/Gradient.h +++ b/src/libs/icon/style/GradientTransformable.h @@ -5,8 +5,8 @@ * Authors: * Stephan Aßmus */ -#ifndef GRADIENT_H -#define GRADIENT_H +#ifndef GRADIENT_TRANSFORMABLE_H +#define GRADIENT_TRANSFORMABLE_H #ifdef ICON_O_MATIC @@ -18,39 +18,27 @@ #include "Transformable.h" #include +#include #include class BMessage; - -namespace BPrivate { -namespace Icon { - -enum gradient_type { +enum gradients_type { GRADIENT_LINEAR = 0, GRADIENT_CIRCULAR, GRADIENT_DIAMOND, GRADIENT_CONIC, GRADIENT_XY, - GRADIENT_SQRT_XY, + GRADIENT_SQRT_XY }; enum interpolation_type { INTERPOLATION_LINEAR = 0, - INTERPOLATION_SMOOTH, + INTERPOLATION_SMOOTH }; -struct color_step { - color_step(const rgb_color c, float o); - color_step(uint8 r, uint8 g, uint8 b, uint8 a, float o); - color_step(const color_step& other); - color_step(); - - bool operator!=(const color_step& other) const; - - rgb_color color; - float offset; -}; +namespace BPrivate { +namespace Icon { #ifdef ICON_O_MATIC class Gradient : public BArchivable, @@ -97,8 +85,8 @@ class Gradient : public Transformable { color_step* ColorAt(int32 index) const; color_step* ColorAtFast(int32 index) const; - void SetType(gradient_type type); - gradient_type Type() const + void SetType(gradients_type type); + gradients_type Type() const { return fType; } void SetInterpolation(interpolation_type type); @@ -122,7 +110,7 @@ class Gradient : public Transformable { void _MakeEmpty(); BList fColors; - gradient_type fType; + gradients_type fType; interpolation_type fInterpolation; bool fInheritTransformation; }; @@ -130,4 +118,4 @@ class Gradient : public Transformable { } // namespace Icon } // namespace BPrivate -#endif // GRADIENT_H +#endif // GRADIENT_TRANSFORMABLE_H diff --git a/src/libs/icon/style/Style.cpp b/src/libs/icon/style/Style.cpp index ce0c4f30af..f326bd7f9d 100644 --- a/src/libs/icon/style/Style.cpp +++ b/src/libs/icon/style/Style.cpp @@ -18,7 +18,7 @@ # define kWhite (rgb_color){ 255, 255, 255, 255 } #endif // ICON_O_MATIC -#include "Gradient.h" +#include "GradientTransformable.h" using std::nothrow; diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index b6986fb323..ab6420e0f2 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -976,7 +976,7 @@ Desktop::_SetWorkspace(int32 index) // is up-to-date if (window->Frame().LeftTop() != position) { BPoint offset = position - window->Frame().LeftTop(); - window->MoveBy(offset.x, offset.y); + window->MoveBy((int32)offset.x, (int32)offset.y); } continue; } @@ -1822,7 +1822,7 @@ Desktop::MoveWindowBy(Window* window, float x, float y, int32 workspace) window->Anchor(workspace).position += BPoint(x, y); _WindowChanged(window); } else - window->MoveBy(x, y); + window->MoveBy((int32)x, (int32)y); UnlockAllWindows(); return; @@ -1834,7 +1834,7 @@ Desktop::MoveWindowBy(Window* window, float x, float y, int32 workspace) // no more drawing for DirectWindows window->ServerWindow()->HandleDirectConnection(B_DIRECT_STOP); - window->MoveBy(x, y); + window->MoveBy((int32)x, (int32)y); BRegion background; _RebuildClippingForAllWindows(background); @@ -1842,7 +1842,7 @@ Desktop::MoveWindowBy(Window* window, float x, float y, int32 workspace) // construct the region that is possible to be blitted // to move the contents of the window BRegion copyRegion(window->VisibleRegion()); - copyRegion.OffsetBy(-x, -y); + copyRegion.OffsetBy((int32)-x, (int32)-y); copyRegion.IntersectWith(&newDirtyRegion); // newDirtyRegion == the windows old visible region @@ -1850,7 +1850,7 @@ Desktop::MoveWindowBy(Window* window, float x, float y, int32 workspace) // moved into the dirty region (for now) newDirtyRegion.Include(&window->VisibleRegion()); - GetDrawingEngine()->CopyRegion(©Region, x, y); + GetDrawingEngine()->CopyRegion(©Region, (int32)x, (int32)y); // allow DirectWindows to draw again after the visual // content is at the new location @@ -1858,7 +1858,7 @@ Desktop::MoveWindowBy(Window* window, float x, float y, int32 workspace) // in the dirty region, exclude the parts that we // could move by blitting - copyRegion.OffsetBy(x, y); + copyRegion.OffsetBy((int32)x, (int32)y); newDirtyRegion.Exclude(©Region); MarkDirty(newDirtyRegion); @@ -1876,7 +1876,7 @@ Desktop::ResizeWindowBy(Window* window, float x, float y) return; if (!window->IsVisible()) { - window->ResizeBy(x, y, NULL); + window->ResizeBy((int32)x, (int32)y, NULL); UnlockAllWindows(); return; } @@ -1888,7 +1888,7 @@ Desktop::ResizeWindowBy(Window* window, float x, float y) // it is shrunk in "previouslyOccupiedRegion" BRegion previouslyOccupiedRegion(window->VisibleRegion()); - window->ResizeBy(x, y, &newDirtyRegion); + window->ResizeBy((int32)x, (int32)y, &newDirtyRegion); BRegion background; _RebuildClippingForAllWindows(background); diff --git a/src/servers/app/ProfileMessageSupport.cpp b/src/servers/app/ProfileMessageSupport.cpp index 87e6699b7a..03feba160a 100644 --- a/src/servers/app/ProfileMessageSupport.cpp +++ b/src/servers/app/ProfileMessageSupport.cpp @@ -202,14 +202,23 @@ string_for_message_code(uint32 code, BString& string) case AS_STROKE_TRIANGLE: string = "AS_STROKE_TRIANGLE"; break; case AS_FILL_ARC: string = "AS_FILL_ARC"; break; + case AS_FILL_ARC_GRADIENT: string = "AS_FILL_ARC_GRADIENT"; break; case AS_FILL_BEZIER: string = "AS_FILL_BEZIER"; break; + case AS_FILL_BEZIER_GRADIENT: string = "AS_FILL_BEZIER_GRADIENT"; break; case AS_FILL_ELLIPSE: string = "AS_FILL_ELLIPSE"; break; + case AS_FILL_ELLIPSE_GRADIENT: string = "AS_FILL_ELLIPSE_GRADIENT"; break; case AS_FILL_POLYGON: string = "AS_FILL_POLYGON"; break; + case AS_FILL_POLYGON_GRADIENT: string = "AS_FILL_POLYGON_GRADIENT"; break; case AS_FILL_RECT: string = "AS_FILL_RECT"; break; + case AS_FILL_RECT_GRADIENT: string = "AS_FILL_RECT_GRADIENT"; break; case AS_FILL_REGION: string = "AS_FILL_REGION"; break; + case AS_FILL_REGION_GRADIENT: string = "AS_FILL_REGION_GRADIENT"; break; case AS_FILL_ROUNDRECT: string = "AS_FILL_ROUNDRECT"; break; + case AS_FILL_ROUNDRECT_GRADIENT: string = "AS_FILL_ROUNDRECT_GRADIENT"; break; case AS_FILL_SHAPE: string = "AS_FILL_SHAPE"; break; + case AS_FILL_SHAPE_GRADIENT: string = "AS_FILL_SHAPE_GRADIENT"; break; case AS_FILL_TRIANGLE: string = "AS_FILL_TRIANGLE"; break; + case AS_FILL_TRIANGLE_GRADIENT: string = "AS_FILL_TRIANGLE_GRADIENT"; break; case AS_DRAW_STRING: string = "AS_DRAW_STRING"; break; case AS_DRAW_STRING_WITH_DELTA: string = "AS_DRAW_STRING_WITH_DELTA"; break; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 2801baa27a..a7d44dcc5a 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -51,6 +51,11 @@ #include #include #include +#include +#include +#include +#include +#include #include @@ -58,6 +63,7 @@ using std::nothrow; //#define TRACE_SERVER_WINDOW //#define TRACE_SERVER_WINDOW_MESSAGES +//#define TRACE_SERVER_GRADIENTS //#define PROFILE_MESSAGE_LOOP @@ -75,6 +81,13 @@ using std::nothrow; # define DTRACE(x) ; #endif +#ifdef TRACE_SERVER_GRADIENTS +# include +# define GTRACE(x) debug_printf x +#else +# define GTRACE(x) ; +#endif + #ifdef PROFILE_MESSAGE_LOOP struct profile { int32 code; int32 count; bigtime_t time; }; static profile sMessageProfile[AS_LAST_CODE]; @@ -2120,6 +2133,23 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li drawingEngine->FillRect(rect); break; } + case AS_FILL_RECT_GRADIENT: + { + GTRACE(("ServerWindow %s: Message AS_FILL_RECT_GRADIENT\n", Title())); + + BRect rect; + link.Read(&rect); + gradient_type gradientType; + link.Read(&gradientType); + BGradient* gradient = _GetNewGradientForType(gradientType); + if (gradient) { + link.ReadGradient(gradient); + fCurrentView->ConvertToScreenForDrawing(&rect); + fCurrentView->ConvertToScreenForDrawing(gradient); + drawingEngine->FillRectGradient(rect, *gradient); + } + break; + } case AS_VIEW_DRAW_BITMAP: { DTRACE(("ServerWindow %s: Message AS_VIEW_DRAW_BITMAP: View name: %s\n", fTitle, fCurrentView->Name())); @@ -2159,6 +2189,26 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC); break; } + case AS_FILL_ARC_GRADIENT: + { + GTRACE(("ServerWindow %s: Message AS_FILL_ARC_GRADIENT\n", Title())); + + float angle, span; + BRect r; + link.Read(&r); + link.Read(&angle); + link.Read(&span); + gradient_type gradientType; + link.Read(&gradientType); + BGradient* gradient = _GetNewGradientForType(gradientType); + if (gradient) { + link.ReadGradient(gradient); + fCurrentView->ConvertToScreenForDrawing(&r); + fCurrentView->ConvertToScreenForDrawing(gradient); + drawingEngine->FillArcGradient(r, angle, span, *gradient); + } + break; + } case AS_STROKE_BEZIER: case AS_FILL_BEZIER: { @@ -2173,6 +2223,25 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li drawingEngine->DrawBezier(pts, code == AS_FILL_BEZIER); break; } + case AS_FILL_BEZIER_GRADIENT: + { + GTRACE(("ServerWindow %s: Message AS_FILL_BEZIER_GRADIENT\n", Title())); + + BPoint pts[4]; + for (int32 i = 0; i < 4; i++) { + link.Read(&(pts[i])); + fCurrentView->ConvertToScreenForDrawing(&pts[i]); + } + gradient_type gradientType; + link.Read(&gradientType); + BGradient* gradient = _GetNewGradientForType(gradientType); + if (gradient) { + link.ReadGradient(gradient); + fCurrentView->ConvertToScreenForDrawing(gradient); + drawingEngine->FillBezierGradient(pts, *gradient); + } + break; + } case AS_STROKE_ELLIPSE: case AS_FILL_ELLIPSE: { @@ -2185,6 +2254,23 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE); break; } + case AS_FILL_ELLIPSE_GRADIENT: + { + GTRACE(("ServerWindow %s: Message AS_FILL_ELLIPSE_GRADIENT\n", Title())); + + BRect rect; + link.Read(&rect); + gradient_type gradientType; + link.Read(&gradientType); + BGradient* gradient = _GetNewGradientForType(gradientType); + if (gradient) { + link.ReadGradient(gradient); + fCurrentView->ConvertToScreenForDrawing(&rect); + fCurrentView->ConvertToScreenForDrawing(gradient); + drawingEngine->FillEllipseGradient(rect, *gradient); + } + break; + } case AS_STROKE_ROUNDRECT: case AS_FILL_ROUNDRECT: { @@ -2200,6 +2286,26 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li drawingEngine->DrawRoundRect(rect, xrad, yrad, code == AS_FILL_ROUNDRECT); break; } + case AS_FILL_ROUNDRECT_GRADIENT: + { + GTRACE(("ServerWindow %s: Message AS_FILL_ROUNDRECT_GRADIENT\n", Title())); + + BRect rect; + float xrad,yrad; + link.Read(&rect); + link.Read(&xrad); + link.Read(&yrad); + gradient_type gradientType; + link.Read(&gradientType); + BGradient* gradient = _GetNewGradientForType(gradientType); + if (gradient) { + link.ReadGradient(gradient); + fCurrentView->ConvertToScreenForDrawing(&rect); + fCurrentView->ConvertToScreenForDrawing(gradient); + drawingEngine->FillRoundRectGradient(rect, xrad, yrad, *gradient); + } + break; + } case AS_STROKE_TRIANGLE: case AS_FILL_TRIANGLE: { @@ -2219,6 +2325,28 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE); break; } + case AS_FILL_TRIANGLE_GRADIENT: + { + DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE_GRADIENT\n", Title())); + + BPoint pts[3]; + BRect rect; + for (int32 i = 0; i < 3; i++) { + link.Read(&(pts[i])); + fCurrentView->ConvertToScreenForDrawing(&pts[i]); + } + link.Read(&rect); + gradient_type gradientType; + link.Read(&gradientType); + BGradient* gradient = _GetNewGradientForType(gradientType); + if (gradient) { + link.ReadGradient(gradient); + fCurrentView->ConvertToScreenForDrawing(&rect); + fCurrentView->ConvertToScreenForDrawing(gradient); + drawingEngine->FillTriangleGradient(pts, rect, *gradient); + } + break; + } case AS_STROKE_POLYGON: case AS_FILL_POLYGON: { @@ -2245,6 +2373,35 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li delete[] pointList; break; } + case AS_FILL_POLYGON_GRADIENT: + { + DTRACE(("ServerWindow %s: Message AS_FILL_POLYGON_GRADIENT\n", Title())); + + BRect polyFrame; + bool isClosed = true; + int32 pointCount; + link.Read(&polyFrame); + link.Read(&pointCount); + + BPoint* pointList = new(nothrow) BPoint[pointCount]; + if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) { + gradient_type gradientType; + link.Read(&gradientType); + BGradient* gradient = _GetNewGradientForType(gradientType); + if (gradient) { + link.ReadGradient(gradient); + for (int32 i = 0; i < pointCount; i++) + fCurrentView->ConvertToScreenForDrawing(&pointList[i]); + fCurrentView->ConvertToScreenForDrawing(&polyFrame); + fCurrentView->ConvertToScreenForDrawing(gradient); + + drawingEngine->FillPolygonGradient(pointList, pointCount, + polyFrame, *gradient, isClosed && pointCount > 2); + } + } + delete[] pointList; + break; + } case AS_STROKE_SHAPE: case AS_FILL_SHAPE: { @@ -2279,6 +2436,45 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li delete[] ptList; break; } + case AS_FILL_SHAPE_GRADIENT: + { + DTRACE(("ServerWindow %s: Message AS_FILL_SHAPE_GRADIENT\n", Title())); + + BRect shapeFrame; + int32 opCount; + int32 ptCount; + + link.Read(&shapeFrame); + link.Read(&opCount); + link.Read(&ptCount); + + uint32* opList = new(nothrow) uint32[opCount]; + BPoint* ptList = new(nothrow) BPoint[ptCount]; + if (link.Read(opList, opCount * sizeof(uint32)) >= B_OK && + link.Read(ptList, ptCount * sizeof(BPoint)) >= B_OK) { + + // this might seem a bit weird, but under R5, the shapes + // are always offset by the current pen location + BPoint penLocation = fCurrentView->CurrentState()->PenLocation(); + for (int32 i = 0; i < ptCount; i++) { + ptList[i] += penLocation; + fCurrentView->ConvertToScreenForDrawing(&ptList[i]); + } + gradient_type gradientType; + link.Read(&gradientType); + BGradient* gradient = _GetNewGradientForType(gradientType); + if (gradient) { + link.ReadGradient(gradient); + fCurrentView->ConvertToScreenForDrawing(gradient); + drawingEngine->FillShapeGradient(shapeFrame, opCount, opList, + ptCount, ptList, *gradient); + } + } + + delete[] opList; + delete[] ptList; + break; + } case AS_FILL_REGION: { DTRACE(("ServerWindow %s: Message AS_FILL_REGION\n", Title())); @@ -2292,6 +2488,24 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li break; } + case AS_FILL_REGION_GRADIENT: + { + DTRACE(("ServerWindow %s: Message AS_FILL_REGION_GRADIENT\n", Title())); + + BRegion region; + if (link.ReadRegion(®ion) < B_OK) + break; + gradient_type gradientType; + link.Read(&gradientType); + BGradient* gradient = _GetNewGradientForType(gradientType); + if (gradient) { + link.ReadGradient(gradient); + fCurrentView->ConvertToScreenForDrawing(®ion); + fCurrentView->ConvertToScreenForDrawing(gradient); + drawingEngine->FillRegionGradient(region, *gradient); + } + break; + } case AS_STROKE_LINEARRAY: { DTRACE(("ServerWindow %s: Message AS_STROKE_LINEARRAY\n", Title())); @@ -3277,3 +3491,30 @@ ServerWindow::PictureToRegion(ServerPicture *picture, BRegion ®ion, region.MakeEmpty(); return B_ERROR; } + + +BGradient* +ServerWindow::_GetNewGradientForType(gradient_type type) +{ + switch (type) { + case B_GRADIENT_LINEAR: { + return new (std::nothrow) BGradientLinear(); + } + case B_GRADIENT_RADIAL: { + return new (std::nothrow) BGradientRadial(); + } + case B_GRADIENT_RADIAL_FOCUS: { + return new (std::nothrow) BGradientRadialFocus(); + } + case B_GRADIENT_DIAMOND: { + return new (std::nothrow) BGradientDiamond(); + } + case B_GRADIENT_CONIC: { + return new (std::nothrow) BGradientConic(); + } + case B_GRADIENT_NONE: { + return new (std::nothrow) BGradient(); + } + } + return NULL; +} diff --git a/src/servers/app/ServerWindow.h b/src/servers/app/ServerWindow.h index 053a77e4ba..b376317957 100644 --- a/src/servers/app/ServerWindow.h +++ b/src/servers/app/ServerWindow.h @@ -130,6 +130,8 @@ private: void _UpdateCurrentDrawingRegion(); bool _MessageNeedsAllWindowsLocked(uint32 code) const; + + BGradient* _GetNewGradientForType(gradient_type type); // TODO: Move me elsewhere status_t PictureToRegion(ServerPicture *picture, diff --git a/src/servers/app/View.cpp b/src/servers/app/View.cpp index e6092fa62d..461433e7a4 100644 --- a/src/servers/app/View.cpp +++ b/src/servers/app/View.cpp @@ -32,6 +32,12 @@ #include // for resize modes #include +#include +#include +#include +#include +#include + #include #include @@ -793,7 +799,7 @@ View::ConvertToScreenForDrawing(BRect* rect) const } -//! converts a region from local *drawing* to screen coordinate system +//! converts a region from local *drawing* to screen coordinate system void View::ConvertToScreenForDrawing(BRegion* region) const { @@ -804,6 +810,71 @@ View::ConvertToScreenForDrawing(BRegion* region) const } +//! converts a gradient from local *drawing* to screen coordinate system +void +View::ConvertToScreenForDrawing(BGradient* gradient) const +{ + switch(gradient->Type()) { + case B_GRADIENT_LINEAR: { + BGradientLinear* linear = (BGradientLinear*) gradient; + BPoint start = linear->Start(); + BPoint end = linear->End(); + fDrawState->Transform(&start); + ConvertToScreen(&start); + fDrawState->Transform(&end); + ConvertToScreen(&end); + linear->SetStart(start); + linear->SetEnd(end); + linear->SortColorStepsByOffset(); + break; + } + case B_GRADIENT_RADIAL: { + BGradientRadial* radial = (BGradientRadial*) gradient; + BPoint center = radial->Center(); + fDrawState->Transform(¢er); + ConvertToScreen(¢er); + radial->SetCenter(center); + radial->SortColorStepsByOffset(); + break; + } + case B_GRADIENT_RADIAL_FOCUS: { + BGradientRadialFocus* radialFocus = (BGradientRadialFocus*) gradient; + BPoint center = radialFocus->Center(); + BPoint focal = radialFocus->Focal(); + fDrawState->Transform(¢er); + ConvertToScreen(¢er); + fDrawState->Transform(&focal); + ConvertToScreen(&focal); + radialFocus->SetCenter(center); + radialFocus->SetFocal(focal); + radialFocus->SortColorStepsByOffset(); + break; + } + case B_GRADIENT_DIAMOND: { + BGradientDiamond* diamond = (BGradientDiamond*) gradient; + BPoint center = diamond->Center(); + fDrawState->Transform(¢er); + ConvertToScreen(¢er); + diamond->SetCenter(center); + diamond->SortColorStepsByOffset(); + break; + } + case B_GRADIENT_CONIC: { + BGradientConic* conic = (BGradientConic*) gradient; + BPoint center = conic->Center(); + fDrawState->Transform(¢er); + ConvertToScreen(¢er); + conic->SetCenter(center); + conic->SortColorStepsByOffset(); + break; + } + case B_GRADIENT_NONE: { + break; + } + } +} + + //! converts points from local *drawing* to screen coordinate system void View::ConvertToScreenForDrawing(BPoint* dst, const BPoint* src, int32 num) const diff --git a/src/servers/app/View.h b/src/servers/app/View.h index 303f70c3e0..1f219e6f81 100644 --- a/src/servers/app/View.h +++ b/src/servers/app/View.h @@ -34,6 +34,7 @@ class Window; class ServerBitmap; class ServerCursor; class ServerPicture; +class BGradient; class View { public: @@ -133,6 +134,7 @@ class View { void ConvertToScreenForDrawing(BPoint* point) const; void ConvertToScreenForDrawing(BRect* rect) const; void ConvertToScreenForDrawing(BRegion* region) const; + void ConvertToScreenForDrawing(BGradient* gradient) const; void ConvertToScreenForDrawing(BPoint* dst, const BPoint* src, int32 num) const; void ConvertToScreenForDrawing(BRect* dst, const BRect* src, int32 num) const; diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index 57c0374a8d..8ba8637526 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -610,6 +610,34 @@ DrawingEngine::DrawArc(BRect r, const float& angle, const float& span, } } +// FillArcGradient +void +DrawingEngine::FillArcGradient(BRect r, const float& angle, const float& span, + const BGradient& gradient) +{ + CRASH_IF_NOT_LOCKED + + make_rect_valid(r); + fPainter->AlignEllipseRect(&r, true); + BRect clipped(r); + + clipped = fPainter->ClipRect(r); + + if (clipped.IsValid()) { + AutoFloatingOverlaysHider _(fGraphicsCard, clipped); + + float xRadius = r.Width() / 2.0; + float yRadius = r.Height() / 2.0; + BPoint center(r.left + xRadius, + r.top + yRadius); + + fPainter->FillArcGradient(center, xRadius, yRadius, angle, span, + gradient); + + _CopyToFront(clipped); + } +} + // DrawBezier void DrawingEngine::DrawBezier(BPoint* pts, bool filled) @@ -624,6 +652,20 @@ DrawingEngine::DrawBezier(BPoint* pts, bool filled) _CopyToFront(touched); } +// FillBezierGradient +void +DrawingEngine::FillBezierGradient(BPoint* pts, const BGradient& gradient) +{ + CRASH_IF_NOT_LOCKED + + // TODO: figure out bounds and hide cursor depending on that + AutoFloatingOverlaysHider _(fGraphicsCard); + + BRect touched = fPainter->FillBezierGradient(pts, gradient); + + _CopyToFront(touched); +} + // DrawEllipse void DrawingEngine::DrawEllipse(BRect r, bool filled) @@ -653,6 +695,32 @@ DrawingEngine::DrawEllipse(BRect r, bool filled) } } +// FillEllipseGradient +void +DrawingEngine::FillEllipseGradient(BRect r, const BGradient& gradient) +{ + CRASH_IF_NOT_LOCKED + + make_rect_valid(r); + BRect clipped = r; + fPainter->AlignEllipseRect(&clipped, true); + + clipped.left = floorf(clipped.left); + clipped.top = floorf(clipped.top); + clipped.right = ceilf(clipped.right); + clipped.bottom = ceilf(clipped.bottom); + + clipped = fPainter->ClipRect(clipped); + + if (clipped.IsValid()) { + AutoFloatingOverlaysHider _(fGraphicsCard, clipped); + + fPainter->FillEllipseGradient(r, gradient); + + _CopyToFront(clipped); + } +} + // DrawPolygon void DrawingEngine::DrawPolygon(BPoint* ptlist, int32 numpts, BRect bounds, @@ -673,6 +741,24 @@ DrawingEngine::DrawPolygon(BPoint* ptlist, int32 numpts, BRect bounds, } } +// FillPolygonGradient +void +DrawingEngine::FillPolygonGradient(BPoint* ptlist, int32 numpts, BRect bounds, + const BGradient& gradient, bool closed) +{ + CRASH_IF_NOT_LOCKED + + make_rect_valid(bounds); + bounds = fPainter->ClipRect(bounds); + if (bounds.IsValid()) { + AutoFloatingOverlaysHider _(fGraphicsCard, bounds); + + fPainter->FillPolygonGradient(ptlist, numpts, gradient, closed); + + _CopyToFront(bounds); + } +} + // #pragma mark - rgb_color void @@ -876,6 +962,25 @@ DrawingEngine::FillRect(BRect r) } +void +DrawingEngine::FillRectGradient(BRect r, const BGradient& gradient) +{ + CRASH_IF_NOT_LOCKED + + make_rect_valid(r); + r = fPainter->AlignAndClipRect(r); + if (!r.IsValid()) + return; + + AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, r); + + fPainter->FillRectGradient(r, gradient); + + if (fGraphicsCard->IsDoubleBuffered()) + _CopyToFront(r); +} + + void DrawingEngine::FillRegion(BRegion& r) { @@ -930,6 +1035,28 @@ DrawingEngine::FillRegion(BRegion& r) } +void +DrawingEngine::FillRegionGradient(BRegion& r, const BGradient& gradient) +{ + CRASH_IF_NOT_LOCKED + + BRect clipped = fPainter->ClipRect(r.Frame()); + if (!clipped.IsValid()) + return; + + AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, clipped); + + BRect touched = fPainter->FillRectGradient(r.RectAt(0), gradient); + + int32 count = r.CountRects(); + for (int32 i = 1; i < count; i++) + touched = touched | fPainter->FillRectGradient(r.RectAt(i), gradient); + + if (fGraphicsCard->IsDoubleBuffered()) + _CopyToFront(r.Frame()); +} + + void DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad, bool filled) { @@ -956,6 +1083,32 @@ DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad, bool filled) } +void +DrawingEngine::FillRoundRectGradient(BRect r, float xrad, float yrad, + const BGradient& gradient) +{ + CRASH_IF_NOT_LOCKED + + // NOTE: the stroke does not extend past "r" in R5, + // though I consider this unexpected behaviour. + make_rect_valid(r); + BRect clipped = fPainter->ClipRect(r); + + clipped.left = floorf(clipped.left); + clipped.top = floorf(clipped.top); + clipped.right = ceilf(clipped.right); + clipped.bottom = ceilf(clipped.bottom); + + if (clipped.IsValid()) { + AutoFloatingOverlaysHider _(fGraphicsCard, clipped); + + BRect touched = fPainter->FillRoundRectGradient(r, xrad, yrad, gradient); + + _CopyToFront(touched); + } +} + + void DrawingEngine::DrawShape(const BRect& bounds, int32 opCount, const uint32* opList, int32 ptCount, const BPoint* ptList, bool filled) @@ -974,6 +1127,24 @@ DrawingEngine::DrawShape(const BRect& bounds, int32 opCount, } +void +DrawingEngine::FillShapeGradient(const BRect& bounds, int32 opCount, + const uint32* opList, int32 ptCount, const BPoint* ptList, + const BGradient& gradient) +{ + CRASH_IF_NOT_LOCKED + + // NOTE: hides cursor regardless of if and where + // shape is drawn on screen, TODO: optimize + AutoFloatingOverlaysHider _(fGraphicsCard); + + BRect touched = fPainter->FillShapeGradient(opCount, opList, ptCount, + ptList, gradient); + + _CopyToFront(touched); +} + + void DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds, bool filled) { @@ -995,6 +1166,23 @@ DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds, bool filled) } } +void +DrawingEngine::FillTriangleGradient(BPoint* pts, const BRect& bounds, + const BGradient& gradient) +{ + CRASH_IF_NOT_LOCKED + + BRect clipped(bounds); + clipped = fPainter->ClipRect(clipped); + if (clipped.IsValid()) { + AutoFloatingOverlaysHider _(fGraphicsCard, clipped); + + fPainter->FillTriangleGradient(pts[0], pts[1], pts[2], gradient); + + _CopyToFront(clipped); + } +} + // StrokeLine void DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end) diff --git a/src/servers/app/drawing/DrawingEngine.h b/src/servers/app/drawing/DrawingEngine.h index c11e4d8851..2e3114451f 100644 --- a/src/servers/app/drawing/DrawingEngine.h +++ b/src/servers/app/drawing/DrawingEngine.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "HWInterface.h" @@ -99,13 +100,22 @@ public: void DrawArc(BRect r, const float& angle, const float& span, bool filled); + void FillArcGradient(BRect r, const float& angle, + const float& span, const BGradient& gradient); void DrawBezier(BPoint* pts, bool filled); + void FillBezierGradient(BPoint* pts, + const BGradient& gradient); void DrawEllipse(BRect r, bool filled); + void FillEllipseGradient(BRect r, + const BGradient& gradient); void DrawPolygon(BPoint* ptlist, int32 numpts, BRect bounds, bool filled, bool closed); + void FillPolygonGradient(BPoint* ptlist, int32 numpts, + BRect bounds, const BGradient& gradient, + bool closed); // these rgb_color versions are used internally by the server void StrokePoint(const BPoint& pt, @@ -116,19 +126,30 @@ public: void StrokeRect(BRect r); void FillRect(BRect r); + void FillRectGradient(BRect r, const BGradient& gradient); void FillRegion(BRegion& r); + void FillRegionGradient(BRegion& r, + const BGradient& gradient); void DrawRoundRect(BRect r, float xrad, float yrad, bool filled); + void FillRoundRectGradient(BRect r, float xrad, + float yrad, const BGradient& gradient); void DrawShape(const BRect& bounds, int32 opcount, const uint32* oplist, int32 ptcount, const BPoint* ptlist, bool filled); - + void FillShapeGradient(const BRect& bounds, + int32 opcount, const uint32* oplist, + int32 ptcount, const BPoint* ptlist, + const BGradient& gradient); + void DrawTriangle(BPoint* pts, const BRect& bounds, bool filled); + void FillTriangleGradient(BPoint* pts, + const BRect& bounds, const BGradient& gradient); // this version used by Decorator void StrokeLine(const BPoint& start, diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 7e7607cb37..56ac9ec439 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -15,6 +15,11 @@ #include #include #include +#include +#include +#include +#include +#include #include @@ -52,13 +57,22 @@ using std::nothrow; #undef TRACE -//#define TRACE_PAINTER +// #define TRACE_PAINTER #ifdef TRACE_PAINTER # define TRACE(x...) printf(x) #else # define TRACE(x...) #endif +//#define TRACE_GRADIENTS +#ifdef TRACE_GRADIENTS +# include +# define GTRACE(x...) debug_printf(x) +#else +# define GTRACE(x...) +#endif + + #define CHECK_CLIPPING if (!fValidClipping) return BRect(0, 0, -1, -1); #define CHECK_CLIPPING_NO_RETURN if (!fValidClipping) return; @@ -492,6 +506,28 @@ Painter::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3) const return _DrawTriangle(pt1, pt2, pt3, true); } +// FillTriangleGradient +BRect +Painter::FillTriangleGradient(BPoint pt1, BPoint pt2, BPoint pt3, + const BGradient& gradient) const +{ + CHECK_CLIPPING + + _Transform(&pt1); + _Transform(&pt2); + _Transform(&pt3); + + fPath.remove_all(); + + fPath.move_to(pt1.x, pt1.y); + fPath.line_to(pt2.x, pt2.y); + fPath.line_to(pt3.x, pt3.y); + + fPath.close_polygon(); + + return _FillPathGradient(fPath, gradient); +} + // DrawPolygon BRect Painter::DrawPolygon(BPoint* p, int32 numPts, @@ -523,6 +559,34 @@ Painter::DrawPolygon(BPoint* p, int32 numPts, return BRect(0.0, 0.0, -1.0, -1.0); } +// FillPolygonGradient +BRect +Painter::FillPolygonGradient(BPoint* p, int32 numPts, + const BGradient& gradient, bool closed) const +{ + CHECK_CLIPPING + + if (numPts > 0) { + + fPath.remove_all(); + + _Transform(p); + fPath.move_to(p->x, p->y); + + for (int32 i = 1; i < numPts; i++) { + p++; + _Transform(p); + fPath.line_to(p->x, p->y); + } + + if (closed) + fPath.close_polygon(); + + return _FillPathGradient(fPath, gradient); + } + return BRect(0.0, 0.0, -1.0, -1.0); +} + // DrawBezier BRect Painter::DrawBezier(BPoint* p, bool filled) const @@ -550,6 +614,28 @@ Painter::DrawBezier(BPoint* p, bool filled) const } } +// FillBezierGradient +BRect +Painter::FillBezierGradient(BPoint* p, const BGradient& gradient) const +{ + CHECK_CLIPPING + + fPath.remove_all(); + + _Transform(&(p[0])); + _Transform(&(p[1])); + _Transform(&(p[2])); + _Transform(&(p[3])); + + fPath.move_to(p[0].x, p[0].y); + fPath.curve4(p[1].x, p[1].y, + p[2].x, p[2].y, + p[3].x, p[3].y); + + + fPath.close_polygon(); + return _FillPathGradient(fCurve, gradient); +} // DrawShape @@ -600,6 +686,51 @@ Painter::DrawShape(const int32& opCount, const uint32* opList, return _StrokePath(fCurve); } +// FillShapeGradient +BRect +Painter::FillShapeGradient(const int32& opCount, const uint32* opList, + const int32& ptCount, const BPoint* points, + const BGradient& gradient) const +{ + CHECK_CLIPPING + + // TODO: if shapes are ever used more heavily in Haiku, + // it would be nice to use BShape data directly (write + // an AGG "VertexSource" adaptor) + fPath.remove_all(); + for (int32 i = 0; i < opCount; i++) { + uint32 op = opList[i] & 0xFF000000; + if (op & OP_MOVETO) { + fPath.move_to(points->x, points->y); + points++; + } + + if (op & OP_LINETO) { + int32 count = opList[i] & 0x00FFFFFF; + while (count--) { + fPath.line_to(points->x, points->y); + points++; + } + } + + if (op & OP_BEZIERTO) { + int32 count = opList[i] & 0x00FFFFFF; + while (count) { + fPath.curve4(points[0].x, points[0].y, + points[1].x, points[1].y, + points[2].x, points[2].y); + points += 3; + count -= 3; + } + } + + if (op & OP_CLOSE) + fPath.close_polygon(); + } + + return _FillPathGradient(fCurve, gradient); +} + // StrokeRect BRect Painter::StrokeRect(const BRect& r) const @@ -723,6 +854,34 @@ Painter::FillRect(const BRect& r) const return _FillPath(fPath); } +// FillRectGradient +BRect +Painter::FillRectGradient(const BRect& r, const BGradient& gradient) const +{ + CHECK_CLIPPING + + // support invalid rects + BPoint a(min_c(r.left, r.right), min_c(r.top, r.bottom)); + BPoint b(max_c(r.left, r.right), max_c(r.top, r.bottom)); + _Transform(&a, false); + _Transform(&b, false); + + // account for stricter interpretation of coordinates in AGG + // the rectangle ranges from the top-left (.0, .0) + // to the bottom-right (.9999, .9999) corner of pixels + b.x += 1.0; + b.y += 1.0; + + fPath.remove_all(); + fPath.move_to(a.x, a.y); + fPath.line_to(b.x, a.y); + fPath.line_to(b.x, b.y); + fPath.line_to(a.x, b.y); + fPath.close_polygon(); + + return _FillPathGradient(fPath, gradient); +} + // FillRect void Painter::FillRect(const BRect& r, const rgb_color& c) const @@ -907,6 +1066,31 @@ Painter::FillRoundRect(const BRect& r, float xRadius, float yRadius) const return _FillPath(rect); } +// FillRoundRectGradient +BRect +Painter::FillRoundRectGradient(const BRect& r, float xRadius, float yRadius, + const BGradient& gradient) const +{ + CHECK_CLIPPING + + BPoint lt(r.left, r.top); + BPoint rb(r.right, r.bottom); + _Transform(<, false); + _Transform(&rb, false); + + // account for stricter interpretation of coordinates in AGG + // the rectangle ranges from the top-left (.0, .0) + // to the bottom-right (.9999, .9999) corner of pixels + rb.x += 1.0; + rb.y += 1.0; + + agg::rounded_rect rect; + rect.rect(lt.x, lt.y, rb.x, rb.y); + rect.radius(xRadius, yRadius); + + return _FillPathGradient(rect, gradient); +} + // AlignEllipseRect void Painter::AlignEllipseRect(BRect* rect, bool filled) const @@ -999,6 +1183,29 @@ Painter::DrawEllipse(BRect r, bool fill) const } } +// FillEllipseGradient +BRect +Painter::FillEllipseGradient(BRect r, const BGradient& gradient) const +{ + CHECK_CLIPPING + + AlignEllipseRect(&r, true); + + float xRadius = r.Width() / 2.0; + float yRadius = r.Height() / 2.0; + BPoint center(r.left + xRadius, r.top + yRadius); + + int32 divisions = (int32)((xRadius + yRadius + 2 * fPenSize) * PI / 2); + if (divisions < 12) + divisions = 12; + if (divisions > 4096) + divisions = 4096; + + agg::ellipse path(center.x, center.y, xRadius, yRadius, divisions); + + return _FillPathGradient(path, gradient); +} + // StrokeArc BRect Painter::StrokeArc(BPoint center, float xRadius, float yRadius, float angle, @@ -1055,6 +1262,42 @@ Painter::FillArc(BPoint center, float xRadius, float yRadius, float angle, return _FillPath(fPath); } +// FillArcGradient +BRect +Painter::FillArcGradient(BPoint center, float xRadius, float yRadius, float angle, + float span, const BGradient& gradient) const +{ + CHECK_CLIPPING + + _Transform(¢er); + + double angleRad = (angle * PI) / 180.0; + double spanRad = (span * PI) / 180.0; + agg::bezier_arc arc(center.x, center.y, xRadius, yRadius, + -angleRad, -spanRad); + + agg::conv_curve segmentedArc(arc); + + fPath.remove_all(); + + // build a new path by starting at the center point, + // then traversing the arc, then going back to the center + fPath.move_to(center.x, center.y); + + segmentedArc.rewind(0); + double x; + double y; + unsigned cmd = segmentedArc.vertex(&x, &y); + while (!agg::is_stop(cmd)) { + fPath.line_to(x, y); + cmd = segmentedArc.vertex(&x, &y); + } + + fPath.close_polygon(); + + return _FillPathGradient(fPath, gradient); +} + // #pragma mark - // DrawString @@ -1161,6 +1404,21 @@ Painter::FillRegion(const BRegion* region) const return touched; } +// FillRegionGradient +BRect +Painter::FillRegionGradient(const BRegion* region, const BGradient& gradient) const +{ + CHECK_CLIPPING + + BRegion copy(*region); + int32 count = copy.CountRects(); + BRect touched = FillRectGradient(copy.RectAt(0), gradient); + for (int32 i = 1; i < count; i++) { + touched = touched | FillRectGradient(copy.RectAt(i), gradient); + } + return touched; +} + // InvertRect BRect Painter::InvertRect(const BRect& r) const @@ -2255,3 +2513,313 @@ Painter::_FillPath(VertexSource& path) const return _Clipped(_BoundingBox(path)); } +// _FillPathGradient +template +BRect +Painter::_FillPathGradient(VertexSource& path, const BGradient& gradient) const +{ + GTRACE("Painter::_FillPathGradient\n"); + + switch(gradient.Type()) { + case B_GRADIENT_LINEAR: { + GTRACE(("Painter::_FillPathGradient> type == B_GRADIENT_LINEAR\n")); + _FillPathGradientLinear(path, *((const BGradientLinear*) &gradient)); + break; + } + case B_GRADIENT_RADIAL: { + GTRACE(("Painter::_FillPathGradient> type == B_GRADIENT_RADIAL\n")); + _FillPathGradientRadial(path, + *((const BGradientRadial*) &gradient)); + break; + } + case B_GRADIENT_RADIAL_FOCUS: { + GTRACE(("Painter::_FillPathGradient> type == B_GRADIENT_RADIAL_FOCUS\n")); + _FillPathGradientRadialFocus(path, + *((const BGradientRadialFocus*) &gradient)); + break; + } + case B_GRADIENT_DIAMOND: { + GTRACE(("Painter::_FillPathGradient> type == B_GRADIENT_DIAMOND\n")); + _FillPathGradientDiamond(path, + *((const BGradientDiamond*) &gradient)); + break; + } + case B_GRADIENT_CONIC: { + GTRACE(("Painter::_FillPathGradient> type == B_GRADIENT_CONIC\n")); + _FillPathGradientConic(path, + *((const BGradientConic*) &gradient)); + break; + } + case B_GRADIENT_NONE: { + GTRACE(("Painter::_FillPathGradient> type == B_GRADIENT_NONE\n")); + break; + } + } + + return _Clipped(_BoundingBox(path)); +} + +// _MakeGradient +template +void +Painter::_MakeGradient(Array& array, const BGradient& gradient) const +{ + for (int i = 0; i < gradient.CountColors() - 1; i++) { + color_step* from = gradient.ColorAtFast(i); + color_step* to = gradient.ColorAtFast(i + 1); + agg::rgba8 fromColor(from->color.red, from->color.green, + from->color.blue, from->color.alpha); + agg::rgba8 toColor(to->color.red, to->color.green, + to->color.blue, to->color.alpha); + GTRACE("Painter::_MakeGradient> fromColor(%d, %d, %d) offset = %f\n", + fromColor.r, fromColor.g, fromColor.b, from->offset); + GTRACE("Painter::_MakeGradient> toColor(%d, %d, %d) offset = %f\n", + toColor.r, toColor.g, toColor.b, to->offset); + float dist = to->offset - from->offset; + GTRACE("Painter::_MakeGradient> dist = %f\n", dist); + if (dist > 0) { + for (int j = from->offset; j <= to->offset; j++) { + float f = (float)(to->offset - j) / (float)(dist + 1); + array[j] = toColor.gradient(fromColor, f); + GTRACE("Painter::_MakeGradient> array[%d](%d, %d, %d)\n", + array[j].r, array[j].g, array[j].b); + } + } + } +} + +// _CalcLinearGradientTransform +void Painter::_CalcLinearGradientTransform(BPoint startPoint, BPoint endPoint, + agg::trans_affine& mtx, + float gradient_d2) const +{ + float dx = endPoint.x - startPoint.x; + float dy = endPoint.y - startPoint.y; + mtx.reset(); + mtx *= agg::trans_affine_scaling(sqrt(dx * dx + dy * dy) / gradient_d2); + mtx *= agg::trans_affine_rotation(atan2(dy, dx)); + mtx *= agg::trans_affine_translation(startPoint.x, startPoint.y); + mtx.invert(); +} + +// _FillPathGradientLinear +template +void +Painter::_FillPathGradientLinear(VertexSource& path, + const BGradientLinear& linear) const +{ + GTRACE("Painter::_FillPathGradientLinear\n"); + + BPoint start = linear.Start(); + BPoint end = linear.End(); + + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::pod_auto_array color_array_type; + typedef agg::span_allocator span_allocator_type; + typedef agg::gradient_x gradient_func_type; + typedef agg::span_gradient span_gradient_type; + typedef agg::renderer_scanline_aa renderer_gradient_type; + + gradient_func_type gradientFunc; + agg::trans_affine gradientMtx; + interpolator_type spanInterpolator(gradientMtx); + span_allocator_type spanAllocator; + color_array_type colorArray; + + _MakeGradient(colorArray, linear); + + span_gradient_type spanGradient(spanInterpolator, gradientFunc, + colorArray, 0, 100); + + renderer_gradient_type gradientRenderer(fBaseRenderer, spanAllocator, + spanGradient); + + _CalcLinearGradientTransform(start, end, gradientMtx); + + fRasterizer.reset(); + fRasterizer.add_path(path); + agg::render_scanlines(fRasterizer, fPackedScanline, gradientRenderer); +} + +// _FillPathGradientRadial +template +void +Painter::_FillPathGradientRadial(VertexSource& path, + const BGradientRadial& radial) const +{ + GTRACE("Painter::_FillPathGradientRadial\n"); + + BPoint center = radial.Center(); + float radius = radial.Radius(); + + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::pod_auto_array color_array_type; + typedef agg::span_allocator span_allocator_type; + typedef agg::gradient_radial gradient_func_type; + typedef agg::span_gradient span_gradient_type; + typedef agg::renderer_scanline_aa renderer_gradient_type; + + gradient_func_type gradientFunc; + agg::trans_affine gradientMtx; + interpolator_type spanInterpolator(gradientMtx); + span_allocator_type spanAllocator; + color_array_type colorArray; + + _MakeGradient(colorArray, radial); + + span_gradient_type spanGradient(spanInterpolator, gradientFunc, + colorArray, 0, 100); + + renderer_gradient_type gradientRenderer(fBaseRenderer, spanAllocator, + spanGradient); + + gradientMtx.reset(); + gradientMtx *= agg::trans_affine_translation(center.x, center.y); + gradientMtx.invert(); + +// _CalcLinearGradientTransform(start, end, gradientMtx); + + fRasterizer.reset(); + fRasterizer.add_path(path); + agg::render_scanlines(fRasterizer, fPackedScanline, gradientRenderer); +} + +// _FillPathGradientRadialFocus +template +void +Painter::_FillPathGradientRadialFocus(VertexSource& path, + const BGradientRadialFocus& focus) const +{ + GTRACE("Painter::_FillPathGradientRadialFocus\n"); + + BPoint center = focus.Center(); + BPoint focal = focus.Focal(); + float radius = focus.Radius(); + + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::pod_auto_array color_array_type; + typedef agg::span_allocator span_allocator_type; + typedef agg::gradient_radial_focus gradient_func_type; + typedef agg::span_gradient span_gradient_type; + typedef agg::renderer_scanline_aa renderer_gradient_type; + + gradient_func_type gradientFunc; + agg::trans_affine gradientMtx; + interpolator_type spanInterpolator(gradientMtx); + span_allocator_type spanAllocator; + color_array_type colorArray; + + _MakeGradient(colorArray, focus); + + span_gradient_type spanGradient(spanInterpolator, gradientFunc, + colorArray, 0, 100); + + renderer_gradient_type gradientRenderer(fBaseRenderer, spanAllocator, + spanGradient); + + gradientMtx.reset(); + gradientMtx *= agg::trans_affine_translation(center.x, center.y); + gradientMtx.invert(); + + // _CalcLinearGradientTransform(start, end, gradientMtx); + + fRasterizer.reset(); + fRasterizer.add_path(path); + agg::render_scanlines(fRasterizer, fPackedScanline, gradientRenderer); +} + +// _FillPathGradientDiamond +template +void +Painter::_FillPathGradientDiamond(VertexSource& path, + const BGradientDiamond& diamond) const +{ + GTRACE("Painter::_FillPathGradientDiamond\n"); + + BPoint center = diamond.Center(); +// float radius = diamond.Radius(); + + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::pod_auto_array color_array_type; + typedef agg::span_allocator span_allocator_type; + typedef agg::gradient_diamond gradient_func_type; + typedef agg::span_gradient span_gradient_type; + typedef agg::renderer_scanline_aa renderer_gradient_type; + + gradient_func_type gradientFunc; + agg::trans_affine gradientMtx; + interpolator_type spanInterpolator(gradientMtx); + span_allocator_type spanAllocator; + color_array_type colorArray; + + _MakeGradient(colorArray, diamond); + + span_gradient_type spanGradient(spanInterpolator, gradientFunc, + colorArray, 0, 100); + + renderer_gradient_type gradientRenderer(fBaseRenderer, spanAllocator, + spanGradient); + + gradientMtx.reset(); + gradientMtx *= agg::trans_affine_translation(center.x, center.y); + gradientMtx.invert(); + + // _CalcLinearGradientTransform(start, end, gradientMtx); + + fRasterizer.reset(); + fRasterizer.add_path(path); + agg::render_scanlines(fRasterizer, fPackedScanline, gradientRenderer); +} + +// _FillPathGradientConic +template +void +Painter::_FillPathGradientConic(VertexSource& path, + const BGradientConic& conic) const +{ + GTRACE("Painter::_FillPathGradientConic\n"); + + BPoint center = conic.Center(); +// float radius = conic.Radius(); + + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::pod_auto_array color_array_type; + typedef agg::span_allocator span_allocator_type; + typedef agg::gradient_conic gradient_func_type; + typedef agg::span_gradient span_gradient_type; + typedef agg::renderer_scanline_aa renderer_gradient_type; + + gradient_func_type gradientFunc; + agg::trans_affine gradientMtx; + interpolator_type spanInterpolator(gradientMtx); + span_allocator_type spanAllocator; + color_array_type colorArray; + + _MakeGradient(colorArray, conic); + + span_gradient_type spanGradient(spanInterpolator, gradientFunc, + colorArray, 0, 100); + + renderer_gradient_type gradientRenderer(fBaseRenderer, spanAllocator, + spanGradient); + + gradientMtx.reset(); + gradientMtx *= agg::trans_affine_translation(center.x, center.y); + gradientMtx.invert(); + + // _CalcLinearGradientTransform(start, end, gradientMtx); + + fRasterizer.reset(); + fRasterizer.add_path(path); + agg::render_scanlines(fRasterizer, fPackedScanline, gradientRenderer); +} diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index 6d25cc3421..7000edfdd5 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -26,6 +26,12 @@ class BBitmap; class BRegion; +class BGradient; +class BGradientLinear; +class BGradientRadial; +class BGradientRadialFocus; +class BGradientDiamond; +class BGradientConic; class DrawState; class FontCacheReference; class RenderingBuffer; @@ -101,16 +107,25 @@ class Painter { BRect FillTriangle( BPoint pt1, BPoint pt2, BPoint pt3) const; - + BRect FillTriangleGradient(BPoint pt1, BPoint pt2, + BPoint pt3, + const BGradient& gradient) const; + // polygons BRect DrawPolygon( BPoint* ptArray, int32 numPts, bool filled, bool closed) const; - + BRect FillPolygonGradient(BPoint* ptArray, + int32 numPts, + const BGradient& gradient, + bool closed) const; + // bezier curves BRect DrawBezier( BPoint* controlPoints, bool filled) const; + BRect FillBezierGradient(BPoint* controlPoints, + const BGradient& gradient) const; // shapes BRect DrawShape( const int32& opCount, @@ -118,7 +133,12 @@ class Painter { const int32& ptCount, const BPoint* ptList, bool filled) const; - + BRect FillShapeGradient(const int32& opCount, + const uint32* opList, + const int32& ptCount, + const BPoint* ptList, + const BGradient& gradient) const; + // rects BRect StrokeRect( const BRect& r) const; @@ -127,6 +147,8 @@ class Painter { const rgb_color& c) const; BRect FillRect( const BRect& r) const; + BRect FillRectGradient(const BRect& r, + const BGradient& gradient) const; // fills a solid rect with color c, no blending void FillRect( const BRect& r, @@ -143,13 +165,19 @@ class Painter { BRect FillRoundRect( const BRect& r, float xRadius, float yRadius) const; - + BRect FillRoundRectGradient(const BRect& r, + float xRadius, + float yRadius, + const BGradient& gradient) const; + // ellipses void AlignEllipseRect(BRect* rect, bool filled) const; BRect DrawEllipse( BRect r, bool filled) const; + BRect FillEllipseGradient(BRect r, + const BGradient& gradient) const; // arcs BRect StrokeArc( BPoint center, @@ -163,7 +191,13 @@ class Painter { float yRadius, float angle, float span) const; - + BRect FillArcGradient(BPoint center, + float xRadius, + float yRadius, + float angle, + float span, + const BGradient& gradient) const; + // strings BRect DrawString( const char* utf8String, uint32 length, @@ -191,6 +225,8 @@ class Painter { // some convenience stuff BRect FillRegion( const BRegion* region) const; + BRect FillRegionGradient(const BRegion* region, + const BGradient& gradient) const; BRect InvertRect( const BRect& r) const; @@ -265,7 +301,31 @@ class Painter { BRect _StrokePath(VertexSource& path) const; template BRect _FillPath(VertexSource& path) const; - + void _CalcLinearGradientTransform(BPoint startPoint, + BPoint endPoint, agg::trans_affine& mtx, + float gradient_d2 = 100.0f) const; + template + void _MakeGradient(Array& array, + const BGradient& gradient) const; + template + BRect _FillPathGradient(VertexSource& path, + const BGradient& gradient) const; + template + void _FillPathGradientLinear(VertexSource& path, + const BGradientLinear& linear) const; + template + void _FillPathGradientRadial(VertexSource& path, + const BGradientRadial& radial) const; + template + void _FillPathGradientRadialFocus(VertexSource& path, + const BGradientRadialFocus& focus) const; + template + void _FillPathGradientDiamond(VertexSource& path, + const BGradientDiamond& diamond) const; + template + void _FillPathGradientConic(VertexSource& path, + const BGradientConic& conic) const; + mutable agg::rendering_buffer fBuffer; // AGG rendering and rasterization classes diff --git a/src/servers/app/drawing/Painter/defines.h b/src/servers/app/drawing/Painter/defines.h index f0420b0808..ae11074fd0 100644 --- a/src/servers/app/drawing/Painter/defines.h +++ b/src/servers/app/drawing/Painter/defines.h @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include #include "agg_rasterizer_scanline_aa_subpix.h" @@ -68,7 +71,6 @@ typedef agg::rasterizer_scanline_aa<> rasterizer_type; typedef agg::rasterizer_scanline_aa_subpix<> rasterizer_subpix_type; - #endif // DEFINES_H