Hi, there!
Please find attached a somewhat larger refactoring of Squeak's project
mechanism. It can be applied to the latest trunk version.
projects-refactoring-may.5.cs
<http://forum.world.st/file/n4893158/projects-refactoring-may.cs>
It's goals were to:
- Reduce the code footprint of new project kinds
- Move several MVC- or Morphic-specific parts from the base system to their
respective packages
- Refactor several dependencies on global state/variables in MVC and Morphic
- Add support to delete projects that have sub-projects
- Improve error handling of severe UI errors such as messing around in
LazyListMorph >> #drawOn:
- Allow parent projects that have a different code base (i.e. are of a
different project kind) to act as fall-back environment before using the
emergency REPL (Object >> #primitiveError:).
I will provide you with an additional third project kind of play around with
in a few days. It will illustrate the simple means in Squeak to write a new
user interface from scratch.
Best,
Marcel
--
View this message in context: http://forum.world.st/Project-Refactoring-Please-test-it-tp4893158.html
Sent from the Squeak - Dev mailing list archive at Nabble.com.
Nicolas Cellier uploaded a new version of Morphic to project The Inbox:
http://source.squeak.org/inbox/Morphic-nice.1133.mcz
==================== Summary ====================
Name: Morphic-nice.1133
Author: nice
Time: 3 May 2016, 11:50:28.750899 pm
UUID: 7ee79d7c-f8fb-49ec-8e3b-06d13bc034ee
Ancestors: Morphic-nice.1132
Avoid dependency of Graphics on Morphic just because some Form examples use Morphic.
Couldn't these examples find their place in some kind of Help?
=============== Diff against Morphic-nice.1132 ===============
Item was added:
+ ----- Method: Form class>>exampleColorSees (in category '*Morphic-examples') -----
+ exampleColorSees
+ "Form exampleColorSees"
+ "First column as above shows the sneaky red/yellow pirate sneaking up on the blue/peach galleon.
+ Second column shows the 1bpp made from the red/yellow/transparent - white -> ignore this, black -> test this
+ Third shows the hit area - where red touches blue - superimposed on the original scene.
+ Fourth column is the tally of hits via the old algorithm
+ Last column shows the tally of hits via the new prim"
+
+ |formA formB maskA offset tally map intersection left top dCanvas sensitiveColor soughtColor index|
+ formA := formB := maskA := offset := tally := map := intersection := nil. "just to shut up the compiler when testing"
+ ActiveWorld restoreMorphicDisplay; doOneCycle.
+
+ sensitiveColor := Color red.
+ soughtColor := Color blue.
+
+ top := 50.
+ dCanvas := FormCanvas on: Display.
+ -50 to: 80 by: 10 do:[:p|
+ offset:= p@0. "vary this to check different states"
+ left := 10.
+
+ formA := (Form extent: 100@50 depth: 32) asFormOfDepth: 16 "so we can try original forms of other depths".
+ formB := Form extent: 100@50 depth: 32.
+
+ "make a red square in the middle of the form"
+ (FormCanvas on: formA) fillRectangle: (25@25 extent: 50@5) fillStyle: sensitiveColor.
+ (FormCanvas on: formA) fillRectangle: (25@30 extent: 50@5) fillStyle: Color transparent.
+ (FormCanvas on: formA) fillRectangle: (25@35 extent: 50@50) fillStyle: Color yellow.
+ "formA displayOn: Display at: left@top rule: Form paint.
+ dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
+ left := left + 150."
+
+ "make a blue block on the right half of the form"
+ (FormCanvas on: formB) fillRectangle: (50@0 extent: 50@100) fillStyle: soughtColor.
+ (FormCanvas on: formB) fillRectangle: (60@0 extent: 10@100) fillStyle: Color palePeach.
+ "formB displayOn: Display at: left@top rule: Form paint.
+ dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
+ left := left + 150."
+
+ intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox).
+
+ formB displayOn: Display at: left@top rule: Form paint.
+ formA displayOn: Display at: (left@top) + offset rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
+ left := left + 150.
+
+ maskA := Form extent: intersection extent depth: 1.
+
+ map := Bitmap new: (1 bitShift: (formA depth min: 15)).
+ map at: (index := sensitiveColor indexInMap: map) put: 1.
+
+ maskA copyBits: (intersection translateBy: offset negated) from: formA at: 0@0 colorMap: map.
+ formB displayOn: Display at: left@top rule: Form paint.
+ formA displayOn: Display at: (left@top) + offset rule: Form paint.
+ maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green. left := left + 150.
+
+ "intersect world pixels of the color we're looking for with sensitive pixels mask"
+ map at: index put: 0. "clear map and reuse it"
+ map at: (soughtColor indexInMap: map) put: 1.
+
+ maskA
+ copyBits: intersection
+ from: formB at: 0@0 clippingBox: formB boundingBox
+ rule: Form and
+ fillColor: nil
+ map: map.
+
+ formB displayOn: Display at: left@top rule: Form paint.
+ formA displayOn: Display at: (left@top) + offset rule: Form paint.
+ maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
+ left := left + 170.
+
+ (maskA tallyPixelValues at: 2) asString asDisplayText displayOn: Display at: left@(top +20).
+ left := left + 70.
+
+ "now try using the new primitive"
+ tally := (BitBlt
+ destForm: formB
+ sourceForm: formA
+ fillColor: nil
+ combinationRule: 3 "really ought to work with nil but prim code checks"
+ destOrigin: intersection origin
+ sourceOrigin: (offset negated max: 0@0)
+ extent: intersection extent
+ clipRect: intersection)
+ primCompareColor: ((sensitiveColor pixelValueForDepth: formA depth) ) to: ((soughtColor pixelValueForDepth: formB depth) ) test: (Form compareMatchColor bitOr: Form compareTallyFlag).
+ tally asString asDisplayText displayOn: Display at: left@(top +20).
+ top:= top + 60]
+
+ !
Item was added:
+ ----- Method: Form class>>exampleTouchTest (in category '*Morphic-examples') -----
+ exampleTouchTest
+ "Form exampleTouchTest"
+ "Demonstrate the algorithm used in Scratch code to determine if a sprite's non-transparent pixels touch a
+ non-transparent pixel of the background upon which it is displayed.
+ First column shows a form with a red block in the midst of transparent area sneaking up on a form with a transparent LHS and blue RHS. The green frame shows the intersection area.
+ Second column shows in grey the part of the red that is within the intersection.
+ Third column shows in black the blue that is within the intersection.
+ Fourth column shows just the A touching B area.
+ Fifth column is the tally of hits via the old algorithm
+ Last column shows the tally of hits via the new prim"
+ |formA formB maskA maskB offset tally map intersection left top dCanvas|
+ formA := formB := maskA := maskB := offset := tally := map := intersection := nil. "just to shut up the compiler when testing"
+
+ ActiveWorld restoreMorphicDisplay; doOneCycle.
+
+ top := 50.
+ dCanvas := FormCanvas on: Display.
+ -50 to: 80 by: 10 do:[:p|
+ offset:= p@0. "vary this to check different states"
+ left := 10.
+
+ formA := Form extent: 100@50 depth: 32.
+ formB := Form extent: 100@50 depth: 16.
+
+ "make a red square in the middle of the form"
+ (FormCanvas on: formA) fillRectangle: (25@25 extent: 50@5) fillStyle: Color yellow.
+ (FormCanvas on: formA) fillRectangle: (25@30 extent: 50@5) fillStyle: Color transparent.
+ (FormCanvas on: formA) fillRectangle: (25@35 extent: 50@50) fillStyle: Color red.
+ "formA displayOn: Display at: left@top rule: Form paint.
+ dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
+ left := left + 150."
+
+ "make a blue block on the right half of the form"
+ (FormCanvas on: formB) fillRectangle: (50@0 extent: 50@100) fillStyle: Color blue.
+ (FormCanvas on: formB) fillRectangle: (60@0 extent: 10@100) fillStyle: Color palePeach.
+ "formB displayOn: Display at: left@top rule: Form paint.
+ dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
+ left := left + 150."
+
+ intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox).
+
+ formB displayOn: Display at: left@top rule: Form paint.
+ formA displayOn: Display at: (left@top) + offset rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
+ left := left + 150.
+
+ maskA := Form extent: intersection extent depth: 2.
+ formA displayOn: maskA at: offset - intersection origin rule: Form paint.
+ formB displayOn: Display at: left@top rule: Form paint.
+ formA displayOn: Display at: (left@top) + offset rule: Form paint.
+ maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
+ left := left + 150.
+
+ maskB := Form extent: intersection extent depth: 2.
+ formB displayOn: maskB at: intersection origin negated rule: Form paint.
+ formB displayOn: Display at: left@top rule: Form paint.
+ formA displayOn: Display at: (left@top) + offset rule: Form paint.
+ maskB displayOn: Display at: (left@top) + intersection origin rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
+ left := left + 150.
+
+ map := Bitmap new: 4 withAll: 1.
+ map at: 1 put: 0. "transparent"
+
+ maskA copyBits: maskA boundingBox from: maskA at: 0@0 colorMap: map.
+ "maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
+ left := left + 150."
+
+ maskB copyBits: maskB boundingBox from: maskB at: 0@0 colorMap: map.
+ "maskB displayOn: Display at: (left@top) + intersection origin rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
+ left := left + 150."
+
+ maskB displayOn: maskA at: 0@0 rule: Form and.
+ maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
+ left := left + 170.
+
+ (maskA boundingBox area -( maskA tallyPixelValues at: 1)) asString asDisplayText displayOn: Display at: left@(top +20).
+ left := left + 70.
+
+ "now try using the new primitive"
+ tally := (BitBlt
+ destForm: formB
+ sourceForm: formA
+ fillColor: nil
+ combinationRule: 3 "really ought to work with nil but prim code checks"
+ destOrigin: intersection origin
+ sourceOrigin: (offset negated max: 0@0)
+ extent: intersection extent
+ clipRect: intersection)
+ primCompareColor: ((Color transparent pixelValueForDepth: formA depth) bitAnd: 16rFFFFFF) to: ((Color transparent pixelValueForDepth: formB depth) bitAnd: 16rFFFFFF) test: (Form compareNotColorANotColorB bitOr: Form compareTallyFlag).
+ tally asString asDisplayText displayOn: Display at: left@(top +20).
+ top:= top + 60]
+
+
+ !
Item was added:
+ ----- Method: Form class>>exampleTouchingColor (in category '*Morphic-examples') -----
+ exampleTouchingColor
+ "Form exampleTouchingColor"
+ "Demonstrate the algorithm used in Scratch code to determine if a sprite's non-transparent pixels touch a
+ particular color pixel of the background upon which it is displayed.
+ First column as above shows the sneaky red/yellow pirate sneaking up on the blue/peach galleon.
+ Second column shows the 1bpp made from the red/yellow/transparent - white -> ignore this, black -> test this
+ Third shows the hit area (black) superimposed on the original scene
+ Fourth column is the tally of hits via the old algorithm
+ Last column shows the tally of hits via the new prim"
+ |formA formB maskA offset tally map intersection left top dCanvas ignoreColor soughtColor|
+ formA := formB := maskA := offset := tally := map := intersection := nil. "just to shut up the compiler when testing"
+ ActiveWorld restoreMorphicDisplay; doOneCycle.
+
+ ignoreColor := Color transparent.
+ soughtColor := Color blue.
+
+ top := 50.
+ dCanvas := FormCanvas on: Display.
+ -50 to: 80 by: 10 do:[:p|
+ offset:= p@0. "vary this to check different states"
+ left := 10.
+
+ formA := (Form extent: 100@50 depth: 32) asFormOfDepth: 16 "so we can try original forms of other depths".
+ formB := Form extent: 100@50 depth: 32.
+
+ "make a red square in the middle of the form"
+ (FormCanvas on: formA) fillRectangle: (25@25 extent: 50@5) fillStyle: Color red.
+ (FormCanvas on: formA) fillRectangle: (25@30 extent: 50@5) fillStyle: Color transparent.
+ (FormCanvas on: formA) fillRectangle: (25@35 extent: 50@50) fillStyle: Color yellow.
+ "formA displayOn: Display at: left@top rule: Form paint.
+ dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
+ left := left + 150."
+
+ "make a blue block on the right half of the form"
+ (FormCanvas on: formB) fillRectangle: (50@0 extent: 50@100) fillStyle: soughtColor.
+ (FormCanvas on: formB) fillRectangle: (60@0 extent: 10@100) fillStyle: Color palePeach.
+ "formB displayOn: Display at: left@top rule: Form paint.
+ dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
+ left := left + 150."
+
+ intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox).
+
+ formB displayOn: Display at: left@top rule: Form paint.
+ formA displayOn: Display at: (left@top) + offset rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
+ left := left + 150.
+
+ maskA := Form extent: intersection extent depth: 1.
+
+ map := Bitmap new: (1 bitShift: (formA depth min: 15)).
+ map atAllPut: 1.
+ map at: ( ignoreColor indexInMap: map) put: 0.
+
+ maskA copyBits: (intersection translateBy: offset negated) from: formA at: 0@0 colorMap: map.
+ formB displayOn: Display at: left@top rule: Form paint.
+ formA displayOn: Display at: (left@top) + offset rule: Form paint.
+ maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green. left := left + 150.
+
+ "intersect world pixels of the color we're looking for with sensitive pixels mask"
+ map atAllPut: 0. "clear map and reuse it"
+ map at: (soughtColor indexInMap: map) put: 1.
+
+ maskA
+ copyBits: intersection
+ from: formB at: 0@0 clippingBox: formB boundingBox
+ rule: Form and
+ fillColor: nil
+ map: map.
+
+ formB displayOn: Display at: left@top rule: Form paint.
+ formA displayOn: Display at: (left@top) + offset rule: Form paint.
+ maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
+ dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
+ left := left + 170.
+
+ (maskA tallyPixelValues at: 2) asString asDisplayText displayOn: Display at: left@(top +20).
+ left := left + 70.
+
+ "now try using the new primitive"
+ tally := (BitBlt
+ destForm: formB
+ sourceForm: formA
+ fillColor: nil
+ combinationRule: 3 "really ought to work with nil but prim code checks"
+ destOrigin: intersection origin
+ sourceOrigin: (offset negated max: 0@0)
+ extent: intersection extent
+ clipRect: intersection)
+ primCompareColor: ((ignoreColor pixelValueForDepth: formA depth) bitAnd: 16rFFFFFF) to: ((soughtColor pixelValueForDepth: formB depth) bitAnd: 16rFFFFFF) test: (Form compareNotColorAMatchColorB bitOr: Form compareTallyFlag).
+ tally asString asDisplayText displayOn: Display at: left@(top +20).
+ top:= top + 60]
+ !
Nicolas Cellier uploaded a new version of Graphics to project The Inbox:
http://source.squeak.org/inbox/Graphics-nice.330.mcz
==================== Summary ====================
Name: Graphics-nice.330
Author: nice
Time: 3 May 2016, 11:43:21.9999 pm
UUID: 123836bb-88cf-4378-8cd9-9f8e044d7e62
Ancestors: Graphics-mt.329
Avoid dependency on Morphic just because some examples use Morphic.
=============== Diff against Graphics-mt.329 ===============
Item was removed:
- ----- Method: Form class>>exampleColorSees (in category 'examples') -----
- exampleColorSees
- "Form exampleColorSees"
- "First column as above shows the sneaky red/yellow pirate sneaking up on the blue/peach galleon.
- Second column shows the 1bpp made from the red/yellow/transparent - white -> ignore this, black -> test this
- Third shows the hit area - where red touches blue - superimposed on the original scene.
- Fourth column is the tally of hits via the old algorithm
- Last column shows the tally of hits via the new prim"
-
- |formA formB maskA offset tally map intersection left top dCanvas sensitiveColor soughtColor index|
- formA := formB := maskA := offset := tally := map := intersection := nil. "just to shut up the compiler when testing"
- ActiveWorld restoreMorphicDisplay; doOneCycle.
-
- sensitiveColor := Color red.
- soughtColor := Color blue.
-
- top := 50.
- dCanvas := FormCanvas on: Display.
- -50 to: 80 by: 10 do:[:p|
- offset:= p@0. "vary this to check different states"
- left := 10.
-
- formA := (Form extent: 100@50 depth: 32) asFormOfDepth: 16 "so we can try original forms of other depths".
- formB := Form extent: 100@50 depth: 32.
-
- "make a red square in the middle of the form"
- (FormCanvas on: formA) fillRectangle: (25@25 extent: 50@5) fillStyle: sensitiveColor.
- (FormCanvas on: formA) fillRectangle: (25@30 extent: 50@5) fillStyle: Color transparent.
- (FormCanvas on: formA) fillRectangle: (25@35 extent: 50@50) fillStyle: Color yellow.
- "formA displayOn: Display at: left@top rule: Form paint.
- dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
- left := left + 150."
-
- "make a blue block on the right half of the form"
- (FormCanvas on: formB) fillRectangle: (50@0 extent: 50@100) fillStyle: soughtColor.
- (FormCanvas on: formB) fillRectangle: (60@0 extent: 10@100) fillStyle: Color palePeach.
- "formB displayOn: Display at: left@top rule: Form paint.
- dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
- left := left + 150."
-
- intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox).
-
- formB displayOn: Display at: left@top rule: Form paint.
- formA displayOn: Display at: (left@top) + offset rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
- left := left + 150.
-
- maskA := Form extent: intersection extent depth: 1.
-
- map := Bitmap new: (1 bitShift: (formA depth min: 15)).
- map at: (index := sensitiveColor indexInMap: map) put: 1.
-
- maskA copyBits: (intersection translateBy: offset negated) from: formA at: 0@0 colorMap: map.
- formB displayOn: Display at: left@top rule: Form paint.
- formA displayOn: Display at: (left@top) + offset rule: Form paint.
- maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green. left := left + 150.
-
- "intersect world pixels of the color we're looking for with sensitive pixels mask"
- map at: index put: 0. "clear map and reuse it"
- map at: (soughtColor indexInMap: map) put: 1.
-
- maskA
- copyBits: intersection
- from: formB at: 0@0 clippingBox: formB boundingBox
- rule: Form and
- fillColor: nil
- map: map.
-
- formB displayOn: Display at: left@top rule: Form paint.
- formA displayOn: Display at: (left@top) + offset rule: Form paint.
- maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
- left := left + 170.
-
- (maskA tallyPixelValues at: 2) asString asDisplayText displayOn: Display at: left@(top +20).
- left := left + 70.
-
- "now try using the new primitive"
- tally := (BitBlt
- destForm: formB
- sourceForm: formA
- fillColor: nil
- combinationRule: 3 "really ought to work with nil but prim code checks"
- destOrigin: intersection origin
- sourceOrigin: (offset negated max: 0@0)
- extent: intersection extent
- clipRect: intersection)
- primCompareColor: ((sensitiveColor pixelValueForDepth: formA depth) ) to: ((soughtColor pixelValueForDepth: formB depth) ) test: (Form compareMatchColor bitOr: Form compareTallyFlag).
- tally asString asDisplayText displayOn: Display at: left@(top +20).
- top:= top + 60]
-
- !
Item was removed:
- ----- Method: Form class>>exampleTouchTest (in category 'examples') -----
- exampleTouchTest
- "Form exampleTouchTest"
- "Demonstrate the algorithm used in Scratch code to determine if a sprite's non-transparent pixels touch a
- non-transparent pixel of the background upon which it is displayed.
- First column shows a form with a red block in the midst of transparent area sneaking up on a form with a transparent LHS and blue RHS. The green frame shows the intersection area.
- Second column shows in grey the part of the red that is within the intersection.
- Third column shows in black the blue that is within the intersection.
- Fourth column shows just the A touching B area.
- Fifth column is the tally of hits via the old algorithm
- Last column shows the tally of hits via the new prim"
- |formA formB maskA maskB offset tally map intersection left top dCanvas|
- formA := formB := maskA := maskB := offset := tally := map := intersection := nil. "just to shut up the compiler when testing"
-
- ActiveWorld restoreMorphicDisplay; doOneCycle.
-
- top := 50.
- dCanvas := FormCanvas on: Display.
- -50 to: 80 by: 10 do:[:p|
- offset:= p@0. "vary this to check different states"
- left := 10.
-
- formA := Form extent: 100@50 depth: 32.
- formB := Form extent: 100@50 depth: 16.
-
- "make a red square in the middle of the form"
- (FormCanvas on: formA) fillRectangle: (25@25 extent: 50@5) fillStyle: Color yellow.
- (FormCanvas on: formA) fillRectangle: (25@30 extent: 50@5) fillStyle: Color transparent.
- (FormCanvas on: formA) fillRectangle: (25@35 extent: 50@50) fillStyle: Color red.
- "formA displayOn: Display at: left@top rule: Form paint.
- dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
- left := left + 150."
-
- "make a blue block on the right half of the form"
- (FormCanvas on: formB) fillRectangle: (50@0 extent: 50@100) fillStyle: Color blue.
- (FormCanvas on: formB) fillRectangle: (60@0 extent: 10@100) fillStyle: Color palePeach.
- "formB displayOn: Display at: left@top rule: Form paint.
- dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
- left := left + 150."
-
- intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox).
-
- formB displayOn: Display at: left@top rule: Form paint.
- formA displayOn: Display at: (left@top) + offset rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
- left := left + 150.
-
- maskA := Form extent: intersection extent depth: 2.
- formA displayOn: maskA at: offset - intersection origin rule: Form paint.
- formB displayOn: Display at: left@top rule: Form paint.
- formA displayOn: Display at: (left@top) + offset rule: Form paint.
- maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
- left := left + 150.
-
- maskB := Form extent: intersection extent depth: 2.
- formB displayOn: maskB at: intersection origin negated rule: Form paint.
- formB displayOn: Display at: left@top rule: Form paint.
- formA displayOn: Display at: (left@top) + offset rule: Form paint.
- maskB displayOn: Display at: (left@top) + intersection origin rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
- left := left + 150.
-
- map := Bitmap new: 4 withAll: 1.
- map at: 1 put: 0. "transparent"
-
- maskA copyBits: maskA boundingBox from: maskA at: 0@0 colorMap: map.
- "maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
- left := left + 150."
-
- maskB copyBits: maskB boundingBox from: maskB at: 0@0 colorMap: map.
- "maskB displayOn: Display at: (left@top) + intersection origin rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
- left := left + 150."
-
- maskB displayOn: maskA at: 0@0 rule: Form and.
- maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
- left := left + 170.
-
- (maskA boundingBox area -( maskA tallyPixelValues at: 1)) asString asDisplayText displayOn: Display at: left@(top +20).
- left := left + 70.
-
- "now try using the new primitive"
- tally := (BitBlt
- destForm: formB
- sourceForm: formA
- fillColor: nil
- combinationRule: 3 "really ought to work with nil but prim code checks"
- destOrigin: intersection origin
- sourceOrigin: (offset negated max: 0@0)
- extent: intersection extent
- clipRect: intersection)
- primCompareColor: ((Color transparent pixelValueForDepth: formA depth) bitAnd: 16rFFFFFF) to: ((Color transparent pixelValueForDepth: formB depth) bitAnd: 16rFFFFFF) test: (Form compareNotColorANotColorB bitOr: Form compareTallyFlag).
- tally asString asDisplayText displayOn: Display at: left@(top +20).
- top:= top + 60]
-
-
- !
Item was removed:
- ----- Method: Form class>>exampleTouchingColor (in category 'examples') -----
- exampleTouchingColor
- "Form exampleTouchingColor"
- "Demonstrate the algorithm used in Scratch code to determine if a sprite's non-transparent pixels touch a
- particular color pixel of the background upon which it is displayed.
- First column as above shows the sneaky red/yellow pirate sneaking up on the blue/peach galleon.
- Second column shows the 1bpp made from the red/yellow/transparent - white -> ignore this, black -> test this
- Third shows the hit area (black) superimposed on the original scene
- Fourth column is the tally of hits via the old algorithm
- Last column shows the tally of hits via the new prim"
- |formA formB maskA offset tally map intersection left top dCanvas ignoreColor soughtColor|
- formA := formB := maskA := offset := tally := map := intersection := nil. "just to shut up the compiler when testing"
- ActiveWorld restoreMorphicDisplay; doOneCycle.
-
- ignoreColor := Color transparent.
- soughtColor := Color blue.
-
- top := 50.
- dCanvas := FormCanvas on: Display.
- -50 to: 80 by: 10 do:[:p|
- offset:= p@0. "vary this to check different states"
- left := 10.
-
- formA := (Form extent: 100@50 depth: 32) asFormOfDepth: 16 "so we can try original forms of other depths".
- formB := Form extent: 100@50 depth: 32.
-
- "make a red square in the middle of the form"
- (FormCanvas on: formA) fillRectangle: (25@25 extent: 50@5) fillStyle: Color red.
- (FormCanvas on: formA) fillRectangle: (25@30 extent: 50@5) fillStyle: Color transparent.
- (FormCanvas on: formA) fillRectangle: (25@35 extent: 50@50) fillStyle: Color yellow.
- "formA displayOn: Display at: left@top rule: Form paint.
- dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
- left := left + 150."
-
- "make a blue block on the right half of the form"
- (FormCanvas on: formB) fillRectangle: (50@0 extent: 50@100) fillStyle: soughtColor.
- (FormCanvas on: formB) fillRectangle: (60@0 extent: 10@100) fillStyle: Color palePeach.
- "formB displayOn: Display at: left@top rule: Form paint.
- dCanvas frameRectangle: (left@top extent: formA extent) width:2 color: Color green.
- left := left + 150."
-
- intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox).
-
- formB displayOn: Display at: left@top rule: Form paint.
- formA displayOn: Display at: (left@top) + offset rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
- left := left + 150.
-
- maskA := Form extent: intersection extent depth: 1.
-
- map := Bitmap new: (1 bitShift: (formA depth min: 15)).
- map atAllPut: 1.
- map at: ( ignoreColor indexInMap: map) put: 0.
-
- maskA copyBits: (intersection translateBy: offset negated) from: formA at: 0@0 colorMap: map.
- formB displayOn: Display at: left@top rule: Form paint.
- formA displayOn: Display at: (left@top) + offset rule: Form paint.
- maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green. left := left + 150.
-
- "intersect world pixels of the color we're looking for with sensitive pixels mask"
- map atAllPut: 0. "clear map and reuse it"
- map at: (soughtColor indexInMap: map) put: 1.
-
- maskA
- copyBits: intersection
- from: formB at: 0@0 clippingBox: formB boundingBox
- rule: Form and
- fillColor: nil
- map: map.
-
- formB displayOn: Display at: left@top rule: Form paint.
- formA displayOn: Display at: (left@top) + offset rule: Form paint.
- maskA displayOn: Display at: (left@top) + intersection origin rule: Form paint.
- dCanvas frameRectangle: (intersection translateBy: left@top) width:2 color: Color green.
- left := left + 170.
-
- (maskA tallyPixelValues at: 2) asString asDisplayText displayOn: Display at: left@(top +20).
- left := left + 70.
-
- "now try using the new primitive"
- tally := (BitBlt
- destForm: formB
- sourceForm: formA
- fillColor: nil
- combinationRule: 3 "really ought to work with nil but prim code checks"
- destOrigin: intersection origin
- sourceOrigin: (offset negated max: 0@0)
- extent: intersection extent
- clipRect: intersection)
- primCompareColor: ((ignoreColor pixelValueForDepth: formA depth) bitAnd: 16rFFFFFF) to: ((soughtColor pixelValueForDepth: formB depth) bitAnd: 16rFFFFFF) test: (Form compareNotColorAMatchColorB bitOr: Form compareTallyFlag).
- tally asString asDisplayText displayOn: Display at: left@(top +20).
- top:= top + 60]
- !
Nicolas Cellier uploaded a new version of Kernel to project The Inbox:
http://source.squeak.org/inbox/Kernel-nice.1017.mcz
==================== Summary ====================
Name: Kernel-nice.1017
Author: nice
Time: 3 May 2016, 11:40:36.82624 pm
UUID: 303ddbb3-6c74-4e3f-9838-501b7b1373f0
Ancestors: Kernel-mt.1016
Avoid dependency on Graphics package just for startup order.
Note that it is going to be a bootstrap problem.
=============== Diff against Kernel-mt.1016 ===============
Item was changed:
----- Method: EventSensor class>>initialize (in category 'class initialization') -----
initialize
+ Smalltalk addToStartUpList: self before: ProcessorScheduler.
- Smalltalk addToStartUpList: self after: Cursor.
Smalltalk addToShutDownList: self.
self installKeyDecodeTable.
self installMouseDecodeTable.
self install.
!
Hi all,
[this is a longish post, you might want to use this toc]
[TOC]
- [INTRO]
- [TERMINOLOGY]
- [DPI]
- [DEFAULT DPI]
- [STATUS]
- [WINDOWS DPI]
- [OSX CARBON DPI]
- [OSX COCOA DPI]
- [SUGGESTIONS] <<<< PLEASE COMMENT
- [OSX COCOA PATCH]
- [VM/IMAGE INTERFACE]
[INTRO]
For some time now, OSX and also Windows support screens of different pixel per inch (DPI, :P).
The approaches are slightly different; but both support a fallback mode where the pixel content of non-aware applications is automatically scaled to look like on "default dpi"[See DEFAULT DPI]. Effectively, we end up with pixel doubling.
One way or another, this means Squeak looks somewhat pixelated on new hardware.
These are some thoughts of mine on how to address this.
[TERMINOLOGY]
[DPI] Actually "dots-per-inch" but freely used in multiple senses by different people. For displays it used to mean "how many pixels are there approximately in an inch?", but for a long time now, The [DEFAULT DPI] that OSes report usually was fixed/defaulted (Win: 96, OS X: 72), _regardless_ of the actual screen's dpi.
[DEFAULT DPI] On OS X, the system reports default DPI as 72 dpi and Retina typically as 144 dpi, _although_ the "actual" dpi is different. For example, My MacBook Pro 15" is reported as 144dpi, but https://www.sven.de/dpi/ calculates that I have 220.53 pixel to the inch. That's why Apple is moving away from DPI and just talking about a "scale factor"[1],[2] and the abstract "point" principle, moving away from actual pixels for "user content"[3]. On Windows, the default dpi is 96 dpi, but Windows always made it a little easier to change that.
Squeak also has a default dpi, namely 96.0 dpi.
[STATUS]
[WINDOWS DPI]
Windows supports different levels of DPI awareness[4], available depending on OS Version[5].
Long story short, with calling a special function[6] or (As we did/do/can do) setting a key in the executables ".manifest" file to "true" or "true/PM", Windows treats our Application as DPI-Aware[7].
Currently the effect of enabling this for our VMs means:
- Looks ok on non-High-DPI screens
- Looks tiny on High-DPI screens
- Moving the VM between High-DPI and non-High-DPI screens changes the outer frame size of the application, the pixel size reported _to_ the VM remains the same.
[OSX CARBON DPI]
DPI-awareness and High-DPI are not possible with the QuickDraw-API the Carbon VM used to use.
[OSX COCOA DPI]
OS X now has a Device-in-pixel mode and a Userspace-in-"point" mode. When opted-in via Info.plist file, on AppKit-Level, one can convert between those with +[NSScreen backingScaleFactor], -convertRectToBacking:, -convertRectFromBacking and similar. On Quartz2D/CoreGraphics-Level, CGContextGetUserSpaceToDeviceSpaceTransform(), CGContextConvertRectToDeviceSpace(), and CGContextConvertRectToUserSpace() can be used. Both approaches are slightly different. OpenGL needs an additional Opt-in.
In contrast (currently) to Windows, when moving between high- and non-high-DPI, the outer frame size of the application stays the same but the pixels of the backing store change.
Up until now, the Cocoa branch is not DPI-aware.
[SUGGESTIONS]
[OSX COCOA PATCH]
Attached is a patch that makes the VM High-DPI ready. PLEASE COMMENT.
Summary:
- Add Info.plist entry to state whether we want High DPI (NSHighResolutionCapable)
THIS IS DISABLED BY DEFAULT (as with the Windows VM's manifest)
- All Views:
-add -sqScreenSize for the Pixel-dimensions to report to Squeak (and use for calculation in Squeak coordinates)
-add -sqMousePosition: to convert Mouse coordinates from the View's system (maybe high-dpi) to Squeak coordinates
- OpenGL view:
- Opt-in for High resolution (-setWantsBestResolutionOpenGLSurface:) (overridden by Info.plist's entry)
- Make texture size/tracking rects based on -sqScreenSize
- Quartz2D/CoreGraphics view:
- Work around deprecation of [[NSGraphicsContext currentContext] graphicsPort] in OS X 10.10
- Draw image in -sqScreenSize size, and position correctly in the View's coordinate system
- (remove some duplication from OpenGL view)
- iPhone SqueakUIView:
- use Fallbacks for -sqScreenSize/-sqMousePosition:, no High-DPI yet.
Note: this patch is against the Cog/platform/ios directory, Interpreter needs similar treating.
[VM/IMAGE INTERFACE]
With the current Windows VM and the Cocoa VM (+patch as above), users can Opt-in for High-DPI.
However, the Image does not know that its high pixel count is on a small display (hello Etoys!). I _want_ the image to know and to be able to react.
I think that the image should treat DPI changes similar screen size changes. Here are my ideas:
- The VM exposes screen size as prim 106, screen depth as 'primitiveScreenDepth'
* We should expose 'primitivePixelPerInch' with a fallback of '^ 96.0'.
* 96.0 dpi shall be the [DEFAULT DPI] of Squeak.
> For OS X that would mean, on non-high-dpi it shall report 96.0 dpi (not 72 dpi), on high-dpi it shall report 192.0 dpi (not 144)
> Windows already has 96.0 dpi as [DEFAULT DPI], it shall reuse that and adhere to [8]
- The image regularly checks the display size (DisplayScreen class>>checkForNewScreenSize).
* We should do the same for DPI (Morphic main loop etc.)
- There's already a client of DPI changes, TextStyles.
* The image shall store changed dpi settings to TextStyles>>pixelsPerInch:
- Projects can react to display size changes via #displaySizeChanged, But only fonts can react to DPI changes via #pixelsPerInchChanged
* We shall make project able to react to dpi changes, maybe via #pixelsPerInchChanged
- The standard tools are currently pixel-oriented and use hard-coded pixel values
* I am unsure.
* We could introduce conventions to act dpi-dependent (integers: pixels with autoscaling (pixels / default dpi * actual dpi or so), floats or scaled: dpi-based, via TextStyle class>>pointsToPixels:).
* We could introduce actual units and say "this tool is 3 cm wide" and calculate pixels via #pointsToPixels:.
* We could eliminate hard-coded values and base tools on font sizes. I tried that with the FontImporterTool (for example: FontImporterTool>>#buttonHeight, #filenameHeight. This may be hard and not very traceable, tho.
- We could move the dpi api from TextStyle to somewhere more general.
I know there are some rough edges here and there; I'd like to hear your suggestions.
Let's make Squeak look nice and sharp :)
Best
-Tobias
PS: Thanks to Marcel for some valuable suggestions and help to get Quartz transformations right.
[1]: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Appli…
[2]: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIVie…
[3]: https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Con…
[4]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).…
[5]: https://msdn.microsoft.com/en-us/library/dn469266(v=vs.85).aspx#high_dpi_fe…
[6]: https://msdn.microsoft.com/en-us/library/dn302122(v=vs.85).aspx
[7]: http://www.squeakvm.org/svn/squeak/branches/Cog/build.win32x86/squeak.cog.s…
[8]: https://msdn.microsoft.com/en-us/library/dn469266(v=vs.85).aspx#dpi_and_the…
Marcel Taeumel uploaded a new version of Graphics to project The Trunk:
http://source.squeak.org/trunk/Graphics-mt.329.mcz
==================== Summary ====================
Name: Graphics-mt.329
Author: mt
Time: 3 May 2016, 1:32:06.694235 pm
UUID: f04b2de7-6533-e54c-a08f-8a9b4425aa22
Ancestors: Graphics-tfel.328
Fixes computation of dominant color in 8-bit color forms. There, we have to look up the own color table.
=============== Diff against Graphics-tfel.328 ===============
Item was added:
+ ----- Method: ColorForm>>dominantColor (in category 'analyzing') -----
+ dominantColor
+ "Overridden to consider color table"
+
+ | tally max maxi |
+ tally := self tallyPixelValues.
+ max := maxi := 0.
+ tally withIndexDo: [:n :i | n > max ifTrue: [max := n. maxi := i]].
+ ^ self colors at: maxi!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1131.mcz
==================== Summary ====================
Name: Morphic-mt.1131
Author: mt
Time: 3 May 2016, 8:42:58.052787 am
UUID: ab03d740-8394-1046-89df-c3597a6c6c89
Ancestors: Morphic-mt.1130
Fix minor slip in prior shadow update. Only acitvate shadow in window again after resizing if the preference allows it.
=============== Diff against Morphic-mt.1130 ===============
Item was changed:
----- Method: CornerGripMorph>>mouseUp: (in category 'as yet unclassified') -----
mouseUp: anEvent
target ifNil: [^ self].
+ target fastFramingOn ifFalse: [
+ target hasDropShadow: Preferences menuAppearance3d].!
- target fastFramingOn ifFalse: [target hasDropShadow: true].!