GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Description: a tiny graphical app kit for ruby
Homepage: http://code.whytheluckystiff.net/shoes
Clone URL: git://github.com/why/shoes.git
 * shoes/image.c: tie the image loader closer into the cache by making the 
 `shoes_cached_image` struct the currency.  also had to separate out 
 `shoes_load_imagesize` since it won't be threaded and only works with 
 local files.
why (author)
Thu Jul 24 23:47:55 -0700 2008
commit  1b428b037c7ea9fde6b40287895b1ac684b38fd4
tree    128c08c4cf89d3f6ef5f0060b6d462bb6bead33d
parent  a7747033fb63e716740aa3f8a63efe9569647939
...
680
681
682
683
 
684
685
686
...
680
681
682
 
683
684
685
686
0
@@ -680,7 +680,7 @@ VALUE
0
 shoes_canvas_imagesize(VALUE self, VALUE _path)
0
 {
0
   int w, h;
0
- if (shoes_load_image(_path, &w, &h, FALSE))
0
+ if (shoes_load_imagesize(_path, &w, &h) == SHOES_OK)
0
     return rb_ary_new3(2, INT2NUM(w), INT2NUM(h));
0
   return Qnil;
0
 }
...
17
18
19
 
20
21
22
...
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
...
183
184
185
186
187
188
189
 
 
190
191
192
...
563
564
565
566
 
 
567
568
...
17
18
19
20
21
22
23
...
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
...
184
185
186
 
 
187
188
189
190
191
192
193
...
564
565
566
 
567
568
569
570
0
@@ -17,6 +17,7 @@
0
 #include <ruby.h>
0
 
0
 #include "shoes/config.h"
0
+#include "shoes/code.h"
0
 
0
 struct _shoes_app;
0
 
0
@@ -138,28 +139,28 @@ typedef struct {
0
 } shoes_text;
0
 
0
 //
0
+// cached image
0
+//
0
+typedef struct {
0
+ cairo_surface_t *surface;
0
+ cairo_pattern_t *pattern;
0
+ int width, height;
0
+} shoes_cached_image;
0
+
0
+//
0
 // image struct
0
 //
0
 typedef struct {
0
   VALUE parent;
0
   VALUE attr;
0
   shoes_place place;
0
- cairo_surface_t *surface;
0
- int width, height;
0
+ shoes_cached_image *cached;
0
   cairo_matrix_t *tf;
0
   VALUE mode;
0
   VALUE path;
0
   char hover;
0
 } shoes_image;
0
 
0
-//
0
-// cached image
0
-//
0
-typedef struct {
0
- cairo_surface_t *surface;
0
- int width, height;
0
-} shoes_cached_image;
0
-
0
 #ifdef VIDEO
0
 //
0
 // video struct
