Code

UnicodeRange class implementation.
authorJucaBlues <JucaBlues@users.sourceforge.net>
Mon, 16 Jun 2008 01:24:19 +0000 (01:24 +0000)
committerJucaBlues <JucaBlues@users.sourceforge.net>
Mon, 16 Jun 2008 01:24:19 +0000 (01:24 +0000)
This class represents a range of unicode codepoints as used in the u1
and u2 attributes of glyph kerning nodes.

src/Makefile_insert
src/display/nr-svgfonts.cpp
src/sp-glyph-kerning.cpp
src/sp-glyph-kerning.h
src/unicoderange.cpp [new file with mode: 0644]
src/unicoderange.h [new file with mode: 0644]

index f49498092f3d7d58fe7b4454dfd62b8355facf3c..7863225743f794c55a07d04c9c70260e6fb46a07 100644 (file)
@@ -290,6 +290,7 @@ libinkpre_a_SOURCES =       \
        text-tag-attributes.h   \
        tools-switch.cpp tools-switch.h\
        tweak-context.h tweak-context.cpp \
+       unicoderange.cpp unicoderange.h \
        uri-references.cpp uri-references.h     \
        vanishing-point.cpp vanishing-point.h   \
        verbs.cpp verbs.h       \
index 143b021889b91f7c1e1afa296646d923f4cca76e..e9d251820ffb23740530a13b2f4f25679e7d85d3 100644 (file)
@@ -166,11 +166,11 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
                for(SPObject* node = this->font->children;previous_unicode && node;node=node->next){
                    //apply glyph kerning if appropriate
                    if (SP_IS_HKERN(node) && is_horizontal_text){
-                       if ( (((SPHkern*)node)->u1[0] == previous_unicode[0]) && (((SPHkern*)node)->u2[0] == this->glyphs[i]->unicode[0]))//TODO: strings
+                       if ( (((SPHkern*)node)->u1->contains(previous_unicode[0])) && (((SPHkern*)node)->u2->contains(this->glyphs[i]->unicode[0]) ))//TODO: verify what happens when using unicode strings.
                                x -= (((SPHkern*)node)->k / this->font->horiz_adv_x);
                    }
                    if (SP_IS_VKERN(node) && !is_horizontal_text){
-                       if ( (((SPVkern*)node)->u1[0] == previous_unicode[0]) && (((SPVkern*)node)->u2[0] == this->glyphs[i]->unicode[0]))//TODO: strings
+                       if ( (((SPVkern*)node)->u1->contains(previous_unicode[0])) && (((SPVkern*)node)->u2->contains(this->glyphs[i]->unicode[0]) ))//TODO: idem
                                y -= (((SPVkern*)node)->k / this->font->vert_adv_y);
                    }
                }
