sproutcore 1.6.0.1-java → 1.7.1.beta-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. data/CHANGELOG +21 -0
  2. data/Gemfile +5 -0
  3. data/Rakefile +26 -13
  4. data/VERSION.yml +2 -2
  5. data/lib/Buildfile +43 -4
  6. data/lib/buildtasks/build.rake +10 -0
  7. data/lib/buildtasks/helpers/file_rule.rb +22 -0
  8. data/lib/buildtasks/helpers/file_rule_list.rb +137 -0
  9. data/lib/buildtasks/manifest.rake +133 -122
  10. data/lib/frameworks/sproutcore/CHANGELOG.md +69 -2
  11. data/lib/frameworks/sproutcore/apps/tests/english.lproj/strings.js +1 -0
  12. data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +28 -22
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +9 -5
  14. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/controller.js +1 -1
  15. data/lib/frameworks/sproutcore/frameworks/core_foundation/controls/button.js +18 -13
  16. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/bind.js +5 -3
  17. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/collection.js +2 -0
  18. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/action_support.js +80 -0
  19. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/text_field_support.js +84 -116
  20. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +8 -5
  21. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +157 -157
  22. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/platform.js +5 -3
  23. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +6 -6
  24. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/sparse_array.js +10 -7
  25. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/action_support.js +106 -0
  26. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/collection.js +18 -0
  27. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/handlebars.js +71 -1
  28. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/attribute_bindings_test.js +38 -0
  29. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/class_name_bindings_test.js +47 -0
  30. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutChildViews.js +18 -18
  31. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +42 -10
  32. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +158 -1
  33. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/keyboard.js +26 -1
  34. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +14 -8
  35. data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +15 -2
  36. data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +108 -108
  37. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +1 -1
  38. data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +2 -4
  39. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/error_methods.js +2 -2
  40. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/single_attribute.js +26 -0
  41. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/builders.js +7 -0
  42. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/error_methods.js +1 -1
  43. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +4 -1
  44. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/tests/system/datetime.js +6 -0
  45. data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +26 -5
  46. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +97 -96
  47. data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +4 -3
  48. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/ui.js +17 -4
  49. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +7 -7
  50. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +7 -5
  51. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +12 -3
  52. data/lib/frameworks/sproutcore/frameworks/desktop/views/web.js +23 -14
  53. data/lib/frameworks/sproutcore/frameworks/experimental/Buildfile +5 -1
  54. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/render_delegates/menu_scroller.js +28 -0
  55. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/tests/menu/scroll.js +235 -0
  56. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroll.js +363 -0
  57. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroller.js +250 -0
  58. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/desktop_scroller.js +92 -0
  59. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/native_scroll.js +25 -0
  60. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/scroll.js +33 -0
  61. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/touch_scroller.js +76 -0
  62. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/integration.js +50 -0
  63. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/methods.js +143 -0
  64. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/ui.js +258 -0
  65. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroll.js +1164 -0
  66. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroller.js +332 -0
  67. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroll.js +236 -0
  68. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroller.js +347 -0
  69. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroll.js +15 -0
  70. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroller.js +10 -0
  71. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroll.js +804 -0
  72. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroller.js +133 -0
  73. data/lib/frameworks/sproutcore/frameworks/foundation/resources/text_field.css +3 -3
  74. data/lib/frameworks/sproutcore/frameworks/foundation/validators/number.js +3 -1
  75. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +3 -3
  76. data/lib/frameworks/sproutcore/frameworks/media/views/audio.js +2 -1
  77. data/lib/frameworks/sproutcore/frameworks/media/views/controls.js +2 -1
  78. data/lib/frameworks/sproutcore/frameworks/media/views/media_slider.js +2 -4
  79. data/lib/frameworks/sproutcore/frameworks/media/views/mini_controls.js +2 -4
  80. data/lib/frameworks/sproutcore/frameworks/media/views/simple_controls.js +2 -4
  81. data/lib/frameworks/sproutcore/frameworks/media/views/video.js +2 -2
  82. data/lib/frameworks/sproutcore/frameworks/routing/system/routes.js +29 -3
  83. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
  84. data/lib/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/replace.js +1 -1
  85. data/lib/frameworks/sproutcore/frameworks/runtime/private/property_chain.js +2 -1
  86. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +3 -3
  87. data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +2 -2
  88. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +1 -1
  89. data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list_item.css +2 -2
  90. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/segmented.css +1 -1
  91. data/lib/gen/app/templates/apps/@target_name@/Buildfile +3 -5
  92. data/lib/gen/app/templates/apps/@target_name@/resources/_theme.css +18 -0
  93. data/lib/gen/project/templates/@filename@/Buildfile +2 -2
  94. data/lib/sproutcore.rb +30 -5
  95. data/lib/sproutcore/builders.rb +1 -0
  96. data/lib/sproutcore/builders/chance_file.rb +9 -16
  97. data/lib/sproutcore/builders/html.rb +2 -1
  98. data/lib/sproutcore/builders/minify.rb +4 -35
  99. data/lib/sproutcore/builders/module.rb +38 -1
  100. data/lib/sproutcore/builders/split.rb +63 -0
  101. data/lib/sproutcore/builders/strings.rb +7 -1
  102. data/lib/sproutcore/helpers.rb +1 -1
  103. data/lib/sproutcore/helpers/css_split.rb +190 -0
  104. data/lib/sproutcore/helpers/entry_sorter.rb +2 -0
  105. data/lib/sproutcore/helpers/minifier.rb +40 -16
  106. data/lib/sproutcore/helpers/static_helper.rb +35 -17
  107. data/lib/sproutcore/models/manifest.rb +26 -0
  108. data/lib/sproutcore/models/target.rb +12 -1
  109. data/lib/sproutcore/rack.rb +1 -0
  110. data/lib/sproutcore/rack/proxy.rb +244 -225
  111. data/lib/sproutcore/rack/restrict_ip.rb +67 -0
  112. data/lib/sproutcore/rack/service.rb +8 -2
  113. data/lib/sproutcore/tools.rb +102 -46
  114. data/lib/sproutcore/tools/build.rb +91 -43
  115. data/lib/sproutcore/tools/gen.rb +2 -3
  116. data/lib/sproutcore/tools/manifest.rb +22 -16
  117. data/lib/sproutcore/tools/server.rb +21 -0
  118. data/spec/buildtasks/helpers/accept_list +22 -0
  119. data/spec/buildtasks/helpers/accept_list.rb +128 -0
  120. data/spec/buildtasks/helpers/list.json +11 -0
  121. data/spec/buildtasks/manifest/prepare_build_tasks/chance_2x_spec.rb +1 -39
  122. data/spec/buildtasks/manifest/prepare_build_tasks/chance_spec.rb +0 -38
  123. data/spec/buildtasks/manifest/prepare_build_tasks/combine_spec.rb +4 -4
  124. data/spec/buildtasks/manifest/prepare_build_tasks/module_spec.rb +2 -2
  125. data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_indirect_spec.rb +7 -16
  126. data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_spec.rb +7 -17
  127. data/spec/buildtasks/manifest/prepare_build_tasks/packed_spec.rb +11 -6
  128. data/spec/fixtures/builder_tests/Buildfile +2 -1
  129. data/spec/fixtures/builder_tests/apps/module_test/modules/required_module/core.js +0 -0
  130. data/spec/lib/builders/module_spec.rb +1 -1
  131. data/spec/spec_helper.rb +1 -0
  132. data/sproutcore.gemspec +4 -9
  133. data/vendor/chance/lib/chance.rb +25 -6
  134. data/vendor/chance/lib/chance/factory.rb +45 -0
  135. data/vendor/chance/lib/chance/instance.rb +173 -28
  136. data/vendor/chance/lib/chance/instance/data_url.rb +0 -29
  137. data/vendor/chance/lib/chance/instance/slicing.rb +57 -4
  138. data/vendor/chance/lib/chance/instance/spriting.rb +112 -21
  139. data/vendor/chance/lib/chance/parser.rb +80 -52
  140. data/vendor/sproutcore/SCCompiler.jar +0 -0
  141. data/vendor/sproutcore/lib/args4j-2.0.12.jar +0 -0
  142. data/vendor/sproutcore/lib/yuicompressor-2.4.2.jar +0 -0
  143. metadata +84 -25
