DeviceGraphicsContext.st
changeset 8281 88f62a43293a
parent 8174 2704c965b97b
child 8283 f0ea83eed994
--- a/DeviceGraphicsContext.st	Wed Jan 31 13:15:13 2018 +0100
+++ b/DeviceGraphicsContext.st	Wed Jan 31 14:44:39 2018 +0100
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
 "
  COPYRIGHT (c) 1992 by Claus Gittinger
 	      All Rights Reserved
@@ -1136,7 +1138,7 @@
     "Modified: 4.6.1996 / 17:59:28 / cg"
 !
 
-displayForm:formToDraw x:x y:y
+displayForm:formOrImageToDraw x:x y:y
     "draw a form or image non opaque;
      if it's a 1-plane bitmap, 1-bits are drawn in the
      current paint-color, leaving pixels with 0-bits unchanged
@@ -1149,9 +1151,9 @@
      certain, that the colors are real colors (actually, only for
      noColor or allColor)."
 
-    |realForm pX pY w h nW nH pO pC|
-
-    realForm := formToDraw.
+    |realFormOrImage pX pY w h nW nH pO pC|
+
+    realFormOrImage := formOrImageToDraw.
 
     transformation notNil ifTrue:[
         pO := transformation transformPoint:x@y.
@@ -1159,8 +1161,8 @@
         pY := pO y.
 
         transformation isNoScale ifFalse:[
-            w := formToDraw width.
-            h := formToDraw height.
+            w := formOrImageToDraw width.
+            h := formOrImageToDraw height.
             pC := transformation applyTo:(x+w-1)@(y+h-1).
             nW := pC x - pX + 1.
             nH := pC y - pY + 1.
@@ -1172,23 +1174,23 @@
                 "/ hard case - someone is drawing forms with scaling in effect
                 "/ look if we have a scaled version in our pocket ...
                 "/
-                realForm := nil.
+                realFormOrImage := nil.
                 CachedScaledForms notNil ifTrue:[
-                    (CachedScales at:formToDraw ifAbsent:nil) = transformation scale ifTrue:[
-                        realForm := CachedScaledForms at:formToDraw ifAbsent:nil.
+                    (CachedScales at:formOrImageToDraw ifAbsent:nil) = transformation scale ifTrue:[
+                        realFormOrImage := CachedScaledForms at:formOrImageToDraw ifAbsent:nil.
                     ]
                 ].
-                realForm isNil ifTrue:[
+                realFormOrImage isNil ifTrue:[
                     "/
                     "/ nope - must do the work ...
                     "/
-                    realForm := formToDraw magnifiedBy:(nW / w) @ (nH / h).
+                    realFormOrImage := formOrImageToDraw magnifiedBy:(nW / w) @ (nH / h).
                     CachedScaledForms isNil ifTrue:[
                         CachedScaledForms := WeakIdentityDictionary new.
                         CachedScales := WeakIdentityDictionary new.
                     ].
-                    CachedScaledForms at:formToDraw put:realForm.
-                    CachedScales at:formToDraw put:transformation scale.
+                    CachedScaledForms at:formOrImageToDraw put:realFormOrImage.
+                    CachedScales at:formOrImageToDraw put:transformation scale.
                 ]
             ]
         ]
@@ -1197,7 +1199,7 @@
         pY := y.
     ].
 
-    self displayDeviceForm:realForm x:pX y:pY
+    self displayDeviceForm:realFormOrImage x:pX y:pY
 
     "Modified: / 12-04-1997 / 12:47:29 / cg"
     "Modified (comment): / 13-02-2017 / 20:00:13 / cg"
@@ -1935,13 +1937,14 @@
      certain, that the colors are real colors (actually, only for
      noColor or allColor)."
 
-    (aFormOrImage isImage and:[aFormOrImage photometric == #rgba]) ifTrue:[
+    (aFormOrImage isImage and:[aFormOrImage hasAlphaChannel]) ifTrue:[
         Error handle:[:ex |
             Logger error:'error when drawing alpha: %1' with:ex description.
         ] do:[    
             self displayDeviceFormWithAlpha:aFormOrImage x:x y:y.
             ^ self.
         ].
+        ^ self.
     ].
     self displayDeviceFormNoAlpha:aFormOrImage x:x y:y.
 
@@ -2303,7 +2306,8 @@
      however, the alpha channel is taken care of.
      This is a (slow) fallback helper for displays which do not support alpha blending"
 
-    |bytesPerLine orgDstData dstData imgData info w h pX pY bppDrawable 
+    |bytesPerLine orgDstData 
+     dstBytes imgBytes info w h pX pY bppDrawable 
      dstBytesPerRow "{Class: SmallInteger}"
      imgBytesPerRow "{Class: SmallInteger}"
      dstIndex "{Class: SmallInteger}"
@@ -2312,8 +2316,14 @@
      imgRowIndex "{Class: SmallInteger}"
      oB "{Class: SmallInteger}"
      oR "{Class: SmallInteger}"
-     oG "{Class: SmallInteger}"|
-
+     oG "{Class: SmallInteger}"
+     iR "{Class: SmallInteger}"  
+     iG "{Class: SmallInteger}"  
+     iB "{Class: SmallInteger}"  
+     iA "{Class: SmallInteger}"  
+     try |
+
+    device flush.
     device sync.
     
     w := anImage width.
@@ -2325,19 +2335,51 @@
 
     "/ give it more than enough bytes
     bytesPerLine := (w * 32 + 31) // 32 * 4.
-    dstData := ByteArray uninitializedNew:(bytesPerLine * h).
-    drawableType == #pixmap ifTrue:[
-        info := device getBitsFromPixmapId:(self drawableId) x:pX y:pY width:w height:h into:dstData.
-    ] ifFalse:[
-        info := device getBitsFromViewId:(self drawableId) x:pX y:pY width:w height:h into:dstData.
+    dstBytes := ByteArray uninitializedNew:(bytesPerLine * h).
+
+    "/ OSX XQuartz bug workaround
+    "/ if I do this, the Inspector can read the window's bits
+    "/ (sometimes after a retry)
+    "/ however, the imageEditor stil has problems to show the image
+    "/ in its lower left preview area.
+    "/ This should really really not be required!!!!!!
+    try := 1.
+    Error handle:[:ex |
+        try < 5 ifTrue:[
+            try := try + 1.
+            device flush.
+            device sync.
+            Delay waitForMilliseconds:20.
+            device flush.
+            device sync.
+            ex restart.
+        ].
+        ex reject
+    ] do:[
+        drawableType == #pixmap ifTrue:[
+            info := device getBitsFromPixmapId:(self drawableId) x:pX y:pY width:w height:h into:dstBytes.
+        ] ifFalse:[
+            info := device getBitsFromViewId:(self drawableId) x:pX y:pY width:w height:h into:dstBytes.
+        ].
     ].
-
     dstBytesPerRow := info at:#bytesPerLine.
     imgBytesPerRow := anImage bytesPerRow.
     
-    imgData := anImage bits.
-    orgDstData := dstData copy.
-    
+    imgBytes := anImage bits.
+    orgDstData := dstBytes copy.
+
+    iR := 0.
+    iG := 1.
+    iB := 2.
+    iA := 3.
+    anImage photometric == #argb ifTrue:[
+        iA := 0.
+        iR := 1.
+        iG := 2.
+        iB := 3.
+    ].
+
+    "/ TODO: the following code is a nr1 candidate for inline c-code
     bppDrawable := info at:#bitsPerPixel.
     bppDrawable == 32 ifTrue:[
         "/ data is coming as bytes in r,g,b,a order
@@ -2365,14 +2407,14 @@
                  nG "{Class: SmallInteger}"
                  nB "{Class: SmallInteger}"|
 
-                rD := dstData at:(dstIndex+oR).
-                gD := dstData at:(dstIndex+oG).
-                bD := dstData at:(dstIndex+oB).
-
-                rI := imgData at:(imgIndex).
-                gI := imgData at:(imgIndex+1).
-                bI := imgData at:(imgIndex+2).
-                aI := imgData at:(imgIndex+3).
+                rD := dstBytes at:(dstIndex+oR).
+                gD := dstBytes at:(dstIndex+oG).
+                bD := dstBytes at:(dstIndex+oB).
+
+                rI := imgBytes at:(imgIndex+iR).
+                gI := imgBytes at:(imgIndex+iG).
+                bI := imgBytes at:(imgIndex+iB).
+                aI := imgBytes at:(imgIndex+iA).
 
                 aI == 255 ifTrue:[
                     nR := rI.
@@ -2391,9 +2433,10 @@
                         nB := (((bI * aI)+(bD * aD)) // 255).
                     ].
                 ].
-                dstData at:(dstIndex+1) put:nR.
-                dstData at:(dstIndex+2) put:nG.
-                dstData at:(dstIndex+3) put:nB.
+                "/ dstBytes at:(dstIndex) put:255.
+                dstBytes at:(dstIndex+1) put:nR.
+                dstBytes at:(dstIndex+2) put:nG.
+                dstBytes at:(dstIndex+3) put:nB.
                 
                 dstIndex := dstIndex + 4.
                 imgIndex := imgIndex + 4.
@@ -2403,11 +2446,15 @@
         ].
         "/ draw the pixels (always MSB)
         device 
-            drawBits:dstData bitsPerPixel:32 depth:24 padding:32 
+            drawBits:dstBytes bitsPerPixel:32 depth:24 padding:32 
             width:w height:h x:0 y:0 
             into:(self drawableId) x:pX y:pY width:w height:h with:gcId.
+
+        device flush.
+        device sync.
         ^ self.
     ].
