sp-mesh-array.h revision 214a2dca4418a9937d7142e42ed91fdfdb86ae16
1N/A#ifndef SEEN_SP_MESH_ARRAY_H
1N/A#define SEEN_SP_MESH_ARRAY_H
1N/A/*
1N/A * Authors:
1N/A * Tavmjong Bah <tavmjong@free.fr>
1N/A *
1N/A * Copyrigt (C) 2012 Tavmjong Bah
1N/A *
1N/A * Released under GNU GPL, read the file 'COPYING' for more information
1N/A */
1N/A
1N/A/**
1N/A A group of classes and functions for manipulating mesh gradients.
1N/A
1N/A A mesh is made up of an array of patches. Each patch has four sides and four corners. The sides can
1N/A be shared between two patches and the corners between up to four.
1N/A
1N/A The order of the points for each side always goes from left to right or top to bottom.
1N/A For sides 2 and 3 the points must be reversed when used (as in calls to cairo functions).
1N/A
1N/A Two patches: (C=corner, S=side, H=handle, T=tensor)
1N/A
1N/A C0 H1 H2 C1 C0 H1 H2 C1
1N/A + ---------- + ---------- +
1N/A | S0 | S0 |
1N/A H1 | T0 T1 |H1 T0 T1 | H1
1N/A |S3 S1|S3 S1|
1N/A H2 | T3 T2 |H2 T3 T2 | H2
1N/A | S2 | S2 |
1N/A + ---------- + ---------- +
1N/A C3 H1 H2 C2 C3 H1 H2 C2
1N/A
1N/A The mesh is stored internally as an array of nodes that includes the tensor nodes.
1N/A
1N/A Note: This code uses tensor points which are not part of the SVG2 plan at the moment.
1N/A Including tensor points was motivated by a desire to experiment with their usefulness
1N/A in smoothing color transitions. There doesn't seem to be much advantage for that
1N/A purpose. However including them internally allows for storing all the points in
1N/A an array which simplifies things like inserting new rows or columns.
1N/A*/
1N/A
1N/A#include <2geom/point.h>
1N/A#include "color.h"
1N/A
1N/A// For color picking
1N/A#include "sp-item.h"
1N/A
1N/Aenum SPMeshSmooth {
1N/A SP_MESH_SMOOTH_NONE,
1N/A SP_MESH_SMOOTH_SMOOTH,
1N/A SP_MESH_SMOOTH_SMOOTH1,
1N/A SP_MESH_SMOOTH_SMOOTH2,
1N/A SP_MESH_SMOOTH_SMOOTH3,
1N/A SP_MESH_SMOOTH_SMOOTH4,
1N/A SP_MESH_SMOOTH_SMOOTH5,
1N/A SP_MESH_SMOOTH_SMOOTH6,
1N/A SP_MESH_SMOOTH_SMOOTH7
1N/A};
1N/A
1N/Aenum NodeType {
1N/A MG_NODE_TYPE_UNKNOWN,
1N/A MG_NODE_TYPE_CORNER,
1N/A MG_NODE_TYPE_HANDLE,
1N/A MG_NODE_TYPE_TENSOR
1N/A};
1N/A
1N/A// Is a node along an edge?
1N/Aenum NodeEdge {
1N/A MG_NODE_EDGE_NONE,
1N/A MG_NODE_EDGE_TOP = 1,
1N/A MG_NODE_EDGE_LEFT = 2,
1N/A MG_NODE_EDGE_BOTTOM = 4,
1N/A MG_NODE_EDGE_RIGHT = 8
1N/A};
1N/A
1N/Aenum MeshCornerOperation {
1N/A MG_CORNER_SIDE_TOGGLE,
1N/A MG_CORNER_SIDE_ARC,
1N/A MG_CORNER_TENSOR_TOGGLE,
1N/A MG_CORNER_COLOR_SMOOTH,
1N/A MG_CORNER_COLOR_PICK
1N/A};
1N/A
1N/Aenum MeshNodeOperation {
1N/A MG_NODE_NO_SCALE,
1N/A MG_NODE_SCALE,
1N/A MG_NODE_SCALE_HANDLE
1N/A};
1N/A
1N/A
1N/Aclass SPMeshNode {
1N/Apublic:
1N/A SPMeshNode() {
1N/A node_type = MG_NODE_TYPE_UNKNOWN;
1N/A node_edge = MG_NODE_EDGE_NONE;
1N/A set = false;
1N/A draggable = -1;
1N/A path_type = 'u';
1N/A opacity = 0.0;
1N/A }
1N/A NodeType node_type;
1N/A unsigned int node_edge;
1N/A bool set;
1N/A Geom::Point p;
1N/A unsigned int draggable; // index of on-screen node
1N/A char path_type;
1N/A SPColor color;
1N/A double opacity;
1N/A};
1N/A
1N/A
1N/A// I for Internal to distinguish it from the Object class
1N/A// This is a convenience class...
1N/Aclass SPMeshPatchI {
1N/A
1N/Aprivate:
1N/A std::vector<std::vector< SPMeshNode* > > *nodes;
1N/A int row;
1N/A int col;
1N/A
1N/Apublic:
1N/A SPMeshPatchI( std::vector<std::vector< SPMeshNode* > > *n, int r, int c );
1N/A Geom::Point getPoint( unsigned int side, unsigned int point );
1N/A std::vector< Geom::Point > getPointsForSide( unsigned int i );
1N/A void setPoint( unsigned int side, unsigned int point, Geom::Point p, bool set = true );
1N/A char getPathType( unsigned int i );
1N/A void setPathType( unsigned int, char t );
1N/A Geom::Point getTensorPoint( unsigned int i );
1N/A void setTensorPoint( unsigned int i, Geom::Point p );
1N/A bool tensorIsSet();
1N/A bool tensorIsSet( unsigned int i );
1N/A Geom::Point coonsTensorPoint( unsigned int i );
1N/A void updateNodes();
1N/A SPColor getColor( unsigned int i );
1N/A void setColor( unsigned int i, SPColor c );
1N/A double getOpacity( unsigned int i );
1N/A void setOpacity( unsigned int i, double o );
1N/A};
1N/A
1N/Aclass SPMeshGradient;
1N/A
1N/A// An array of mesh nodes.
1N/Aclass SPMeshNodeArray {
1N/A
1N/A// Should be private
1N/Apublic:
1N/A SPMeshGradient *mg;
1N/A std::vector< std::vector< SPMeshNode* > > nodes;
1N/A
1N/Apublic:
1N/A // Draggables to nodes
1N/A bool drag_valid;
1N/A std::vector< SPMeshNode* > corners;
1N/A std::vector< SPMeshNode* > handles;
1N/A std::vector< SPMeshNode* > tensors;
1N/A
1N/Apublic:
1N/A
1N/A friend class SPMeshPatchI;
1N/A
1N/A SPMeshNodeArray() { built = false; mg = NULL; drag_valid = false; };
1N/A SPMeshNodeArray( SPMeshGradient *mg );
1N/A SPMeshNodeArray( const SPMeshNodeArray& rhs );
1N/A SPMeshNodeArray& operator=(const SPMeshNodeArray& rhs);
1N/A
1N/A ~SPMeshNodeArray() { clear(); };
1N/A bool built;
1N/A
1N/A void read( SPMeshGradient *mg );
1N/A void write( SPMeshGradient *mg );
1N/A void create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bbox );
1N/A void clear();
1N/A void print();
1N/A
1N/A // Fill 'smooth' with a smoothed version by subdividing each patch.
1N/A void smooth( SPMeshNodeArray* smooth, SPMeshSmooth type);
1N/A void smooth2( SPMeshNodeArray* smooth, SPMeshSmooth type);
1N/A
1N/A // Get size of patch
1N/A unsigned int patch_rows();
1N/A unsigned int patch_columns();
1N/A
1N/A SPMeshNode * node( unsigned int i, unsigned int j ) { return nodes[i][j]; }
1N/A
1N/A // Operations on corners
1N/A bool adjacent_corners( unsigned int i, unsigned int j, SPMeshNode* n[4] );
1N/A unsigned int side_toggle( std::vector< unsigned int > );
1N/A unsigned int side_arc( std::vector< unsigned int > );
1N/A unsigned int tensor_toggle( std::vector< unsigned int > );
1N/A unsigned int color_smooth( std::vector< unsigned int > );
1N/A unsigned int color_pick( std::vector< unsigned int >, SPItem* );
1N/A
1N/A // Update other nodes in response to a node move.
1N/A void update_handles( unsigned int corner, std::vector< unsigned int > selected_corners, Geom::Point old_p, MeshNodeOperation op );
1N/A
1N/A void split_row( unsigned int i, unsigned int n );
1N/A void split_column( unsigned int j, unsigned int n );
1N/A void split_row( unsigned int i, double coord );
1N/A void split_column( unsigned int j, double coord );
1N/A};
1N/A
1N/A#endif /* !SEEN_SP_MESH_ARRAY_H */
1N/A
1N/A/*
1N/A Local Variables:
1N/A mode:c++
1N/A c-file-style:"stroustrup"
1N/A c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1N/A c-basic-offset:2
1N/A indent-tabs-mode:nil
1N/A fill-column:99
1N/A End:
1N/A*/
1N/A// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
1N/A