source: trunk/src/memphis-rule-set.c @ 142

Last change on this file since 142 was 142, checked in by simon, 5 years ago

Add an autotools based build system

  • moved all code to the src directory
  • generates pkg-config files

remove memphis-uninstalled.pc.in

File size: 13.9 KB
Line 
1/*
2 * Memphis - Cairo Rederer for OSM in C
3 * Copyright (C) 2009  Simon Wenner <simon@wenner.ch>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20#include <string.h>
21#include "mlib.h"
22#include "memphis-rule-set.h"
23#include "memphis-data-pool.h"
24
25G_DEFINE_TYPE (MemphisRuleSet, memphis_rule_set, G_TYPE_OBJECT)
26
27#define MEMPHIS_RULE_SET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MEMPHIS_TYPE_RULE_SET, MemphisRuleSetPrivate))
28
29enum
30{
31  PROP_0,
32  PROP_DEBUG_LEVEL
33};
34
35typedef struct _MemphisRuleSetPrivate MemphisRuleSetPrivate;
36
37struct _MemphisRuleSetPrivate {
38  gint8 debug_level;
39};
40
41static void
42memphis_rule_set_get_property (GObject *object, guint property_id,
43                              GValue *value, GParamSpec *pspec)
44{
45  MemphisRuleSet *self = MEMPHIS_RULE_SET (object);
46  MemphisRuleSetPrivate *priv = MEMPHIS_RULE_SET_GET_PRIVATE (self);
47  switch (property_id)
48  {
49    case PROP_DEBUG_LEVEL:
50      g_value_set_int (value, priv->debug_level);
51      break;
52    default:
53      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
54  }
55}
56
57static void
58memphis_rule_set_set_property (GObject *object, guint property_id,
59                              const GValue *value, GParamSpec *pspec)
60{
61  MemphisRuleSet *self = MEMPHIS_RULE_SET (object);
62  switch (property_id)
63  {
64    case PROP_DEBUG_LEVEL:
65        memphis_rule_set_set_debug_level (self, g_value_get_int (value));
66        break;
67    default:
68      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
69  }
70}
71
72static void
73memphis_rule_set_finalize (GObject *object)
74{
75  MemphisRuleSet *self = MEMPHIS_RULE_SET (object);
76
77  if (self->ruleset != NULL)
78    rulesetFree(self->ruleset);
79 
80  G_OBJECT_CLASS (memphis_rule_set_parent_class)->finalize (object);
81}
82
83static void
84memphis_rule_set_class_init (MemphisRuleSetClass *klass)
85{
86  GObjectClass *object_class = G_OBJECT_CLASS (klass);
87
88  g_type_class_add_private (klass, sizeof (MemphisRuleSetPrivate));
89
90  object_class->get_property = memphis_rule_set_get_property;
91  object_class->set_property = memphis_rule_set_set_property;
92  object_class->finalize = memphis_rule_set_finalize;
93
94  /**
95  * MemphisRuleSet:debug-level:
96  *
97  * The debug level of the rule parser.
98  *
99  * Since: 0.1
100  */
101  g_object_class_install_property (object_class,
102      PROP_DEBUG_LEVEL,
103      g_param_spec_int ("debug-level",
104        "Debug level",
105        "The parser debug level",
106        0,
107        2,
108        1,
109        G_PARAM_READWRITE));
110}
111
112static void
113memphis_rule_set_init (MemphisRuleSet *self)
114{
115  MemphisRuleSetPrivate *priv = MEMPHIS_RULE_SET_GET_PRIVATE (self);
116  self->ruleset = NULL;
117  priv->debug_level = 1;
118}
119
120MemphisRuleSet*
121memphis_rule_set_new ()
122{
123  return g_object_new (MEMPHIS_TYPE_RULE_SET, NULL);
124}
125
126void
127memphis_rule_set_load_from_file (MemphisRuleSet *rules, const gchar *filename)
128{
129  g_return_if_fail (MEMPHIS_IS_RULE_SET (rules) && filename != NULL);
130
131  MemphisRuleSetPrivate *priv = MEMPHIS_RULE_SET_GET_PRIVATE (rules);
132  if (rules->ruleset != NULL)
133    rulesetFree (rules->ruleset);
134
135  rules->ruleset = rulesetRead (filename, priv->debug_level);
136}
137
138void
139memphis_rule_set_load_from_data (MemphisRuleSet *rules,
140    const gchar *data,
141    guint size)
142{
143  g_return_if_fail (MEMPHIS_IS_RULE_SET (rules) && data != NULL);
144
145  MemphisRuleSetPrivate *priv = MEMPHIS_RULE_SET_GET_PRIVATE (rules);
146  if (rules->ruleset != NULL)
147    rulesetFree (rules->ruleset);
148
149  rules->ruleset = rulesetRead_from_buffer (data, size, priv->debug_level);
150}
151
152void
153memphis_rule_set_free (MemphisRuleSet *rules)
154{
155  g_return_if_fail (MEMPHIS_IS_RULE_SET (rules));
156
157  g_object_unref (G_OBJECT (rules));
158}
159
160void
161memphis_rule_set_set_debug_level (MemphisRuleSet *rules,
162    gint8 debug_level)
163{
164  g_return_if_fail (MEMPHIS_IS_RULE_SET (rules));
165
166  MemphisRuleSetPrivate *priv = MEMPHIS_RULE_SET_GET_PRIVATE (rules);
167  priv->debug_level = debug_level;
168}
169
170gint8
171memphis_rule_set_get_debug_level (MemphisRuleSet *rules)
172{
173  g_return_val_if_fail (MEMPHIS_IS_RULE_SET (rules), -1);
174
175  MemphisRuleSetPrivate *priv = MEMPHIS_RULE_SET_GET_PRIVATE (rules);
176  return priv->debug_level;
177}
178
179void
180memphis_rule_set_set_bg_color (MemphisRuleSet *self,
181    guint16 r, guint16 g, guint16 b)
182{
183  self->ruleset->background[0] = (gint16) r;
184  self->ruleset->background[1] = (gint16) g;
185  self->ruleset->background[2] = (gint16) b;
186}
187
188void
189memphis_rule_set_get_bg_color (MemphisRuleSet *self,
190    guint16 *r, guint16 *g, guint16 *b)
191{
192  *r = (guint16) self->ruleset->background[0];
193  *g = (guint16) self->ruleset->background[1];
194  *b = (guint16) self->ruleset->background[2];
195}
196
197GList *
198memphis_rule_set_get_rule_ids (MemphisRuleSet *self)
199{
200  g_return_val_if_fail (MEMPHIS_IS_RULE_SET (self), NULL);
201
202  GList *list = NULL;
203  cfgRule *curr = self->ruleset->rule;
204  while (curr != NULL)
205   {
206     if (curr->draw != NULL)
207      {
208        gchar *keys = g_strjoinv ("|", curr->key);
209        gchar *values = g_strjoinv ("|", curr->value);
210        gchar *id = g_strconcat (keys, ":", values, NULL);
211        list = g_list_append (list, id);
212        g_free (keys);
213        g_free (values);
214      }
215      curr = curr->next;
216   }
217   return list;
218}
219
220static MemphisRule *
221rule_new_from_cfgRule (cfgRule *curr)
222{
223  MemphisRule *rule;
224  rule = memphis_rule_new ();
225  rule->keys = g_strdupv (curr->key);
226  rule->values = g_strdupv (curr->value);
227  rule->type = curr->type;
228
229  cfgDraw *drw = curr->draw;
230  gboolean line_seen = FALSE;
231  while (drw != NULL)
232    {
233      if (drw->type == POLYGONE)
234        {
235          rule->polygon_color[0] = drw->color[0];
236          rule->polygon_color[1] = drw->color[1];
237          rule->polygon_color[2] = drw->color[2];
238          rule->polygon_z[0] = drw->minzoom;
239          rule->polygon_z[1] = drw->maxzoom;
240          // TODO support pattern
241        }
242      else if (drw->type == LINE)
243        {
244          if (line_seen) {
245            rule->line_color[0] = drw->color[0];
246            rule->line_color[1] = drw->color[1];
247            rule->line_color[2] = drw->color[2];
248            rule->line_size = drw->width;
249            rule->line_z[0] = drw->minzoom;
250            rule->line_z[1] = drw->maxzoom;
251          } else {
252            rule->border_color[0] = drw->color[0];
253            rule->border_color[1] = drw->color[1];
254            rule->border_color[2] = drw->color[2];
255            rule->border_size = drw->width;
256            rule->border_z[0] = drw->minzoom;
257            rule->border_z[1] = drw->maxzoom;
258            line_seen = TRUE;
259          }
260        }
261      else if (drw->type == TEXT)
262        {
263          rule->text_color[0] = drw->color[0];
264          rule->text_color[1] = drw->color[1];
265          rule->text_color[2] = drw->color[2];
266          rule->text_size = drw->width;
267          rule->text_z[0] = drw->minzoom;
268          rule->text_z[1] = drw->maxzoom;
269        }
270      drw = drw->next;
271    }
272  /*
273  cfgDraw *ndrw = curr->ndraw;
274  while (ndrw != NULL)
275    {
276      g_print ("NDRAW: %d\n", ndrw->type);
277      ndrw = ndrw->next;
278    }
279  */
280
281  return rule;
282}
283
284static void
285add_new_cfgDraws (cfgRule *out, MemphisRule *rule)
286{
287  cfgDraw *tmp;
288  cfgDraw *drw = NULL;
289
290  if (rule->polygon_color[0] != -1)
291    {
292      tmp = g_new (cfgDraw, 1);
293      tmp->next = drw;
294      tmp->type = POLYGONE;
295      tmp->minzoom = rule->polygon_z[0];
296      tmp->maxzoom = rule->polygon_z[1];
297      tmp->color[0] = rule->polygon_color[0];
298      tmp->color[1] = rule->polygon_color[1];
299      tmp->color[2] = rule->polygon_color[2];
300      drw = tmp;
301    }
302  if (rule->line_color[0] != -1)
303    {
304      tmp = g_new (cfgDraw, 1);
305      tmp->next = drw;
306      tmp->type = LINE;
307      tmp->minzoom = rule->line_z[0];
308      tmp->maxzoom = rule->line_z[1];
309      tmp->color[0] = rule->line_color[0];
310      tmp->color[1] = rule->line_color[1];
311      tmp->color[2] = rule->line_color[2];
312      tmp->width = rule->line_size;
313      drw = tmp;
314    }
315  if (rule->border_color[0] != -1)
316    {
317      tmp = g_new (cfgDraw, 1);
318      tmp->next = drw;
319      tmp->type = LINE;
320      tmp->minzoom = rule->border_z[0];
321      tmp->maxzoom = rule->border_z[1];
322      tmp->color[0] = rule->border_color[0];
323      tmp->color[1] = rule->border_color[1];
324      tmp->color[2] = rule->border_color[2];
325      tmp->width = rule->border_size;
326      drw = tmp;
327    }
328  if (rule->text_color[0] != -1)
329    {
330      tmp = g_new (cfgDraw, 1);
331      tmp->next = drw;
332      tmp->type = TEXT;
333      tmp->minzoom = rule->text_z[0];
334      tmp->maxzoom = rule->text_z[1];
335      tmp->color[0] = rule->text_color[0];
336      tmp->color[1] = rule->text_color[1];
337      tmp->color[2] = rule->text_color[2];
338      tmp->width = rule->text_size;
339      drw = tmp;
340    }
341    out->draw = drw;
342}
343
344static cfgRule *
345cfgRule_new_from_rule (MemphisRule *rule)
346{
347  int c, len;
348  MemphisDataPool *pool = memphis_data_pool_new ();
349  cfgRule *new = g_new (cfgRule, 1);
350
351  new->type = rule->type;
352  new->value = g_strdupv (rule->values);
353  len = g_strv_length (new->value);
354  for(c = 0; c < len; c++)
355    {
356      char *tmp = new->value[c];
357      new->value[c] = m_string_chunk_get(pool->stringChunk,
358                                         pool->stringTree, tmp);
359      g_free(tmp);
360    }
361  new->key = g_strdupv (rule->keys);
362  len = g_strv_length(new->key);
363  for(c = 0; c < len; c++)
364    {
365      char *tmp = new->key[c];
366      new->key[c] = m_string_chunk_get(pool->stringChunk,
367                                       pool->stringTree, tmp);
368      g_free(tmp);
369    }
370
371  g_object_unref (pool);
372
373  new->parent = NULL;
374  new->nparent = NULL;
375  new->next = NULL;
376  new->draw = NULL;
377  new->ndraw = NULL;
378
379  add_new_cfgDraws (new, rule);
380
381  return new;
382}
383
384static cfgRule *
385search_rule (cfgRule *rules, gchar **keys, gchar **values)
386{
387  int i;
388  gint len;
389  gboolean found = FALSE;
390  gboolean miss = FALSE;
391  gint num_keys = g_strv_length (keys);
392  gint num_values = g_strv_length (values);
393  cfgRule *curr = rules;
394
395  while (curr != NULL && !found)
396   {
397      miss = FALSE;
398      if (curr->draw != NULL)
399      {
400        len = g_strv_length (curr->key);
401        if (len != num_keys)
402          {
403            curr = curr->next;
404            continue;
405          }
406        for (i = 0; i < len; i++)
407          {
408            if (strcmp (curr->key[i], keys[i]) != 0)
409              miss = TRUE;
410          }
411
412        len = g_strv_length (curr->value);
413        if (len != num_values || miss)
414          {
415            curr = curr->next;
416            continue;
417          }
418        for (i = 0; i < len; i++)
419          {
420            if (strcmp (curr->value[i], values[i]) != 0)
421              miss = TRUE;
422          }
423        if (miss)
424          {
425            curr = curr->next;
426            continue;
427          }
428
429        found = TRUE;
430      }
431    else
432      {
433        curr = curr->next;
434      }
435   }
436
437  return curr;
438}
439
440MemphisRule *
441memphis_rule_set_get_rule (MemphisRuleSet *self, const gchar *id)
442{
443  g_return_val_if_fail (MEMPHIS_IS_RULE_SET (self) && id != NULL, NULL);
444
445  gchar **tmp = g_strsplit (id, ":", -1);
446  gchar **keys = g_strsplit (tmp[0], "|", -1);
447  gchar **values = g_strsplit (tmp[1], "|", -1);
448  g_strfreev (tmp);
449
450  cfgRule *res = search_rule (self->ruleset->rule, keys, values);
451
452  g_strfreev (keys);
453  g_strfreev (values);
454
455  if (res != NULL)
456    return rule_new_from_cfgRule (res);
457
458  return NULL;
459}
460
461void
462memphis_rule_set_set_rule (MemphisRuleSet *self, MemphisRule *rule)
463{
464  g_return_if_fail (MEMPHIS_IS_RULE_SET (self) && MEMPHIS_IS_RULE (rule));
465
466  cfgRule *res = search_rule (self->ruleset->rule, rule->keys, rule->values);
467  cfgDraw *drw, *tmp;
468
469  if (res != NULL)
470    {
471      drw = res->draw;
472      /* delete old cfgDraw's */
473      while (drw != NULL)
474        {
475          tmp = drw;
476          drw = drw->next;
477          g_free (tmp);
478        }
479
480      /* Add new cfgDraw's */
481      add_new_cfgDraws (res, rule);
482    }
483  else
484    {
485      /* Append cfgRule at last position */
486      cfgRule *curr = self->ruleset->rule;
487      while (curr->next != NULL)
488        curr = curr->next;
489
490      cfgRule *new = cfgRule_new_from_rule (rule);
491
492      curr->next = new;
493      self->ruleset->cntRule++;
494    }
495}
496
497gboolean
498memphis_rule_set_remove_rule (MemphisRuleSet *self, const gchar *id)
499{
500  g_return_val_if_fail (MEMPHIS_IS_RULE_SET (self) && id != NULL, FALSE);
501
502  gchar **tmp = g_strsplit (id, ":", -1);
503  gchar **keys = g_strsplit (tmp[0], "|", -1);
504  gchar **values = g_strsplit (tmp[1], "|", -1);
505  g_strfreev (tmp);
506
507  int i;
508  gint len;
509  gboolean found = FALSE;
510  gboolean miss = FALSE;
511  gint num_keys = g_strv_length (keys);
512  gint num_values = g_strv_length (values);
513  cfgRule *curr = self->ruleset->rule;
514  cfgRule *prev = NULL;
515
516  while (curr != NULL && !found)
517   {
518      miss = FALSE;
519      len = g_strv_length (curr->key);
520      if (len != num_keys)
521        {
522          prev = curr;
523          curr = curr->next;
524          continue;
525        }
526      for (i = 0; i < len; i++)
527        {
528          if (strcmp (curr->key[i], keys[i]) != 0)
529            miss = TRUE;
530        }
531
532      len = g_strv_length (curr->value);
533      if (len != num_values || miss)
534        {
535          prev = curr;
536          curr = curr->next;
537          continue;
538        }
539      for (i = 0; i < len; i++)
540        {
541          if (strcmp (curr->value[i], values[i]) != 0)
542            miss = TRUE;
543        }
544      if (miss)
545        {
546          prev = curr;
547          curr = curr->next;
548          continue;
549        }
550
551      found = TRUE;
552   }
553
554  g_strfreev (keys);
555  g_strfreev (values);
556
557  if (curr == NULL)
558    return FALSE;
559
560  prev->next = curr->next;
561  cfgRuleFree (curr);
562  self->ruleset->cntRule--;
563  return TRUE;
564}
Note: See TracBrowser for help on using the repository browser.