我想渲染到我的应用程序的statusicon。如何在haskell应用程序中使用cairo渲染成gtk3状态图标?
我知道我可以通过设置statusIconPixbuf来使状态图显示pixbuf。
我可以通过pixbufNew创建一个空的pixbuf并执行诸如使用单一颜色填充它。
但是如何使用cairo渲染成pixbuf?
或者是pixbuf不正确的使用?有没有更好的方法来渲染到状态图?
我想渲染到我的应用程序的statusicon。如何在haskell应用程序中使用cairo渲染成gtk3状态图标?
我知道我可以通过设置statusIconPixbuf来使状态图显示pixbuf。
我可以通过pixbufNew创建一个空的pixbuf并执行诸如使用单一颜色填充它。
但是如何使用cairo渲染成pixbuf?
或者是pixbuf不正确的使用?有没有更好的方法来渲染到状态图?
使用Pixbuf
我需要一种方法来渲染它。
以下解决方案需要开罗渲染render :: Render a
和(平方)的所需的X和Y尺寸Pixbuf
(如果你需要创建非方形Pixbufs你可以改变这一点。)
import qualified Foreign.Ptr as Pointer
import qualified ByteString as B
renderPixbuf :: Int -> Render a -> IO Pixbuf
renderPixbuf size render = withImageSurface FormatARGB32 size size $ \surface -> do
renderWith surface render
stride <- imageSurfaceGetStride surface
surfaceData <- swapRB stride <$> imageSurfaceGetData surface
B.useAsCStringLen surfaceData $ \(pointer, _) -> do
let pointer' = Pointer.castPtr pointer
pixbufNewFromData pointer' ColorspaceRgb True 8 size size stride
它使用函数withImageSurface创建一个表面供cairo渲染,然后调用renderWith来执行由render
指定的实际渲染。
接下来的两行提取图像跨度,即一行中的字节数和实际图像数据作为ByteString。
swapRB
是一个函数,它转换ByteString,因为不知何故红色和蓝色通道的顺序是错误的。请参阅下文了解如何完成此操作。
在B.useAsCStringLen它得到的低级别:它TAKS由imageSurfaceGetData返回的字节字符串,并将其转换为Ptr CUChar
使用pixbufNewFromData创建一个新的pixbuf。
就是这样。
swapRB
定义如下:
import Data.Word (Word8)
import Data.List (unfoldr)
splitAtIfNotNull :: Int -> B.ByteString -> Maybe (B.ByteString,B.ByteString)
splitAtIfNotNull i string
| B.null string = Nothing
| otherwise = Just $ B.splitAt i string
mapChunks :: (B.ByteString -> B.ByteString) -> Int -> B.ByteString -> B.ByteString
mapChunks mapper chunkSize = B.concat . map mapper . unfoldr (splitAtIfNotNull chunkSize)
swapRB :: Int -> B.ByteString -> B.ByteString
swapRB = mapChunks swapRBforLine
where swapRBforLine :: B.ByteString -> B.ByteString
swapRBforLine = mapChunks (B.pack . swapRBforPixel . B.unpack) 4
swapRBforPixel :: [Word8] -> [Word8]
swapRBforPixel [b,g,r,a] = [r,g,b,a]
swapRBforPixel other = other
它分裂PixelData取出的字节串为行,然后拆分线到像素的每个包括4个字节:一个字节的每个所述信道的红色,绿色,蓝色, α。最内侧是实际交换:
swapRBforPixel [b,g,r,a] = [r,g,b,a]