2016-11-18 17 views
3

내 응용 프로그램의 statusicon으로 렌더링하고 싶습니다.haskell 응용 프로그램에서 cairo를 사용하여 gtk3 statusicon으로 렌더링하는 방법은 무엇입니까?

statusIconPixbuf을 설정하여 statusicon 디스플레이에 pixbuf를 만들 수 있음을 알고 있습니다.

pixbufNew을 통해 빈 pixbuf를 만들고 단일 색상으로 채우는 것과 같은 작업을 수행 할 수 있습니다.

그러나 어떻게 카이로를 사용하여 pixbuf로 렌더링합니까?

또는 pixbuf를 사용하는 것이 옳지 않습니까? statusicon으로 렌더링하는 더 좋은 방법이 있습니까?

답변

0

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 함수를 사용하여 렌더링 할 카이로 서페이스를 만들고 renderWith을 호출하여 render에 지정된 실제 렌더링을 수행합니다.

다음 두 라인은 이미지 스트라이드, 즉 라인의 바이트 수와 실제 이미지 데이터를 ByteString으로 추출합니다.

swapRB은 어떻게 든 빨강 및 파랑 채널의 순서가 잘못되어 ByteString을 변환하는 함수입니다. 이것이 어떻게 행해지는지 아래를보십시오. 그것은 낮은 수준을 얻는다 B.useAsCStringLen에서

: imageSurfaceGetData에 의해 반환 된 ByteString TAKS 그것과 Ptr CUChar로 변환이 pixbufNewFromData을 사용하여 새 Pixbuf을 만들 수 있습니다.

그게 전부입니다. 그것은 라인으로 pixeldata의 ByteString 분할

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 

다음 화소에 라인이 각각 4 바이트로 이루어진 분할 : 다음

swapRB 정의되어 하나의 바이트 청색, 적색, 녹색 채널 용 각각, 알파. 가장 바깥 쪽은 실제 스와핑입니다.

swapRBforPixel [b,g,r,a] = [r,g,b,a]