@@ -23,11 +23,6 @@ module Chance
23
23
  output += "\n-webkit-background-size: #{width}px #{height}px;"
24
24
  end
25
25
 
26
-
27
- # FOR IE < 8:
28
- output += '*background-image: url("mhtml:chance-mhtml.txt!' + slice[:css_name] + '")'
29
- output += "\n"
30
-
31
26
  output
32
27
  }
33
28
 
@@ -57,29 +52,5 @@ module Chance
57
52
  end
58
53
  end
59
54
 
60
- def mhtml(opts)
61
- # If there are no slices, ensure that we return an empty file.
62
- return "" if @slices.length == 0
63
-
64
- output = "Content-Type: multipart/related; boundary=\"CHANCE__\"\r\n"
65
-
66
- @slices.each {|name, slice|
67
- output += "\r\n--CHANCE__\r\n"
68
- output += "Content-Location:" + slice[:css_name] + "\r\n"
69
- output += "Content-Type:image/png\r\n"
70
- output += "Content-Transfer-Encoding:base64\r\n\r\n"
71
-
72
- base64Image = base64_for(slice)
73
- output += base64Image.gsub("[^\r]\n", "\r\n")
74
-
75
- output
76
- }
77
-
78
- output += "\r\n--CHANCE__--"
79
-
80
- output
81
- end
82
-
83
-
84
55
  end
