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

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

Make cfgRules private

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