0
@@ -183,10 +184,10 @@ typedef struct {
0
 typedef struct {
0
   VALUE parent;
0
   VALUE attr;
0
- cairo_pattern_t *pattern;
0
- int width, height; // dimensions of the underlying surface
0
   VALUE source;
0
   char hover;
0
+ shoes_cached_image *cached;
0
+ cairo_pattern_t *pattern;
0
 } shoes_pattern;
0
 
0
 //
0
@@ -563,6 +564,7 @@ extern const double SHOES_PIM2, SHOES_PI, SHOES_RAD2PI;
0
 //
0
 // shoes/image.c
0
 //
0
-cairo_surface_t *shoes_load_image(VALUE, int *, int *, unsigned char);
0
+shoes_code shoes_load_imagesize(VALUE, int *, int *);
0
+shoes_cached_image *shoes_load_image(VALUE);
0
 
0
 #endif
...
137
138
139
140
141
 
 
 
 
142
143
144
...
382
383
384
385
386
 
 
 
 
387
388
389
...
479
480
481
482
483
 
 
484
485
486
...
489
490
491
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
492
493
494
495
496
497
498
499
500
501
502
503
504
 
 
 
 
505
506
507
 
508
509
 
510
511
512
...
519
520
521
522
 
523
524
525
 
526
527
528
529
530
531
532
533
534
535
 
536
...
137
138
139
 
 
140
141
142
143
144
145
146
...
384
385
386
 
 
387
388
389
390
391
392
393
...
483
484
485
 
 
486
487
488
489
490
...
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
 
 
 
 
 
 
 
540
541
542
543
544
545
 
546
547
 
548
549
550
551
...
558
559
560
 
561
562
563
 
564
565
566
 
 
567
 
568
 
 
 
569
570
0
@@ -137,8 +137,10 @@ shoes_surface_create_from_gif(char *filename, int *width, int *height, unsigned
0
            /* PrintGifError(); */
0
            rec = TERMINATE_RECORD_TYPE;
0
         }
0
- *width = w = gif->Image.Width;
0
- *height = h = gif->Image.Height;
0
+ w = gif->Image.Width;
0
+ if (width != NULL) *width = w;
0
+ h = gif->Image.Height;
0
+ if (height != NULL) *height = h;
0
       if ((w < 1) || (h < 1) || (w > 8192) || (h > 8192))
0
         goto done;
0
 
0
@@ -382,8 +384,10 @@ shoes_surface_create_from_jpeg(char *filename, int *width, int *height, unsigned
0
   cinfo.do_block_smoothing = FALSE;
0
 
0
   jpeg_start_decompress(&cinfo);
0
- *width = w = cinfo.output_width;
0
- *height = h = cinfo.output_height;
0
+ w = cinfo.output_width;
0
+ if (width != NULL) *width = w;
0
+ h = cinfo.output_height;
0
+ if (height != NULL) *height = h;
0
 
0
   if ((w < 1) || (h < 1) || (w > 8192) || (h > 8192))
0
     goto done;
0
@@ -479,8 +483,8 @@ shoes_failed_image(VALUE path)
0
     RSTRING_PTR(path), RSTRING_PTR(ext));
0
 }
0
 
0
-cairo_surface_t *
0
-shoes_load_image(VALUE imgpath, int *width, int *height, unsigned char load)
0
+shoes_code
0
+shoes_load_imagesize(VALUE imgpath, int *width, int *height)
0
 {
0
   shoes_cached_image *cached = NULL;
0
   cairo_surface_t *img = NULL;
0
@@ -489,24 +493,59 @@ shoes_load_image(VALUE imgpath, int *width, int *height, unsigned char load)
0
   int len = RSTRING_LEN(filename);
0
 
0
   if (st_lookup(shoes_world->image_cache, (st_data_t)RSTRING_PTR(imgpath), (st_data_t *)&cached))
0
+ {
0
+ *width = cached->width;
0
+ *height = cached->height;
0
+ return SHOES_OK;
0
+ }
0
+
0
+ if (!shoes_check_file_exists(imgpath))
0
+ return SHOES_FAIL;
0
+ else if (shoes_has_ext(fname, len, ".png"))
0
+ img = shoes_png_size(RSTRING_PTR(imgpath), width, height);
0
+ else if (shoes_has_ext(fname, len, ".jpg") || shoes_has_ext(fname, len, ".jpeg"))
0
+ img = shoes_surface_create_from_jpeg(RSTRING_PTR(imgpath), width, height, FALSE);
0
+ else if (shoes_has_ext(fname, len, ".gif"))
0
+ img = shoes_surface_create_from_gif(RSTRING_PTR(imgpath), width, height, FALSE);
0
+ else
0
+ {
0
+ shoes_unsupported_image(imgpath);
0
+ return SHOES_FAIL;
0
+ }
0
+
0
+ if (img != SIZE_SURFACE)
0
+ {
0
+ shoes_failed_image(imgpath);
0
+ return SHOES_FAIL;
0
+ }
0
+ return SHOES_OK;
0
+}
0
+
0
+shoes_cached_image *
0
+shoes_load_image(VALUE imgpath)
0
+{
0
+ shoes_cached_image *cached = NULL;
0
+ cairo_surface_t *img = NULL;
0
+ VALUE filename = rb_funcall(imgpath, s_downcase, 0);
0
+ char *fname = RSTRING_PTR(filename);
0
+ int len = RSTRING_LEN(filename), width = 1, height = 1;
0
+
0
+ if (st_lookup(shoes_world->image_cache, (st_data_t)RSTRING_PTR(imgpath), (st_data_t *)&cached))
0
     goto done;
0
 
0
   if (!shoes_check_file_exists(imgpath))
0
     img = shoes_world->blank_image;
0
   else if (shoes_has_ext(fname, len, ".png"))
0
   {
0
- img = shoes_png_size(RSTRING_PTR(imgpath), width, height);
0
- if (load)
0
- {
0
- img = cairo_image_surface_create_from_png(RSTRING_PTR(imgpath));
0
- if (cairo_surface_status(img) != CAIRO_STATUS_SUCCESS)
0
- img = NULL;
0
- }
0
+ img = shoes_png_size(RSTRING_PTR(imgpath), &width, &height);
0
+ img = cairo_image_surface_create_from_png(RSTRING_PTR(imgpath));
0
+ if (cairo_surface_status(img) != CAIRO_STATUS_SUCCESS)
0
+ img = NULL;
0
   }
0
   else if (shoes_has_ext(fname, len, ".jpg") || shoes_has_ext(fname, len, ".jpeg"))
0
- img = shoes_surface_create_from_jpeg(RSTRING_PTR(imgpath), width, height, load);
0
+ img = shoes_surface_create_from_jpeg(RSTRING_PTR(imgpath), &width, &height, TRUE);
0
   else if (shoes_has_ext(fname, len, ".gif"))
0
- img = shoes_surface_create_from_gif(RSTRING_PTR(imgpath), width, height, load);
0
+ img = shoes_surface_create_from_gif(RSTRING_PTR(imgpath), &width, &height, TRUE);
0
   else
0
   {
0
     shoes_unsupported_image(imgpath);
0
@@ -519,18 +558,13 @@ shoes_load_image(VALUE imgpath, int *width, int *height, unsigned char load)
0
     img = shoes_world->blank_image;
0
   }
0
 
0
- if (load && img != shoes_world->blank_image)
0
+ if (img != shoes_world->blank_image)
0
   {
0
     cached = SHOE_ALLOC(shoes_cached_image);
0
- cached->surface = img; cached->width = *width; cached->height = *height;
0
+ cached->surface = img; cached->pattern = NULL; cached->width = width; cached->height = height;
0
     st_insert(shoes_world->image_cache, (st_data_t)strdup(RSTRING_PTR(imgpath)), (st_data_t)cached);
0
   }
0
- else if (!load && img == shoes_world->blank_image)
0
- img = NULL;
0
 
0
- return img;
0
 done:
0
- *width = cached->width;
0
- *height = cached->height;
0
- return cached->surface;
0
+ return cached;
0
 }