85
56
  end
@@ -2,17 +2,57 @@ require "chance/perf"
2
2
 
3
3
  module Chance
4
4
  class Instance
5
-
6
5
  # The Slicing module handles taking a collection of slice definitions to
7
6
  # produce sliced images. It uses ChunkyPNG to perform the slicing, and
8
7
  # stores the sliced image in the slice definition.
9
8
  module Slicing
9
+ class << self
10
+ def add_canvas_to_cache(canvas, file, rect)
11
+ if @canvas_cache.nil?
12
+ @canvas_cache = {}
13
+ end
14
+
15
+ left = rect[:left]
16
+ top = rect[:top]
17
+ width = rect[:width]
18
+ height = rect[:height]
19
+
20
+ key = "#{file[:path]}:#{left},#{top},#{width},#{height}"
21
+ @canvas_cache[key] = {
22
+ mtime: file[:mtime],
23
+ canvas: canvas
24
+ }
25
+ end
26
+
27
+ def get_canvas_from_cache(file, rect)
28
+ if @canvas_cache.nil?
29
+ @canvas_cache = {}
30
+ end
31
+
32
+ left = rect[:left]
33
+ top = rect[:top]
34
+ width = rect[:width]
35
+ height = rect[:height]
36
+
37
+ key = "#{file[:path]}:#{left},#{top},#{width},#{height}"
38
+ hash = @canvas_cache[key]
39
+
40
+ # Check to see if it is new enough
41
+ if not hash.nil? and hash[:mtime] == file[:mtime]
42
+ return hash[:canvas]
43
+ end
44
+
45
+ @canvas_cache[key] = nil
46
+ nil
47
+ end
48
+ end
49
+
10
50
  # performs the slicing indicated by each slice definition, and puts the resulting
11
51
  # image in the slice definition's :image property.
12
52
  #
13
53
  # if x2 is supplied, this will assume it is a second pass to locate any @2x images
14
54
  # and use them to replace the originals.
15
- def slice_images(opts)
55
+ def slice_images(opts)
16
56
  slices = @slices
17
57
  output = ""
18
58
 
@@ -21,7 +61,7 @@ module Chance
21
61
  # Otherwise, consumers will use slice[:file] [:canvas] or [:contents]
22
62
  # to get the original data as needed.
23
63
  slice[:canvas] = nil
24
-
64
+
25
65
  # In any case, if there is one, we need to get the original file and canvas;
26
66
  # this process also tells us if the slice is 2x, etc.
27
67
  canvas = canvas_for slice, opts
@@ -53,7 +93,17 @@ module Chance
53
93
  rect = slice_rect(slice, canvas_width / f, canvas_height / f)
54
94
 
55
95
  if not rect.nil?
56
- slice[:canvas] = canvas.crop(rect[:left] * f, rect[:top] * f, rect[:width] * f, rect[:height] * f)
96
+
97
+ ## CHECK CACHE ##
98
+ file = file_for(slice, opts)
99
+ cached_canvas = Chance::Instance::Slicing.get_canvas_from_cache(file, rect)
100
+ if cached_canvas
101
+ slice[:canvas] = cached_canvas
102
+ else
103
+ slice[:canvas] = canvas.crop(rect[:left] * f, rect[:top] * f, rect[:width] * f, rect[:height] * f)
104
+ Chance::Instance::Slicing.add_canvas_to_cache(slice[:canvas], file, rect)
105
+ end
106
+
57
107
  canvas_width = rect[:height] * f
58
108
  canvas_height = rect[:width] * f
59
109
  end
@@ -62,8 +112,11 @@ module Chance
62
112
  slice[:target_width] = canvas_width / f
63
113
  slice[:target_height] = canvas_height / f
64
114
  end
115
+
116
+
65
117
 
66
118
  end
119
+
67
120
  end
68
121
 
69
122
  # Returns either a RMagick image or a ChunkyPNG canvas for a slice, as applicable.
