summaryrefslogtreecommitdiff
path: root/gsk/gskpathopprivate.h
blob: da1c3e63e46243eabd9ff914ddfe815d3c6d426d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
 * Copyright © 2020 Benjamin Otte
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors: Benjamin Otte <otte@gnome.org>
 */


#ifndef __GSK_PATHOP_PRIVATE_H__
#define __GSK_PATHOP_PRIVATE_H__

#include <gsk/gskpath.h>
#include <gsk/gskpathbuilder.h>

G_BEGIN_DECLS

typedef gpointer gskpathop;

static inline
gskpathop               gsk_pathop_encode                       (GskPathOperation        op,
                                                                 const graphene_point_t *pts);
static inline
const graphene_point_t *gsk_pathop_points                       (gskpathop               pop);
static inline
GskPathOperation        gsk_pathop_op                           (gskpathop               pop);

static inline
gboolean                gsk_pathop_foreach                      (gskpathop               pop,
                                                                 GskPathForeachFunc      func,
                                                                 gpointer                user_data);

/* included inline so tests can use them */
static inline
void                    gsk_path_builder_pathop_to              (GskPathBuilder         *builder,
                                                                 gskpathop               op);
static inline
void                    gsk_path_builder_pathop_reverse_to      (GskPathBuilder         *builder,
                                                                 gskpathop               op);

/* IMPLEMENTATION */

#define GSK_PATHOP_OPERATION_MASK (0x7)

static inline gskpathop
gsk_pathop_encode (GskPathOperation        op,
                   const graphene_point_t *pts)
{
  /* g_assert (op & GSK_PATHOP_OPERATION_MASK == op); */
  g_assert ((GPOINTER_TO_SIZE (pts) & GSK_PATHOP_OPERATION_MASK) == 0);

  return GSIZE_TO_POINTER (GPOINTER_TO_SIZE (pts) | op);
}

static inline const graphene_point_t *
gsk_pathop_points (gskpathop pop)
{
  return GSIZE_TO_POINTER (GPOINTER_TO_SIZE (pop) & ~GSK_PATHOP_OPERATION_MASK);
}

static inline
GskPathOperation gsk_pathop_op (gskpathop pop)
{
  return GPOINTER_TO_SIZE (pop) & GSK_PATHOP_OPERATION_MASK;
}

static inline gboolean
gsk_pathop_foreach (gskpathop          pop,
                    GskPathForeachFunc func,
                    gpointer           user_data)
{
  switch (gsk_pathop_op (pop))
  {
    case GSK_PATH_MOVE:
      return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 1, 0, user_data);

    case GSK_PATH_CLOSE:
    case GSK_PATH_LINE:
      return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 2, 0, user_data);

    case GSK_PATH_CURVE:
      return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 4, 0, user_data);

    case GSK_PATH_CONIC:
      {
        const graphene_point_t *pts = gsk_pathop_points (pop);
        return func (gsk_pathop_op (pop), (graphene_point_t[3]) { pts[0], pts[1], pts[3] }, 3, pts[2].x, user_data);
      }

    default:
      g_assert_not_reached ();
      return TRUE;
    }
}

static inline void
gsk_path_builder_pathop_to (GskPathBuilder *builder,
                            gskpathop       op)
{
  const graphene_point_t *pts = gsk_pathop_points (op);

  switch (gsk_pathop_op (op))
  {
    case GSK_PATH_MOVE:
      gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
      break;

    case GSK_PATH_CLOSE:
      gsk_path_builder_close (builder);
      break;

    case GSK_PATH_LINE:
      gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
      break;

    case GSK_PATH_CURVE:
      gsk_path_builder_curve_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
      break;

    case GSK_PATH_CONIC:
      gsk_path_builder_conic_to (builder, pts[1].x, pts[1].y, pts[3].x, pts[3].y, pts[2].x);
      break;

    default:
      g_assert_not_reached ();
      break;
  }
}

static inline void
gsk_path_builder_pathop_reverse_to (GskPathBuilder *builder,
                                    gskpathop       op)
{
  const graphene_point_t *pts = gsk_pathop_points (op);

  switch (gsk_pathop_op (op))
  {
    case GSK_PATH_MOVE:
      gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
      break;

    case GSK_PATH_CLOSE:
      gsk_path_builder_line_to (builder, pts[0].x, pts[0].y);
      break;

    case GSK_PATH_LINE:
      gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
      break;

    case GSK_PATH_CURVE:
      gsk_path_builder_curve_to (builder, pts[2].x, pts[2].y, pts[1].x, pts[1].y, pts[0].x, pts[0].y);
      break;

    case GSK_PATH_CONIC:
      gsk_path_builder_conic_to (builder, pts[1].x, pts[1].y, pts[0].x, pts[0].y, pts[2].x);
      break;

    default:
      g_assert_not_reached ();
      break;
  }
}


G_END_DECLS

#endif /* __GSK_PATHOP_PRIVATE_H__ */