...
505
506
507
 
 
 
508
509
 
510
511
512
 
 
513
514
515
 
516
517
518
519
 
520
521
 
522
523
524
...
702
703
704
705
706
707
708
...
712
713
714
715
 
716
717
 
718
719
720
...
722
723
724
 
725
726
727
728
729
730
731
732
733
734
 
735
736
737
...
763
764
765
766
 
767
768
769
770
771
772
773
 
774
775
776
...
785
786
787
788
789
 
790
791
792
...
813
814
815
816
 
817
818
819
...
860
861
862
863
864
865
 
866
867
868
...
1108
1109
1110
1111
 
1112
1113
1114
...
1466
1467
1468
1469
 
 
1470
1471
1472
...
1501
1502
1503
1504
1505
1506
1507
...
1544
1545
1546
1547
1548
1549
1550
1551
 
1552
1553
 
 
1554
1555
1556
...
1584
1585
1586
1587
 
1588
1589
1590
...
1593
1594
1595
1596
 
1597
1598
1599
...
1608
1609
1610
1611
 
1612
1613
1614
...
1622
1623
1624
1625
 
1626
1627
1628
...
1643
1644
1645
 
1646
1647
1648
1649
1650
1651
1652
...
505
506
507
508
509
510
511
 
512
513
 
 
514
515
516
517
 
518
519
520
521
 
522
523
 
524
525
526
527
...
705
706
707
 
708
709
710
...
714
715
716
 
717
718
719
720
721
722
723
...
725
726
727
728
729
730
731
 
 
 
 
 
 
 
732
733
734
735
...
761
762
763
 
764
765
766
767
768
769
770
 
771
772
773
774
...
783
784
785
 
 
786
787
788
789
...
810
811
812
 
813
814
815
816
...
857
858
859
 
 
 
860
861
862
863
...
1103
1104
1105
 
