Merge pull request 'fix/Tensor-luminosity-gradient' (#326) from fix/Tensor-luminosity-gradient into release/v9.0.0

Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/core/pulls/326
This commit is contained in:
Oleg Korshul
2025-05-27 18:38:41 +00:00
10 changed files with 479 additions and 102 deletions

View File

@ -416,6 +416,16 @@ namespace agg
{ {
return self_type(rgba::from_wavelength(wl, gamma)); return self_type(rgba::from_wavelength(wl, gamma));
} }
bool operator==(const self_type& other)
{
return a == other.a && r == other.r && g == other.g && b == other.b;
}
bool operator!=(const self_type& other)
{
return !operator==(other);
}
}; };

View File

@ -1000,7 +1000,17 @@ namespace agg
{ {
if (i < RES && j < RES) if (i < RES && j < RES)
{ {
precalc[i][j] = c; if (m_oGradientInfo.luminocity)
{
ColorT fillC;
fillC.r = m_oGradientInfo.shading.fill_color.r * c.r / 255 + 255 - c.r;
fillC.g = m_oGradientInfo.shading.fill_color.g * c.g / 255 + 255 - c.g;
fillC.b = m_oGradientInfo.shading.fill_color.b * c.b / 255 + 255 - c.b;
fillC.a = 255;
precalc[i][j] = fillC;
}
else
precalc[i][j] = c;
} }
} }
} }

View File

