BGradient: add Flatten, Unflatten methods

Change-Id: I861bab8ae19628d34297c294fd6ce3e5b6c82b34
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2827
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
X512 2020-05-28 09:25:21 +09:00 committed by Adrien Destugues
parent 4399ec510d
commit 36ef16bf08
3 changed files with 171 additions and 18 deletions

View File

@ -11,6 +11,7 @@
#include <List.h>
class BDataIO;
class BMessage;
class BRect;
@ -39,9 +40,9 @@ public:
ColorStop(uint8 r, uint8 g, uint8 b, uint8 a, float o);
ColorStop(const ColorStop& other);
ColorStop();
bool operator!=(const ColorStop& other) const;
rgb_color color;
float offset;
};
@ -50,42 +51,45 @@ 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 ColorStopsAreEqual(
const BGradient& other) const;
void SetColorStops(const BGradient& other);
int32 AddColor(const rgb_color& color,
float offset);
bool AddColorStop(const ColorStop& colorStop,
int32 index);
bool RemoveColor(int32 index);
bool SetColorStop(int32 index,
const ColorStop& colorStop);
bool SetColor(int32 index, const rgb_color& color);
bool SetOffset(int32 index, float offset);
int32 CountColorStops() const;
ColorStop* ColorStopAt(int32 index) const;
ColorStop* ColorStopAtFast(int32 index) const;
ColorStop* ColorStops() const;
void SortColorStopsByOffset();
Type GetType() const
{ return fType; }
void MakeEmpty();
status_t Flatten(BDataIO* stream) const;
static status_t Unflatten(BGradient *&output, BDataIO* stream);
private:
friend class BGradientLinear;
friend class BGradientRadial;

View File

@ -9,6 +9,11 @@ USES_BE_API on <libbe_build>interface_kit.o = true ;
BuildPlatformMergeObjectPIC <libbe_build>interface_kit.o :
Bitmap.cpp
Gradient.cpp
GradientLinear.cpp
GradientRadial.cpp
GradientRadialFocus.cpp
GradientDiamond.cpp
GradientConic.cpp
GraphicsDefs.cpp
Point.cpp
Rect.cpp

View File