+
     bppDrawable == 24 ifTrue:[
         "/ data is coming as bytes in r,g,b order
         dstRowIndex := 1.
@@ -2436,14 +2483,14 @@
                  nG "{Class: SmallInteger}"
                  nB "{Class: SmallInteger}"|
 
-                rD := dstData at:(dstIndex+oR).
-                gD := dstData at:(dstIndex+oG).
-                bD := dstData at:(dstIndex+oB).
-
-                rI := imgData at:(imgIndex).
-                gI := imgData at:(imgIndex+1).
-                bI := imgData at:(imgIndex+2).
-                aI := imgData at:(imgIndex+3).
+                rD := dstBytes at:(dstIndex+oR).
+                gD := dstBytes at:(dstIndex+oG).
+                bD := dstBytes at:(dstIndex+oB).
+
+                rI := imgBytes at:(imgIndex+iR).
+                gI := imgBytes at:(imgIndex+iG).
+                bI := imgBytes at:(imgIndex+iB).
+                aI := imgBytes at:(imgIndex+iA).
 
                 aI == 255 ifTrue:[
                     nR := rI.
@@ -2462,9 +2509,9 @@
                         nB := (((bI * aI)+(bD * aD)) // 255).
                     ].
                 ].
-                dstData at:(dstIndex+2) put:nR.
-                dstData at:(dstIndex+1) put:nG.
-                dstData at:(dstIndex+0) put:nB.
+                dstBytes at:(dstIndex+2) put:nR.
+                dstBytes at:(dstIndex+1) put:nG.
+                dstBytes at:(dstIndex+0) put:nB.
 
                 dstIndex := dstIndex + 3.
                 imgIndex := imgIndex + 4.
@@ -2474,12 +2521,17 @@
         ].
         "/ draw the pixels (always MSB)
         device 
-            drawBits:dstData bitsPerPixel:24 depth:24 padding:32 
+            drawBits:dstBytes bitsPerPixel:24 depth:24 padding:32 
             width:w height:h x:0 y:0 
             into:(self drawableId) x:pX y:pY width:w height:h with:gcId.
+
+        device flush.
+        device sync.
         ^ self.
     ].
-    self halt.
+
+    Logger info:'(X11GC): drawing alpha into non24, non-32 displays is currently not supported'.
+    self displayDeviceFormNoAlpha:anImage x:x y:y.
 
     "Created: / 11-04-2017 / 16:45:39 / cg"
     "Modified: / 12-04-2017 / 10:38:52 / cg"