@ -1020,22 +1020,39 @@ void CBooleanOperations::TracePaths()
{ {
size_t length = Segments1.size(); size_t length = Segments1.size();
Result.StartFigure(); Result.StartFigure();
bool first_start = true;
for (size_t i = 0; i < length + Segments2.size(); i++) for (size_t i = 0; i < length + Segments2.size(); i++)
{ {
Segment s = i >= length ? Segments2[i - length] : Segments1[i]; Segment s = i >= length ? Segments2[i - length] : Segments1[i];
bool valid = s.IsValid(Op), bool valid = s.IsValid(Op),
start = true; start = true;
PointD start_point;
while (valid) while (valid)
{ {
if (!start || (Op == Intersection && s.Inters && !GetNextSegment(s).Inters)) if (!start || (Op == Intersection && s.Inters && !GetNextSegment(s).Inters))
SetVisited(s); SetVisited(s);
if (start) if (first_start)
{
Result.MoveTo(s.P.X, s.P.Y); Result.MoveTo(s.P.X, s.P.Y);
start_point = s.P;
}
else if (start)
{
double x, y;
Result.GetLastPoint(x, y);
if (isZero(start_point.X - x) && isZero(start_point.Y - y))
{
Result.MoveTo(s.P.X, s.P.Y);
start_point = s.P;
}
else
Result.LineTo(s.P.X, s.P.Y);
}
else if (s.IsCurve) else if (s.IsCurve)
Result.CurveTo(s.HI.X + s.P.X, s.HI.Y + s.P.Y, Result.CurveTo(s.HI.X + s.P.X, s.HI.Y + s.P.Y,
s.HO.X + s.P.X, s.HO.Y + s.P.Y, s.HO.X + s.P.X, s.HO.Y + s.P.Y,
s.P.X, s.P.Y); s.P.X, s.P.Y);
else else
Result.LineTo(s.P.X, s.P.Y); Result.LineTo(s.P.X, s.P.Y);
@ -1065,6 +1082,9 @@ void CBooleanOperations::TracePaths()
if (start) if (start)
start = false; start = false;
if (first_start)
first_start = false;
} }
if (!start && AllOverlap()) break; if (!start && AllOverlap()) break;
@ -1645,12 +1665,14 @@ int CBooleanOperations::CheckInters(const PointD& point, const Segment& segment,
std::vector<double> roots = curve.GetCurveLineIntersection(segment.P.X,segment.P.Y, point.X - segment.P.X, point.Y - segment.P.Y); std::vector<double> roots = curve.GetCurveLineIntersection(segment.P.X,segment.P.Y, point.X - segment.P.X, point.Y - segment.P.Y);
Curve line(segment, Segment(point)); Curve line(segment, Segment(point));
int count = 0; return roots.size() % 2;
for (const auto& r : roots)
if (line.GetTimeOf(curve.GetPoint(r)) != -1)
count++;
return count; // int count = 0;
// for (const auto& r : roots)
// if (line.GetTimeOf(curve.GetPoint(r)) != -1)
// count++;
// return count;
} }
return 0; return 0;
} }

View File

@ -863,20 +863,22 @@ namespace Aggplus
double CGraphicsPath::GetArea(unsigned idx, bool isCurve) const noexcept double CGraphicsPath::GetArea(unsigned idx, bool isCurve) const noexcept
{ {
float area; double area;
if (isCurve) if (isCurve)
{ {
std::vector<PointD> points = GetPoints(idx, 4); std::vector<PointD> points = GetPoints(idx, 4);
area = 3 * ((points[3].Y - points[0].Y) * (points[1].X + points[2].X) area = (points[3].Y - points[0].Y) * (points[1].X + points[2].X)
- (points[3].X - points[0].X) * (points[1].Y * points[2].Y) - (points[3].X - points[0].X) * (points[1].Y + points[2].Y)
+ points[1].Y * (points[0].X - points[2].X) + points[1].Y * (points[0].X - points[2].X)
- points[1].X * (points[0].Y - points[2].Y) - points[1].X * (points[0].Y - points[2].Y)
+ points[3].Y * (points[2].X + points[0].X / 3) + points[3].Y * (points[2].X + points[0].X / 3.0)
- points[3].X * (points[2].Y - points[0].Y / 3)) / 20; - points[3].X * (points[2].Y + points[0].Y / 3.0);
}
else
{
std::vector<PointD> points = GetPoints(idx, 2);
area = 4.0 * (points[1].Y * points[0].X - points[1].X * points[0].Y) / 3.0;
} }
std::vector<PointD> points = GetPoints(idx, 2);
area = (points[1].Y * points[0].X - points[1].X * points[0].Y) / 20;
return area; return area;
} }

View File

@ -371,6 +371,7 @@ namespace NSStructures
* *
* Наверное напишу адаптор который переводит порядок точек из 6 типа в общий. * Наверное напишу адаптор который переводит порядок точек из 6 типа в общий.
*/ */
agg::rgba8 fill_color;
std::vector<std::vector<Point>> patch; std::vector<std::vector<Point>> patch;
std::vector<std::vector<agg::rgba8>> patch_colors; // 2 на 2 цвета по углам std::vector<std::vector<agg::rgba8>> patch_colors; // 2 на 2 цвета по углам
std::vector<std::vector<float>> patch_parameters; // 2 на 2 параметра std::vector<std::vector<float>> patch_parameters; // 2 на 2 параметра
@ -388,8 +389,8 @@ namespace NSStructures
xsize(1.0f), ysize(1.0f), xsize(1.0f), ysize(1.0f),
linstretch(1.0f), linoffset(0.0f), linstretch(1.0f), linoffset(0.0f),
continue_shading_f(false), continue_shading_f(false),
continue_shading_b(false) continue_shading_b(false),
luminocity(false)
{ {
} }
void setAngleDegrees(float deg) void setAngleDegrees(float deg)
@ -404,6 +405,57 @@ namespace NSStructures
{ {
discrete_step = 1.0f / n; discrete_step = 1.0f / n;
} }
bool checkLuminosity() const
{
if (shading.patch_colors.empty())
return false;
for (const auto& ar : shading.patch_colors)
for (const auto& c : ar)
if (c.r != c.g || c.g != c.b)
return false;
return true;
}
bool colorEqual(const agg::rgba8& c1, const agg::rgba8& c2) const
{
return c1.r == c2.r &&
c1.g == c2.g &&
c1.b == c2.b &&
c1.a == c2.a;
}
bool isOneColor() const
{
switch (shading.shading_type)
{
case ShadingInfo::FunctionOnly:
case ShadingInfo::Parametric:
return false;
case ShadingInfo::TriangleInterpolation:
return colorEqual(shading.triangle_colors[0], shading.triangle_colors[1]) &&
colorEqual(shading.triangle_colors[1], shading.triangle_colors[2]);
case ShadingInfo::CurveInterpolation:
case ShadingInfo::TensorCurveInterpolation:
return colorEqual(shading.patch_colors[0][0], shading.patch_colors[0][1]) &&
colorEqual(shading.patch_colors[0][1], shading.patch_colors[1][0]) &&
colorEqual(shading.patch_colors[1][0], shading.patch_colors[1][1]);
default:
return false;
}
}
agg::rgba8 getFillColor() const
{
if (!shading.triangle_colors.empty())
return shading.triangle_colors[0];
if (!shading.patch_colors.empty())
return shading.patch_colors[0][0];
return agg::rgba8(0, 0, 0);
}
void setFillColor(const agg::rgba8& color)
{
shading.fill_color = color;
luminocity = true;
}
void transform(const Aggplus::CMatrix& matrix) void transform(const Aggplus::CMatrix& matrix)
{ {
// shading transform // shading transform
@ -502,6 +554,7 @@ namespace NSStructures
float linstretch; // stretch linear gradient, can be negative (eq angle = 180) can not be zero float linstretch; // stretch linear gradient, can be negative (eq angle = 180) can not be zero
float linoffset; // offset relative to image size float linoffset; // offset relative to image size
float continue_shading_b, continue_shading_f; float continue_shading_b, continue_shading_f;
bool luminocity;
ShadingInfo shading; ShadingInfo shading;
}; };
@ -643,6 +696,7 @@ namespace NSStructures
const std::vector<std::vector<float>> &curve_parametrs, const std::vector<std::vector<float>> &curve_parametrs,
const std::vector<std::vector<agg::rgba8>> &curve_colors, const std::vector<std::vector<agg::rgba8>> &curve_colors,
bool parametric, bool parametric,
bool luminosity = false,
float t0 = 0.0f, float t1 = 1.0f) float t0 = 0.0f, float t1 = 1.0f)
{ {
GradientInfo ginfo; GradientInfo ginfo;
@ -651,6 +705,7 @@ namespace NSStructures
ginfo.shading.f_type = ShadingInfo::UseNew; ginfo.shading.f_type = ShadingInfo::UseNew;
ginfo.shading.function = ColorFunction<agg::rgba8>(256, t0, t1); ginfo.shading.function = ColorFunction<agg::rgba8>(256, t0, t1);
ginfo.luminocity = luminosity;
ginfo.continue_shading_f = false; ginfo.continue_shading_f = false;
ginfo.continue_shading_b = false; ginfo.continue_shading_b = false;

View File

@ -32,7 +32,7 @@ namespace NSDocxRenderer
} }
else if (lType == c_nClipType) else if (lType == c_nClipType)
{ {
// closing clip path if non-closed //closing clip path if non-closed
if (!m_oCurrVectorGraphics.IsEmpty() && m_oCurrVectorGraphics.GetData().back().type != CVectorGraphics::ePathCommandType::pctClose) if (!m_oCurrVectorGraphics.IsEmpty() && m_oCurrVectorGraphics.GetData().back().type != CVectorGraphics::ePathCommandType::pctClose)
m_oCurrVectorGraphics.Add({CVectorGraphics::ePathCommandType::pctClose, {}}); m_oCurrVectorGraphics.Add({CVectorGraphics::ePathCommandType::pctClose, {}});
@ -44,6 +44,9 @@ namespace NSDocxRenderer
else else
m_oClipVectorGraphics = std::move(m_oCurrVectorGraphics); m_oClipVectorGraphics = std::move(m_oCurrVectorGraphics);
} }
if (!m_arLuminosityShapes.empty() && !m_arOneColorGradientShape.empty())
FillLuminosityShapes();
} }
void CPage::Clear() void CPage::Clear()
@ -66,6 +69,7 @@ namespace NSDocxRenderer
m_oCurrVectorGraphics.Clear(); m_oCurrVectorGraphics.Clear();
m_oClipVectorGraphics.Clear(); m_oClipVectorGraphics.Clear();
m_arCompleteObjectsXml.clear(); m_arCompleteObjectsXml.clear();
m_arLuminosityShapes.clear();
} }
CPage::~CPage() CPage::~CPage()
@ -227,84 +231,31 @@ namespace NSDocxRenderer
} }
shape->SetVector(std::move(m_oCurrVectorGraphics)); shape->SetVector(std::move(m_oCurrVectorGraphics));
bool skip_shape = false;
auto info = pInfo; auto info = pInfo;
if (!info && m_bIsGradient) if (!info && m_bIsGradient)
{ {
// image with gradient must be closed if (m_oBrush.m_oGradientInfo.checkLuminosity())
if (!shape->m_oVector.IsEmpty() && shape->m_oVector.GetData().back().type != CVectorGraphics::ePathCommandType::pctClose) m_arLuminosityShapes.push_back(shape);
shape->m_oVector.Add({CVectorGraphics::ePathCommandType::pctClose, {}}); else if (m_oBrush.m_oGradientInfo.isOneColor())
{
long width_pix = static_cast<long>(shape->m_dWidth * c_dMMToPix); m_arOneColorGradientShape.push_back(shape);
long height_pix = static_cast<long>(shape->m_dHeight * c_dMMToPix); skip_shape = true;
}
if (width_pix == 0) width_pix = 1; else
if (height_pix == 0) height_pix = 1; DrawGradient(shape);
const long step = 4;
const long stride = -step * width_pix;
std::unique_ptr<CBgraFrame> frame(new CBgraFrame());
size_t data_size = width_pix * height_pix * step;
BYTE* data = new BYTE[data_size];
// white and alpha is min (full transparent)
for (size_t i = 0; i < width_pix * height_pix; ++i)
reinterpret_cast<unsigned int*>(data)[i] = 0x00ffffff;
frame->put_Data(data);
frame->put_Height(height_pix);
frame->put_Width(width_pix);
frame->put_Stride(stride);
auto shifted_vector = shape->m_oVector;
Aggplus::CMatrix transform_matrix;
transform_matrix.Translate(-shifted_vector.GetLeft(), -shifted_vector.GetTop());
shifted_vector.Transform(transform_matrix);
NSStructures::CBrush shifted_brush = m_oBrush;
shifted_brush.Bounds.left = shifted_vector.GetLeft();
shifted_brush.Bounds.right = shifted_vector.GetRight();
shifted_brush.Bounds.bottom = shifted_vector.GetBottom();
shifted_brush.Bounds.top = shifted_vector.GetTop();
shifted_brush.m_oGradientInfo.transform(transform_matrix);
NSGraphics::IGraphicsRenderer* g_renderer = NSGraphics::Create();
g_renderer->CreateFromBgraFrame(frame.get());
g_renderer->SetSwapRGB(false);
g_renderer->put_Width(shape->m_dWidth);
g_renderer->put_Height(shape->m_dHeight);
g_renderer->RestoreBrush(shifted_brush);
g_renderer->RestorePen(m_oPen);
g_renderer->BeginCommand(c_nPathType);
shifted_vector.DrawOnRenderer(g_renderer);
g_renderer->DrawPath(c_nWindingFillMode);
g_renderer->EndCommand(c_nPathType);
Aggplus::CImage img;
img.Create(data, width_pix, height_pix, stride, true);
info = m_oManagers.pImageManager->WriteImage(&img, shape->m_dTop, shape->m_dBaselinePos, shape->m_dWidth, shape->m_dHeight);
rotation = 0;
image_vector = shape->m_oVector;
m_bIsGradient = false; m_bIsGradient = false;
RELEASEINTERFACE(g_renderer)
} }
shape->m_dRotation = rotation; else if (info)
if (info)
{ {
shape->m_pImageInfo = info; shape->m_dRotation = rotation;
shape->m_eType = CShape::eShapeType::stVectorTexture; DrawImage(shape, info, image_vector);
image_vector.RotateAt(-shape->m_dRotation, shape->m_oVector.GetCenter());
shape->m_dImageBot = image_vector.GetBottom();
shape->m_dImageTop = image_vector.GetTop();
shape->m_dImageLeft = image_vector.GetLeft();
shape->m_dImageRight = image_vector.GetRight();
} }
else else
shape->m_eType = CShape::eShapeType::stVectorGraphics; shape->m_eType = CShape::eShapeType::stVectorGraphics;
if (!shape->IsOoxmlValid()) if (!shape->IsOoxmlValid())
return; return;
@ -314,8 +265,11 @@ namespace NSDocxRenderer
shape->m_oBrush.Color1 == c_iWhiteColor) shape->m_oBrush.Color1 == c_iWhiteColor)
return; return;
shape->m_nOrder = ++m_nShapeOrder; if (!skip_shape)
m_arShapes.push_back(shape); {
shape->m_nOrder = ++m_nShapeOrder;
m_arShapes.push_back(shape);
}
} }
void CPage::AddText( void CPage::AddText(
@ -2155,4 +2109,127 @@ namespace NSDocxRenderer
else else
oWriter.WriteString(L"<w:pgMar w:top=\"0\" w:right=\"0\" w:bottom=\"0\" w:left=\"0\" w:header=\"0\" w:footer=\"0\" w:gutter=\"0\"/></w:sectPr>"); oWriter.WriteString(L"<w:pgMar w:top=\"0\" w:right=\"0\" w:bottom=\"0\" w:left=\"0\" w:header=\"0\" w:footer=\"0\" w:gutter=\"0\"/></w:sectPr>");
} }
void CPage::DrawImage(shape_ptr_t pShape, std::shared_ptr<CImageInfo> oImgInfo, CVectorGraphics& imageVector)
{
pShape->m_pImageInfo = oImgInfo;
pShape->m_eType = CShape::eShapeType::stVectorTexture;
imageVector.RotateAt(-pShape->m_dRotation, pShape->m_oVector.GetCenter());
pShape->m_dImageBot = imageVector.GetBottom();
pShape->m_dImageTop = imageVector.GetTop();
pShape->m_dImageLeft = imageVector.GetLeft();
pShape->m_dImageRight = imageVector.GetRight();
}
void CPage::DrawGradient(shape_ptr_t pShape)
{
// image with gradient must be closed
if (!pShape->m_oVector.IsEmpty() && pShape->m_oVector.GetData().back().type != CVectorGraphics::ePathCommandType::pctClose)
pShape->m_oVector.Add({CVectorGraphics::ePathCommandType::pctClose, {}});
long width_pix = static_cast<long>(pShape->m_dWidth * c_dMMToPix);
long height_pix = static_cast<long>(pShape->m_dHeight * c_dMMToPix);
if (width_pix == 0) width_pix = 1;
if (height_pix == 0) height_pix = 1;
const long step = 4;
const long stride = -step * width_pix;
std::unique_ptr<CBgraFrame> frame(new CBgraFrame());
size_t data_size = width_pix * height_pix * step;
BYTE* data = new BYTE[data_size];
// white and alpha is min (full transparent)
for (size_t i = 0; i < width_pix * height_pix; ++i)
reinterpret_cast<unsigned int*>(data)[i] = 0x00ffffff;
frame->put_Data(data);
frame->put_Height(height_pix);
frame->put_Width(width_pix);
frame->put_Stride(stride);
auto shifted_vector = pShape->m_oVector;
Aggplus::CMatrix transform_matrix;
transform_matrix.Translate(-shifted_vector.GetLeft(), -shifted_vector.GetTop());
shifted_vector.Transform(transform_matrix);
NSStructures::CBrush shifted_brush = pShape->m_oBrush;
shifted_brush.Bounds.left = shifted_vector.GetLeft();
shifted_brush.Bounds.right = shifted_vector.GetRight();
shifted_brush.Bounds.bottom = shifted_vector.GetBottom();
shifted_brush.Bounds.top = shifted_vector.GetTop();
shifted_brush.m_oGradientInfo.transform(transform_matrix);
NSGraphics::IGraphicsRenderer* g_renderer = NSGraphics::Create();
g_renderer->CreateFromBgraFrame(frame.get());
g_renderer->SetSwapRGB(false);
g_renderer->put_Width(pShape->m_dWidth);
g_renderer->put_Height(pShape->m_dHeight);
g_renderer->RestoreBrush(shifted_brush);
g_renderer->RestorePen(m_oPen);
g_renderer->BeginCommand(c_nPathType);
shifted_vector.DrawOnRenderer(g_renderer);
g_renderer->DrawPath(c_nWindingFillMode);
g_renderer->EndCommand(c_nPathType);
Aggplus::CImage img;
img.Create(data, width_pix, height_pix, stride, true);
auto info = m_oManagers.pImageManager->WriteImage(&img, pShape->m_dTop, pShape->m_dBaselinePos, pShape->m_dWidth, pShape->m_dHeight);
pShape->m_dRotation = 0;
DrawImage(pShape, info, pShape->m_oVector);
RELEASEINTERFACE(g_renderer)
}
agg::rgba8 CPage::GetFillColor()
{
bool is_one = true;
agg::rgba8 color = m_arOneColorGradientShape[0]->m_oBrush.m_oGradientInfo.getFillColor();
for (const auto& s : m_arOneColorGradientShape)
if (s->m_oBrush.m_oGradientInfo.getFillColor() != color)
is_one = false;
if (is_one)
return color;
else
return agg::rgba8();
}
void CPage::FillLuminosityShapes()
{
if (GetFillColor() == agg::rgba8::no_color())
{
for (auto itt = m_arOneColorGradientShape.begin(); itt != m_arOneColorGradientShape.end();)
{
for (auto it = m_arLuminosityShapes.begin(); it != m_arLuminosityShapes.end();)
{
if ((*it)->m_oVector.GetRight() > (*itt)->m_oVector.GetLeft() && (*it)->m_oVector.GetBottom() > (*itt)->m_oVector.GetTop() &&
(*it)->m_oVector.GetLeft() < (*itt)->m_oVector.GetRight() && (*it)->m_oVector.GetTop() < (*itt)->m_oVector.GetBottom())
{
(*it)->m_oBrush.m_oGradientInfo.setFillColor((*itt)->m_oBrush.m_oGradientInfo.getFillColor());
DrawGradient((*it));
it = m_arLuminosityShapes.erase(it);
}
else
++it;
}
itt = m_arOneColorGradientShape.erase(itt);
}
}
else
{
auto fill_color = GetFillColor();
for (auto& s : m_arLuminosityShapes)
{
s->m_oBrush.m_oGradientInfo.setFillColor(fill_color);
DrawGradient(s);
}
m_arLuminosityShapes.clear();
m_arOneColorGradientShape.clear();
}
}
} }

