Author: fejj
Date: 2007-10-03 13:40:44 -0400 (Wed, 03 Oct 2007)
New Revision: 86824

Modified:
   trunk/moon/src/ChangeLog
   trunk/moon/src/font.cpp
   trunk/moon/src/font.h
   trunk/moon/src/mplayer.cpp
   trunk/moon/src/text.cpp
   trunk/moon/src/text.h
Log:
2007-10-03  Jeffrey Stedfast  <[EMAIL PROTECTED]>

        * text.cpp: Implemented the Glyphs element.

        * font.cpp: Made GlyphMetrics and GlyphInfo structs public for use
        with the the Glyphs element implemented in text.cpp.
        (GetGlyphInfo): Fixes to allow loading of the index=0 glyph.
        (GetGlyphInfoByIndex): New method.
        (CreatePattern): If the filename is specified, don't call
        FcFontMatch(), simply return the constructed pattern.



Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog    2007-10-03 17:35:36 UTC (rev 86823)
+++ trunk/moon/src/ChangeLog    2007-10-03 17:40:44 UTC (rev 86824)
@@ -1,3 +1,14 @@
+2007-10-03  Jeffrey Stedfast  <[EMAIL PROTECTED]>
+
+       * text.cpp: Implemented the Glyphs element.
+
+       * font.cpp: Made GlyphMetrics and GlyphInfo structs public for use
+       with the the Glyphs element implemented in text.cpp.
+       (GetGlyphInfo): Fixes to allow loading of the index=0 glyph.
+       (GetGlyphInfoByIndex): New method.
+       (CreatePattern): If the filename is specified, don't call
+       FcFontMatch(), simply return the constructed pattern.
+
 2007-10-02  Chris Toshok  <[EMAIL PROTECTED]>
 
        * clock.h, clock.cpp: remove TimeManager::current_fps, it's

Modified: trunk/moon/src/font.cpp
===================================================================
--- trunk/moon/src/font.cpp     2007-10-03 17:35:36 UTC (rev 86823)
+++ trunk/moon/src/font.cpp     2007-10-03 17:40:44 UTC (rev 86824)
@@ -22,6 +22,16 @@
 #include FT_OUTLINE_H
 
 
+struct GlyphBitmap {
+       cairo_surface_t *surface;
+       unsigned char *buffer;
+       int height;
+       int width;
+       int left;
+       int top;
+};
+
+
 static GHashTable *font_cache = NULL;
 static bool initialized = false;
 static FT_Library libft2;
@@ -121,35 +131,6 @@
        }
 }
 
-
-struct GlyphMetrics {
-       double horiBearingX;
-       double horiBearingY;
-       double horiAdvance;
-       double vertBearingX;
-       double vertBearingY;
-       double vertAdvance;
-       double height;
-       double width;
-};
-
-struct GlyphBitmap {
-       cairo_surface_t *surface;
-       unsigned char *buffer;
-       int height;
-       int width;
-       int left;
-       int top;
-};
-
-struct GlyphInfo {
-       uint32_t unichar;
-       uint32_t index;
-       GlyphMetrics metrics;
-       GlyphBitmap *bitmap;
-       moon_path *path;
-};
-
 static const FT_Matrix invert_y = {
         65535, 0,
         0, -65535,
@@ -276,7 +257,7 @@
 }
 
 double
-TextFont::Kerning (uint32_t left, uint32_t right)
+TextFont::Kerning (gunichar left, gunichar right)
 {
        FT_Vector kerning;
        
@@ -446,19 +427,19 @@
 }
 
 GlyphInfo *