@@ -18,12 +18,12 @@ module Chance
18
18
  # images in the class's @sprites property and updating the individual slices
19
19
  # with a :sprite property containing the identifier of the sprite, and offset
20
20
  # properties for the offsets within the image.
21
- def generate_sprite_definitions(opts)
21
+ def generate_sprite_definitions(opts)
22
22
  @sprites = {}
23
23
 
24
24
  group_slices_into_sprites(opts)
25
25
  @sprites.each do |key, sprite|
26
- layout_slices_in_sprite sprite
26
+ layout_slices_in_sprite sprite, opts
27
27
  end
28
28
  end
29
29
 
@@ -70,7 +70,7 @@ module Chance
70
70
  # Determines the name of the sprite for the given slice. The sprite
71
71
  # by this name may not exist yet.
72
72
  def sprite_name_for_slice(slice, opts)
73
- if slice[:repeat] == "repeat-both"
73
+ if slice[:repeat] == "repeat"
74
74
  return slice[:path] + (opts[:x2] ? "@2x" : "")
75
75
  end
76
76
 
@@ -79,10 +79,23 @@ module Chance
79
79
 
80
80
  # Performs the layout operation, laying either up-to-down, or "
81
81
  # (for repeat-y slices) left-to-right.
82
- def layout_slices_in_sprite(sprite)
82
+ def layout_slices_in_sprite(sprite, opts)
83
83
  # The position is the position in the layout direction. In vertical mode
84
84
  # (the usual) it is the Y position.
85
85
  pos = 0
86
+
87
+ # Adds some padding that will be painted with a pattern so that it is apparent that
88
+ # CSS is wrong.
89
+ # NOTE: though this is only in debug mode, we DO need to make sure it is on a 2px boundary.
90
+ # This makes sure 2x works properly.
91
+ padding = @options[:pad_sprites_for_debugging] ? 2 : 0
92
+
93
+ # The position within a row. It starts at 0 even if we have padding,
94
+ # because we always just add padding when we set the individual x/y pos.
95
+ inset = 0
96
+
97
+ # The length of the row. Length, when layout out vertically (the usual), is the height
98
+ row_length = 0
86
99
 
87
100
  # The size is the current size of the sprite in the non-layout direction;
88
101
  # for example, in the usual, vertical mode, the size is the width.
@@ -94,17 +107,19 @@ module Chance
94
107
  smallest_size = nil
95
108
 
96
109
  is_horizontal = sprite[:use_horizontal_layout]
97
-
98
- sprite[:slices].each do |slice|
110
+
111
+ # Figure out slice width/heights. We cannot rely on slicing to do this for us
112
+ # because some images may be being passed through as-is.
113
+ sprite[:slices].each {|slice|
99
114
  # We must find a canvas either on the slice (if it was actually sliced),
100
115
  # or on the slice's file. Otherwise, we're in big shit.
101
116
  canvas = slice[:canvas] || slice[:file][:canvas]
102
-
117
+
103
118
  # TODO: MAKE A BETTER ERROR.
104
119
  unless canvas
105
- throw "Could not sprite image " + slice[:path] + "; if it is not a PNG"
120
+ throw "Could not sprite image " + slice[:path] + "; if it is not a PNG, make sure you have rmagick installed"
106
121
  end
107
-
122
+
108
123
  # RMagick has a different API than ChunkyPNG; we have to detect
109
124
  # which one we are using, and use the correct API accordingly.
110
125
  if canvas.respond_to?('columns')
@@ -114,10 +129,10 @@ module Chance
114
129
  slice_width = canvas.width
115
130
  slice_height = canvas.height
116
131
  end
117
-
132
+
118
133
  slice_length = is_horizontal ? slice_width : slice_height
119
134
  slice_size = is_horizontal ? slice_height : slice_width
120
-
135
+
121
136
  # When repeating, we must use the least common multiple so that
122
137
  # we can ensure the repeat pattern works even with multiple repeat
123
138
  # sizes. However, we should take into account how much extra we are
@@ -128,8 +143,41 @@ module Chance
128
143
 
129
144
  size = size.lcm slice_size
130
145
  else
131
- size = [size, slice_size].max
146
+ size = [size, slice_size + padding * 2].max
147
+ end
148
+
149
+ slice[:slice_width] = slice_width.to_i
150
+ slice[:slice_height] = slice_height.to_i
151
+ }
152
+
153
+ # Sort slices from widest/tallest (dependent on is_horizontal) or is_vertical
154
+ # NOTE: This means we are technically sorting reversed
155
+ sprite[:slices].sort! {|a, b|
156
+ # WHY <=> NO WORK?
157
+ if is_horizontal
158
+ b[:slice_height] <=> a[:slice_height]
159
+ else
160
+ b[:slice_width] <=> a[:slice_width]
161
+ end
162
+ }
163
+
164
+ sprite[:slices].each do |slice|
165
+ # We must find a canvas either on the slice (if it was actually sliced),
166
+ # or on the slice's file. Otherwise, we're in big shit.
167
+ canvas = slice[:canvas] || slice[:file][:canvas]
168
+
169
+ slice_width = slice[:slice_width]
170
+ slice_height = slice[:slice_height]
171
+
172
+ slice_length = is_horizontal ? slice_width : slice_height
173
+ slice_size = is_horizontal ? slice_height : slice_width
174
+
175
+ if slice[:repeat] != "no-repeat" or inset + slice_size + padding * 2 > size or not @options[:optimize_sprites]
176
+ pos += row_length
177
+ inset = 0
178
+ row_length = 0
132
179
  end