1106
1107
1108
1109
...
1461
1462
1463
 
1464
1465
1466
1467
1468
...
1497
1498
1499
 
1500
1501
1502
...
1539
1540
1541
 
1542
1543
1544
 
1545
1546
 
1547
1548
1549
1550
1551
...
1579
1580
1581
 
1582
1583
1584
1585
...
1588
1589
1590
 
1591
1592
1593
1594
...
1603
1604
1605
 
1606
1607
1608
1609
...
1617
1618
1619
 
1620
1621
1622
1623
...
1638
1639
1640
1641
1642
1643
 
 
1644
1645
1646
0
@@ -505,20 +505,23 @@ shoes_control_show_ref(SHOES_CONTROL_REF ref)
0
     canvas->cy = canvas->endy; \
0
   }
0
 
0
+#define PATTERN_DIM(self_t, x) (self_t->cached != NULL ? self_t->cached->x : 1)
0
+#define PATTERN(self_t) (self_t->cached != NULL ? self_t->cached->pattern : self_t->pattern)
0
+
0
 #define PATTERN_SCALE(self_t) \
0
- if (self_t->width == 1.0 && self_t->height == 1.0) \
0
+ if (self_t->cached == NULL) \
0
   { \
0
- cairo_pattern_get_matrix(self_t->pattern, &matrix1); \
0
- cairo_pattern_get_matrix(self_t->pattern, &matrix2); \
0
+ cairo_pattern_get_matrix(PATTERN(self_t), &matrix1); \
0
+ cairo_pattern_get_matrix(PATTERN(self_t), &matrix2); \
0
     cairo_matrix_scale(&matrix2, 1. / (place.iw + (sw * 2.)), 1. / (place.ih + (sw * 2.))); \
0
     if (sw != 0.0) cairo_matrix_translate(&matrix2, sw, sw); \
0
- cairo_pattern_set_matrix(self_t->pattern, &matrix2); \
0
+ cairo_pattern_set_matrix(PATTERN(self_t), &matrix2); \
0
   }
0
 
0
 #define PATTERN_RESET(self_t) \
0
- if (self_t->width == 1.0 && self_t->height == 1.0) \
0
+ if (self_t->cached == NULL) \
0
   { \
0
- cairo_pattern_set_matrix(self_t->pattern, &matrix1); \
0
+ cairo_pattern_set_matrix(PATTERN(self_t), &matrix1); \
0
   }
0
 
0
 //
