88 std::vector< SPMeshNode* >
row;
101 (*nodes)[
row+i].push_back(
node );
117 p = (*nodes)[
row ][
col+pt ]->p;
120 p = (*nodes)[
row+pt ][
col+3 ]->p;
123 p = (*nodes)[
row+3 ][
col+3-pt ]->p;
126 p = (*nodes)[
row+3-pt ][
col ]->p;
139 std::vector< Geom::Point> points;
140 points.push_back(
getPoint( i, 0 ) );
141 points.push_back(
getPoint( i, 1 ) );
142 points.push_back(
getPoint( i, 2 ) );
143 points.push_back(
getPoint( i, 3 ) );
167 (*nodes)[
row ][
col+pt ]->p = p;
169 (*nodes)[
row ][
col+pt ]->node_type = node_type;
172 (*nodes)[
row+pt ][
col+3 ]->p = p;
174 (*nodes)[
row+pt ][
col+3 ]->node_type = node_type;
177 (*nodes)[
row+3 ][
col+3-pt ]->p = p;
178 (*nodes)[
row+3 ][
col+3-pt ]->set =
set;
179 (*nodes)[
row+3 ][
col+3-pt ]->node_type = node_type;
182 (*nodes)[
row+3-pt ][
col ]->p = p;
184 (*nodes)[
row+3-pt ][
col ]->node_type = node_type;
199 type = (*nodes)[
row ][
col+1 ]->path_type;
202 type = (*nodes)[
row+1 ][
col+3 ]->path_type;
205 type = (*nodes)[
row+3 ][
col+2 ]->path_type;
208 type = (*nodes)[
row+2 ][
col ]->path_type;
224 (*nodes)[
row ][
col+1 ]->path_type = t;
225 (*nodes)[
row ][
col+2 ]->path_type = t;
228 (*nodes)[
row+1 ][
col+3 ]->path_type = t;
229 (*nodes)[
row+2 ][
col+3 ]->path_type = t;
232 (*nodes)[
row+3 ][
col+1 ]->path_type = t;
233 (*nodes)[
row+3 ][
col+2 ]->path_type = t;
236 (*nodes)[
row+1 ][
col ]->path_type = t;
237 (*nodes)[
row+2 ][
col ]->path_type = t;
251 (*nodes)[
row + 1 ][
col + 1 ]->p = p;
252 (*nodes)[
row + 1 ][
col + 1 ]->set =
true;
256 (*nodes)[
row + 1 ][
col + 2 ]->p = p;
257 (*nodes)[
row + 1 ][
col + 2 ]->set =
true;
261 (*nodes)[
row + 2 ][
col + 2 ]->p = p;
262 (*nodes)[
row + 2 ][
col + 2 ]->set =
true;
266 (*nodes)[
row + 2 ][
col + 1 ]->p = p;
267 (*nodes)[
row + 2 ][
col + 1 ]->set =
true;
277 for(
unsigned i = 0; i < 4; ++i ) {
295 set = (*nodes)[
row + 1 ][
col + 1 ]->set;
298 set = (*nodes)[
row + 1 ][
col + 2 ]->set;
301 set = (*nodes)[
row + 2 ][
col + 2 ]->set;
304 set = (*nodes)[
row + 2 ][
col + 1 ]->set;
343 p = (*nodes)[
row + i ][
col + j ]->p;
375 t = ( -4.0 * p[0][0] +
376 6.0 * ( p[0][1] + p[1][0] ) +
377 -2.0 * ( p[0][3] + p[3][0] ) +
378 3.0 * ( p[3][1] + p[1][3] ) +
379 -1.0 * p[3][3] ) / 9.0;
383 t = ( -4.0 * p[0][3] +
384 6.0 * ( p[0][2] + p[1][3] ) +
385 -2.0 * ( p[0][0] + p[3][3] ) +
386 3.0 * ( p[3][2] + p[1][0] ) +
387 -1.0 * p[3][0] ) / 9.0;
391 t = ( -4.0 * p[3][3] +
392 6.0 * ( p[3][2] + p[2][3] ) +
393 -2.0 * ( p[3][0] + p[0][3] ) +
394 3.0 * ( p[0][2] + p[2][0] ) +
395 -1.0 * p[0][0] ) / 9.0;
399 t = ( -4.0 * p[3][0] +
400 6.0 * ( p[3][1] + p[2][0] ) +
401 -2.0 * ( p[3][3] + p[0][0] ) +
402 3.0 * ( p[0][1] + p[2][3] ) +
403 -1.0 * p[0][3] ) / 9.0;
408 g_warning(
"Impossible!" );
421 for(
unsigned i = 0; i < 4; ++i ) {
422 for(
unsigned j = 0; j < 4; ++j ) {
430 if( i == 0 || i == 3 ) {
434 if( j == 2 ) dp *= 2.0;
435 (*nodes)[
row + i ][
col + j ]->p = p0 + dp;
438 if( j == 0 || j == 3 ) {
442 if( i == 2 ) dp *= 2.0;
443 (*nodes)[
row + i ][
col + j ]->p = p0 + dp;
451 for(
unsigned i = 1; i < 3; ++i ) {
452 for(
unsigned j = 1; j < 3; ++j ) {
453 if( (*
nodes)[
row + i ][
col + j ]->set == false ) {
458 if( i == 1 && j == 2 ) t = 1;
459 if( i == 2 && j == 2 ) t = 2;
460 if( i == 2 && j == 1 ) t = 3;
498 (*nodes)[
row ][
col ]->color = color;
501 (*nodes)[
row ][
col+3 ]->color = color;
504 (*nodes)[
row+3 ][
col+3 ]->color = color;
507 (*nodes)[
row+3 ][
col ]->color = color;
522 stop = (*nodes)[
row ][
col ]->stop;
525 stop = (*nodes)[
row ][
col+3 ]->stop;
528 stop = (*nodes)[
row+3 ][
col+3 ]->stop;
531 stop = (*nodes)[
row+3 ][
col ]->stop;
547 (*nodes)[
row ][
col ]->stop = stop;
550 (*nodes)[
row ][
col+3 ]->stop = stop;
553 (*nodes)[
row+3 ][
col+3 ]->stop = stop;
556 (*nodes)[
row+3 ][
col ]->stop = stop;
573 for(
unsigned i=0; i <
nodes.size(); ++i ) {
574 for(
unsigned j=0; j <
nodes[i].size(); ++j ) {
584 if(
this == &rhs )
return *
this;
593 for(
unsigned i=0; i <
nodes.size(); ++i ) {
594 for(
unsigned j=0; j <
nodes[i].size(); ++j ) {
610 for (
auto &row :
nodes) {
611 for (
auto &
node : row) {
612 switch (
node->node_type) {
623 std::cerr <<
"Bad Mesh draggable type" << std::endl;
635 auto mg_array = cast<SPMeshGradient>(
mg->
getArray());
637 std::cerr <<
"SPMeshNodeArray::read: No mesh array!" << std::endl;
645 for (
auto& ro: mg_array->children) {
646 if (is<SPMeshrow>(&ro)) {
649 for (
auto& po: ro.children) {
650 if (is<SPMeshpatch>(&po)) {
657 bool same_size =
true;
666 unsigned max_column = 0;
668 for (
auto& ro: mg_array->children) {
670 if (is<SPMeshrow>(&ro)) {
672 unsigned icolumn = 0;
673 for (
auto& po: ro.children) {
675 if (is<SPMeshpatch>(&po)) {
677 auto patch = cast<SPMeshpatch>(&po);
686 if( irow != 0 ) ++istop;
688 for (
auto& so: po.children) {
689 if (is<SPStop>(&so)) {
696 auto stop = cast<SPStop>(&so);
699 if( istop == 0 && icolumn == 0 ) {
701 new_patch.
setPoint( 0, 0, current_p );
704 current_p = new_patch.
getPoint( istop, 0 );
708 if( icolumn == 0 && istop == 3 ) closed =
true;
709 if( icolumn > 0 && istop == 2 ) closed =
true;
712 std::string path_string = stop->path_string.raw();
713 std::replace(path_string.begin(),path_string.end(),
',',
' ');
718 std::stringstream os( path_string );
728 switch ( path_type ) {
734 new_patch.
setPoint( istop, 3, current_p + dp );
736 std::cerr <<
"Failed to read l" << std::endl;
742 dp = (p - current_p)/3.0;
748 new_patch.
setPoint( istop, 1, current_p + dp,
false );
749 new_patch.
setPoint( istop, 2, current_p + 2.0 * dp,
false );
758 std::cerr <<
"Failed to read L" << std::endl;
764 dp = (p - current_p)/3.0;
765 new_patch.
setPoint( istop, 1, current_p + dp,
false );
766 new_patch.
setPoint( istop, 2, current_p + 2.0 * dp,
false );
770 if( closed ) max = 3;
771 for(
unsigned i = 1; i < max; ++i ) {
778 std::cerr <<
"Failed to read c: " << i << std::endl;
784 if( closed ) max = 3;
785 for(
unsigned i = 1; i < max; ++i ) {
791 std::cerr <<
"Failed to read C: " << i << std::endl;
797 std::cerr <<
"Path Error: unhandled path type: " << path_type << std::endl;
799 current_p = new_patch.
getPoint( istop, 3 );
802 if( (istop == 0 && irow == 0 && icolumn > 0) || (istop == 1 && irow > 0 ) ) {
805 auto color = stop->getColor();
816 if( patch->tensor_string ) {
817 std::string tensor_string = patch->tensor_string->raw();
818 std::replace(tensor_string.begin(),tensor_string.end(),
',',
' ');
822 std::stringstream os( tensor_string );
823 for(
unsigned i = 0; i < 4; ++i ) {
830 std::cerr <<
"Failed to read p: " << i << std::endl;
836 if( max_column < icolumn ) max_column = icolumn;
845 node.resize( max_column * 3 + 1 );
849 for(
unsigned i = 0; i <
nodes.size(); ++i ) {
850 for(
unsigned j = 0; j <
nodes[i].size(); ++j ) {
878 auto mg_array = cast<SPMeshGradient>(
mg->
getArray());
888 std::vector<SPObject*> children_pointers;
889 for (
auto& row : mg_array->children) {
890 children_pointers.push_back(&row);
893 for (
auto i : children_pointers) {
912 for(
unsigned i = 0; i < rows; ++i ) {
919 for(
unsigned j = 0; j < columns; ++j ) {
929 std::stringstream
is;
931 for(
unsigned k = 0; k < 4; ++k ) {
933 is << p[X] <<
"," << p[Y];
934 if( k < 3 )
is <<
" ";
944 for(
unsigned k = 0; k < 4; ++k ) {
947 if( k == 0 && i != 0 )
continue;
950 if( k == 3 && j != 0 )
continue;
955 std::stringstream
is;
960 current_p = patchi.
getPoint( k, 0 );
962 switch ( path_type ) {
965 << ( p[3][X] - current_p[X] ) <<
","
966 << ( p[3][Y] - current_p[Y] );
975 << ( p[1][X] - current_p[X] ) <<
","
976 << ( p[1][Y] - current_p[Y] ) <<
" "
977 << ( p[2][X] - current_p[X] ) <<
","
978 << ( p[2][Y] - current_p[Y] ) <<
" "
979 << ( p[3][X] - current_p[X] ) <<
","
980 << ( p[3][Y] - current_p[Y] );
993 std::cerr <<
"SPMeshNodeArray::write(): bad path type" << path_type << std::endl;
996 std::cerr <<
"SPMeshNodeArray::write(): unhandled path type" << path_type << std::endl;
1001 if( ( k == 0 && i == 0 && j == 0 ) ||
1002 ( k == 1 && i == 0 ) ||
1004 ( k == 3 && j == 0 ) ) {
1030 auto gradient = cast<SPGradient>(server);
1031 if (gradient && gradient->getVector()) {
1032 SPStop *firstStop = gradient->getVector()->getFirstStop();
1039 std::cerr <<
" SPMeshNodeArray: default_color(): No style" << std::endl;
1051 std::cerr <<
"SPMeshNodeArray::create(): bbox empty" << std::endl;
1055 std::cerr <<
"SPMeshNodeArray::create: ERROR: No bounding box!" << std::endl;
1074 if( !
nodes.empty() )
return;
1085 if (color == white) {
1092 unsigned prows = prefs->
getInt(
"/tools/mesh/mesh_rows", 1);
1093 unsigned pcols = prefs->
getInt(
"/tools/mesh/mesh_cols", 1);
1100 double rx =
width/2.0;
1105 double end = 2.0 * M_PI;
1107 if ( is<SPStar>(
item ) ) {
1109 auto star = cast<SPStar>(
item );
1110 center = star->center;
1113 start = star->arg[0];
1117 if ( is<SPGenericEllipse>(
item ) ) {
1119 auto arc = cast<SPGenericEllipse>(
item );
1120 center[
Geom::X] = arc->cx.computed;
1121 center[
Geom::Y] = arc->cy.computed;
1122 rx = arc->rx.computed;
1123 ry = arc->ry.computed;
1137 unsigned sections = pcols;
1140 if( sections < 4 ) sections = 4;
1142 double arc = (
end -
start) / (
double)sections;
1145 double kappa = 4.0/3.0 * tan(arc/4.0);
1146 double lenx = rx * kappa;
1147 double leny = ry * kappa;
1150 for(
unsigned i = 0; i < sections; ++i ) {
1154 double x0 = center[
Geom::X] + rx * cos(s);
1155 double y0 = center[
Geom::Y] + ry * sin(s);
1156 double x1 = x0 - lenx * sin(s);
1157 double y1 = y0 + leny * cos(s);
1160 double x3 = center[
Geom::X] + rx * cos(s);
1161 double y3 = center[
Geom::Y] + ry * sin(s);
1162 double x2 = x3 + lenx * sin(s);
1163 double y2 = y3 - leny * cos(s);
1173 for(
unsigned k = 0; k < 4; ++k ) {
1175 patch.
setColor( k, (i+k)%2 ? color : white );
1190 if( is<SPGenericEllipse>(
item ) ) {
1194 auto arc = cast<SPGenericEllipse>(
item );
1195 center[
Geom::X] = arc->cx.computed;
1196 center[
Geom::Y] = arc->cy.computed;
1197 double rx = arc->rx.computed;
1198 double ry = arc->ry.computed;
1200 double s = -3.0/2.0 * M_PI_2;
1205 double lenx = rx * 4*tan(M_PI_2/4)/3;
1206 double leny = ry * 4*tan(M_PI_2/4)/3;
1209 for (
int i = 0; i < 4; ++i) {
1210 double x0 = center[
Geom::X] + rx * cos(s);
1211 double y0 = center[
Geom::Y] + ry * sin(s);
1212 double x1 = x0 + lenx * cos(s + M_PI_2);
1213 double y1 = y0 + leny * sin(s + M_PI_2);
1216 double x3 = center[
Geom::X] + rx * cos(s);
1217 double y3 = center[
Geom::Y] + ry * sin(s);
1218 double x2 = x3 + lenx * cos(s - M_PI_2);
1219 double y2 = y3 + leny * sin(s - M_PI_2);
1230 patch.
setColor( i, i%2 ? color : white );
1241 }
else if ( is<SPStar>(
item ) ) {
1246 auto star = cast<SPStar>(
item );
1247 unsigned sides = star->sides;
1255 for(
unsigned i = 0; i < sides; ++i ) {
1257 if( star->flatsided ) {
1263 if( ii == sides ) ii = 0;
1265 patch.
setPoint( 2, 0, star->center );
1266 patch.
setPoint( 3, 0, star->center );
1268 for(
unsigned s = 0; s < 4; ++s ) {
1270 patch.
setColor( s, (i+s)%2 ? color : white );
1282 patch0.
setPoint( 2, 0, star->center );
1283 patch0.
setPoint( 3, 0, star->center );
1286 if( ii == sides ) ii = 0;
1292 patch1.
setPoint( 2, 0, star->center );
1293 patch1.
setPoint( 3, 0, star->center );
1295 for(
unsigned s = 0; s < 4; ++s ) {
1297 patch0.
setColor( s, s%2 ? color : white );
1299 patch1.
setColor( s, s%2 ? white : color );
1322 unsigned nrows = prows * 3 + 1;
1323 unsigned ncols = pcols * 3 + 1;
1325 double dx =
width / (double)(ncols-1.0);
1326 double dy =
height / (double)(nrows-1.0);
1330 for(
unsigned i = 0; i < nrows; ++i ) {
1331 std::vector< SPMeshNode* > row;
1332 for(
unsigned j = 0; j < ncols; ++j ) {
1348 node->color = (i+j)%2 ? color : white;
1354 node->path_type =
'c';
1363 node->path_type =
'c';
1372 row.push_back(
node );
1374 nodes.push_back( row );
1393 for (
auto & j :
node) {
1405 for(
unsigned i = 0; i <
nodes.size(); ++i ) {
1406 std::cout <<
"New node row:" << std::endl;
1407 for(
unsigned j = 0; j <
nodes[i].size(); ++j ) {
1410 std::cout <<
" Node: " << i <<
"," << j <<
": "
1412 <<
" Node type: " <<
nodes[i][j]->node_type
1413 <<
" Node edge: " <<
nodes[i][j]->node_edge
1414 <<
" Set: " <<
nodes[i][j]->set
1415 <<
" Path type: " <<
nodes[i][j]->path_type
1416 <<
" Stop: " <<
nodes[i][j]->stop
1419 std::cout <<
"Error: missing mesh node." << std::endl;
1439class SPMeshSmoothCorner final {
1441 SPMeshSmoothCorner() {
1443 for(
unsigned j = 0; j < 4; ++j ) {
1456 double const d01,
double const d12)
1460 if( d01 > 0 && d12 > 0 ) {
1461 slope = 0.5 * ( (p1 - p0)/d01 + (p2 - p1)/d12 );
1463 if( ( p0 > p1 && p1 < p2 ) ||
1464 ( p0 < p1 && p1 > p2 ) ) {
1469 if( fabs(slope) > fabs(3*(p1-p0)/d01) ) {
1470 slope = 3*(p1-p0)/d01;
1472 if( fabs(slope) > fabs(3*(p2-p1)/d12) ) {
1473 slope = 3*(p2-p1)/d12;
1513void invert(
const double v[16],
double alpha[16] ) {
1515 const double A[16][16] = {
1517 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1518 { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1519 {-3, 3, 0, 0, -2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1520 { 2,-2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1521 { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
1522 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
1523 { 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -2,-1, 0, 0 },
1524 { 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 1, 1, 0, 0 },
1525 {-3, 0, 3, 0, 0, 0, 0, 0, -2, 0,-1, 0, 0, 0, 0, 0 },
1526 { 0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0, 0, -2, 0,-1, 0 },
1527 { 9,-9,-9, 9, 6, 3,-6,-3, 6,-6, 3,-3, 4, 2, 2, 1 },
1528 {-6, 6, 6,-6, -3,-3, 3, 3, -4, 4,-2, 2, -2,-2,-1,-1 },
1529 { 2, 0,-2, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
1530 { 0, 0, 0, 0, 2, 0,-2, 0, 0, 0, 0, 0, 1, 0, 1, 0 },
1531 {-6, 6, 6,-6, -4,-2, 4, 2, -3, 3,-3, 3, -2,-1,-2,-1 },
1532 { 4,-4,-4, 4, 2, 2,-2,-2, 2,-2, 2,-2, 1, 1, 1, 1 }
1535 for(
unsigned i = 0; i < 16; ++i ) {
1537 for(
unsigned j = 0; j < 16; ++j ) {
1538 alpha[i] += A[i][j]*v[j];
1543double sum(
const double alpha[16],
const double& x,
const double& y ) {
1548 double xxx = xx * x;
1550 double yyy = yy * y;
1553 result += alpha[ 1 ] * x;
1554 result += alpha[ 2 ] * xx;
1555 result += alpha[ 3 ] * xxx;
1556 result += alpha[ 4 ] * y;
1557 result += alpha[ 5 ] * y * x;
1558 result += alpha[ 6 ] * y * xx;
1559 result += alpha[ 7 ] * y * xxx;
1560 result += alpha[ 8 ] * yy;
1561 result += alpha[ 9 ] * yy * x;
1562 result += alpha[ 10 ] * yy * xx;
1563 result += alpha[ 11 ] * yy * xxx;
1564 result += alpha[ 12 ] * yyy;
1565 result += alpha[ 13 ] * yyy * x;
1566 result += alpha[ 14 ] * yyy * xx;
1567 result += alpha[ 15 ] * yyy * xxx;
1584 std::vector< std::vector <SPMeshSmoothCorner> > d;
1585 d.resize(
smooth->patch_rows() + 1 );
1586 for(
unsigned i = 0; i < d.size(); ++i ) {
1587 d[i].resize(
smooth->patch_columns() + 1 );
1588 for(
unsigned j = 0; j < d[i].size(); ++j ) {
1590 auto rgb_color = this->
nodes[i * 3][j * 3]->color->converted(Colors::Space::Type::RGB);
1591 d[i][j].g[0][0] = rgb_color->get(0);
1592 d[i][j].g[1][0] = rgb_color->get(1);
1593 d[i][j].g[2][0] = rgb_color->get(2);
1594 d[i][j].p = this->
nodes[ i*3 ][ j*3 ]->p;
1599 for(
unsigned i = 0; i < d.size(); ++i ) {
1600 for(
unsigned j = 0; j < d[i].size(); ++j ) {
1601 for(
unsigned k = 0; k < 3; ++k ) {
1605 if( i != 0 && i != d.size()-1 ) {
1608 d[i][j].g[k][1] =
find_slope1( d[i-1][j].g[k][0], d[i][j].g[k][0], d[i+1][j].g[k][0], lm, lp );
1612 if( j != 0 && j != d[i].
size()-1 ) {
1615 d[i][j].g[k][2] =
find_slope1( d[i][j-1].g[k][0], d[i][j].g[k][0], d[i][j+1].g[k][0], lm, lp );
1631 for(
unsigned j = 0; j< d[0].size(); ++j ) {
1632 for(
unsigned k = 0; k < 3; ++k ) {
1637 d[0][j].g[k][1] = 2.0*(d[1][j].g[k][0] - d[0 ][j].g[k][0])/d0 - d[1][j].g[k][1];
1639 d[0][j].g[k][1] = 0;
1642 unsigned z = d.size()-1;
1645 d[z][j].g[k][1] = 2.0*(d[z][j].g[k][0] - d[z-1][j].g[k][0])/dz - d[z-1][j].g[k][1];
1647 d[z][j].g[k][1] = 0;
1652 for(
unsigned i = 0; i< d.size(); ++i ) {
1653 for(
unsigned k = 0; k < 3; ++k ) {
1658 d[i][0].g[k][2] = 2.0*(d[i][1].g[k][0] - d[i][0 ].g[k][0])/d0 - d[i][1].g[k][2];
1660 d[i][0].g[k][2] = 0;
1663 unsigned z = d[0].size()-1;
1666 d[i][z].g[k][2] = 2.0*(d[i][z].g[k][0] - d[i][z-1].g[k][0])/dz - d[i][z-1].g[k][2];
1668 d[i][z].g[k][2] = 0;
1679 for(
int i =
smooth->patch_rows() - 1; i >= 0; --i ) {
1680 smooth->split_row( i,
unsigned(8) );
1685 for(
int i =
smooth->patch_columns() - 1; i >= 0; --i ) {
1686 smooth->split_column( i, (
unsigned)8 );
1690 for(
unsigned i = 0; i < this->
patch_rows(); ++i ) {
1700 for(
unsigned m = 0; m < 3; ++m ) {
1703 v[ 0] = d[i ][j ].g[m][0];
1704 v[ 1] = d[i+1][j ].g[m][0];
1705 v[ 2] = d[i ][j+1].g[m][0];
1706 v[ 3] = d[i+1][j+1].g[m][0];
1707 v[ 4] = d[i ][j ].g[m][1]*dx0;
1708 v[ 5] = d[i+1][j ].g[m][1]*dx0;
1709 v[ 6] = d[i ][j+1].g[m][1]*dx1;
1710 v[ 7] = d[i+1][j+1].g[m][1]*dx1;
1711 v[ 8] = d[i ][j ].g[m][2]*dy0;
1712 v[ 9] = d[i+1][j ].g[m][2]*dy1;
1713 v[10] = d[i ][j+1].g[m][2]*dy0;
1714 v[11] = d[i+1][j+1].g[m][2]*dy1;
1715 v[12] = d[i ][j ].g[m][3];
1716 v[13] = d[i+1][j ].g[m][3];
1717 v[14] = d[i ][j+1].g[m][3];
1718 v[15] = d[i+1][j+1].g[m][3];
1723 for(
unsigned k = 0; k < 9; ++k ) {
1724 for(
unsigned l = 0; l < 9; ++l ) {
1727 r[m][k][l] =
sum( alpha, x, y );
1729 if( r[m][k][l] > 1.0 )
1731 if( r[m][k][l] < 0.0 )
1738 for(
unsigned k = 0; k < 9; ++k ) {
1739 for(
unsigned l = 0; l < 9; ++l ) {
1741 auto op =
smooth->nodes[(i*8+k)*3 ][(j*8+l)*3]->color->getOpacity();
1743 smooth->nodes[(i*8+k)*3 ][(j*8+l)*3]->color->set(
1757 return nodes.size()/3;
1764 if (
nodes.empty()) {
1767 return nodes[0].size()/3;
1783 bool adjacent =
false;
1795 unsigned crow1 = c1 / ncorners;
1796 unsigned crow2 = c2 / ncorners;
1797 unsigned ccol1 = c1 % ncorners;
1798 unsigned ccol2 = c2 % ncorners;
1800 unsigned nrow = crow1 * 3;
1801 unsigned ncol = ccol1 * 3;
1817 if ( crow1 == crow2 && (ccol2 - ccol1) == 1 ) {
1819 for(
unsigned k = 0; k < 4; ++k ) {
1820 n[k] =
nodes[nrow][ncol+k];
1825 if ( ccol1 == ccol2 && (crow2 - crow1) == 1 ) {
1827 for(
unsigned k = 0; k < 4; ++k ) {
1828 n[k] =
nodes[nrow+k][ncol];
1841 unsigned toggled = 0;
1843 if(
corners.size() < 2 )
return 0;
1845 for(
unsigned i = 0; i <
corners.size()-1; ++i ) {
1846 for(
unsigned j = i+1; j <
corners.size(); ++j ) {
1851 char path_type = n[1]->path_type;
1855 n[1]->path_type =
'C';
1856 n[2]->path_type =
'C';
1862 n[1]->path_type =
'c';
1863 n[2]->path_type =
'c';
1869 n[1]->path_type =
'L';
1870 n[2]->path_type =
'L';
1875 n[1]->p = n[0]->p + dp;
1876 n[2]->p = n[3]->p - dp;
1880 n[1]->path_type =
'l';
1881 n[2]->path_type =
'l';
1886 n[1]->p = n[0]->p + dp;
1887 n[2]->p = n[3]->p - dp;
1897 std::cerr <<
"Toggle sides: Invalid path type: " << path_type << std::endl;
1903 if( toggled > 0 )
built =
false;
1916 if(
corners.size() < 2 )
return 0;
1919 for(
unsigned i = 0; i <
corners.size()-1; ++i ) {
1920 for(
unsigned j = i+1; j <
corners.size(); ++j ) {
1925 char path_type = n[1]->path_type;
1930 std::cerr <<
"SPMeshNodeArray::side_arc: Can't convert straight lines to arcs." << std::endl;
1946 const double f = 4.0/3.0 * tan( M_PI/2.0/4.0 );
1951 n[1]->p = n[0]->p + f*h1;
1952 n[2]->p = n[3]->p + f*h2;
1956 std::cerr <<
"SPMeshNodeArray::side_arc: No crossing, can't turn into arc." << std::endl;
1959 std::cerr <<
"SPMeshNodeArray::side_arc: Handles parallel, can't turn into arc." << std::endl;
1964 std::cerr <<
"SPMeshNodeArray::side_arc: Invalid path type: " << n[1]->path_type << std::endl;
1969 if( arced > 0 )
built =
false;
1981 if(
corners.size() < 4 )
return 0;
1983 unsigned toggled = 0;
1988 for(
unsigned i = 0; i <
corners.size()-3; ++i ) {
1989 for(
unsigned j = i+1; j <
corners.size()-2; ++j ) {
1990 for(
unsigned k = j+1; k <
corners.size()-1; ++k ) {
1991 for(
unsigned l = k+1; l <
corners.size(); ++l ) {
1998 std::sort(
c,
c+4 );
2001 if(
c[1]-
c[0] == 1 &&
2003 c[2]-
c[0] == ncorners &&
2004 c[3]-
c[1] == ncorners &&
2005 c[0] % ncorners < ncorners - 1 ) {
2008 unsigned prow =
c[0] / ncorners;
2009 unsigned pcol =
c[0] % ncorners;
2012 unsigned irow = prow * 3;
2013 unsigned jcol = pcol * 3;
2033 nodes[irow+1][jcol+1]->set =
false;
2034 nodes[irow+1][jcol+2]->set =
false;
2035 nodes[irow+2][jcol+1]->set =
false;
2036 nodes[irow+2][jcol+2]->set =
false;
2039 nodes[irow+1][jcol+1]->set =
true;
2040 nodes[irow+1][jcol+2]->set =
true;
2041 nodes[irow+2][jcol+1]->set =
true;
2042 nodes[irow+2][jcol+2]->set =
true;
2051 if( toggled > 0 )
built =
false;
2063 unsigned smoothed = 0;
2072 for(
unsigned int corner :
corners) {
2077 unsigned nrow = (corner / ncorners) * 3;
2078 unsigned ncol = (corner % ncorners) * 3;
2081 for(
unsigned s = 0; s < 2; ++s ) {
2089 if( ncol > 2 && ncol+3 < ncols) {
2090 for(
unsigned j = 0; j < 7; ++j ) {
2091 n[j] =
nodes[ nrow ][ ncol - 3 + j ];
2099 if( nrow > 2 && nrow+3 < nrows) {
2100 for(
unsigned j = 0; j < 7; ++j ) {
2101 n[j] =
nodes[ nrow - 3 + j ][ ncol ];
2114 double slope_ave[3];
2115 double slope_diff[3];
2118 auto &color0 = n[0]->color;
2119 auto &color3 = n[3]->color;
2120 auto &color6 = n[6]->color;
2124 for(
unsigned k = 0; k < 7; ++k ) {
2125 d[k]= n[k]->p - n[3]->p;
2131 for(
unsigned c = 0;
c < 3; ++
c ) {
2132 if( d[2].length() != 0.0 ) {
2133 slope[0][
c] = (color3->get(
c) - color0->get(
c)) / d[2].length();
2135 if( d[4].length() != 0.0 ) {
2136 slope[1][
c] = (color6->get(
c) - color3->get(
c)) / d[4].length();
2138 slope_ave[
c] = (slope[0][
c]+slope[1][
c]) / 2.0;
2139 slope_diff[
c] = (slope[0][
c]-slope[1][
c]);
2152 if( std::abs( slope_diff[
c] ) > sdm ) {
2153 sdm = std::abs( slope_diff[
c] );
2160 double length_left = d[0].
length();
2161 double length_right = d[6].
length();
2162 if( slope_ave[ cdm ] != 0.0 ) {
2163 length_left = std::abs( (color3->get(cdm) - color0->get(cdm)) / slope_ave[ cdm ] );
2164 length_right = std::abs( (color6->get(cdm) - color3->get(cdm)) / slope_ave[ cdm ] );
2169 if( length_left > max * d[0].length() && length_left > d[2].length() ) {
2170 std::cerr <<
" Can't smooth left side" << std::endl;
2171 length_left = std::max( max * d[0].length(), d[2].length() );
2173 if( length_right > max * d[6].length() && length_right > d[4].length() ) {
2174 std::cerr <<
" Can't smooth right side" << std::endl;
2175 length_right = std::max( max * d[6].length(), d[4].length() );
2178 if( d[2].length() != 0.0 ) d[2] *= length_left/d[2].
length();
2179 if( d[4].length() != 0.0 ) d[4] *= length_right/d[4].
length();
2187 n[2]->p = n[3]->p + d[2];
2188 n[4]->p = n[3]->p + d[4];
2196 if( smoothed > 0 )
built =
false;
2207 unsigned picked = 0;
2247 for(
unsigned int corner : icorners) {
2262 unsigned col = corner % cols;
2263 unsigned row = corner / cols;
2264 unsigned ncol = col * 3;
2265 unsigned nrow = row * 3;
2267 const double size = 3.0;
2272 p += unit_vector( dp ) *
size;
2275 if( col == cols-1 ) {
2277 p += unit_vector( dp ) *
size;
2280 if( row == rows-1 ) {
2282 p += unit_vector( dp ) *
size;
2287 p += unit_vector( dp ) *
size;
2301 pick_drawing->
render(dc, ibox);
2303 cairo_surface_destroy(s);
2307 delete pick_drawing;
2310 if( picked > 0 )
built =
false;
2320 unsigned inserted = 0;
2322 if(
corners.size() < 2 )
return 0;
2324 std::set<unsigned> columns;
2325 std::set<unsigned> rows;
2327 for(
unsigned i = 0; i <
corners.size()-1; ++i ) {
2328 for(
unsigned j = i+1; j <
corners.size(); ++j ) {
2344 unsigned crow1 = c1 / ncorners;
2345 unsigned crow2 = c2 / ncorners;
2346 unsigned ccol1 = c1 % ncorners;
2347 unsigned ccol2 = c2 % ncorners;
2350 if ( crow1 == crow2 && (ccol2 - ccol1) == 1 ) {
2351 columns.insert( ccol1 );
2355 if ( ccol1 == ccol2 && (crow2 - crow1) == 1 ) {
2356 rows.insert( crow1 );
2362 for (
auto rit = columns.rbegin(), rend = columns.rend(); rit != rend; ++rit) {
2366 for (
auto rit = rows.rbegin(), rend = rows.rend(); rit != rend; ++rit) {
2371 if( inserted > 0 )
built =
false;
2384 std::vector<unsigned>
const & ,
2398 unsigned ncorners = mcol + 1;
2401 unsigned crow = corner / ncorners;
2402 unsigned ccol = corner % ncorners;
2405 unsigned nrow = crow * 3;
2406 unsigned ncol = ccol * 3;
2429 patch[0] = patch[1] = patch[2] = patch[3] =
false;
2430 if( ccol > 0 && crow > 0 ) patch[0] =
true;
2431 if( ccol < mcol && crow > 0 ) patch[1] =
true;
2432 if( ccol < mcol && crow < mrow ) patch[2] =
true;
2433 if( ccol > 0 && crow < mrow ) patch[3] =
true;
2441 if( patch[0] || patch[1] ) {
2442 if(
nodes[nrow-1][ncol]->path_type ==
'l' ||
2443 nodes[nrow-1][ncol]->path_type ==
'L' ) {
2445 nodes[nrow-1][ncol ]->p =
nodes[nrow][ncol]->p + s;
2446 nodes[nrow-2][ncol ]->p =
nodes[nrow-3][ncol]->p - s;
2448 nodes[nrow-1][ncol ]->p += dp;
2452 if( patch[1] || patch[2] ) {
2453 if(
nodes[nrow ][ncol+1]->path_type ==
'l' ||
2454 nodes[nrow ][ncol+1]->path_type ==
'L' ) {
2456 nodes[nrow ][ncol+1]->p =
nodes[nrow][ncol]->p + s;
2457 nodes[nrow ][ncol+2]->p =
nodes[nrow][ncol+3]->p - s;
2459 nodes[nrow ][ncol+1]->p += dp;
2463 if( patch[2] || patch[3] ) {
2464 if(
nodes[nrow+1][ncol ]->path_type ==
'l' ||
2465 nodes[nrow+1][ncol ]->path_type ==
'L' ) {
2467 nodes[nrow+1][ncol ]->p =
nodes[nrow][ncol]->p + s;
2468 nodes[nrow+2][ncol ]->p =
nodes[nrow+3][ncol]->p - s;
2470 nodes[nrow+1][ncol ]->p += dp;
2474 if( patch[3] || patch[0] ) {
2475 if(
nodes[nrow ][ncol-1]->path_type ==
'l' ||
2476 nodes[nrow ][ncol-1]->path_type ==
'L' ) {
2478 nodes[nrow ][ncol-1]->p =
nodes[nrow][ncol]->p + s;
2479 nodes[nrow ][ncol-2]->p =
nodes[nrow][ncol-3]->p - s;
2481 nodes[nrow ][ncol-1]->p += dp;
2486 if( patch[0] )
nodes[nrow-1][ncol-1]->p += dp;
2487 if( patch[1] )
nodes[nrow-1][ncol+1]->p += dp;
2488 if( patch[2] )
nodes[nrow+1][ncol+1]->p += dp;
2489 if( patch[3] )
nodes[nrow+1][ncol-1]->p += dp;
2655 if (
nodes.empty() ) {
2656 std::cerr <<
"SPMeshNodeArray::outline_path: empty array!" << std::endl;
2660 outline.moveto(
nodes[0][0]->p );
2663 int nrow =
nodes.size();
2666 for (
int i = 1; i < ncol; i += 3 ) {
2671 for (
int i = 1; i < nrow; i += 3 ) {
2672 outline.curveto(
nodes[i][ncol-1]->p,
nodes[i+1][ncol-1]->p,
nodes[i+2][ncol-1]->p);
2676 for (
int i = 1; i < ncol; i += 3 ) {
2677 outline.curveto(
nodes[nrow-1][ncol-i-1]->p,
nodes[nrow-1][ncol-i-2]->p,
nodes[nrow-1][ncol-i-3]->p);
2681 for (
int i = 1; i < nrow; i += 3 ) {
2682 outline.curveto(
nodes[nrow-i-1][0]->p,
nodes[nrow-i-2][0]->p,
nodes[nrow-i-3][0]->p);
2685 outline.closepath();
2692 for (
int i = 0; i <
nodes[0].size(); ++i) {
2713 if (mesh_bbox->width() == 0 || mesh_bbox->height() == 0) {
2717 double scale_x = (*box).width() /(*mesh_bbox).width() ;
2718 double scale_y = (*box).height()/(*mesh_bbox).height();
2740 if( n > 1 )
split_row( row, (nn-1)/nn );
2761 assert( coord >= 0.0 && coord <= 1.0 );
2771 patch.updateNodes();
2775 for(
unsigned i = 0; i < 3; ++i ) {
2776 std::vector< SPMeshNode* > new_row;
2777 for(
unsigned j = 0; j <
nodes[0].size(); ++j ) {
2779 new_row.push_back( new_node );
2781 nodes.insert(
nodes.begin()+3*(row+1), new_row );
2784 unsigned i = 3 * row;
2785 for(
unsigned j = 0; j <
nodes[i].size(); ++j ) {
2790 for(
unsigned k = 0; k < 4; ++k ) {
2803 for(
unsigned n = 0;
n < 4; ++
n ) {
2804 nodes[i+
n ][j]->p = b_new.first[
n];
2805 nodes[i+
n+3][j]->p = b_new.second[
n];
2813 char path_type =
nodes[i+1][j]->path_type;
2814 nodes[i+4][j]->path_type = path_type;
2815 nodes[i+5][j]->path_type = path_type;
2823 nodes[i+3][j]->color =
nodes[i][j]->color->averaged(*
nodes[i+6][j]->color, coord);
2825 nodes[i+3][j]->set =
true;
2837 char path_type0 =
nodes[i ][j]->path_type;
2838 char path_type1 =
nodes[i+6][j]->path_type;
2839 char path_type =
'l';
2840 if( path_type0 ==
'L' || path_type1 ==
'L') path_type =
'L';
2841 if( path_type0 ==
'c' || path_type1 ==
'c') path_type =
'c';
2842 if( path_type0 ==
'C' || path_type1 ==
'C') path_type =
'C';
2843 nodes[i+3][j]->path_type = path_type;
2845 if( path_type ==
'c' || path_type ==
'C' )
nodes[i+3][j]->set =
true;
2875 assert( coord >= 0.0 && coord <= 1.0 );
2883 for(
unsigned i = 0; i <
patch_rows(); ++ i ) {
2885 patch.updateNodes();
2888 unsigned j = 3 * col;
2889 for(
unsigned i = 0; i <
nodes.size(); ++i ) {
2894 for(
unsigned k = 0; k < 4; ++k ) {
2895 p[k] =
nodes[i][j+k]->p;
2904 for(
unsigned n = 0;
n < 3; ++
n ) {
2906 nodes[i].insert(
nodes[i].begin()+j+3, new_node );
2910 for(
unsigned n = 0;
n < 4; ++
n ) {
2912 nodes[i][j+
n+3]->p = b_new.second[
n];
2919 char path_type =
nodes[i][j+1]->path_type;
2920 nodes[i][j+4]->path_type = path_type;
2921 nodes[i][j+5]->path_type = path_type;
2929 nodes[i][j+3]->color =
nodes[i][j]->color->averaged(*
nodes[i][j+6]->color, coord);
2931 nodes[i][j+3]->set =
true;
2943 char path_type0 =
nodes[i][j ]->path_type;
2944 char path_type1 =
nodes[i][j+6]->path_type;
2945 char path_type =
'l';
2946 if( path_type0 ==
'L' || path_type1 ==
'L') path_type =
'L';
2947 if( path_type0 ==
'c' || path_type1 ==
'c') path_type =
'c';
2948 if( path_type0 ==
'C' || path_type1 ==
'C') path_type =
'C';
2949 nodes[i][j+3]->path_type = path_type;
2951 if( path_type ==
'c' || path_type ==
'C' )
nodes[i][j+3]->set =
true;
2963 if( i ==
nodes.size() - 1 ) {
Colors::Color ink_cairo_surface_average_color(cairo_surface_t *surface, cairo_surface_t *mask)
Get the average color from the given surface.
Cairo integration helpers.
bool is(S const *s)
Equivalent to the boolean value of dynamic_cast<T const*>(...).
3x3 matrix representing an affine transformation.
bool isIdentity(Coord eps=EPSILON) const
Check whether this matrix is an identity matrix.
void setIdentity()
Sets this matrix to be the Identity Affine.
Bezier curve with compile-time specified order.
std::pair< BezierCurveN, BezierCurveN > subdivide(Coord t) const
Divide a Bezier curve into two curves.
Axis aligned, non-empty, generic rectangle.
C height() const
Get the vertical extent of the rectangle.
C width() const
Get the horizontal extent of the rectangle.
CPoint min() const
Get the corner of the rectangle with smallest coordinate values.
Infinite line on a plane.
Axis-aligned rectangle that can be empty.
size_type size() const
Get the number of paths in the vector.
OptRect boundsExact() const
Two-dimensional point that doubles as a vector.
Coord length() const
Compute the distance from origin.
Straight ray from a specific point to infinity.
Point pointAt(Coord t) const
Axis aligned, non-empty rectangle.
IntRect roundOutwards() const
Return the smallest integer rectangle which contains this one.
Minimal wrapper over Cairo.
void setRoot(DrawingItem *root)
void update(Geom::IntRect const &area=Geom::IntRect::infinite(), Geom::Affine const &affine=Geom::identity(), unsigned flags=DrawingItem::STATE_ALL, unsigned reset=0)
void render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags=0) const
Preference storage class.
static Preferences * get()
Access the singleton Preferences object.
int getInt(Glib::ustring const &pref_path, int def=0)
Retrieve an integer.
Interface for refcounted XML nodes.
virtual void appendChild(Node *child)=0
Append a node as the last child of this node.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
virtual Document * document()=0
Get the node's associated document.
bool setAttributeSvgDouble(Util::const_char_ptr key, double val)
For attributes where an exponent is allowed.
Wrapper around a Geom::PathVector object.
Geom::PathVector const & get_pathvector() const
Typed SVG document implementation.
SPRoot * getRoot()
Returns our SPRoot.
int ensureUpToDate(unsigned int object_modified_tag=0)
Repeatedly works on getting the document updated, since sometimes it takes more than one pass to get ...
SPGradient * getArray(bool force_private=false)
Returns private mesh of given gradient (the gradient at the end of the href chain which has patches),...
Geom::Affine gradientTransform
gradientTransform attribute
unsigned int gradientTransform_set
Paint type internal to SPStyle.
bool isPaintserver() const
Colors::Color const & getColor() const
Base class for visual SVG elements.
Inkscape::DrawingItem * invoke_show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags)
void invoke_hide(unsigned int key)
Geom::OptRect geometricBounds(Geom::Affine const &transform=Geom::identity()) const
Get item's geometric bounding box in this item's coordinate system.
Geom::Affine i2doc_affine() const
Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
static unsigned int display_key_new(unsigned numkeys)
Allocates unique integer keys.
std::vector< std::vector< SPMeshNode * > > nodes
bool fill_box(Geom::OptRect &box)
unsigned insert(std::vector< unsigned > const &)
Splits selected rows and/or columns in half (according to the path 't' parameter).
void split_row(unsigned i, unsigned n)
void split_column(unsigned j, unsigned n)
void update_node_vectors()
unsigned color_smooth(std::vector< unsigned > const &)
Attempts to smooth color transitions across corners.
void clear()
Clear mesh gradient.
unsigned patch_columns()
Number of patch columns.
unsigned side_arc(std::vector< unsigned > const &)
Converts generic Beziers to Beziers approximating elliptical arcs, preserving handle direction.
std::vector< SPMeshNode * > handles
bool read(SPMeshGradient *mg)
void bicubic(SPMeshNodeArray *smooth, SPMeshType type)
Fill 'smooth' with a smoothed version of the array by subdividing each patch into smaller patches.
unsigned side_toggle(std::vector< unsigned > const &)
Toggle sides between lineto and curve to if both corners selected.
void create(SPMeshGradient *mg, SPItem *item, Geom::OptRect bbox)
Create a default mesh.
unsigned tensor_toggle(std::vector< unsigned > const &)
Toggle sides between lineto and curve to if both corners selected.
std::vector< SPMeshNode * > corners
void transform(Geom::Affine const &m)
SPMeshNodeArray & operator=(const SPMeshNodeArray &rhs)
void print()
Print mesh gradient (for debugging).
void update_handles(unsigned corner, std::vector< unsigned > const &selected_corners, Geom::Point const &old_p, MeshNodeOperation op)
Moves handles in response to a corner node move.
bool adjacent_corners(unsigned i, unsigned j, SPMeshNode *n[4])
Inputs: i, j: Corner draggable indices.
void write(SPMeshGradient *mg)
Write repr using our array.
SPCurve outline_path() const
unsigned patch_rows()
Number of patch rows.
unsigned color_pick(std::vector< unsigned > const &, SPItem *)
Pick color from background for selected corners.
std::vector< SPMeshNode * > tensors
void setColor(unsigned i, Inkscape::Colors::Color const &c)
Set color for corner of patch.
void setPoint(unsigned side, unsigned point, Geom::Point const &p, bool set=true)
Set point for side in proper order for patch.
char getPathType(unsigned i)
Get path type for side (stored in handle nodes).
std::vector< Geom::Point > getPointsForSide(unsigned i)
Returns vector of points for a side in proper order for a patch (clockwise order).
void setTensorPoint(unsigned i, Geom::Point const &p)
Set tensor control point for "corner" i.
bool tensorIsSet()
Return if any tensor control point is set.
void setStopPtr(unsigned i, SPStop *)
Set stop pointer for corner of patch.
std::vector< std::vector< SPMeshNode * > > * nodes
Geom::Point getTensorPoint(unsigned i)
Return tensor control point for "corner" i.
SPStop * getStopPtr(unsigned i)
Return stop pointer for corner of patch.
Geom::Point coonsTensorPoint(unsigned i)
Find default tensor point (equivalent point to Coons Patch).
std::optional< Inkscape::Colors::Color > getColor(unsigned i)
Return color for corner of patch.
Geom::Point getPoint(unsigned side, unsigned point)
Returns point for side in proper order for patch.
SPMeshPatchI(std::vector< std::vector< SPMeshNode * > > *n, int r, int c)
void setPathType(unsigned, char t)
Set path type for side (stored in handle nodes).
void updateNodes()
Update default values for handle and tensor nodes.
void requestModified(unsigned int flags)
Requests that a modification notification signal be emitted later (e.g.
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
void deleteObject(bool propagate, bool propagate_descendants)
Deletes an object, unparenting it from its parent.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
Inkscape::Colors::Color getColor() const
SPPaintServer * getFillPaintServer()
T< SPAttr::FILL, SPIPaint > fill
fill
constexpr uint32_t SP_RGBA32_F_COMPOSE(double r, double g, double b, double a)
TODO: insert short description here.
Cairo drawing context with Inkscape extensions.
struct _cairo_surface cairo_surface_t
double Coord
Floating point type used to store coordinates.
Inkscape::XML::Node * node
Angle distance(Angle const &a, Angle const &b)
std::optional< Crossing > OptCrossing
Singleton class to access the preferences file in a convenient way.
SPCSSAttr * sp_repr_css_attr_new()
Creates an empty SPCSSAttr (a class for manipulating CSS style properties).
void sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr)
Sets an attribute (e.g.
void sp_repr_css_set_property_double(SPCSSAttr *css, gchar const *name, double value)
Set a style property to a new float value (e.g.
void sp_repr_css_attr_unref(SPCSSAttr *css)
Unreferences an SPCSSAttr (will be garbage collected if no references remain).
void sp_repr_css_set_property_string(SPCSSAttr *css, char const *name, std::string const &value)
Set a style property to a standard string.
double sum(const double alpha[16], const double &x, const double &y)
void invert(const double v[16], double alpha[16])
double find_slope1(double const p0, double const p1, double const p2, double const d01, double const d12)
static Inkscape::Colors::Color default_color(SPItem *item)
Find default color based on colors in existing fill.
@ SP_MESH_GEOMETRY_NORMAL
@ SP_MESH_GEOMETRY_CONICAL
SPMeshType
A group of classes and functions for manipulating mesh gradients.
TODO: insert short description here.
SPMeshpatch: SVG <meshpatch> implementation.
SPMeshrow: SVG <meshrow> implementation.
SPRoot: SVG <svg> implementation.
Geom::Point sp_star_get_xy(SPStar const *star, SPStarPoint point, gint index, bool randomized)
sp_star_get_xy: Get X-Y value as item coordinate system @star: star item @point: point type to obtain...
TODO: insert short description here.
Interface for XML documents.
virtual Node * createElement(char const *name)=0
SPStyle - a style object for SPItem objects.
Glib::RefPtr< Gtk::Adjustment > smooth
Interface for XML documents.