180
+
133
181
 
134
182
  # We have extras for manual tweaking of offsetx/y. We have to make sure there
135
183
  # is padding for this (on either side)
@@ -149,20 +197,44 @@ module Chance
149
197
  elsif slice[:max_offset_y] > 0 and not is_horizontal
150
198
  pos += slice[:max_offset_y]
151
199
  end
152
-
153
-
154
- slice[:sprite_slice_x] = is_horizontal ? pos : 0
155
- slice[:sprite_slice_y] = is_horizontal ? 0 : pos
200
+
201
+ slice[:sprite_slice_x] = (is_horizontal ? pos : inset)
202
+ slice[:sprite_slice_y] = (is_horizontal ? inset : pos)
203
+
204
+ # add padding for x, only if it a) doesn't repeat or b) repeats vertically because it has horizontal layout
205
+ if slice[:repeat] == "no-repeat" or slice[:repeat] == "repeat-y"
206
+ slice[:sprite_slice_x] += padding
207
+ end
208
+
209
+ if slice[:repeat] == "no-repeat" or slice[:repeat] == "repeat-x"
210
+ slice[:sprite_slice_y] += padding
211
+ end
212
+
156
213
  slice[:sprite_slice_width] = slice_width
157
214
  slice[:sprite_slice_height] = slice_height
158
215
 
159
- pos += slice_length
216
+ inset += slice_size + padding * 2
217
+
218
+ # We pad the row length ONLY if it is a repeat-x, repeat-y, or no-repeat image.
219
+ # If it is 'repeat', we do not pad it, because it should be processed raw.
220
+ row_length = [slice_length + (slice[:repeat] != "repeat" ? padding * 2 : 0), row_length].max
221
+
222
+ # In 2X, make sure we are aligned on a 2px grid.
223
+ # We correct this AFTER positioning because we always position on an even grid anyway;
224
+ # we just may leave that even grid if we have an odd-sized image. We do this after positioning
225
+ # so that the next loop knows if there is space.
226
+ if opts[:x2]
227
+ row_length = (row_length.to_f / 2).ceil * 2
228
+ inset = (inset.to_f / 2).ceil * 2
229
+ end
230
+
160
231
  end
232
+ pos += row_length
161
233
 
162
234
  # TODO: USE A CONSTANT FOR THIS WARNING
163
235
  smallest_size = size if smallest_size == nil
164
236
  if size - smallest_size > 10
165
- puts "WARNING: Used more than 10 extra rows or columns to accomdate repeating slices."
237
+ puts "WARNING: Used more than 10 extra rows or columns to accommodate repeating slices."
166
238
  puts "Wasted up to " + (pos * size-smallest_size).to_s + " pixels"
167
239
  end
168
240
 
@@ -177,6 +249,14 @@ module Chance
177
249
  def generate_sprite(sprite)
178
250
  canvas = canvas_for_sprite(sprite)
179
251
  sprite[:canvas] = canvas
252
+
253
+ # If we are padding sprites, we should paint the background something really
254
+ # obvious & obnoxious. Say, magenta. That's obnoxious. A nice light purple wouldn't
255
+ # be bad, but magenta... that will stick out like a sore thumb (I hope)
256
+ if @options[:pad_sprites_for_debugging]
257
+ magenta = ChunkyPNG::Color.rgb(255, 0, 255)
258
+ canvas.rect(0, 0, sprite[:width], sprite[:height], magenta, magenta)
259
+ end
180
260
 
181
261
  sprite[:slices].each do |slice|