View File

@ -41,12 +41,13 @@ namespace NSDocxRenderer
NSStructures::CEdgeText m_oEdgeText{}; NSStructures::CEdgeText m_oEdgeText{};
Aggplus::CMatrix m_oTransform{}; Aggplus::CMatrix m_oTransform{};
bool m_bIsDeleteTextClipPage{true}; bool m_bIsDeleteTextClipPage {true};
bool m_bIsRecalcFontSize {true}; bool m_bIsRecalcFontSize {true};
bool m_bIsGradient {false}; bool m_bIsGradient {false};
bool m_bUseDefaultFont {false}; bool m_bUseDefaultFont {false};
bool m_bWriteStyleRaw {false}; bool m_bWriteStyleRaw {false};
bool m_bIsBuildTables {false}; bool m_bIsBuildTables {false};
bool m_bIsLuminosityShapesFiled{false};
CPage(NSFonts::IApplicationFonts* pAppFonts, const CManagers& oManagers); CPage(NSFonts::IApplicationFonts* pAppFonts, const CManagers& oManagers);
~CPage(); ~CPage();
@ -189,6 +190,12 @@ namespace NSDocxRenderer
static shape_ptr_t CreateSingleLineShape(line_ptr_t& pLine); static shape_ptr_t CreateSingleLineShape(line_ptr_t& pLine);
static shape_ptr_t CreateSingleParagraphShape(paragraph_ptr_t& pParagraph); static shape_ptr_t CreateSingleParagraphShape(paragraph_ptr_t& pParagraph);
void DrawImage(shape_ptr_t pShape, std::shared_ptr<CImageInfo> oImg, CVectorGraphics& imageVector);
void DrawGradient(shape_ptr_t pShape);
agg::rgba8 GetFillColor();
void FillLuminosityShapes();
CManagers m_oManagers; CManagers m_oManagers;
CVectorGraphics m_oCurrVectorGraphics; CVectorGraphics m_oCurrVectorGraphics;
@ -207,6 +214,10 @@ namespace NSDocxRenderer
std::vector<item_ptr_t> m_arOutputObjects; std::vector<item_ptr_t> m_arOutputObjects;
std::vector<std::wstring> m_arCompleteObjectsXml; std::vector<std::wstring> m_arCompleteObjectsXml;
// save the luminosity shapes for later filling
std::vector<shape_ptr_t> m_arLuminosityShapes;
std::vector<shape_ptr_t> m_arOneColorGradientShape;
size_t m_nShapeOrder = 0; size_t m_nShapeOrder = 0;
}; };
} }