@ -13,8 +13,16 @@
#include <math.h>
#include <stdio.h>
#include <DataIO.h>
#include <Message.h>
#include <AutoDeleter.h>
#include <GradientLinear.h>
#include <GradientRadial.h>
#include <GradientRadialFocus.h>
#include <GradientDiamond.h>
#include <GradientConic.h>
// constructor
BGradient::ColorStop::ColorStop(const rgb_color c, float o)
@ -195,7 +203,7 @@ BGradient::Archive(BMessage* into, bool deep) const
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);
@ -203,7 +211,7 @@ BGradient::Archive(BMessage* into, bool deep) const
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);
@ -215,7 +223,7 @@ BGradient::Archive(BMessage* into, bool deep) const
ret = into->AddFloat("radial_f_fy", (float)fData.radial_focus.fy);
if (ret >= B_OK)
ret = into->AddFloat("radial_f_radius", (float)fData.radial_focus.radius);
// diamond
if (ret >= B_OK)
ret = into->AddFloat("diamond_cx", (float)fData.diamond.cx);
@ -229,11 +237,11 @@ BGradient::Archive(BMessage* into, bool deep) const
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;
}
@ -271,7 +279,7 @@ BGradient::ColorStopsAreEqual(const BGradient& other) const
int32 count = CountColorStops();
if (count == other.CountColorStops() &&
fType == other.fType) {
bool equal = true;
for (int32 i = 0; i < count; i++) {
ColorStop* ourStop = ColorStopAtFast(i);
@ -447,3 +455,139 @@ BGradient::MakeEmpty()
delete ColorStopAtFast(i);
fColorStops.MakeEmpty();
}
status_t
BGradient::Flatten(BDataIO* stream) const
{
int32 stopCount = CountColorStops();
stream->Write(&fType, sizeof(Type));
stream->Write(&stopCount, sizeof(int32));
if (stopCount > 0) {
for (int i = 0; i < stopCount; i++) {
stream->Write(ColorStopAtFast(i),
sizeof(ColorStop));
}
}
switch (fType) {
case TYPE_LINEAR:
stream->Write(&fData.linear.x1, sizeof(float));
stream->Write(&fData.linear.y1, sizeof(float));
stream->Write(&fData.linear.x2, sizeof(float));
stream->Write(&fData.linear.y2, sizeof(float));
break;
case TYPE_RADIAL:
stream->Write(&fData.radial.cx, sizeof(float));
stream->Write(&fData.radial.cy, sizeof(float));
stream->Write(&fData.radial.radius, sizeof(float));
break;
case TYPE_RADIAL_FOCUS:
stream->Write(&fData.radial_focus.cx, sizeof(float));
stream->Write(&fData.radial_focus.cy, sizeof(float));
stream->Write(&fData.radial_focus.fx, sizeof(float));
stream->Write(&fData.radial_focus.fy, sizeof(float));
stream->Write(&fData.radial_focus.radius, sizeof(float));
break;
case TYPE_DIAMOND:
stream->Write(&fData.diamond.cx, sizeof(float));
stream->Write(&fData.diamond.cy, sizeof(float));
break;
case TYPE_CONIC:
stream->Write(&fData.conic.cx, sizeof(float));
stream->Write(&fData.conic.cy, sizeof(float));
stream->Write(&fData.conic.angle, sizeof(float));
break;
case TYPE_NONE:
break;
}
return B_OK;
}
static BGradient*
gradient_for_type(BGradient::Type type)
{
switch (type) {
case BGradient::TYPE_LINEAR:
return new (std::nothrow) BGradientLinear();
case BGradient::TYPE_RADIAL:
return new (std::nothrow) BGradientRadial();
case BGradient::TYPE_RADIAL_FOCUS:
return new (std::nothrow) BGradientRadialFocus();
case BGradient::TYPE_DIAMOND:
return new (std::nothrow) BGradientDiamond();
case BGradient::TYPE_CONIC:
return new (std::nothrow) BGradientConic();
case BGradient::TYPE_NONE:
return new (std::nothrow) BGradient();
}
return NULL;
}
status_t
BGradient::Unflatten(BGradient *&output, BDataIO* stream)
{
output = NULL;
Type gradientType;
int32 colorsCount;
stream->Read(&gradientType, sizeof(Type));
status_t status = stream->Read(&colorsCount, sizeof(int32));
if (status < B_OK)
return status;
ObjectDeleter<BGradient> gradient(gradient_for_type(gradientType));
if (gradient.Get() == NULL)
return B_NO_MEMORY;
if (colorsCount > 0) {
ColorStop stop;
for (int i = 0; i < colorsCount; i++) {
if ((status = stream->Read(&stop, sizeof(ColorStop))) < B_OK)
return status;
if (!gradient->AddColorStop(stop, i))
return B_NO_MEMORY;
}
}
switch (gradientType) {
case TYPE_LINEAR:
stream->Read(&gradient->fData.linear.x1, sizeof(float));
stream->Read(&gradient->fData.linear.y1, sizeof(float));
stream->Read(&gradient->fData.linear.x2, sizeof(float));
if ((status = stream->Read(&gradient->fData.linear.y2, sizeof(float))) < B_OK)
return status;
break;
case TYPE_RADIAL:
stream->Read(&gradient->fData.radial.cx, sizeof(float));
stream->Read(&gradient->fData.radial.cy, sizeof(float));
if ((stream->Read(&gradient->fData.radial.radius, sizeof(float))) < B_OK)
return status;
break;
case TYPE_RADIAL_FOCUS:
stream->Read(&gradient->fData.radial_focus.cx, sizeof(float));
stream->Read(&gradient->fData.radial_focus.cy, sizeof(float));
stream->Read(&gradient->fData.radial_focus.fx, sizeof(float));
stream->Read(&gradient->fData.radial_focus.fy, sizeof(float));
if ((stream->Read(&gradient->fData.radial_focus.radius, sizeof(float))) < B_OK)
return status;
break;
case TYPE_DIAMOND:
stream->Read(&gradient->fData.diamond.cx, sizeof(float));
if ((stream->Read(&gradient->fData.diamond.cy, sizeof(float))) < B_OK)
return status;
break;
case TYPE_CONIC:
stream->Read(&gradient->fData.conic.cx, sizeof(float));
stream->Read(&gradient->fData.conic.cy, sizeof(float));
if ((stream->Read(&gradient->fData.conic.angle, sizeof(float))) < B_OK)
return status;
break;
case TYPE_NONE:
break;
}
output = gradient.Detach();
return B_OK;
}