182
262
  x = slice[:sprite_slice_x]
@@ -221,14 +301,18 @@ module Chance
221
301
 
222
302
  # Repeat the pattern to fill the width/height.
223
303
  while top < height do
304
+ left = 0
305
+
224
306
  while left < width do
225
- if target.respond_to?(:compose)
226
- target.compose!(source_canvas, left + x, top + y)
307
+ if target.respond_to?(:replace!)
308
+ target.replace!(source_canvas, left + x, top + y)
227
309
  else
228
310
  target.composite!(source_canvas, left + x, top + y)
229
311
  end
312
+
230
313
  left += source_width
231
314
  end
315
+
232
316
  top += source_height
233
317
  end
234
318
 
@@ -295,7 +379,14 @@ module Chance
295
379
 
296
380
  generate_sprite(sprite) if not sprite[:has_generated]
297
381
 
298
- sprite[:canvas].to_blob
382
+ ret = sprite[:canvas].to_blob
383
+
384
+ if Chance.clear_files_immediately
385
+ sprite[:canvas] = nil
386
+ sprite[:has_generated] = false
387
+ end
388
+
389
+ ret
299
390
  end
300
391
 
301
392
  def sprite_names(opts={})
@@ -23,15 +23,6 @@
23
23
  # - :theme: a selector that will make up the initial value of the $theme
24
24
  # variable. For example: :theme => "ace.test-controls"
25
25
  #
26
- # - :compress: if true, the slice names in the CSS will be shortened.
27
- # This has two drawbacks: 1) the slice names will not be helpful for
28
- # debugging, and 2) if using Chance in a standalone way and committing
29
- # the output to a source control system, the output can change dramatically
30
- # between runs, even if the input CSS is unchanged.
31
- #
32
- # As the most common use of Chance is as part of the SC build tools,
33
- # and this debugging support is usually only required to debug Chance
34
- # itself, :compress defaults to true
35
26
  #
36
27
  # How Slice & Slices work
37
28
  # -------------------------------
@@ -56,16 +47,15 @@ module Chance
56
47
  BEGIN_SCOPE = /\{/
57
48
  END_SCOPE = /\}/
58
49
  THEME_DIRECTIVE = /@theme\s*/
59
- SELECTOR_THEME_VARIABLE = /\$theme\./
50
+ SELECTOR_THEME_VARIABLE = /\$theme(?=[^\w:-])/
60
51
  INCLUDE_SLICES_DIRECTIVE = /@include\s+slices\s*/
61
52
  INCLUDE_SLICE_DIRECTIVE = /@include\s+slice\s*/
62
53
  CHANCE_FILE_DIRECTIVE = /@_chance_file /
63
54
  NORMAL_SCAN_UNTIL = /[^{}@$]+/
64
55
 
65
- @@uid = 0
66
56
 
67
57
  def initialize(string, opts = {})
68
- @opts = { :theme => "", :compress => true }
58
+ @opts = { :theme => "" }
69
59
  @opts.merge!(opts)
70
60
  @path = ""
71
61
 
@@ -77,9 +67,6 @@ module Chance
77
67
 
78
68
  @theme = @opts[:theme]
79
69
 
80
- @@uid += 1
81
- @uid = @@uid
82
-
83
70
  end
84
71
 
85
72
  # SLICE MANAGEMENT
@@ -135,12 +122,8 @@ module Chance
135
122
  slice[:max_offset_x] = [slice[:max_offset_x], opts[:offset_x]].max
136
123
  slice[:max_offset_y] = [slice[:max_offset_y], opts[:offset_y]].max
137
124
  else
138
- parts = slice_path.split("/")
139
- css_name = "__slice_" + parts.join("_")
140
-
141
- if @opts[:compress]
142
- css_name = "__s" + @uid.to_s + "_" + @slices.length.to_s
143
- end
125
+ modified_path = @opts[:instance_id].to_s.gsub(/[^a-zA-Z0-9]/, '_') + "_" + slice_path.gsub(/[^a-zA-Z0-9]/, '_')
126
+ css_name = "__chance_slice_#{modified_path}"
144
127
 
145
128
  slice = opts.merge({
146
129
  :name => slice_path,
@@ -151,12 +134,16 @@ module Chance
151
134
  :max_offset_x => opts[:offset_x],
152
135
  :max_offset_y => opts[:offset_y],
153
136
  :imaged_offset_x => 0, # the imaging process will re-define these.
154
- :imaged_offset_y => 0
137
+ :imaged_offset_y => 0,
138
+
139
+ :used_by => []
155
140
  })
156
141
 