View File

@ -12,6 +12,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
listOfCheckBox = ui->centralwidget->findChildren<QCheckBox*>(); listOfCheckBox = ui->centralwidget->findChildren<QCheckBox*>();
listOfColorLabels = ui->centralwidget->findChildren<CustomColorLabel*>(); listOfColorLabels = ui->centralwidget->findChildren<CustomColorLabel*>();
listOfParametricLines = ui->centralwidget->findChildren<CustomParametrLineEdit*>(); listOfParametricLines = ui->centralwidget->findChildren<CustomParametrLineEdit*>();
listOfAlphas = ui->centralwidget->findChildren<CustomAlphaLineEdit*>();
connect(ui->label_test, SIGNAL(mousePressed()), this, SLOT(on_label_test_clicked())); connect(ui->label_test, SIGNAL(mousePressed()), this, SLOT(on_label_test_clicked()));
@ -61,6 +62,9 @@ QImage GenerateImg(std::vector<NSStructures::Point> &points, Info &info, const i
NSStructures::GradientInfo ginfo = info.ginfo; NSStructures::GradientInfo ginfo = info.ginfo;
ginfo.shading.f_type = NSStructures::ShadingInfo::UseNew; ginfo.shading.f_type = NSStructures::ShadingInfo::UseNew;
NSStructures::CBrush brush;
brush.m_oGradientInfo = ginfo;
//pRasterRenderer->RestoreBrush(brush);
pRasterRenderer->put_BrushGradInfo(&ginfo); pRasterRenderer->put_BrushGradInfo(&ginfo);
auto a = info.c; auto a = info.c;
auto b = info.p; auto b = info.p;
@ -96,6 +100,7 @@ void MainWindow::initializeColors(bool Triangle)
{ {
listOfColorLabels[3]->setColor(QColor(Qt::yellow)); listOfColorLabels[3]->setColor(QColor(Qt::yellow));
} }
listOfColorLabels[4]->setColor(QColor(Qt::black));
} }
void MainWindow::on_actionLinear_Gradient_triggered() void MainWindow::on_actionLinear_Gradient_triggered()
@ -189,6 +194,18 @@ void MainWindow::on_actionTensor_Coons_Patch_Parametric_triggered()
ui->statusbar->showMessage("Tensor Coons Patch Parametric"); ui->statusbar->showMessage("Tensor Coons Patch Parametric");
} }
void MainWindow::on_actionactionLuminocity_Gradient_triggered()
{
ui->stackedWidget_1->setCurrentIndex(4);
ui->stackedWidget_2->setCurrentIndex(6);
ui->stackedWidget_3->setCurrentIndex(2);
info.gradient = Luminosity;
info.offset = TensorCoonsPatchOffset;
info.gradient_type = c_BrushTypeTensorCurveGradient;
initializeColors(false);
ui->statusbar->showMessage("Tensor Coons Patch");
}
inline agg::rgba8 getRGB(CustomColorLabel *label) inline agg::rgba8 getRGB(CustomColorLabel *label)
{ {
return {static_cast<unsigned int>(label->getColor().red()), return {static_cast<unsigned int>(label->getColor().red()),
@ -230,6 +247,24 @@ std::vector<std::vector<agg::rgba8>> MainWindow::qColor2rgbaMatrix()
return colors; return colors;
} }
std::vector<std::vector<agg::rgba8>> MainWindow::setAlphas()
{
std::vector<std::vector<agg::rgba8>> colors;
size_t size = listOfAlphas.size() / 2;
for (int i = 0; i < size; i++)
{
std::vector<agg::rgba8> sub_colors;
for (int j = 0; j < size; j++)
{
sub_colors.push_back({0, 0, 0, listOfAlphas[2 * i + j]->text().toUInt()});
}
colors.push_back(sub_colors);
}
return colors;
}
NSStructures::Point MainWindow::scaleCoord(NSStructures::Point p) NSStructures::Point MainWindow::scaleCoord(NSStructures::Point p)
{ {
return {p.x * MM_TO_COORD(ui->label_test->width()), p.y * MM_TO_COORD(ui->label_test->height())}; return {p.x * MM_TO_COORD(ui->label_test->width()), p.y * MM_TO_COORD(ui->label_test->height())};
@ -279,6 +314,7 @@ void MainWindow::setPoints(QImage *image)
break; break;
case TensorCoonsPatch: case TensorCoonsPatch:
case TensorCoonsPatchParametric: case TensorCoonsPatchParametric:
case Luminosity:
for (std::vector<NSStructures::Point> v : info.tensorcurve) for (std::vector<NSStructures::Point> v : info.tensorcurve)
{ {
for (NSStructures::Point p : v) for (NSStructures::Point p : v)
@ -440,6 +476,11 @@ void MainWindow::on_pushButton_clicked()
info.ginfo = NSStructures::GInfoConstructor::get_tensor_curve(info.tensorcurve, info.tensor_curve_parametrs, info.ginfo = NSStructures::GInfoConstructor::get_tensor_curve(info.tensorcurve, info.tensor_curve_parametrs,
qColor2rgbaMatrix(), info.gradient == TensorCoonsPatchParametric); qColor2rgbaMatrix(), info.gradient == TensorCoonsPatchParametric);
break; break;
case Luminosity:
info.ginfo = NSStructures::GInfoConstructor::get_tensor_curve(info.tensorcurve, info.tensor_curve_parametrs,
setAlphas(), false, true);
info.ginfo.setFillColor(getRGB(listOfColorLabels[4]));
break;
default: default:
break; break;
} }
@ -479,3 +520,6 @@ void MainWindow::on_pushButton_clicked()
ui->label_test->setPixmap(QPixmap::fromImage(pm)); ui->label_test->setPixmap(QPixmap::fromImage(pm));
ui->label_test->setScaledContents(true); ui->label_test->setScaledContents(true);
} }

View File

@ -64,6 +64,25 @@ public slots:
} }
}; };
class CustomAlphaLineEdit : public QLineEdit
{
Q_OBJECT
public:
CustomAlphaLineEdit(QWidget *parent = nullptr) : QLineEdit(parent)
{
connect(this, &QLineEdit::editingFinished, this, &CustomAlphaLineEdit::onEditingFinished);
}
~CustomAlphaLineEdit() {}
public slots:
void onEditingFinished()
{
if (this->text() == "")
this->setText(this->placeholderText());
if (this->text().toUInt() > 255)
this->setText("255");
}
};
class CustomLabel : public QLabel class CustomLabel : public QLabel
{ {
Q_OBJECT Q_OBJECT
@ -198,7 +217,8 @@ typedef enum
CoonsPatch, CoonsPatch,
CoonsPatchParametric, CoonsPatchParametric,
TensorCoonsPatch, TensorCoonsPatch,
TensorCoonsPatchParametric TensorCoonsPatchParametric,
Luminosity
} GradientType; } GradientType;
typedef enum typedef enum
@ -246,6 +266,7 @@ public:
void initializeColors(bool triangle); void initializeColors(bool triangle);
std::vector<agg::rgba8> qColor2rgba(bool triangle); std::vector<agg::rgba8> qColor2rgba(bool triangle);
std::vector<std::vector<agg::rgba8>> qColor2rgbaMatrix(); std::vector<std::vector<agg::rgba8>> qColor2rgbaMatrix();
std::vector<std::vector<agg::rgba8>> setAlphas();
void setPoints(QImage *image); void setPoints(QImage *image);
NSStructures::Point scaleCoord(NSStructures::Point p); NSStructures::Point scaleCoord(NSStructures::Point p);
@ -278,6 +299,8 @@ private slots:
void on_actionTensor_Coons_Patch_Parametric_triggered(); void on_actionTensor_Coons_Patch_Parametric_triggered();
void on_actionactionLuminocity_Gradient_triggered();
private: private:
QImage img; QImage img;
Info info; Info info;
@ -287,6 +310,7 @@ private:
QList<CustomLineEdit *> listOfLines; QList<CustomLineEdit *> listOfLines;
QList<CustomColorLabel *> listOfColorLabels; QList<CustomColorLabel *> listOfColorLabels;
QList<CustomParametrLineEdit *> listOfParametricLines; QList<CustomParametrLineEdit *> listOfParametricLines;
QList<CustomAlphaLineEdit *> listOfAlphas;
Ui::MainWindow *ui; Ui::MainWindow *ui;
}; };

