func (s CairoSurface) status() error { status := C.cairo_surface_status(s.nativePointer()) if status != 0 { return cairoStatusToError(status) } return nil }
// pdf, ps, and svg surfaces use the current surface (page) func (g *Graphic) Image() (image.Image, error) { var surface *C.cairo_surface_t switch g.format { case "eps", "pdf", "ps", "svg": // map vector surfaces to an image surface surface = C.cairo_surface_map_to_image(g.surface, nil) defer C.cairo_surface_unmap_image(g.surface, surface) status := C.cairo_surface_status(surface) err := statusToError(status) if err != nil { return nil, err } case "png", "jpeg": // no conversion needed surface = g.surface } width := int(C.cairo_image_surface_get_width(surface)) height := int(C.cairo_image_surface_get_height(surface)) stride := int(C.cairo_image_surface_get_stride(surface)) format := C.cairo_image_surface_get_format(surface) dataPtr := C.cairo_image_surface_get_data(surface) data := C.GoBytes(unsafe.Pointer(dataPtr), C.int(stride*height)) var img image.Image switch format { case C.CAIRO_FORMAT_ARGB32: img = &extimage.ARGB{ Pix: data, Stride: stride, Rect: image.Rect(0, 0, width, height), } case C.CAIRO_FORMAT_RGB24: img = &extimage.RGB{ Pix: data, Stride: stride, Rect: image.Rect(0, 0, width, height), } case C.CAIRO_FORMAT_A8: img = &image.Alpha{ Pix: data, Stride: stride, Rect: image.Rect(0, 0, width, height), } default: // known unsupported formats: // CAIRO_FORMAT_INVALID = -1, // CAIRO_FORMAT_A1 = 3, // CAIRO_FORMAT_RGB16_565 = 4, // CAIRO_FORMAT_RGB30 = 5 panic(fmt.Sprintf("unsupported cairo image surface format: %d", int(format))) } return img, nil }
func RedrawWindow(W *XWindow, tweetsList []*TweetInfo, mouseClick [2]int) { var Attribs C.XWindowAttributes C.XGetWindowAttributes(W.Display, W.Window, &Attribs) // TODO -- Do this only when resizing? C.cairo_xlib_surface_set_size(W.Surface, Attribs.width, Attribs.height) C.cairo_set_source_rgb(W.Cairo, 0.1, 0.1, 0.1) C.cairo_paint(W.Cairo) var Rect C.PangoRectangle yPos := 10.0 + W.Scroll WindowWidth := Attribs.width maxTweetWidth := PixelsToPango(float64(WindowWidth - 5*UIPadding - UserImageSize)) for i := 0; i < len(tweetsList); i++ { t := tweetsList[i] C.pango_layout_set_width(t.Layout, maxTweetWidth) C.pango_layout_get_extents(t.Layout, nil, &Rect) // Get tweet text size _, ry, _, rh := PangoRectToPixels(&Rect) // Position and add padding ry += yPos if rh < UserImageSize+2*UIPadding-UIPadding { rh = UserImageSize + 2*UIPadding } else { rh += UIPadding } // Draw rectangle around tweet C.cairo_set_source_rgb(W.Cairo, 0.2, 0.2, 0.2) C.cairo_rectangle(W.Cairo, UIPadding, C.double(ry), C.double(WindowWidth-2*UIPadding), C.double(rh)) C.cairo_fill(W.Cairo) if mouseClick[0] >= UIPadding && float64(mouseClick[1]) >= ry && float64(mouseClick[1]) <= ry+rh { fmt.Println("Clicked tweet", t.Text) } // Draw user image userImage := GetCachedImage(W.UserImages, t.UserImage) if userImage == nil || C.cairo_surface_status(userImage) != C.CAIRO_STATUS_SUCCESS { userImage = placeholderImage } C.cairo_set_source_surface(W.Cairo, userImage, 2*UIPadding, C.double(yPos+UIPadding)) C.cairo_paint(W.Cairo) // Draw tweet text C.cairo_move_to(W.Cairo, 63, C.double(yPos+SmallPadding)) C.cairo_set_source_rgb(W.Cairo, 0.95, 0.95, 0.95) C.pango_cairo_show_layout(W.Cairo, t.Layout) yPos += 5 + rh } }
//Index returns the ith surface of this tee. // //The returned error is set if there's an error on the returned surface. //If the index does not exist, Index returns (nil, nil). // //Originally cairo_tee_surface_index. func (s Surface) Index(i int) (cairo.Surface, error) { if i < 0 { return nil, nil } sir := C.cairo_tee_surface_index(s.XtensionRaw(), C.uint(i)) if C.cairo_surface_status(sir) == C.CAIRO_STATUS_INVALID_INDEX { return nil, nil } si, err := cairo.XtensionRevivifySurface(sir) if err != nil { return nil, err } return si, nil }
func NewSurfaceFromPNG(fileName string) (*Surface, error) { cstr := C.CString(fileName) defer C.free(unsafe.Pointer(cstr)) surfaceNative := C.cairo_image_surface_create_from_png(cstr) status := Status(C.cairo_surface_status(surfaceNative)) if status != STATUS_SUCCESS { return nil, ErrorStatus(status) } return &Surface{surfaceNative}, nil }
//export our_area_draw_callback func our_area_draw_callback(widget *C.GtkWidget, cr *C.cairo_t, data C.gpointer) C.gboolean { var x0, y0, x1, y1 C.double var maxwid, maxht C.gint s := (*sysData)(unsafe.Pointer(data)) // thanks to desrt in irc.gimp.net/#gtk+ // these are in user coordinates, which match what coordinates we want by default, even out of a draw event handler (thanks johncc3, mclasen, and Company in irc.gimp.net/#gtk+) C.cairo_clip_extents(cr, &x0, &y0, &x1, &y1) // we do not need to clear the cliprect; GtkDrawingArea did it for us beforehand cliprect := image.Rect(int(x0), int(y0), int(x1), int(y1)) // the cliprect can actually fall outside the size of the Area; clip it by intersecting the two rectangles C.gtk_widget_get_size_request(widget, &maxwid, &maxht) cliprect = image.Rect(0, 0, int(maxwid), int(maxht)).Intersect(cliprect) if cliprect.Empty() { // no intersection; nothing to paint return C.FALSE // signals handled without stopping the event chain (thanks to desrt again) } i := s.handler.Paint(cliprect) surface := C.cairo_image_surface_create( C.CAIRO_FORMAT_ARGB32, // alpha-premultiplied; native byte order C.int(i.Rect.Dx()), C.int(i.Rect.Dy())) if status := C.cairo_surface_status(surface); status != C.CAIRO_STATUS_SUCCESS { panic(fmt.Errorf("cairo_create_image_surface() failed: %s\n", C.GoString(C.cairo_status_to_string(status)))) } // the flush and mark_dirty calls are required; see the cairo docs and https://git.gnome.org/browse/gtk+/tree/gdk/gdkcairo.c#n232 (thanks desrt in irc.gimp.net/#gtk+) C.cairo_surface_flush(surface) toARGB(i, uintptr(unsafe.Pointer(C.cairo_image_surface_get_data(surface))), int(C.cairo_image_surface_get_stride(surface))) C.cairo_surface_mark_dirty(surface) C.cairo_set_source_surface(cr, surface, 0, 0) // origin of the surface // that just set the brush that cairo uses: we have to actually draw now // (via https://developer.gnome.org/gtkmm-tutorial/stable/sec-draw-images.html.en) C.cairo_rectangle(cr, x0, y0, x1, y1) // breaking the nrom here since we have the coordinates as a C double already C.cairo_fill(cr) C.cairo_surface_destroy(surface) // free surface return C.FALSE // signals handled without stopping the event chain (thanks to desrt again) }
func (i *imagelist) Append(img *image.RGBA) { var width, height C.gint surface := C.cairo_image_surface_create(C.CAIRO_FORMAT_ARGB32, C.int(img.Rect.Dx()), C.int(img.Rect.Dy())) if status := C.cairo_surface_status(surface); status != C.CAIRO_STATUS_SUCCESS { panic(fmt.Errorf("cairo_create_image_surface() failed in ImageList.Append(): %s\n", C.GoString(C.cairo_status_to_string(status)))) } C.cairo_surface_flush(surface) toARGB(img, uintptr(unsafe.Pointer(C.cairo_image_surface_get_data(surface))), int(C.cairo_image_surface_get_stride(surface)), false) // not NRGBA C.cairo_surface_mark_dirty(surface) basepixbuf := C.gdk_pixbuf_get_from_surface(surface, 0, 0, C.gint(img.Rect.Dx()), C.gint(img.Rect.Dy())) if basepixbuf == nil { panic(fmt.Errorf("gdk_pixbuf_get_from_surface() failed in ImageList.Append() (no reason available)")) } if C.gtk_icon_size_lookup(scaleTo, &width, &height) == C.FALSE { panic(fmt.Errorf("gtk_icon_size_lookup() failed in ImageList.Append() (no reason available)")) } if int(width) == img.Rect.Dx() && int(height) == img.Rect.Dy() { // just add the base pixbuf; we're good i.list = append(i.list, basepixbuf) C.cairo_surface_destroy(surface) return } // else scale pixbuf := C.gdk_pixbuf_scale_simple(basepixbuf, C.int(width), C.int(height), C.GDK_INTERP_NEAREST) if pixbuf == nil { panic(fmt.Errorf("gdk_pixbuf_scale_simple() failed in ImageList.Append() (no reason available)")) } i.list = append(i.list, pixbuf) C.gdk_pixbuf_unref(basepixbuf) C.cairo_surface_destroy(surface) }
func NewSurfaceFromPNG(filename string) (*Surface, Status) { cstr := C.CString(filename) defer C.free(unsafe.Pointer(cstr)) surfaceNative := C.cairo_image_surface_create_from_png(cstr) status := Status(C.cairo_surface_status(surfaceNative)) if status != STATUS_SUCCESS { return nil, status } contextNative := C.cairo_create(surfaceNative) status = Status(C.cairo_status(contextNative)) if status != STATUS_SUCCESS { return nil, status } surface := &Surface{ surface: surfaceNative, context: contextNative, } return surface, STATUS_SUCCESS }
func (self *Surface) GetStatus() Status { return Status(C.cairo_surface_status(self.surface)) }
// Status is a wrapper around cairo_surface_status(). func (v *Surface) Status() Status { c := C.cairo_surface_status(v.native()) return Status(c) }
func (surface *Surface) SurfaceStatus() int { return int(C.cairo_surface_status(surface.surface)) }
//Err reports any errors on the surface. // //Originally cairo_surface_status. func (e *XtensionSurface) Err() error { if e.s == nil { return ErrInvalidLibcairoHandle } return toerrIded(C.cairo_surface_status(e.s), e) }
// gets the status of the cairo surface and returns it as an error func (g *Graphic) cairoSurfaceStatus() error { status := C.cairo_surface_status(g.surface) return statusToError(status) }