157
142
  @slices[slice_path] = slice
158
143
  end
159
144
 
145
+ slice[:used_by] << { :path => @path }
146
+
160
147
  return slice
161
148
  end
162
149
 
@@ -358,7 +345,7 @@ module Chance
358
345
  scanner = @scanner
359
346
  scanner.scan SELECTOR_THEME_VARIABLE
360
347
 
361
- output = "\#{$theme}."
348
+ output = "\#{$theme}"
362
349
 
363
350
  return output
364
351
  end
@@ -486,7 +473,7 @@ module Chance
486
473
 
487
474
  # We prefix with -chance; this should let everything be passed through more
488
475
  # or less as-is. Postprocessing will turn it into -background-position.
489
- output += "-chance-offset: \"#{slice[:name]}\" #{slice[:offset_x]} #{slice[:offset_y]};"
476
+ output += "-chance-offset: \"#{slice[:name]}\" #{offset[0]} #{offset[1]};"
490
477
  output += "background-repeat: " + slice[:repeat]
491
478
  return output
492
479
  end
@@ -564,17 +551,25 @@ module Chance
564
551
  fill_width = Integer(fill[0])
565
552
  fill_height = Integer(fill[1])
566
553
 
567
- skip_top_left = values.include? 'skip-top-left'
568
- skip_top = values.include? 'skip-top'
569
- skip_top_right = values.include? 'skip-top-right'
554
+ # skip control
555
+ skip = arguments[:skip]
556
+ if skip.nil?
557
+ skip = []
558
+ else
559
+ skip = skip.split /\s+/
560
+ end
561
+
562
+ skip_top_left = skip.include? 'top-left'
563
+ skip_top = skip.include? 'top'
564
+ skip_top_right = skip.include? 'skip-top-right'
570
565
 
571
- skip_left = values.include? 'skip-left'
572
- skip_middle = values.include? 'skip-middle'
573
- skip_right = values.include? 'skip-right'
566
+ skip_left = skip.include? 'left'
567
+ skip_middle = skip.include? 'middle'
568
+ skip_right = skip.include? 'right'
574
569
 
575
- skip_bottom_left = values.include? 'skip-bottom-left'
576
- skip_bottom = values.include? 'skip-bottom'
577
- skip_bottom_right = values.include? 'skip-bottom-right'
570
+ skip_bottom_left = skip.include? 'bottom-left'
571
+ skip_bottom = skip.include? 'bottom'
572
+ skip_bottom_right = skip.include? 'bottom-right'
578
573
 
579
574
  filename = parse_string(arguments[0])
580
575
 
@@ -645,7 +640,7 @@ module Chance
645
640
  :sprite_padding => arguments[:"middle-padding"],
646
641
  :offset => arguments[:"middle-offset"],
647
642
  :filename => filename,
648
- :repeat => fill_height != 0 ? (fill_width != 0 ? "repeat-both" : "repeat-y") : (fill_width != 0 ? "repeat-x" : nil)
643
+ :repeat => fill_height != 0 ? (fill_width != 0 ? "repeat" : "repeat-y") : (fill_width != 0 ? "repeat-x" : nil)
649
644
 
650
645
 
651
646
  # fill in width, height or right, bottom depending on fill settings
@@ -734,9 +729,18 @@ module Chance
734
729
  output = ""
735
730
 
736
731
  # LEFT
737
- if should_include_slice?(top_left_slice) and not skip_top_left
732
+ # NOTE: we write it even if we are supposed to skip; we only wrap the slice include portion in
733
+ if should_include_slice?(top_left_slice)
738
734
  output += "& > .top-left {\n"
739
- output += generate_slice_include(top_left_slice) + ";"
735
+
736
+ # IF we are skipping the top left slice, we don't want the actual slice include-- but the layout
737
+ # information we still want. So, only bracket the generate_slice_include.
738
+ #
739
+ # Potential issue: slice_layout doesn't handle repeat settings. In theory, this should rarely be
740
+ # an issue (because you aren't setting a background for the skipped slice.
741
+ if not skip_top_left
742
+ output += generate_slice_include(top_left_slice) + ";"
743
+ end
740
744
 
741
745
  output += "\nposition: absolute;\n"
742
746
  output += slice_layout(top_left_slice)
@@ -744,9 +748,12 @@ module Chance
744
748
  output += "}\n"
745
749
  end
746
750
 
747
- if should_include_slice?(left_slice) and not skip_left
751
+ if should_include_slice?(left_slice)
748
752
  output += "& > .left {\n"