View File

@ -55,7 +55,7 @@
</rect> </rect>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>4</number>
</property> </property>
<widget class="QWidget" name="Linear_Page"> <widget class="QWidget" name="Linear_Page">
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
@ -2468,7 +2468,7 @@
</rect> </rect>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>2</number>
</property> </property>
<widget class="QWidget" name="page_11"> <widget class="QWidget" name="page_11">
<widget class="QGroupBox" name="groupBox_Linear"> <widget class="QGroupBox" name="groupBox_Linear">
@ -2607,6 +2607,111 @@
</widget> </widget>
</widget> </widget>
</widget> </widget>
<widget class="QWidget" name="page_9">
<widget class="QGroupBox" name="groupBox_26">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>201</width>
<height>101</height>
</rect>
</property>
<property name="title">
<string>Set alphas and fill color</string>
</property>
<widget class="CustomColorLabel" name="label_125">
<property name="geometry">
<rect>
<x>70</x>
<y>70</y>
<width>30</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="CustomAlphaLineEdit" name="lineEdit_88">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>31</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>0</string>
</property>
<property name="placeholderText">
<string>0</string>
</property>
</widget>
<widget class="CustomAlphaLineEdit" name="lineEdit_89">
<property name="geometry">
<rect>
<x>60</x>
<y>30</y>
<width>31</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>150</string>
</property>
<property name="placeholderText">
<string>150</string>
</property>
</widget>
<widget class="CustomAlphaLineEdit" name="lineEdit_90">
<property name="geometry">
<rect>
<x>100</x>
<y>30</y>
<width>31</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>150</string>
</property>
<property name="placeholderText">
<string>150</string>
</property>
</widget>
<widget class="CustomAlphaLineEdit" name="lineEdit_91">
<property name="geometry">
<rect>
<x>140</x>
<y>30</y>
<width>31</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>255</string>
</property>
<property name="placeholderText">
<string>255</string>
</property>
</widget>
<widget class="QLabel" name="label_35">
<property name="geometry">
<rect>
<x>20</x>
<y>70</y>
<width>49</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Fill color</string>
</property>
</widget>
</widget>
</widget>
</widget> </widget>
</widget> </widget>
<widget class="QStackedWidget" name="stackedWidget_2"> <widget class="QStackedWidget" name="stackedWidget_2">
@ -3360,7 +3465,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1126</width> <width>1126</width>
<height>25</height> <height>21</height>
</rect> </rect>
</property> </property>
</widget> </widget>
@ -3383,6 +3488,7 @@
<addaction name="actionCoons_Patch_Parametric"/> <addaction name="actionCoons_Patch_Parametric"/>
<addaction name="actionTensor_Coons_Patch_Gradient"/> <addaction name="actionTensor_Coons_Patch_Gradient"/>
<addaction name="actionTensor_Coons_Patch_Parametric"/> <addaction name="actionTensor_Coons_Patch_Parametric"/>
<addaction name="actionactionLuminocity_Gradient"/>
</widget> </widget>
<action name="actionLinear_Gradient"> <action name="actionLinear_Gradient">
<property name="text"> <property name="text">
@ -3442,6 +3548,17 @@
<enum>QAction::TextHeuristicRole</enum> <enum>QAction::TextHeuristicRole</enum>
</property> </property>
</action> </action>
<action name="actionactionLuminocity_Gradient">
<property name="text">
<string>Luminocity Gradient</string>
</property>
<property name="toolTip">
<string>TensorPatchLuminosity</string>
</property>
<property name="menuRole">
<enum>QAction::TextHeuristicRole</enum>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>
@ -3467,6 +3584,11 @@
<slot>onMouseClicked()</slot> <slot>onMouseClicked()</slot>
</slots> </slots>
</customwidget> </customwidget>
<customwidget>
<class>CustomAlphaLineEdit</class>
<extends>QLineEdit</extends>
<header>mainwindow.h</header>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections/> <connections/>