Added support for paths

This commit is contained in:
Edward Hennessy 2010-09-13 15:52:51 -07:00
parent 1e7ade8765
commit d09aae6c20
15 changed files with 1976 additions and 18 deletions

View File

@ -130,6 +130,8 @@ libsch_la_SOURCES = \
sch-multiline.c \
sch-net.c \
sch-output-stream.c \
sch-path.c \
sch-path-command.c \
sch-pin.c \
sch-shape.c \
sch-text.c
@ -147,6 +149,7 @@ libschgui_la_SOURCES = \
schgui-cairo-factory.c \
schgui-cairo-line.c \
schgui-cairo-net.c \
schgui-cairo-path.c \
schgui-cairo-pin.c \
schgui-cairo-text.c \
schgui-clipboard.c \

View File

@ -41,7 +41,7 @@
* \c VOLTS Voltage.
*/
/* FIXME Below needs to work with all compilers. The following will work in
/*! \todo Below needs to work with all compilers. The following will work in
* GCC even without C99 support, but it will issue a warning.
*/
//#ifdef __STDC__VERSION__
@ -156,7 +156,7 @@ static const GPartsUnitsFormat gparts_units_format[] =
/*!
*
*
* FIXME Add sentinel to the table.
* \todo Add sentinel to the table.
*/
static const GPartsUnitsMetricPrefix gparts_units_metric_prefixes[] =
{

View File

@ -202,11 +202,11 @@ sch_file_format_2_write_net(const SchFileFormat2 *format, SchOutputStream *strea
}
//void
//sch_file_format_2_write_path(const SchFileFormat2 *format, SchOutputStream *stream, const SchPath *shape, GError **error)
//{
//sch_output_stream_write_path_2(stream, shape, NULL);
//}
void
sch_file_format_2_write_path(const SchFileFormat2 *format, SchOutputStream *stream, const SchPath *shape, GError **error)
{
sch_output_stream_write_path_2(stream, shape, NULL);
}
void
sch_file_format_2_write_picture(const SchFileFormat2 *format, SchOutputStream *stream, const SchPicture *shape, GError **error)

View File

@ -70,8 +70,8 @@ sch_file_format_2_write_line(const SchFileFormat2 *format, SchOutputStream *stre
void
sch_file_format_2_write_net(const SchFileFormat2 *format, SchOutputStream *stream, const SchNet *shape, GError **error);
//void
//sch_file_format_2_write_path(const SchFileFormat2 *format, SchOutputStream *stream, const SchPath *shape, GError **error);
void
sch_file_format_2_write_path(const SchFileFormat2 *format, SchOutputStream *stream, const SchPath *shape, GError **error);
void
sch_file_format_2_write_picture(const SchFileFormat2 *format, SchOutputStream *stream, const SchPicture *shape, GError **error);

View File

@ -68,6 +68,9 @@ typedef struct _SchNetClass SchNetClass;
typedef struct _SchOutputStream SchOutputStream;
typedef struct _SchOutputStreamClass SchOutputStreamClass;
typedef struct _SchPath SchPath;
typedef struct _SchPathClass SchPathClass;
typedef struct _SchPin SchPin;
typedef struct _SchPinClass SchPinClass;

View File

@ -19,6 +19,8 @@
*/
/*! \file sch-loader.c
*
* \todo Clean up this mess!
*/
#include <errno.h>
@ -118,7 +120,11 @@ read_file(SchDrawing *drawing, FILE *file, GError **error);
static gchar*
read_line(FILE *file);
static gchar*
read_lines(FILE *file, int count);
static void
process_path_commands(SchPath *path, const char* string);
void
@ -522,6 +528,25 @@ static const struct PARAM net_params[] =
{ NULL, 0 }
};
static const struct PARAM path_params[] =
{
{ NULL, 1 },
{ "color", 1 },
{ "line-width", 3 },
{ "line-cap-style", 3 },
{ "line-dash-style", 3 },
{ "line-dash-length", 3 },
{ "line-dash-space", 3 },
{ "fill-type", 3 },
{ "fill-width", 3 },
{ "fill-angle1", 3 },
{ "fill-pitch1", 3 },
{ "fill-angle2", 3 },
{ "fill-pitch2", 3 },
{ NULL, 0 }
};
static const struct PARAM pin_params[] =
{
@ -873,6 +898,10 @@ process_object(FILE *file, gchar **tokens)
static GObject*
process_path(FILE *file, gchar **tokens)
{
SchPath *path = sch_path_new(NULL);
process_params(G_OBJECT(path), tokens, path_params, 14);
//g_debug("Process path");
if ((tokens != NULL) && (g_strv_length(tokens) > 13))
{
@ -891,18 +920,20 @@ process_path(FILE *file, gchar **tokens)
}
else
{
long index;
gchar *line = read_lines(file, lines);
for (index=0; index<lines; index++)
{
gchar *line = read_line(file);
g_free(line);
}
g_debug("Got some path stuff");
g_debug("%d", lines);
g_debug("%s", line);
process_path_commands(path, line);
g_free(line);
}
}
return NULL;
return path;
}
static GObject*
@ -1008,6 +1039,41 @@ read_line(FILE *file)
return result;
}
/*! \brief Reads a line from a file
*/
static gchar*
read_lines(FILE *file, int count)
{
gchar *result = NULL;
if (!feof(file) && (count > 0))
{
gint c = fgetc(file);
GString *line = g_string_sized_new(10);
while (!ferror(file) && !feof(file))
{
if (c == '\n')
{
count--;
if (count <= 0)
{
break;
}
}
g_string_append_c(line, c);
c = fgetc(file);
}
result = g_string_free(line, ferror(file));
}
return result;
}
static void
read_file(SchDrawing *drawing, FILE *file, GError **error)
@ -1145,3 +1211,190 @@ process_params(GObject *object, gchar **token, const struct PARAM paramv[], gint
}
}
static void
process_path_command_closepath(SchPath *path, GMatchInfo *match_info);
static void
process_path_command_curveto(SchPath *path, GMatchInfo *match_info);
static void
process_path_command_lineto(SchPath *path, GMatchInfo *match_info);
static void
process_path_command_moveto(SchPath *path, GMatchInfo *match_info);
static void
process_path_commands(SchPath *path, const char* string)
{
GRegex *re = g_regex_new(
"([MmLlCcZz])([[:space:]]*([0-9]+)([[:space:]]*[,]?[[:space:]]*([0-9]+))*)*",
0,
0,
NULL
);
if (re != NULL)
{
GMatchInfo *match_info;
g_regex_match(re, string, 0, &match_info);
while (g_match_info_matches (match_info))
{
gchar *word = g_match_info_fetch (match_info, 0);
switch (*word)
{
case 'C':
process_path_command_curveto(path, match_info);
break;
case 'L':
process_path_command_lineto(path, match_info);
break;
case 'M':
process_path_command_moveto(path, match_info);
break;
case 'z':
process_path_command_closepath(path, match_info);
break;
deafult:
break;
}
g_free (word);
g_match_info_next (match_info, NULL);
}
g_match_info_free(match_info);
g_regex_unref(re);
}
}
static void
process_path_command_closepath(SchPath *path, GMatchInfo *match_info)
{
gchar *word = g_match_info_fetch (match_info, 0);
SchPathCommand command;
g_debug("Closepath: %s", word);
command.type = SCH_PATH_COMMAND_CLOSEPATH;
sch_path_append(path, &command);
g_free (word);
}
static void
process_path_command_curveto(SchPath *path, GMatchInfo *match_info)
{
gchar *word = g_match_info_fetch (match_info, 0);
SchPathCommand command;
int i;
int count = g_match_info_get_match_count(match_info);
g_debug("Curveto: %s", word);
command.type = SCH_PATH_COMMAND_CURVETO_ABS;
for (i=0; (i+13)<count; i++)
{
gchar *a = g_match_info_fetch (match_info, i+3);
command.curveto.x[0] = atoi(a);
g_free (a);
a = g_match_info_fetch (match_info, i+5);
command.curveto.y[0] = atoi(a);
g_free (a);
a = g_match_info_fetch (match_info, i+7);
command.curveto.x[1] = atoi(a);
g_free (a);
a = g_match_info_fetch (match_info, i+9);
command.curveto.y[1] = atoi(a);
g_free (a);
a = g_match_info_fetch (match_info, i+11);
command.curveto.x[2] = atoi(a);
g_free (a);
a = g_match_info_fetch (match_info, i+13);
command.curveto.y[2] = atoi(a);
g_free (a);
sch_path_append(path, &command);
}
g_free (word);
}
static void
process_path_command_lineto(SchPath *path, GMatchInfo *match_info)
{
gchar *word = g_match_info_fetch (match_info, 0);
SchPathCommand command;
int i;
int count = g_match_info_get_match_count(match_info);
g_debug("Lineto: %s", word);
command.type = SCH_PATH_COMMAND_LINETO_ABS;
for (i=0; (i+5)<count; i++)
{
gchar *a = g_match_info_fetch (match_info, i+3);
command.lineto.x = atoi(a);
g_free (a);
a = g_match_info_fetch (match_info, i+5);
command.lineto.y = atoi(a);
g_free (a);
sch_path_append(path, &command);
}
g_free (word);
}
static void
process_path_command_moveto(SchPath *path, GMatchInfo *match_info)
{
gchar *word = g_match_info_fetch (match_info, 0);
SchPathCommand command;
int i;
int count = g_match_info_get_match_count(match_info);
g_debug("Moveto: %s", word);
command.type = SCH_PATH_COMMAND_MOVETO_ABS;
for (i=0; (i+5)<count; i++)
{
gchar *a = g_match_info_fetch (match_info, i+3);
command.lineto.x = atoi(a);
g_free (a);
a = g_match_info_fetch (match_info, i+5);
command.lineto.y = atoi(a);
g_free (a);
sch_path_append(path, &command);
command.type = SCH_PATH_COMMAND_LINETO_ABS;
}
g_free (word);
}