749
- output += generate_slice_include(left_slice) + ";"
753
+
754
+ if not skip_left
755
+ output += generate_slice_include(left_slice) + ";"
756
+ end
750
757
 
751
758
  output += "\nposition: absolute;\n"
752
759
  output += slice_layout(left_slice.merge({ :bottom => bottom }))
@@ -754,9 +761,12 @@ module Chance
754
761
  output += "}\n"
755
762
  end
756
763
 
757
- if should_include_slice?(bottom_left_slice) and not skip_bottom_left
764
+ if should_include_slice?(bottom_left_slice)
758
765
  output += "& > .bottom-left {\n"
759
- output += generate_slice_include(bottom_left_slice) + ";"
766
+
767
+ if not skip_bottom_left
768
+ output += generate_slice_include(bottom_left_slice) + ";"
769
+ end
760
770
 
761
771
  output += "\nposition: absolute;\n"
762
772
  output += slice_layout(bottom_left_slice)
@@ -765,9 +775,12 @@ module Chance
765
775
  end
766
776
 
767
777
  # MIDDLE
768
- if should_include_slice?(top_slice) and not skip_top
778
+ if should_include_slice?(top_slice)
769
779
  output += "& > .top {\n"
770
- output += generate_slice_include(top_slice) + ";"
780
+
781
+ if not skip_top
782
+ output += generate_slice_include(top_slice) + ";"
783
+ end
771
784
 
772
785
  output += "\nposition: absolute;\n"
773
786
  output += slice_layout(top_slice.merge({ :right => right }))
@@ -775,9 +788,12 @@ module Chance
775
788
  output += "}\n"
776
789
  end
777
790
 
778
- if should_include_slice?(middle_slice) and not skip_middle
791
+ if should_include_slice?(middle_slice)
779
792
  output += "& > .middle {\n"
780
- output += generate_slice_include(middle_slice) + ";"
793
+
794
+ if not skip_middle
795
+ output += generate_slice_include(middle_slice) + ";"
796
+ end
781
797
 
782
798
  output += "\nposition: absolute;\n"
783
799
  output += slice_layout(middle_slice.merge({ :bottom => bottom, :right => right }))
@@ -786,9 +802,12 @@ module Chance
786
802
  output += "}\n"
787
803
  end
788
804
 
789
- if should_include_slice?(bottom_slice) and not skip_bottom
805
+ if should_include_slice?(bottom_slice)
790
806
  output += "& > .bottom {\n"
791
- output += generate_slice_include(bottom_slice) + ";"
807
+
808
+ if not skip_bottom
809
+ output += generate_slice_include(bottom_slice) + ";"
810
+ end
792
811
 
793
812
  output += "\nposition: absolute;\n"
794
813
  output += slice_layout(bottom_slice.merge({ :right => right }))
@@ -798,9 +817,12 @@ module Chance
798
817
  end
799
818
 
800
819
  # RIGHT
801
- if should_include_slice?(top_right_slice) and not skip_top_right
820
+ if should_include_slice?(top_right_slice)
802
821
  output += "& > .top-right {\n"
803
- output += generate_slice_include(top_right_slice) + ";"
822
+
823
+ if not skip_top_right
824
+ output += generate_slice_include(top_right_slice) + ";"
825
+ end
804
826
 
805
827
  output += "\nposition: absolute;\n"
806
828
  output += slice_layout(top_right_slice)
@@ -808,9 +830,12 @@ module Chance
808
830
  output += "}\n"
809
831
  end
810
832
 
811
- if should_include_slice?(right_slice) and not skip_right
833
+ if should_include_slice?(right_slice)
812
834
  output += "& > .right {\n"
813
- output += generate_slice_include(right_slice) + ";"
835
+
836
+ if not skip_right
837
+ output += generate_slice_include(right_slice) + ";"
838
+ end
814
839
 
815
840
  output += "\nposition: absolute;\n"
816
841
  output += slice_layout(right_slice.merge({ :bottom => bottom }))
@@ -818,9 +843,12 @@ module Chance
818
843
  output += "}\n"
819
844
  end
820
845
 
821
- if should_include_slice?(bottom_right_slice) and not skip_bottom_right
846
+ if should_include_slice?(bottom_right_slice)
822
847
  output += "& > .bottom-right {\n"
823
- output += generate_slice_include(bottom_right_slice) + ";"
848
+
849
+ if not skip_bottom_right
850
+ output += generate_slice_include(bottom_right_slice) + ";"
851
+ end
824
852
 
825
853
  output += "\nposition: absolute;\n"
826
854
  output += slice_layout(bottom_right_slice)