0
@@ -702,7 +705,6 @@ shoes_image_new(VALUE klass, VALUE path, VALUE realpath, VALUE attr, VALUE paren
0
   GError *error = NULL;
0
   VALUE obj = Qnil;
0
   shoes_image *image;
0
- cairo_surface_t *surf;
0
 
0
   obj = shoes_image_alloc(klass);
0
   Data_Get_Struct(obj, shoes_image, image);
0
@@ -712,9 +714,10 @@ shoes_image_new(VALUE klass, VALUE path, VALUE realpath, VALUE attr, VALUE paren
0
   {
0
     shoes_image *image2;
0
     Data_Get_Struct(path, shoes_image, image2);
0
- cairo_surface_reference(image->surface = image2->surface);
0
+ image->cached = image2->cached;
0
     attr = realpath;
0
   }
0
+ /* TODO: cached image blocks
0
   else if (rb_obj_is_kind_of(path, cImageBlock))
0
   {
0
     shoes_canvas *c;
0
@@ -722,16 +725,11 @@ shoes_image_new(VALUE klass, VALUE path, VALUE realpath, VALUE attr, VALUE paren
0
     cairo_surface_reference(image->surface = cairo_get_target(c->cr));
0
     attr = realpath;
0
   }
0
+ */
0
   else
0
   {
0
     image->path = path;
0
- image->surface = shoes_load_image(realpath, &image->width, &image->height, TRUE);
0
- }
0
-
0
- if (image->surface != NULL && image->width == 0)
0
- {
0
- image->width = cairo_image_surface_get_width(image->surface);
0
- image->height = cairo_image_surface_get_height(image->surface);
0
+ image->cached = shoes_load_image(realpath);
0
   }
0
 
0
   cairo_matrix_init_identity(image->tf);
0
@@ -763,14 +761,14 @@ VALUE
0
 shoes_image_get_full_width(VALUE self)
0
 {
0
   GET_STRUCT(image, image);
0
- return INT2NUM(image->width);
0
+ return INT2NUM(image->cached->width);
0
 }
0
 
0
 VALUE
0
 shoes_image_get_full_height(VALUE self)
0
 {
0
   GET_STRUCT(image, image);
0
- return INT2NUM(image->height);
0
+ return INT2NUM(image->cached->height);
0
 }
0
 
0
 VALUE
0
@@ -785,8 +783,7 @@ shoes_image_set_path(VALUE self, VALUE path)
0
 {
0
   GET_STRUCT(image, image);
0
   image->path = path;
0
- image->surface = shoes_load_image(path, &image->width, &image->height, TRUE);
0
- shoes_canvas_repaint_all(image->parent);
0
+ image->cached = shoes_load_image(path);
0
   return path;
0
 }
0
 
0
@@ -813,7 +810,7 @@ shoes_image_set_path(VALUE self, VALUE path)
0
 VALUE
0
 shoes_image_draw(VALUE self, VALUE c, VALUE actual)
0
 {
0
- SHOES_IMAGE_PLACE(image, self_t->width, self_t->height, self_t->surface);
0
+ SHOES_IMAGE_PLACE(image, self_t->cached->width, self_t->cached->height, self_t->cached->surface);
0
 }
0
 
0
 VALUE
0
@@ -860,9 +857,7 @@ VALUE
0
 shoes_image_size(VALUE self)
0
 {
0
   GET_STRUCT(image, self_t);
0
- return rb_ary_new3(2,
0
- INT2NUM(cairo_image_surface_get_width(self_t->surface)),
0
- INT2NUM(cairo_image_surface_get_height(self_t->surface)));
0
+ return rb_ary_new3(2, INT2NUM(self_t->cached->width), INT2NUM(self_t->cached->height));
0
 }
0
 
0
 static unsigned char *
0
@@ -1108,7 +1103,7 @@ shoes_image_motion(VALUE self, int x, int y, char *touch)
0
   GET_STRUCT(image, self_t);
0
 
0
   click = ATTR(self_t->attr, click);
0
- if (self_t->surface == NULL) return Qnil;
0
+ if (self_t->cached == NULL) return Qnil;
0
 
0
   if (IS_INSIDE(self_t, x, y))
0
   {
0
@@ -1466,7 +1461,8 @@ shoes_pattern_mark(shoes_pattern *pattern)
0
 static void
0
 shoes_pattern_free(shoes_pattern *pattern)
0
 {
0
- cairo_pattern_destroy(pattern->pattern);
0
+ if (pattern->pattern != NULL)
0
+ cairo_pattern_destroy(pattern->pattern);
0
   RUBY_CRITICAL(free(pattern));
0
 }
0
 
0
@@ -1501,7 +1497,6 @@ shoes_pattern_gradient(shoes_pattern *pattern, VALUE r1, VALUE r2, VALUE attr)
0
   }
0
   shoes_color_grad_stop(pattern->pattern, 0.0, r1);
0
   shoes_color_grad_stop(pattern->pattern, 1.0, r2);
0
- pattern->width = pattern->height = 1.;
0
 }
0
 
0
 VALUE
0
@@ -1544,13 +1539,13 @@ shoes_pattern_new(VALUE klass, VALUE source, VALUE attr, VALUE parent)
0
     if (rb_obj_is_kind_of(source, cColor))
0
     {
0
       pattern->pattern = shoes_color_pattern(source);
0
- pattern->width = pattern->height = 1.;
0
     }
0
     else
0
     {
0
- cairo_surface_t *surface = shoes_load_image(source, &pattern->width, &pattern->height, TRUE);
0
+ pattern->cached = shoes_load_image(source);
0
       pattern->source = source;
0
- pattern->pattern = cairo_pattern_create_for_surface(surface);
0
+ if (pattern->cached->pattern == NULL)
0
+ pattern->cached->pattern = cairo_pattern_create_for_surface(pattern->cached->surface);
0
     }
0
     cairo_pattern_set_extend(pattern->pattern, CAIRO_EXTEND_REPEAT);
0
   }