View File

@ -52,6 +52,8 @@ sch_output_stream_get_property(GObject *object, guint property_id, GValue *value
static void
sch_output_stream_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
static void
sch_output_stream_write_path_2_proc(SchPathCommand *command, gpointer user_data);
static void
@ -778,8 +780,187 @@ sch_output_stream_write_net_2(SchOutputStream *stream, const SchNet *shape, GErr
}
//void
//sch_output_stream_write_path_2(SchOutputStream *stream, const SchPath *shape, GError **error);
void
sch_output_stream_write_path_2(SchOutputStream *stream, const SchPath *shape, GError **error)
{
SchOutputStreamPrivate *privat = SCH_OUTPUT_STREAM_GET_PRIVATE(stream);
if (privat != NULL && shape != NULL)
{
gchar *str;
int x;
int y;
int radius;
int color;
int line_width;
int capstyle;
int dashstyle;
int dashlength;
int dashspace;
int fill_type;
int fill_width;
int fill_angle1;
int fill_pitch1;
int fill_angle2;
int fill_pitch2;
int count = sch_path_count(shape);
g_object_get(
(gpointer) shape,
"color", &color,
"line-width", &line_width,
"line-cap-style", &capstyle,
"line-dash-style", &dashstyle,
"line-dash-length", &dashlength,
"line-dash-space", &dashspace,
"fill-type", &fill_type,
"fill-width", &fill_width,
"fill-angle1", &fill_angle1,
"fill-pitch1", &fill_pitch1,
"fill-angle2", &fill_angle2,
"fill-pitch2", &fill_pitch2,
NULL
);
str = g_strdup_printf(
"%s %d %d %d %d %d %d %d %d %d %d %d %d %d%s",
"H",
color,
line_width,
capstyle,
dashstyle,
dashlength,
dashspace,
fill_type,
fill_width,
fill_angle1,
fill_pitch1,
fill_angle2,
fill_pitch2,
count,
SCH_OUTPUT_STREAM_EOL
);
g_output_stream_write(
privat->base_stream,
str,
strlen(str),
NULL,
error
);
sch_path_foreach(shape, sch_output_stream_write_path_2_proc, stream);
g_free(str);
}
}
static void
sch_output_stream_write_path_2_proc(SchPathCommand *command, gpointer user_data)
{
SchOutputStreamPrivate *privat = SCH_OUTPUT_STREAM_GET_PRIVATE(user_data);
if ((privat != NULL) && (command != NULL))
{
gchar *str = NULL;
switch (command->type)
{
case SCH_PATH_COMMAND_INVALID:
g_debug("SchGUICairoPath: invalid path command");
break;
case SCH_PATH_COMMAND_CLOSEPATH:
str = g_strdup_printf(
"%s%s",
"z",
SCH_OUTPUT_STREAM_EOL
);
break;
case SCH_PATH_COMMAND_CURVETO_ABS:
str = g_strdup_printf(
"%s %d %d %d %d %d %d%s",
"C",
command->curveto.x[0],
command->curveto.y[0],
command->curveto.x[1],
command->curveto.y[1],
command->curveto.x[2],
command->curveto.y[2],
SCH_OUTPUT_STREAM_EOL
);
break;
case SCH_PATH_COMMAND_CURVETO_REL:
str = g_strdup_printf(
"%s %d %d %d %d %d %d%s",
"c",
command->curveto.x[0],
command->curveto.y[0],
command->curveto.x[1],
command->curveto.y[1],
command->curveto.x[2],
command->curveto.y[2],
SCH_OUTPUT_STREAM_EOL
);
break;
case SCH_PATH_COMMAND_LINETO_ABS:
str = g_strdup_printf(
"%s %d %d%s",
"L",
command->lineto.x,
command->lineto.y,
SCH_OUTPUT_STREAM_EOL
);
break;
case SCH_PATH_COMMAND_LINETO_REL:
str = g_strdup_printf(
"%s %d %d%s",
"l",
command->lineto.x,
command->lineto.y,
SCH_OUTPUT_STREAM_EOL
);
break;
case SCH_PATH_COMMAND_MOVETO_ABS:
str = g_strdup_printf(
"%s %d %d%s",
"M",
command->moveto.x,
command->moveto.y,
SCH_OUTPUT_STREAM_EOL
);
break;
case SCH_PATH_COMMAND_MOVETO_REL:
str = g_strdup_printf(
"%s %d %d%s",
"m",
command->moveto.x,
command->moveto.y,
SCH_OUTPUT_STREAM_EOL
);
break;
default:
g_debug("SchGUICairoPath: unknown path command");
}
g_output_stream_write(
privat->base_stream,
str,
strlen(str),
NULL,
NULL /*! \todo FIXME error */
);
g_free(str);
}
}
void
sch_output_stream_write_picture_2(SchOutputStream *stream, const SchPicture *shape, GError **error)

158
src/sch-path-command.c Normal file
View File

@ -0,0 +1,158 @@
/* gEDA - GPL Electronic Design Automation
* gparts - gEDA Parts Manager
* Copyright (C) 2009 Edward C. Hennessy
* Copyright (C) 2009 gEDA Contributors (see ChangeLog for details)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
/*! \file sch-path-command.c
*/
#include <glib.h>
#include <glib-object.h>
#include "sch.h"
SchPathCommand*
sch_path_command_copy(const SchPathCommand *command)
{
return (SchPathCommand*) g_memdup(command, sizeof(SchPathCommand));
}
GType
sch_path_command_get_type(void)
{
static GType type = G_TYPE_INVALID;
if (type == G_TYPE_INVALID)
{
g_boxed_type_register_static(
"SchPathCommand",
(GBoxedCopyFunc) sch_path_command_copy,
(GBoxedFreeFunc) sch_path_command_free
);
}
return type;
}
void
sch_path_command_free(SchPathCommand *command)
{
g_free(command);
}
void
sch_path_command_rotate(SchPathCommand *command, int angle)
{
/*! \todo Implement */
if (command != NULL)
{
switch (command->type)
{
case SCH_PATH_COMMAND_CURVETO_ABS:
case SCH_PATH_COMMAND_CURVETO_REL:
break;
case SCH_PATH_COMMAND_LINETO_ABS:
case SCH_PATH_COMMAND_LINETO_REL:
break;
case SCH_PATH_COMMAND_MOVETO_ABS:
case SCH_PATH_COMMAND_MOVETO_REL:
break;
case SCH_PATH_COMMAND_INVALID:
case SCH_PATH_COMMAND_CLOSEPATH:
default:
break;
}
}
}
void
sch_path_command_transform(SchPathCommand *command, const GeomTransform *transform)
{
/*! \todo Implement */
if (command != NULL)
{
switch (command->type)
{
case SCH_PATH_COMMAND_CURVETO_ABS:
break;
case SCH_PATH_COMMAND_CURVETO_REL:
break;
case SCH_PATH_COMMAND_LINETO_ABS:
break;
case SCH_PATH_COMMAND_LINETO_REL:
break;
case SCH_PATH_COMMAND_MOVETO_ABS:
break;
case SCH_PATH_COMMAND_MOVETO_REL:
break;
case SCH_PATH_COMMAND_INVALID:
case SCH_PATH_COMMAND_CLOSEPATH:
default:
break;
}
}
}
void
sch_path_command_translate(SchPathCommand *command, int dx, int dy)
{
if (command != NULL)
{
switch (command->type)
{
case SCH_PATH_COMMAND_CURVETO_ABS:
command->curveto.x[0] += dx;
command->curveto.y[0] += dy;
command->curveto.x[1] += dx;
command->curveto.y[1] += dy;
command->curveto.x[2] += dx;
command->curveto.y[2] += dy;
break;
case SCH_PATH_COMMAND_LINETO_ABS:
command->lineto.x += dx;
command->lineto.y += dy;
break;
case SCH_PATH_COMMAND_MOVETO_ABS:
command->moveto.x += dx;
command->moveto.y += dy;
break;
case SCH_PATH_COMMAND_INVALID:
case SCH_PATH_COMMAND_CLOSEPATH:
case SCH_PATH_COMMAND_CURVETO_REL:
case SCH_PATH_COMMAND_LINETO_REL:
case SCH_PATH_COMMAND_MOVETO_REL:
default:
break;
}
}
}

134
src/sch-path-command.h Normal file
View File

@ -0,0 +1,134 @@
/* gEDA - GPL Electronic Design Automation
* gparts - gEDA Parts Manager
* Copyright (C) 2009 Edward C. Hennessy
* Copyright (C) 2009 gEDA Contributors (see ChangeLog for details)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
/*! \file sch-path-command.h
*
* \brief A boxed type for storing a path command
*/
#define SCH_TYPE_PATH_COMMAND (sch_path_command_get_type())
#define SCH_PATH_COMMAND(obj) ((SchPathCommand*)obj)
typedef enum _SchPathCommandType SchPathCommandType;
typedef union _SchPathCommand SchPathCommand;
typedef struct _SchPathCommandCurveTo SchPathCommandCurveTo;
typedef struct _SchPathCommandLineTo SchPathCommandLineTo;
typedef struct _SchPathCommandMoveTo SchPathCommandMoveTo;
enum _SchPathCommandType
{
SCH_PATH_COMMAND_INVALID,
SCH_PATH_COMMAND_CLOSEPATH,
SCH_PATH_COMMAND_CURVETO_ABS,
SCH_PATH_COMMAND_CURVETO_REL,
SCH_PATH_COMMAND_LINETO_ABS,
SCH_PATH_COMMAND_LINETO_REL,
SCH_PATH_COMMAND_MOVETO_ABS,
SCH_PATH_COMMAND_MOVETO_REL
};
struct _SchPathCommandCurveTo
{
SchPathCommandType type;
int x[3];
int y[3];
};
struct _SchPathCommandLineTo
{
SchPathCommandType type;
int x;
int y;
};
struct _SchPathCommandMoveTo
{
SchPathCommandType type;
int x;
int y;
};
union _SchPathCommand
{
SchPathCommandType type;
SchPathCommandCurveTo curveto;
SchPathCommandLineTo lineto;
SchPathCommandMoveTo moveto;
};
/*! \brief Make a copy of the
*
* \param [in] command The command to be copied
* \return A pointer to the copied command
*/
SchPathCommand*
sch_path_command_copy(const SchPathCommand *command);
/*! \brief Free the memory associated with a path command
*
* \param [in] command The path command to be freed
*/
void
sch_path_command_free(SchPathCommand *command);
/*! \brief Rotate the path command
*
* This function requires calls to sin() and cos(). If the caller is rotating
* a number of path commands, performance may be better to use a transform.
*
* \param [in] command The path command to be rotated
* \param [in] angle The angle to rotate, in degrees
*/
void
sch_path_command_rotate(SchPathCommand *command, int angle);
/*! \brief Transform the path command
*
* Ablolute path commands undergo the full transformation. Relative path
* commands only undergo scaling and rotation.
*
* \todo May require functionality to force the command to be interpreted as
* absolute for the special case of a relative moveto as the first command
* in a path.
*
* \param [in] command The path command to be transformed
* \param [in] transform The transformation matrix
*/
void
sch_path_command_transform(SchPathCommand *command, const GeomTransform *transform);
/*! \brief Translate the path command
*
* This function only modifies absolute commands. Relative commands do not
* require translation.
*
* \todo May require functionality to force the command to be interpreted as
* absolute for the special case of a relative moveto as the first command
* in a path.
*
* \param [in] command The path command to be translated
* \param [in] dx The distance to translate on the x axis
* \param [in] dy The distance to translate on the y axis
*/
void
sch_path_command_translate(SchPathCommand *command, int dx, int dy);

654
src/sch-path.c Normal file
View File

@ -0,0 +1,654 @@
/* gEDA - GPL Electronic Design Automation
* gparts - gEDA Parts Manager
* Copyright (C) 2009 Edward C. Hennessy
* Copyright (C) 2009 gEDA Contributors (see ChangeLog for details)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
/*! \file sch-path.c
*/
#include <glib.h>
#include <glib-object.h>
#include "misc-object.h"
#include "sch.h"
#define SCH_PATH_DEFAULT_COLOR (SCH_CONFIG_DEFAULT_GRAPHIC_COLOR)
#define SCH_PATH_DEFAULT_LINE_WIDTH (SCH_CONFIG_DEFAULT_LINE_WIDTH)
#define SCH_PATH_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj),SCH_TYPE_PATH,SchPathPrivate))
enum
{
SCH_PATH_COLOR = 1,
SCH_PATH_WIDTH,
SCH_PATH_CAP_STYLE,
SCH_PATH_DASH_STYLE,
SCH_PATH_DASH_LENGTH,
SCH_PATH_DASH_SPACE,
SCH_PATH_FILL_TYPE,
SCH_PATH_FILL_WIDTH,
SCH_PATH_FILL_ANGLE1,
SCH_PATH_FILL_PITCH1,
SCH_PATH_FILL_ANGLE2,
SCH_PATH_FILL_PITCH2
};
typedef struct _SchPathPrivate SchPathPrivate;
struct _SchPathPrivate
{
GSList *commands;
gint color;
gint line_width;
SchLineStyle line_style;
SchFillStyle fill_style;
};
static void
sch_path_class_init(gpointer g_class, gpointer g_class_data);
static void
sch_path_finalize(GObject *object);
static void
sch_path_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
static void
sch_path_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
static void
sch_path_rotate(SchShape *shape, int angle);
static void
sch_path_transform(SchShape *shape, const GeomTransform *transform);
static void
sch_path_translate(SchShape *shape, int dx, int dy);
static void
sch_path_write(SchShape *shape, SchFileFormat2 *format, SchOutputStream *stream, GError **error);
void
sch_path_append(SchPath *path, const SchPathCommand *command)
{
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(path);
if (privat != NULL)
{
SchPathCommand *copy = sch_path_command_copy(command);
if (copy != NULL)
{
privat->commands = g_slist_append(privat->commands, copy);
}
}
}
static void
sch_path_class_init(gpointer g_class, gpointer g_class_data)
{
GObjectClass *klasse = G_OBJECT_CLASS(g_class);
SchPathClass *klasse1 = SCH_PATH_CLASS(g_class);
g_type_class_add_private(klasse, sizeof(SchPathPrivate));
klasse->finalize = sch_path_finalize;
klasse->get_property = sch_path_get_property;
klasse->set_property = sch_path_set_property;
klasse1->parent.rotate = sch_path_rotate;
klasse1->parent.transform = sch_path_transform;
klasse1->parent.translate = sch_path_translate;
klasse1->parent.write = sch_path_write;
g_object_class_install_property(
klasse,
SCH_PATH_COLOR,
g_param_spec_int(
"color",
"Color",
"Color",
0,
G_MAXINT,
SCH_PATH_DEFAULT_COLOR,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
g_object_class_install_property(
klasse,
SCH_PATH_WIDTH,
g_param_spec_int(
"line-width",
"Line Width",
"Line Width",
0,
G_MAXINT,
SCH_PATH_DEFAULT_LINE_WIDTH,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
g_object_class_install_property(
klasse,
SCH_PATH_CAP_STYLE,
g_param_spec_int(
"line-cap-style",
"Line Cap Style",
"Line Cap Style",
0,
2,
0,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
g_object_class_install_property(
klasse,
SCH_PATH_DASH_STYLE,
g_param_spec_int(
"line-dash-style",
"Line dash Style",
"Line dash Style",
0,
4,
0,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
g_object_class_install_property(
klasse,
SCH_PATH_DASH_LENGTH,
g_param_spec_int(
"line-dash-length",
"Line Dash Length",
"Line Dash Length",
-1,
G_MAXINT,
-1,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
g_object_class_install_property(
klasse,
SCH_PATH_DASH_SPACE,
g_param_spec_int(
"line-dash-space",
"Line Dash Space",
"Line Dash Space",
-1,
G_MAXINT,
-1,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
g_object_class_install_property(
klasse,
SCH_PATH_FILL_TYPE,
g_param_spec_int(
"fill-type",
"Fill Type",
"Fill Type",
-1,
G_MAXINT,
-1,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
g_object_class_install_property(
klasse,
SCH_PATH_FILL_WIDTH,
g_param_spec_int(
"fill-width",
"Fill Width",
"Fill Width",
-1,
G_MAXINT,
-1,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
g_object_class_install_property(
klasse,
SCH_PATH_FILL_ANGLE1,
g_param_spec_int(
"fill-angle1",
"Fill Angle 1",
"Fill Angle 1",
-1,
G_MAXINT,
-1,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
g_object_class_install_property(
klasse,
SCH_PATH_FILL_PITCH1,
g_param_spec_int(
"fill-pitch1",
"Fill Pitch 1",
"Fill Pitch 1",
-1,
G_MAXINT,
-1,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
g_object_class_install_property(
klasse,
SCH_PATH_FILL_ANGLE2,
g_param_spec_int(
"fill-angle2",
"Fill Angle 2",
"Fill Angle 2",
-1,
G_MAXINT,
-1,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
g_object_class_install_property(
klasse,
SCH_PATH_FILL_PITCH2,
g_param_spec_int(
"fill-pitch2",
"Fill Pitch 2",
"Fill Pitch 2",
-1,
G_MAXINT,
-1,
G_PARAM_LAX_VALIDATION | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
)
);
}
int
sch_path_count(const SchPath *path)
{
int count;
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(path);
if (privat != NULL)
{
count = g_slist_length(privat->commands);
}
return count;
}
static void
sch_path_finalize(GObject *object)
{
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(object);
if (privat != NULL)
{
GSList *node = privat->commands;
while (node != NULL)
{
sch_path_command_free(SCH_PATH_COMMAND(node->data));
node = g_slist_next(node);
}
g_slist_free(privat->commands);
privat->commands = NULL;
}
misc_object_chain_finalize(object);
}
void
sch_path_foreach(SchPath *path, GFunc func, gpointer user_data)
{
if (func != NULL)
{
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(path);
if (privat != NULL)
{
GSList *node = privat->commands;
while (node != NULL)
{
func(node->data, user_data);
node = g_slist_next(node);
}
}
}
}
void
sch_path_get_fill_style(const SchPath *path, SchFillStyle *style)
{
if (style != NULL)
{
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(path);
if (privat != NULL)
{
*style = privat->fill_style;
}
else
{
sch_fill_style_init(style);
}
}
}
static void
sch_path_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(object);
if (privat != NULL)
{
switch (property_id)
{
case SCH_PATH_COLOR:
g_value_set_int(value, privat->color);
break;
case SCH_PATH_WIDTH:
g_value_set_int(value, privat->line_width);
break;
case SCH_PATH_CAP_STYLE:
g_value_set_int(value, privat->line_style.cap_style);
break;
case SCH_PATH_DASH_STYLE:
g_value_set_int(value, privat->line_style.dash_style);
break;
case SCH_PATH_DASH_LENGTH:
g_value_set_int(value, privat->line_style.dash_length);
break;
case SCH_PATH_DASH_SPACE:
g_value_set_int(value, privat->line_style.dash_space);
break;
case SCH_PATH_FILL_TYPE:
g_value_set_int(value, privat->fill_style.type);
break;
case SCH_PATH_FILL_WIDTH:
g_value_set_int(value, privat->fill_style.width);
break;
case SCH_PATH_FILL_ANGLE1:
g_value_set_int(value, privat->fill_style.angle1);
break;
case SCH_PATH_FILL_PITCH1:
g_value_set_int(value, privat->fill_style.pitch1);
break;
case SCH_PATH_FILL_ANGLE2:
g_value_set_int(value, privat->fill_style.angle2);
break;
case SCH_PATH_FILL_PITCH2:
g_value_set_int(value, privat->fill_style.pitch2);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
}
}
}
GType
sch_path_get_type(void)
{
static GType type = G_TYPE_INVALID;
if (type == G_TYPE_INVALID)
{
static const GTypeInfo tinfo = {
sizeof(SchPathClass), /* class_size */
NULL, /* base_init */
NULL, /* base_finalize */
sch_path_class_init, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
sizeof(SchPath), /* instance_size */
0, /* n_preallocs */
NULL, /* instance_init */
NULL /* value_table */
};
type = g_type_register_static(
SCH_TYPE_SHAPE,
"SchPath",
&tinfo,
0
);
}
return type;
}
static void
sch_path_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(object);
if (privat != NULL)
{
switch (property_id)
{
case SCH_PATH_COLOR:
privat->color = g_value_get_int(value);
break;
case SCH_PATH_WIDTH:
privat->line_width = g_value_get_int(value);
break;
case SCH_PATH_CAP_STYLE:
privat->line_style.cap_style = g_value_get_int(value);
break;
case SCH_PATH_DASH_STYLE:
privat->line_style.dash_style = g_value_get_int(value);
break;
case SCH_PATH_DASH_LENGTH:
privat->line_style.dash_length = g_value_get_int(value);
break;
case SCH_PATH_DASH_SPACE:
privat->line_style.dash_space = g_value_get_int(value);
break;
case SCH_PATH_FILL_TYPE:
privat->fill_style.type = g_value_get_int(value);
break;
case SCH_PATH_FILL_WIDTH:
privat->fill_style.width = g_value_get_int(value);
break;
case SCH_PATH_FILL_ANGLE1:
privat->fill_style.angle1 = g_value_get_int(value);
break;
case SCH_PATH_FILL_PITCH1:
privat->fill_style.pitch1 = g_value_get_int(value);
break;
case SCH_PATH_FILL_ANGLE2:
privat->fill_style.angle2 = g_value_get_int(value);
break;
case SCH_PATH_FILL_PITCH2:
privat->fill_style.pitch2 = g_value_get_int(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
}
}
}
int
sch_path_get_color(const SchPath *path)
{
int color = SCH_PATH_DEFAULT_COLOR;
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(path);
if (privat != NULL)
{
color = privat->color;
}
return color;
}
void
sch_path_get_line_style(const SchPath *shape, SchLineStyle *style)
{
if (style != NULL)
{
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(shape);
if (privat != NULL)
{
*style = privat->line_style;
}
else
{
sch_line_style_init(style);
}
}
}
int
sch_path_get_line_width(const SchPath *path)
{
int line_width = SCH_PATH_DEFAULT_LINE_WIDTH;
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(path);
if (privat != NULL)
{
line_width = privat->line_width;
}
return line_width;
}
SchPath*
sch_path_new(const SchConfig *config)
{
return SCH_PATH(g_object_new(
SCH_TYPE_PATH,
"color", sch_config_get_graphic_color(config),
"line-width", sch_config_get_line_width(config),
NULL
));
}
/*! \todo May be faster to create a transform than have each command call
* sin() and cos().
*/
static void
sch_path_rotate(SchShape *shape, int angle)
{
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(shape);
if (privat != NULL)
{
GSList *node = privat->commands;
while (node != NULL)
{
sch_path_command_rotate(SCH_PATH_COMMAND(node->data), angle);
node = g_slist_next(node);
}
}
}
static void
sch_path_transform(SchShape *shape, const GeomTransform *transform)
{
if (transform != NULL)
{
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(shape);
if (privat != NULL)
{
GSList *node = privat->commands;
while (node != NULL)
{
sch_path_command_transform(SCH_PATH_COMMAND(node->data), transform);
node = g_slist_next(node);
}
}
}
}
static void
sch_path_translate(SchShape *shape, int dx, int dy)
{
SchPathPrivate *privat = SCH_PATH_GET_PRIVATE(shape);
if (privat != NULL)
{
GSList *node = privat->commands;
while (node != NULL)
{
sch_path_command_translate(SCH_PATH_COMMAND(node->data), dx, dy);
node = g_slist_next(node);
}
}
}
static void
sch_path_write(SchShape *shape, SchFileFormat2 *format, SchOutputStream *stream, GError **error)
{
sch_file_format_2_write_path(format, stream, SCH_PATH(shape), error);
}

108
src/sch-path.h Normal file
View File

@ -0,0 +1,108 @@
/* gEDA - GPL Electronic Design Automation
* gparts - gEDA Parts Manager
* Copyright (C) 2010 Edward C. Hennessy
* Copyright (C) 2010 gEDA Contributors (see ChangeLog for details)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
/*! \file sch-path.h
*/
#define SCH_TYPE_PATH (sch_path_get_type())
#define SCH_PATH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),SCH_TYPE_PATH,SchPath))
#define SCH_PATH_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST((cls),SCH_TYPE_PATH,SchPathClass))
#define SCH_IS_PATH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),SCH_TYPE_PATH))
#define SCH_IS_PATH_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE((cls),SCH_TYPE_PATH))
#define SCH_PATH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),SCH_TYPE_PATH,SchPathClass))
struct _SchPath
{
SchShape parent;
};
struct _SchPathClass
{
SchShapeClass parent;
};
GType
sch_path_get_type(void);
/*! \brief Append a command to the path
*
* The first command in a path must be a moveto. Regardless of an absolute or
* relative moveto, the first command in the path gets interpreted as an
* absolute moveto.
*
* \todo Should this command return an error if the first command is not a
* moveto?
*
* \param [in] path The path
* \param [in] command The command to append
*/
void
sch_path_append(SchPath *path, const SchPathCommand *command);
/*! \brief Return the number of commands in the path
*
* \param [in] path The path
* \return The number of commands in the path
*/
int
sch_path_count(const SchPath *path);
/*! \brief Call a function for each command in the path
*
* \param [in] path
* \param [in] func
* \param [in] user_data
*/
void
sch_path_foreach(SchPath *path, GFunc func, gpointer user_data);
/*! \brief Get the color of the path
*
* \param [in] path The path
* \return The color index
*/
int
sch_path_get_color(const SchPath *path);
/*! \brief Get the fill style of the path
*
* \param [in] path The path
* \param [out] style The fill style of the path
*/
void
sch_path_get_fill_style(const SchPath *path, SchFillStyle *style);
/*! \brief Get the line width of the path
*
* \param [in] path The path
* \return The line width
*/
int
sch_path_get_line_width(const SchPath *path);
/*! \brief Create an empty path
*
* \param [in] config The configuration
* \return A new path
*/
SchPath*
sch_path_new(const SchConfig *config);

View File

@ -33,6 +33,7 @@
#include "sch-fill-style.h"
#include "sch-line-style.h"
#include "sch-path-command.h"
#include "sch-attributes.h"
#include "sch-multiline.h"
@ -48,6 +49,7 @@
#include "sch-component.h"
#include "sch-line.h"
#include "sch-net.h"
#include "sch-path.h"
#include "sch-picture.h"
#include "sch-pin.h"
#include "sch-text.h"

View File

@ -40,6 +40,7 @@
#include "schgui-cairo-circle.h"
#include "schgui-cairo-line.h"
#include "schgui-cairo-net.h"
#include "schgui-cairo-path.h"
#include "schgui-cairo-pin.h"
#include "schgui-cairo-text.h"
@ -98,6 +99,12 @@ schgui_cairo_factory_create_from_line(SchGUICairoFactory *factory, SchLine *line
static SchGUICairoDrawItem*
schgui_cairo_factory_create_from_net(SchGUICairoFactory *factory, SchNet *net);
static SchGUICairoDrawItem*
schgui_cairo_factory_create_from_path(SchGUICairoFactory *factory, SchPath *path);
static SchGUICairoDrawItem*
schgui_cairo_factory_create_from_path_proc(SchPathCommand *command, gpointer user_data);
static SchGUICairoDrawItem*
schgui_cairo_factory_create_from_pin(SchGUICairoFactory *factory, SchPin *pin);
@ -173,6 +180,12 @@ schgui_cairo_factory_base_init(gpointer g_class)
schgui_cairo_factory_create_from_net
);
g_hash_table_insert(
klasse->table,
GINT_TO_POINTER(SCH_TYPE_PATH),
schgui_cairo_factory_create_from_path
);
g_hash_table_insert(
klasse->table,
GINT_TO_POINTER(SCH_TYPE_PIN),
@ -425,6 +438,20 @@ schgui_cairo_factory_create_from_net(SchGUICairoFactory *factory, SchNet *shape)
return item;
}
static SchGUICairoDrawItem*
schgui_cairo_factory_create_from_path(SchGUICairoFactory *factory, SchPath *path)
{
SchGUICairoDrawItem *item = NULL;
SchGUICairoFactoryPrivate *privat = SCHGUI_CAIRO_FACTORY_GET_PRIVATE(factory);
if (privat != NULL)
{
item = SCHGUI_CAIRO_DRAW_ITEM(schgui_cairo_path_new(SCH_PATH(path), privat->config));
}
return item;
}
static SchGUICairoDrawItem*
schgui_cairo_factory_create_from_pin(SchGUICairoFactory *factory, SchPin *shape)
{

386
src/schgui-cairo-path.c Normal file
View File

@ -0,0 +1,386 @@
/* gEDA - GPL Electronic Design Automation
* gparts - gEDA Parts Manager
* Copyright (C) 2010 Edward C. Hennessy
* Copyright (C) 2010 gEDA Contributors (see ChangeLog for details)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
/*! \file schgui-cairo-pin.c
*/
#include <math.h>
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include "misc-object.h"
#include "sch.h"
#include "schgui-drawing-cfg.h"
#include "schgui-cairo-draw-item.h"
#include "schgui-cairo-path.h"
#define SCHGUI_CAIRO_PATH_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj),SCHGUI_TYPE_CAIRO_PATH,SchGUICairoPathPrivate))
typedef struct _SchGUICairoPathPrivate SchGUICairoPathPrivate;
struct _SchGUICairoPathPrivate
{
double red;
double green;
double blue;
double alpha;
GSList *commands;
double line_width;
int solid;
int visible;
};
static void
schgui_cairo_path_bounds(SchGUICairoDrawItem *item, cairo_t *cairo, GeomBounds *bounds);
static void
schgui_cairo_path_class_init(gpointer g_class, gpointer g_class_data);
static void
schgui_cairo_path_draw(SchGUICairoDrawItem *item, cairo_t *cairo);
static void
schgui_cairo_path_finalize(GObject *object);
static void
schgui_cairo_path_mirror_y(SchGUICairoDrawItem *item);
static void
schgui_cairo_path_rotate(SchGUICairoDrawItem *item, double dt);
static void
schgui_cairo_path_translate(SchGUICairoDrawItem *item, double dx, double dy);
void
schgui_cairo_path_append_rev(SchPathCommand *command, SchGUICairoPath *path)
{
SchGUICairoPathPrivate *privat = SCHGUI_CAIRO_PATH_GET_PRIVATE(path);
if (privat != NULL)
{
privat->commands = g_slist_append(privat->commands, sch_path_command_copy(command));
}
}
static void
schgui_cairo_path_bounds(SchGUICairoDrawItem *item, cairo_t *cairo, GeomBounds *bounds)
{
#if 0
if (bounds != NULL)
{
SchGUICairoPathPrivate *privat = SCHGUI_CAIRO_PATH_GET_PRIVATE(item);
if (privat != NULL)
{
GeomBounds temp;
if (privat->x[0] < privat->x[1])
{
temp.min_x = privat->x[0];
temp.max_x = privat->x[1];
}
else
{
temp.min_x = privat->x[1];
temp.max_x = privat->x[0];
}
if (privat->y[0] < privat->y[1])
{
temp.min_y = privat->y[0];
temp.max_y = privat->y[1];
}
else
{
temp.min_y = privat->y[1];
temp.max_y = privat->y[0];
}
geom_bounds_expand(&temp, &temp, privat->width);
geom_bounds_union(bounds, bounds, &temp);
}
}
#endif
}
static void
schgui_cairo_path_class_init(gpointer g_class, gpointer g_class_data)
{
SchGUICairoDrawItemClass *i_klasse = SCHGUI_CAIRO_DRAW_ITEM_CLASS(g_class);
GObjectClass *o_klasse = G_OBJECT_CLASS(g_class);
g_type_class_add_private(o_klasse, sizeof(SchGUICairoPathPrivate));
o_klasse->finalize = schgui_cairo_path_finalize;
i_klasse->bounds = schgui_cairo_path_bounds;
i_klasse->draw = schgui_cairo_path_draw;
i_klasse->mirror_y = schgui_cairo_path_mirror_y;
i_klasse->rotate = schgui_cairo_path_rotate;
i_klasse->translate = schgui_cairo_path_translate;
}
static void
schgui_cairo_path_draw(SchGUICairoDrawItem *item, cairo_t *cairo)
{
if (cairo != NULL)
{
SchGUICairoPathPrivate *privat = SCHGUI_CAIRO_PATH_GET_PRIVATE(item);
if (privat != NULL)
{
GSList *node;
SchPathCommand *command;
cairo_set_source_rgba(cairo, privat->red, privat->green, privat->blue, privat->alpha);
cairo_set_line_width(cairo, privat->line_width);
node = privat->commands;
while (node != NULL)
{
command = SCH_PATH_COMMAND(node->data);
switch (command->type)
{
case SCH_PATH_COMMAND_INVALID:
g_debug("SchGUICairoPath: invalid path command");
break;
case SCH_PATH_COMMAND_CLOSEPATH:
cairo_close_path(cairo);
break;
case SCH_PATH_COMMAND_CURVETO_ABS:
cairo_curve_to(
cairo,
command->curveto.x[0], command->curveto.y[0],
command->curveto.x[1], command->curveto.y[1],
command->curveto.x[2], command->curveto.y[2]
);
break;
case SCH_PATH_COMMAND_CURVETO_REL:
cairo_rel_curve_to(
cairo,
command->curveto.x[0], command->curveto.y[0],
command->curveto.x[1], command->curveto.y[1],
command->curveto.x[2], command->curveto.y[2]
);
break;
case SCH_PATH_COMMAND_LINETO_ABS:
cairo_line_to(cairo, command->lineto.x, command->lineto.y);
break;
case SCH_PATH_COMMAND_LINETO_REL:
cairo_rel_line_to(cairo, command->lineto.x, command->lineto.y);
break;
case SCH_PATH_COMMAND_MOVETO_ABS:
cairo_move_to(cairo, command->moveto.x, command->moveto.y);
break;
case SCH_PATH_COMMAND_MOVETO_REL:
cairo_rel_move_to(cairo, command->moveto.x, command->moveto.y);
break;
default:
g_debug("SchGUICairoPath: unknown path command");
}
node = g_slist_next(node);
}
if (privat->solid)
{
cairo_fill_preserve(cairo);
}
cairo_stroke(cairo);
}
}
}
static void
schgui_cairo_path_finalize(GObject *object)
{
SchGUICairoPathPrivate *privat = SCHGUI_CAIRO_PATH_GET_PRIVATE(object);
if (privat != NULL)
{
GSList *node = privat->commands;
while (node != NULL)
{
sch_path_command_free(SCH_PATH_COMMAND(node->data));
node = g_slist_next(node);
}
g_slist_free(privat->commands);
privat->commands = NULL;
}
misc_object_chain_finalize(object);
}
GType
schgui_cairo_path_get_type(void)
{
static GType type = G_TYPE_INVALID;
if (type == G_TYPE_INVALID)
{
static const GTypeInfo tinfo = {
sizeof(SchGUICairoPathClass), /* class_size */
NULL, /* base_init */
NULL, /* base_finalize */
schgui_cairo_path_class_init, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
sizeof(SchGUICairoPath), /* instance_size */
0, /* n_preallocs */
NULL, /* instance_init */
NULL /* value_table */
};
type = g_type_register_static(
SCHGUI_TYPE_CAIRO_DRAW_ITEM,
"SchGUICairoPath",
&tinfo,
0
);
}
return type;
}
static void
schgui_cairo_path_mirror_y(SchGUICairoDrawItem *item)
{
SchGUICairoPathPrivate *privat = SCHGUI_CAIRO_PATH_GET_PRIVATE(item);
if (privat != NULL)
{
GSList *node = privat->commands;
while (node != NULL)
{
//sch_path_command_mirror_y(SCH_PATH_COMMAND(node->data));
node = g_slist_next(node);
}
}
}
SchGUICairoPath*
schgui_cairo_path_new(const SchPath *shape, SchGUIDrawingCfg *config)
{
SchGUICairoPath *item = SCHGUI_CAIRO_PATH(g_object_new(SCHGUI_TYPE_CAIRO_PATH, NULL));
SchGUICairoPathPrivate *privat = SCHGUI_CAIRO_PATH_GET_PRIVATE(item);
if (privat != NULL)
{
GeomLine line;
SchGUIDrawingCfgColor color;
SchFillStyle fill_style;
int index;
double item_width;
int shape_width;
index = sch_path_get_color(shape);
privat->visible = schgui_drawing_cfg_get_color(config, index, &color);
privat->red = color.red;
privat->green = color.green;
privat->blue = color.blue;
privat->alpha = privat->visible ? 1.0 : 0.0;
shape_width = sch_path_get_line_width(shape);
schgui_drawing_cfg_get_output_line_width(config, shape_width, &item_width);
privat->line_width = item_width;
sch_path_get_fill_style(shape, &fill_style);
privat->solid = (fill_style.type == SCH_FILL_STYLE_FILL_TYPE_SOLID);
sch_path_foreach(shape, schgui_cairo_path_append_rev, item);
}
return item;
}
static void
schgui_cairo_path_rotate(SchGUICairoDrawItem *item, double dt)
{
SchGUICairoPathPrivate *privat = SCHGUI_CAIRO_PATH_GET_PRIVATE(item);
if (privat != NULL)
{
GSList *node = privat->commands;
while (node != NULL)
{
sch_path_command_rotate(SCH_PATH_COMMAND(node->data), dt);
node = g_slist_next(node);
}
}
}
static void
schgui_cairo_path_translate(SchGUICairoDrawItem *item, double dx, double dy)
{
SchGUICairoPathPrivate *privat = SCHGUI_CAIRO_PATH_GET_PRIVATE(item);
if (privat != NULL)
{
GSList *node = privat->commands;
while (node != NULL)
{
sch_path_command_translate(SCH_PATH_COMMAND(node->data), dx, dy);
node = g_slist_next(node);
}
}
}

49
src/schgui-cairo-path.h Normal file
View File

@ -0,0 +1,49 @@
/* gEDA - GPL Electronic Design Automation
* gparts - gEDA Parts Manager
* Copyright (C) 2010 Edward C. Hennessy
* Copyright (C) 2010 gEDA Contributors (see ChangeLog for details)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
/*! \file schgui-cairo-path.h
*/
#define SCHGUI_TYPE_CAIRO_PATH (schgui_cairo_path_get_type())
#define SCHGUI_CAIRO_PATH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),SCHGUI_TYPE_CAIRO_PATH,SchGUICairoPath))
#define SCHGUI_CAIRO_PATH_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST((cls),SCHGUI_TYPE_CAIRO_PATH,SchGUICairoPathClass))
#define SCHGUI_IS_CAIRO_PATH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),SCHGUI_TYPE_CAIRO_PATH))
#define SCHGUI_IS_CAIRO_PATH_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE((cls),SCHGUI_TYPE_CAIRO_PATH))
#define SCHGUI_CAIRO_PATH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),SCHGUI_TYPE_CAIRO_PATH,SchGUICairoPathClass))
typedef struct _SchGUICairoPath SchGUICairoPath;
typedef struct _SchGUICairoPathClass SchGUICairoPathClass;
struct _SchGUICairoPath
{
SchGUICairoDrawItem parent;
};
struct _SchGUICairoPathClass
{
SchGUICairoDrawItemClass parent;
};
GType
schgui_cairo_path_get_type(void);
SchGUICairoPath*
schgui_cairo_path_new(const SchPath *shape, SchGUIDrawingCfg *config);