index 173747af3a7ecf1d132e04e39b61e8f13bbffc63..1c439be19aa365e9cb6088860f8a7c9377eece13 100644 (file)
@@ -132,13 +132,13 @@ static void sp_glyph_kerning_set(SPObject *object, unsigned int key, const gchar
     switch (key) {
         case SP_ATTR_U1:
             if (glyphkern->u1) g_free(glyphkern->u1);
-            glyphkern->u1 = g_strdup(value);//todo: 
+            glyphkern->u1 = new UnicodeRange(value);
             object->requestModified(SP_OBJECT_MODIFIED_FLAG);
 g_warning("<%s>: SP_ATTR_U1: %s", tag, value);
              break;
         case SP_ATTR_U2:
             if (glyphkern->u2) g_free(glyphkern->u2);
-            glyphkern->u2 = g_strdup(value);//todo: 
+            glyphkern->u2 = new UnicodeRange(value);
             object->requestModified(SP_OBJECT_MODIFIED_FLAG);
 g_warning("<%s>: SP_ATTR_U2: %s", tag, value);
              break;
index 806ec0986731fc67a281340acdf93e32ba13ab09..9e8395d3b96e6e90072a653e72907e547a361a06 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include "sp-object.h"
+#include "unicoderange.h"
 
 #define SP_TYPE_HKERN (sp_glyph_kerning_h_get_type ())
 #define SP_HKERN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_HKERN, SPHkern))
@@ -29,9 +30,9 @@
 #define SP_IS_VKERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_VKERN))
 
 struct SPGlyphKerning : public SPObject {
-    char* u1;
+    UnicodeRange* u1;
     char* g1;
-    char* u2;
+    UnicodeRange* u2;
     char* g2;
     double k;
 };
diff --git a/src/unicoderange.cpp b/src/unicoderange.cpp
new file mode 100644 (file)
index 0000000..c408910
--- /dev/null
@@ -0,0 +1,96 @@
+#include<unicoderange.h>
+
+static unsigned int hex2int(char* s){
+       int res=0;
+       int i=0, mul=1;
+       while(s[i+1]!='\0') i++;
+
+       while(i>=0){
+               if (s[i] > '9') res += mul * (s[i]-'A'+10);
+               else res += mul * (s[i]-'0');
+               i--;
+               mul*=16;
+       }
+       return res;
+}
+
+UnicodeRange::UnicodeRange(const gchar* value){
+       gchar* val = (gchar*) value;
+       while(val[0] != '\0'){
+               if (val[0]=='U' && val[1]=='+'){
+                       val += add_range(val);
+               } else {
+//                     g_warning("adding unichar. unichar=%c", g_utf8_get_char(&val[0]));
+                       this->unichars.push_back(g_utf8_get_char(&val[0]));
+                       val++;
+               }
+               //skip spaces or commas
+               while(val[0]==' ' || val[0]==',') val++;
+       }
+}
+
+int
+UnicodeRange::add_range(gchar* val){
+               Urange r;
+               //U+
+               val+=2;
+               int i=0, count=2;
+               while(val[i]!='\0' && val[i]!='-' && val[i]!=' ' && val[i]!=',') i++;
+               r.start = (gchar*) malloc((i+1)*sizeof(gchar*));
+               strncpy(r.start, val, i);
+               r.start[i] = '\0';
+               val+=i;
+               count+=i;
+               i=0;
+               if (val[0]=='-'){
+                       val++;
+                       while(val[i]!='\0' && val[i]!='-' && val[i]!=' ' && val[i]!=',') i++;
+                       r.end = (gchar*) malloc((i+1)*sizeof(gchar*));
+                       strncpy(r.end, val, i);
+                       r.end[i] = '\0';
+                       val+=i;
+                       count+=i;
+               } else {
+                       r.end=NULL;
+               }
+//             g_warning("adding range. from %s to %s", r.start, r.end);
+               this->range.push_back(r);
+               return count+1;
+}
+
+bool UnicodeRange::contains(gchar unicode){
+       for(unsigned int i=0;i<this->unichars.size();i++){
+               if ((gunichar) unicode == this->unichars[i]) return true;
+       }
+
+       unsigned int unival;
+       unival = g_utf8_get_char (&unicode);
+       g_warning("unival=%d", unival);
+       char uni[9] = "00000000";
+       uni[8]= '\0';
+       unsigned char val;
+       for (unsigned int i=7; unival>0; i--){
+               val = unival & 0xf;
+               unival = unival >> 4;
+               if (val < 10) uni[i] = '0' + val;
+               else uni[i] = 'A'+ val - 10;
+       }
+//     g_warning("uni=%s", uni);
+
+       bool found;
+       for(unsigned int i=0;i<this->range.size();i++){
+               Urange r = this->range[i];
+               if (r.end){
+//                     g_warning("hex2int: start=%d", hex2int(r.start));
+//                     g_warning("hex2int: end=%d", hex2int(r.end));
+                       if (unival >= hex2int(r.start) && unival <= hex2int(r.end)) return true;
+               } else {
+                       found = true;
+                       for (int pos=0;pos<8;pos++){
+                               if (uni[pos]!='?' && uni[pos]!=r.start[pos]) found = false;
+                       }
+                       if (found) return true;
+               }
+       }
+       return false;
+}
diff --git a/src/unicoderange.h b/src/unicoderange.h
new file mode 100644 (file)
index 0000000..656f53c
--- /dev/null
@@ -0,0 +1,19 @@
+#include <glib-object.h>
+#include<vector>
+
+struct Urange{
+       gchar* start;
+       gchar* end;
+};
+
+class UnicodeRange{
+public:
+UnicodeRange(const gchar* val);
+int add_range(gchar* val);
+bool contains(gchar unicode);
+
+private:
+std::vector<Urange> range;
+std::vector<gunichar> unichars;
+};
+