0
@@ -1584,7 +1579,7 @@ shoes_background_draw(VALUE self, VALUE c, VALUE actual)
0
 {
0
   cairo_matrix_t matrix1, matrix2;
0
   double r = 0., sw = 1.;
0
- SETUP(shoes_pattern, REL_TILE, self_t->width, self_t->height);
0
+ SETUP(shoes_pattern, REL_TILE, PATTERN_DIM(self_t, width), PATTERN_DIM(self_t, height));
0
   r = ATTR2(dbl, self_t->attr, curve, 0.);
0
 
0
   if (RTEST(actual))
0
@@ -1593,7 +1588,7 @@ shoes_background_draw(VALUE self, VALUE c, VALUE actual)
0
     cairo_translate(canvas->cr, place.ix + place.dx, place.iy + place.dy);
0
     PATTERN_SCALE(self_t);
0
     shoes_cairo_rect(canvas->cr, 0, 0, place.iw, place.ih, r);
0
- cairo_set_source(canvas->cr, self_t->pattern);
0
+ cairo_set_source(canvas->cr, PATTERN(self_t));
0
     cairo_fill(canvas->cr);
0
     cairo_restore(canvas->cr);
0
     PATTERN_RESET(self_t);
0
@@ -1608,7 +1603,7 @@ shoes_border_draw(VALUE self, VALUE c, VALUE actual)
0
 {
0
   cairo_matrix_t matrix1, matrix2;
0
   double r = 0., sw = 1.;
0
- SETUP(shoes_pattern, REL_TILE, self_t->width, self_t->height);
0
+ SETUP(shoes_pattern, REL_TILE, PATTERN_DIM(self_t, width), PATTERN_DIM(self_t, height));
0
   r = ATTR2(dbl, self_t->attr, curve, 0.);
0
   sw = ATTR2(dbl, self_t->attr, strokewidth, 1.);
0
 
0
@@ -1622,7 +1617,7 @@ shoes_border_draw(VALUE self, VALUE c, VALUE actual)
0
     cairo_save(canvas->cr);
0
     cairo_translate(canvas->cr, place.ix + place.dx, place.iy + place.dy);
0
     PATTERN_SCALE(self_t);
0
- cairo_set_source(canvas->cr, self_t->pattern);
0
+ cairo_set_source(canvas->cr, PATTERN(self_t));
0
     shoes_cairo_rect(canvas->cr, 0, 0, place.iw, place.ih, r);
0
     cairo_set_antialias(canvas->cr, CAIRO_ANTIALIAS_NONE);
0
     cairo_set_line_width(canvas->cr, sw);
0
@@ -1643,10 +1638,9 @@ shoes_subpattern_new(VALUE klass, VALUE pat, VALUE parent)
0
   Data_Get_Struct(obj, shoes_pattern, back);
0
   Data_Get_Struct(pat, shoes_pattern, pattern);
0
   back->source = pattern->source;
0
+ back->cached = pattern->cached;
0
   back->pattern = pattern->pattern;
0
   cairo_pattern_reference(back->pattern);
0
- back->width = pattern->width;
0
- back->height = pattern->height;
0
   back->attr = pattern->attr;
0
   back->parent = parent;
0
   return obj;
...
42
43
44
 
 
45
46
47
...
42
43
44
45
46
47
48
49
0
@@ -42,6 +42,8 @@ shoes_world_alloc()
0
 int
0
 shoes_world_free_image_cache(char *key, shoes_cached_image *cached, char *arg)
0
 {
0
+ if (cached->pattern != NULL)
0
+ cairo_pattern_destroy(cached->pattern);
0
   cairo_surface_destroy(cached->surface);
0
   free(cached);
0
   free(key);
...
600
601
602
 
 
603
604
605
...
600
601
602
603
604
605
606
607
0
@@ -600,6 +600,8 @@ The `path` can be a file path or a URL. All images loaded are temporarily cache
0
 
0
 Quickly grab the width and height of an image. The image won't be loaded into the cache or displayed.
0
 
0
+URGENT NOTE: This method cannot be used with remote images (loaded from HTTP, rather than the hard drive.)
0
+
0
 === ins(text) ยป Shoes::Ins ===
0
 
0
 Creates an Ins text fragment (short for "inserted") which Shoes styles with a single underline.

Comments

    No one has commented yet.