-TextFont::GetGlyphInfo (uint32_t unichar)
+TextFont::GetGlyphInfo (gunichar unichar)
 {
        GlyphInfo *glyph;
-       uint32_t index;
+       uint32_t i;
        
-       if (unichar == 0)
-               return NULL;
+       i = unichar & 0xff;
+       glyph = &glyphs[i];
        
-       index = unichar & 0xff;
-       glyph = &glyphs[index];
-       
        if (glyph->unichar != unichar) {
-               glyph->index = FcFreeTypeCharIndex (face, unichar);
+               if (unichar)
+                       glyph->index = FcFreeTypeCharIndex (face, unichar);
+               else
+                       glyph->index = 0;
                glyph->unichar = unichar;
                
                if (glyph->bitmap) {
@@ -480,7 +461,7 @@
                        glyph->path = NULL;
                }
                
-               if (glyph->index > 0 && FT_Load_Glyph (face, glyph->index, 
LOAD_FLAGS) == 0) {
+               if (FT_Load_Glyph (face, glyph->index, LOAD_FLAGS) == 0) {
                        if (FT_Render_Glyph (face->glyph, 
FT_RENDER_MODE_NORMAL) != 0)
                                goto unavail;
                        
@@ -557,6 +538,26 @@
        return NULL;
 }
 
+GlyphInfo *
+TextFont::GetGlyphInfoByIndex (uint32_t index)
+{
+       gunichar unichar;
+       uint32_t idx;
+       
+       if (index != 0) {
+               unichar = FT_Get_First_Char (face, &idx);
+               while (idx != index && idx != 0)
+                       unichar = FT_Get_Next_Char (face, unichar, &idx);
+               
+               if (idx == 0)
+                       return NULL;
+       } else {
+               unichar = 0;
+       }
+       
+       return GetGlyphInfo (unichar);
+}
+
 double
 TextFont::UnderlinePosition ()
 {
@@ -611,7 +612,7 @@
 }
 
 void
-TextFont::Render (cairo_t *cr, uint32_t unichar, double x, double y)
+TextFont::Render (cairo_t *cr, gunichar unichar, double x, double y)
 {
        GlyphInfo *glyph;
        
@@ -636,7 +637,7 @@
 }
 
 void
-TextFont::Path (cairo_t *cr, uint32_t unichar, double x, double y)
+TextFont::Path (cairo_t *cr, gunichar unichar, double x, double y)
 {
        GlyphInfo *glyph;
        
@@ -703,6 +704,9 @@
        
        FcDefaultSubstitute (pattern);
        
+       if ((set & FontMaskFilename))
+               return pattern;
+       
        if (!(matched = FcFontMatch (NULL, pattern, &result)))
                return pattern;
        
@@ -1307,7 +1311,7 @@
 {
        TextSegment *segment;
        bool clipped = false;
-       uint32_t prev = 0;
+       gunichar prev = 0;
        GlyphInfo *glyph;
        TextLine *line;
        double advance;
@@ -1512,8 +1516,8 @@
        TextSegment *segment;
        TextDecorations deco;
        TextFont *font = NULL;
-       const uint32_t *text;
-       uint32_t prev = 0;
+       const gunichar *text;
+       gunichar prev = 0;
        Brush *cur_fg = NULL;
        Brush *fg = NULL;
        GlyphInfo *glyph;

Modified: trunk/moon/src/font.h
===================================================================
--- trunk/moon/src/font.h       2007-10-03 17:35:36 UTC (rev 86823)
+++ trunk/moon/src/font.h       2007-10-03 17:40:44 UTC (rev 86824)
@@ -13,6 +13,7 @@
 
 #include <stdint.h>
 
+#include <glib.h>
 #include <cairo.h>
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -87,8 +88,27 @@
 void font_init (void);
 G_END_DECLS
 
-struct GlyphInfo;
+struct GlyphBitmap;
 
+struct GlyphMetrics {
+       double horiBearingX;
+       double horiBearingY;
+       double horiAdvance;
+       double vertBearingX;
+       double vertBearingY;
+       double vertAdvance;
+       double height;
+       double width;
+};
+
+struct GlyphInfo {
+       gunichar unichar;
+       uint32_t index;
+       GlyphMetrics metrics;
+       GlyphBitmap *bitmap;
+       moon_path *path;
+};
+
 class TextFont {
        int ref_count;
        
@@ -111,11 +131,12 @@
        
        static TextFont *Load (FcPattern *pattern);
        
-       GlyphInfo *GetGlyphInfo (uint32_t unichar);
+       GlyphInfo *GetGlyphInfo (gunichar unichar);
+       GlyphInfo *GetGlyphInfoByIndex (uint32_t index);
        
        bool IsScalable ();
        
-       double Kerning (uint32_t left, uint32_t right);
+       double Kerning (gunichar left, gunichar right);
        double Descender ();
         double Ascender ();
        double Height ();
@@ -125,10 +146,10 @@
        double UnderlineThickness ();
        
        void Path (cairo_t *cr, GlyphInfo *glyph, double x, double y);
-       void Path (cairo_t *cr, uint32_t unichar, double x, double y);
+       void Path (cairo_t *cr, gunichar unichar, double x, double y);
        
        void Render (cairo_t *cr, GlyphInfo *glyph, double x, double y);
-       void Render (cairo_t *cr, uint32_t unichar, double x, double y);
+       void Render (cairo_t *cr, gunichar unichar, double x, double y);
 };
 
 
@@ -190,7 +211,7 @@
 class TextRun : public List::Node {
 public:
        TextDecorations deco;
-       uint32_t *text;
+       gunichar *text;
        TextFont *font;
        Brush **fg;
        

Modified: trunk/moon/src/mplayer.cpp
===================================================================
--- trunk/moon/src/mplayer.cpp  2007-10-03 17:35:36 UTC (rev 86823)
+++ trunk/moon/src/mplayer.cpp  2007-10-03 17:40:44 UTC (rev 86824)
@@ -390,7 +390,7 @@
        current_pts = 0;
        target_pts = 0;
        seek_pts = 0;
-
+       
        height = 0;
        width = 0;
 }

Modified: trunk/moon/src/text.cpp
===================================================================
--- trunk/moon/src/text.cpp     2007-10-03 17:35:36 UTC (rev 86823)
+++ trunk/moon/src/text.cpp     2007-10-03 17:40:44 UTC (rev 86824)
@@ -15,11 +15,13 @@
 #include <gtk/gtk.h>
 #include <cairo.h>
 
+#include <stdlib.h>
 #include <string.h>
 
 #include "runtime.h"
 #include "color.h"
 #include "text.h"
+#include "uri.h"
 
 
 extern guint32 moonlight_flags;
@@ -354,7 +356,7 @@
        
        foreground = NULL;
        
-       dirty_actual_values = true;
+       dirty = true;
        actual_height = 0.0;
        actual_width = 0.0;
        bbox_height = 0.0;
@@ -583,7 +585,7 @@
        text_block_set_actual_height (this, actual_height);
        text_block_set_actual_width (this, actual_width);
        
-       dirty_actual_values = false;
+       dirty = false;
 }
 
 void
@@ -743,9 +745,9 @@
        
        text_block_set_actual_height (this, (double) h);
        text_block_set_actual_width (this, (double) w);
-       dirty_actual_values = false;
        bbox_height = actual_height;
        bbox_width = actual_width;
+       dirty = false;
 }
 
 void
@@ -777,7 +779,6 @@
 void
 TextBlock::OnPropertyChanged (DependencyProperty *prop)
 {
-       bool recalc_actual = true;
        bool invalidate = true;
        
        if (prop->type != Type::TEXTBLOCK) {
@@ -791,32 +792,43 @@
                        pango_font_description_set_family (font.pango, family);
                else
                        font.custom->SetFamily (family);
+               
+               dirty = true;
        } else if (prop == TextBlock::FontSizeProperty) {
                double size = text_block_get_font_size (this);
                if (RENDER_USING_PANGO)
                        pango_font_description_set_absolute_size (font.pango, 
size * PANGO_SCALE);
                else
                        font.custom->SetSize (size);
+               
+               dirty = true;
        } else if (prop == TextBlock::FontStretchProperty) {
                FontStretches stretch = text_block_get_font_stretch (this);
                if (RENDER_USING_PANGO)
                        pango_font_description_set_stretch (font.pango, 
font_stretch (stretch));
                else
                        font.custom->SetStretch (stretch);
+               
+               dirty = true;
        } else if (prop == TextBlock::FontStyleProperty) {
                FontStyles style = text_block_get_font_style (this);
                if (RENDER_USING_PANGO)
                        pango_font_description_set_style (font.pango, 
font_style (style));
                else
                        font.custom->SetStyle (style);
+               
+               dirty = true;
        } else if (prop == TextBlock::FontWeightProperty) {
                FontWeights weight = text_block_get_font_weight (this);
                if (RENDER_USING_PANGO)
                        pango_font_description_set_weight (font.pango, 
font_weight (weight));
                else
                        font.custom->SetWeight (weight);
+               
+               dirty = true;
        } else if (prop == TextBlock::TextProperty) {
                // handled elsewhere
+               dirty = true;
        } else if (prop == TextBlock::InlinesProperty) {
                Inlines *newcol = GetValue (prop)->AsInlines ();
                
@@ -825,6 +837,8 @@
                                printf ("Warning we attached a property that 
was already attached\n");
                        newcol->closure = this;
                }
+               
+               dirty = true;
        } else if (prop == TextBlock::ForegroundProperty) {
                if (foreground != NULL) {
                        foreground->Detach (NULL, this);
@@ -835,22 +849,15 @@
                        foreground->Attach (NULL, this);
                        foreground->ref ();
                }
-               
-               // Foreground property changes do not require a re-layout of 
the text
-               recalc_actual = false;
        } else if (prop == TextBlock::ActualHeightProperty) {
-               recalc_actual = false;
                invalidate = false;
        } else if (prop == TextBlock::ActualWidthProperty) {
-               recalc_actual = false;
                invalidate = false;
        }
        
        if (invalidate) {
-               if (recalc_actual) {
-                       dirty_actual_values = true;
+               if (dirty)
                        UpdateBounds (true);
-               }
                
                Invalidate ();
        }
@@ -871,7 +878,7 @@
 TextBlock::OnCollectionChanged (Collection *col, CollectionChangeType type, 
DependencyObject *obj, DependencyProperty *prop)
 {
        if (prop != Inline::ForegroundProperty) {
-               dirty_actual_values = true;
+               dirty = true;
                UpdateBounds (true);
        }
        
@@ -881,7 +888,7 @@
 Value *
 TextBlock::GetValue (DependencyProperty *property)
 {
-       if (dirty_actual_values && ((property == 
TextBlock::ActualHeightProperty) || (property == 
TextBlock::ActualWidthProperty)))
+       if (dirty && ((property == TextBlock::ActualHeightProperty) || 
(property == TextBlock::ActualWidthProperty)))
                CalcActualWidthHeight (NULL);
        
        if (property == TextBlock::TextProperty) {
@@ -946,7 +953,7 @@
                Run *run = new Run ();
                if (value)
                        run_set_text (run, value->AsString ());
-
+               
                Inlines *inlines = text_block_get_inlines (this);
                
                if (!inlines) {
@@ -959,6 +966,7 @@
                
                inlines->Add (run);
                run->unref ();
+               dirty = true;
                return;
        }
        
@@ -1148,17 +1156,303 @@
 DependencyProperty *Glyphs::StyleSimulationsProperty;
 DependencyProperty *Glyphs::UnicodeStringProperty;
 
+enum GlyphAttrMask {
+       Index   = 1 << 1,
+       Advance = 1 << 2,
+       uOffset = 1 << 3,
+       vOffset = 1 << 4,
+};
+
+class GlyphAttr : public List::Node {
+public:
+       uint32_t index;
+       double advance;
+       double uoffset;
+       double voffset;
+       uint8_t set;
+       
+       GlyphAttr ();
+};
+
+GlyphAttr::GlyphAttr ()
+{
+       set = 0;
+}
+
+Glyphs::Glyphs ()
+{
+       desc = new TextFontDescription ();
+       desc->SetSize (0.0);
+       downloader = NULL;
+       font = NULL;
+       
+       fill = NULL;
+       path = NULL;
+       
+       attrs = new List ();
+       text = NULL;
+       
+       origin_y_specified = false;
+       origin_x = 0.0;
+       origin_y = 0.0;
+       
+       height = 0.0;
+       width = 0.0;
+       
+       invalid = false;
+       dirty = false;
+}
+
+Glyphs::~Glyphs ()
+{
+       if (fill)
+               fill->unref ();
+       
+       if (font)
+               font->unref ();
+       
+       if (path)
+               cairo_path_destroy (path);
+       
+       if (downloader) {
+               downloader_abort (downloader);
+               downloader->unref ();
+       }
+       
+       attrs->Clear (true);
+       delete attrs;
+       
+       g_free (text);
+       
+       delete desc;
+}
+
 void
+Glyphs::Layout ()
+{
+       double x, y, w, h;
+       GlyphInfo *glyph;
+       GlyphAttr *attr;
+       int n = 0;
+       
+       invalid = false;
+       dirty = false;
+       
+       height = 0.0;
+       width = 0.0;
+       
+       if (font) {
+               font->unref ();
+               font = NULL;
+       }
+       
+       if (path) {
+               cairo_path_destroy (path);
+               path = NULL;
+       }
+       
+       if (!desc->GetFilename () || desc->GetSize () == 0.0) {
+               // required font fields have not been set
+               return;
+       }
+       
+       if (((!text || !text[0]) && attrs->IsEmpty ())) {
+               // no glyphs to render
+               return;
+       }
+       
+       if (fill == NULL) {
+               // no fill specified (unlike TextBlock, there is no default 
brush)
+               return;
+       }
+       
+       font = desc->GetFont ();
+       
+       x = origin_x;
+       if (!origin_y_specified)
+               y = font->Height ();
+       else
+               y = origin_y;
+       
+       h = y - font->Descender ();
+       w = x;
+       
+       attr = (GlyphAttr *) attrs->First ();
+       
+       if (text && text[0]) {
+               gunichar *c = text;
+               
+               while (*c != 0) {
+                       if (attr && (attr->set & Index))
+                               glyph = font->GetGlyphInfoByIndex (attr->index);
+                       else
+                               glyph = font->GetGlyphInfo (*c);
+                       
+                       if (!glyph)
+                               goto next1;
+                       
+                       if (attr && (attr->set & vOffset))
+                               h = MAX (y - attr->voffset, h);
+                       
+                       if (attr && (attr->set & uOffset))
+                               x += attr->uoffset;
+                       
+                       w = MAX (x + glyph->metrics.horiAdvance, w);
+                       
+                       if (attr && (attr->set & Advance))
+                               x += attr->advance;
+                       else
+                               x += glyph->metrics.horiAdvance;
+                       
+               next1:
+                       
+                       attr = attr ? (GlyphAttr *) attr->next : NULL;
+                       n++;
+                       c++;
+               }
+       }
+       
+       while (attr) {
+               if (!(attr->set & Index)) {
+                       fprintf (stderr, "No index specified for glyph %d\n", n 
+ 1);
+                       invalid = true;
+                       return;
+               }
+               
+               if (!(glyph = font->GetGlyphInfoByIndex (attr->index)))
+                       goto next2;
+               
+               if ((attr->set & vOffset))
+                       h = MAX (y - attr->voffset, h);
+               
+               if ((attr->set & uOffset))
+                       x += attr->uoffset;
+               
+               w = MAX (x + glyph->metrics.horiAdvance, w);
+               
+               if ((attr->set & Advance))
+                       x += attr->advance;
+               else
+                       x += glyph->metrics.horiAdvance;
+               
+       next2:
+               
+               attr = (GlyphAttr *) attr->next;
+               n++;
+       }
+       
+       height = h > 0.0 ? h : 0.0;
+       width = w;
+}
+
+void
 Glyphs::Render (cairo_t *cr, int x, int y, int width, int height)
 {
-       // FIXME: implement me
+       GlyphInfo *glyph;
+       GlyphAttr *attr;
+       double x0, y0;
+       double y1;
+       
+       if ((width == 0.0 && height == 0.0) || invalid)
+               return;
+       
+       fill->SetupBrush (cr, this);
+       
+       if (path) {
+               cairo_append_path (cr, path);
+               cairo_fill (cr);
+               return;
+       }
+       
+       x0 = origin_x;
+       if (!origin_y_specified)
+               y0 = font->Height ();
+       else
+               y0 = origin_y;
+       
+       attr = (GlyphAttr *) attrs->First ();
+       
+       if (font->IsScalable ())
+               cairo_new_path (cr);
+       
+       if (text && text[0]) {
+               gunichar *c = text;
+               
+               while (*c != 0) {
+                       if (attr && (attr->set & Index)) {
+                               printf ("glyph index %lu was specified to use 
in place of char %c\n", attr->index, (char) *c);
+                               glyph = font->GetGlyphInfoByIndex (attr->index);
+                       } else
+                               glyph = font->GetGlyphInfo (*c);
+                       
+                       if (!glyph)
+                               goto next1;
+                       
+                       if (attr && (attr->set & vOffset))
+                               y1 = y0 - attr->voffset;
+                       else
+                               y1 = y0;
+                       
+                       if (attr && (attr->set & uOffset))
+                               x0 += attr->uoffset;
+                       
+                       font->Path (cr, glyph, x0, y1);
+                       
+                       if (attr && (attr->set & Advance))
+                               x0 += attr->advance;
+                       else
+                               x0 += glyph->metrics.horiAdvance;
+                       
+               next1:
+                       
+                       attr = attr ? (GlyphAttr *) attr->next : NULL;
+                       c++;
+               }
+       }
+       
+       while (attr) {
+               if (!(glyph = font->GetGlyphInfoByIndex (attr->index)))
+                       goto next2;
+               
+               if ((attr->set & vOffset))
+                       y1 = y0 - attr->voffset;
+               else
+                       y1 = y0;
+               
+               if ((attr->set & uOffset))
+                       x0 += attr->uoffset;
+               
+               if (!font->IsScalable ())
+                       font->Render (cr, glyph, x0, y1);
+               else
+                       font->Path (cr, glyph, x0, y1);
+               
+               if ((attr->set & Advance))
+                       x0 += attr->advance;
+               else
+                       x0 += glyph->metrics.horiAdvance;
+               
+       next2:
+               
+               attr = (GlyphAttr *) attr->next;
+       }
+       
+       if (font->IsScalable ()) {
+               cairo_close_path (cr);
+               
+               path = cairo_copy_path (cr);
+               
+               cairo_fill (cr);
+       }
 }
 
 void 
 Glyphs::ComputeBounds ()
 {
-       // FIXME: implement me
-       bounds = Rect (0, 0, 0, 0);
+       if (dirty)
+               Layout ();
+       
+       bounds = bounding_rect_for_transformed_rect (&absolute_xform, Rect (0, 
0, width, height));
 }
 
 Point
@@ -1171,48 +1465,238 @@
 void
 Glyphs::OnSubPropertyChanged (DependencyProperty *prop, DependencyProperty 
*subprop)
 {
-       if (prop == Glyphs::FillProperty) {
-               printf ("Glyphs::FillProperty subproperty changed\n");
-       }
+       if (prop == Glyphs::FillProperty)
+               Invalidate ();
        else
                FrameworkElement::OnSubPropertyChanged (prop, subprop);
 }
 
 void
+Glyphs::data_write (guchar *buf, gsize offset, gsize count, gpointer data)
+{
+       ;
+}
+
+void
+Glyphs::size_notify (int64_t size, gpointer data)
+{
+       ;
+}
+
+void
+Glyphs::downloader_complete (EventObject *sender, gpointer calldata, gpointer 
closure)
+{
+       ((Glyphs *) closure)->DownloaderComplete ();
+}
+
+void
+Glyphs::DownloaderComplete ()
+{
+       char *filename = downloader_get_response_file (downloader, "");
+       Value *value = downloader->GetValue (Downloader::UriProperty);
+       const char *str;
+       int id = 0;
+       Uri *uri;
+       
+       /* the download was aborted */
+       if (!filename)
+               return;
+       
+       if (value && (str = value->AsString ())) {
+               uri = new Uri ();
+               
+               if (uri->Parse (str) && uri->fragment) {
+                       if ((id = strtol (uri->fragment, NULL, 10)) < 0)
+                               id = 0;
+               }
+               
+               delete uri;
+       }
+       
+       desc->SetFilename (filename);
+       desc->SetIndex (id);
+       g_free (filename);
+       dirty = true;
+       
+       UpdateBounds (true);
+       Invalidate ();
+}
+
+void
+Glyphs::SetIndices (const char *in)
+{
+       register const char *inptr = in;
+       GlyphAttr *glyph;
+       double value;
+       char *end;
+       uint bit;
+       int n;
+       
+       attrs->Clear (true);
+       
+       if (in == NULL)
+               return;
+       
+       while (g_ascii_isspace (*inptr))
+               inptr++;
+       
+       while (*inptr) {
+               glyph = new GlyphAttr ();
+               
+               while (g_ascii_isspace (*inptr))
+                       inptr++;
+               
+               glyph->index = strtoul (inptr, &end, 10);
+               if (end > inptr)
+                       glyph->set |= Index;
+               
+               inptr = end;
+               while (g_ascii_isspace (*inptr))
+                       inptr++;
+               
+               bit = (uint) Advance;
+               n = 0;
+               
+               while (*inptr == ',' && n < 3) {
+                       inptr++;
+                       while (g_ascii_isspace (*inptr))
+                               inptr++;
+                       
+                       value = strtod (inptr, &end);
+                       
+                       if (end > inptr) {
+                               switch ((GlyphAttrMask) bit) {
+                               case Advance:
+                                       glyph->advance = value / 4.0;
+                                       glyph->set |= Advance;
+                                       break;
+                               case uOffset:
+                                       glyph->uoffset = value / 4.0;
+                                       glyph->set |= uOffset;
+                                       break;
+                               case vOffset:
+                                       glyph->voffset = value / 4.0;
+                                       glyph->set |= vOffset;
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+                       
+                       inptr = end;
+                       while (g_ascii_isspace (*inptr))
+                               inptr++;
+                       
+                       bit <<= 1;
+                       n++;
+               }
+               
+               attrs->Append (glyph);
+               
+               while (g_ascii_isspace (*inptr))
+                       inptr++;
+               
+               if (*inptr != ';') {
+                       if (*inptr) {
+                               int i;
+                               
+                               fprintf (stderr, "Parse error: %s\n", in);
+                               fprintf (stderr, "             ");
+                               for (i = 0; i < (inptr - in); i++)
+                                       fputc (' ', stderr);
+                               fprintf (stderr, "^\n");
+                       }
+                       
+                       break;
+               }
+               
+               inptr++;
+       }
+}
+
+void
 Glyphs::OnPropertyChanged (DependencyProperty *prop)
 {
+       bool invalidate = true;
+       
        if (prop->type != Type::GLYPHS) {
                FrameworkElement::OnPropertyChanged (prop);
                return;
        }
        
-       if (prop == Glyphs::FillProperty) {
-               printf ("Glyphs::Fill property changed\n");
+       if (prop == Glyphs::FontUriProperty) {
+               char *uri = glyphs_get_font_uri (this);
+               
+               if (downloader) {
+                       downloader_abort (downloader);
+                       downloader->unref ();
+                       downloader = NULL;
+               }
+               
+               if (uri && *uri) {
+                       downloader = new Downloader ();
+                       
+                       //printf ("setting media source to %s\n", uri);
+                       downloader_open (downloader, "GET", uri);
+                       downloader->AddHandler (downloader->CompletedEvent, 
downloader_complete, this);
+                       if (downloader->Started () || downloader->Completed ()) 
{
+                               if (downloader->Completed ())
+                                       DownloaderComplete ();
+                       } else {
+                               downloader->SetWriteFunc (data_write, 
size_notify, this);
+                               
+                               // This is what actually triggers the download
+                               downloader->Send ();
+                       }
+               }
+               
+               invalidate = false;
+       } else if (prop == Glyphs::FillProperty) {
+               if (fill != NULL) {
+                       fill->Detach (NULL, this);
+                       fill->unref ();
+               }
+               
+               if ((fill = glyphs_get_fill (this)) != NULL) {
+                       fill->Attach (NULL, this);
+                       fill->ref ();
+               }
+       } else if (prop == Glyphs::UnicodeStringProperty) {
+               char *str = glyphs_get_unicode_string (this);
+               g_free (text);
+               
+               if (str != NULL)
+                       text = g_utf8_to_ucs4_fast (str, -1, NULL);
+               else
+                       text = NULL;
+               
+               dirty = true;
+       } else if (prop == Glyphs::IndicesProperty) {
+               char *str = glyphs_get_indices (this);
+               SetIndices (str);
+               dirty = true;
        } else if (prop == Glyphs::FontRenderingEmSizeProperty) {
                double size = glyphs_get_font_rendering_em_size (this);
-               printf ("Glyphs::FontRenderingEmSize property changed to %g\n", 
size);
-       } else if (prop == Glyphs::FontUriProperty) {
-               char *uri = glyphs_get_font_uri (this);
-               printf ("Glyphs::FontUri property changed to %s\n", uri);
-       } else if (prop == Glyphs::IndicesProperty) {
-               char *indices = glyphs_get_indices (this);
-               printf ("Glyphs::Indicies property changed to %s\n", indices);
+               desc->SetSize (size);
+               dirty = true;
        } else if (prop == Glyphs::OriginXProperty) {
-               double x = glyphs_get_origin_x (this);
-               printf ("Glyphs::OriginX property changed to %g\n", x);
-       } else if (prop == Glyphs::OriginXProperty) {
-               double y = glyphs_get_origin_y (this);
-               printf ("Glyphs::OriginY property changed to %g\n", y);
+               origin_x = glyphs_get_origin_x (this);
+               dirty = true;
+       } else if (prop == Glyphs::OriginYProperty) {
+               origin_y = glyphs_get_origin_y (this);
+               origin_y_specified = true;
+               dirty = true;
        } else if (prop == Glyphs::StyleSimulationsProperty) {
-               StyleSimulations sims = glyphs_get_style_simulations (this);
-               printf ("Glyphs::StyleSimulations property changed to %d\n", 
sims);
-       } else if (prop == Glyphs::UnicodeStringProperty) {
-               char *str = glyphs_get_unicode_string (this);
-               printf ("Glyphs::UnicodeString property changed to %s\n", str);
+               // Silverlight 1.0 does not implement this property
+               invalidate = false;
        }
        
-       FullInvalidate (false);
-
+       if (invalidate)
+               Invalidate ();
+       
+       if (dirty)
+               UpdateBounds (true);
+       
        NotifyAttacheesOfPropertyChange (prop);
 }
 

Modified: trunk/moon/src/text.h
===================================================================
--- trunk/moon/src/text.h       2007-10-03 17:35:36 UTC (rev 86823)
+++ trunk/moon/src/text.h       2007-10-03 17:40:44 UTC (rev 86824)
@@ -16,6 +16,8 @@
 #include <cairo.h>
 #include <pango/pango.h>
 
+#include "downloader.h"
+#include "moon-path.h"
 #include "brush.h"
 #include "mango.h"
 #include "font.h"
@@ -106,11 +108,11 @@
        MangoRenderer *renderer;
        Brush *foreground;
        
-       bool dirty_actual_values;
        double actual_height;
        double actual_width;
        double bbox_height;
        double bbox_width;
+       bool dirty;
        
        void CalcActualWidthHeight (cairo_t *cr);
        void Layout (cairo_t *cr);
@@ -118,14 +120,14 @@
        
        double GetBoundingWidth ()
        {
-               if (dirty_actual_values)
+               if (dirty)
                        CalcActualWidthHeight (NULL);
                return bbox_width;
        }
        
        double GetBoundingHeight ()
        {
-               if (dirty_actual_values)
+               if (dirty)
                        CalcActualWidthHeight (NULL);
                return bbox_height;
        }
@@ -155,14 +157,14 @@
        
        double GetActualWidth ()
        {
-               if (dirty_actual_values)
+               if (dirty)
                        CalcActualWidthHeight (NULL);
                return actual_width;
        }
        
        double GetActualHeight ()
        {
-               if (dirty_actual_values)
+               if (dirty)
                        CalcActualWidthHeight (NULL);
                return actual_height;
        }
@@ -226,6 +228,33 @@
 
 
 class Glyphs : public FrameworkElement {
+       TextFontDescription *desc;
+       Downloader *downloader;
+       TextFont *font;
+       
+       cairo_path_t *path;
+       gunichar *text;
+       List *attrs;
+       Brush *fill;
+       
+       bool origin_y_specified;
+       double origin_x;
+       double origin_y;
+       double height;
+       double width;
+       
+       bool invalid;
+       bool dirty;
+       
+       void Layout ();
+       void SetIndices (const char *in);
+       
+       void DownloaderComplete ();
+       
+       static void data_write (guchar *data, gsize n, gsize nn, void *closure);
+       static void downloader_complete (EventObject *sender, gpointer 
calldata, gpointer closure);
+       static void size_notify (int64_t size, gpointer data);
+       
 public:
        static DependencyProperty *FillProperty;
        static DependencyProperty *FontRenderingEmSizeProperty;
@@ -236,7 +265,9 @@
        static DependencyProperty *StyleSimulationsProperty;
        static DependencyProperty *UnicodeStringProperty;
        
-       Glyphs () { }
+       Glyphs ();
+       ~Glyphs ();
+       
        virtual Type::Kind GetObjectType () { return Type::GLYPHS; };
        
        virtual void Render (cairo_t *cr, int x, int y, int width, int height);

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to