Explorar o código

Extracted everything to source.*

Viktor Sokolov hai 3 meses
pai
achega
55d5113c56
Modificáronse 6 ficheiros con 193 adicións e 157 borrados
  1. 99 0
      vips/source.c
  2. 65 0
      vips/source.go
  3. 25 0
      vips/source.h
  4. 0 84
      vips/vips.c
  5. 4 49
      vips/vips.go
  6. 0 24
      vips/vips.h

+ 99 - 0
vips/source.c

@@ -0,0 +1,99 @@
+#include "source.h"
+
+// --- async source ----------------------------------------------------------------------
+
+// define glib subtype for vips async source
+#define VIPS_TYPE_ASYNC_SOURCE (vips_async_source_get_type())
+G_DEFINE_FINAL_TYPE(VipsAsyncSource, vips_async_source, VIPS_TYPE_SOURCE)
+
+extern void closeAsyncReader(uintptr_t handle);
+extern gint64 asyncReaderSeek(uintptr_t handle, gint64 offset, int whence);
+extern gint64 asyncReaderRead(uintptr_t handle, gpointer buffer, gint64 size);
+
+// loads jpeg from a source
+int
+vips_jpegloadsource_go(VipsAsyncSource *source, int shrink, VipsImage **out)
+{
+  if (shrink > 1)
+    return vips_jpegload_source(VIPS_SOURCE(source), out, "shrink", shrink,
+        NULL);
+
+  return vips_jpegload_source(VIPS_SOURCE(source), out, NULL);
+}
+
+// dereferences source
+void
+unref_source(VipsAsyncSource *source)
+{
+  VIPS_UNREF(source);
+}
+
+// read function for vips async source
+static gint64
+vips_async_source_read(VipsSource *source, void *buffer, size_t length)
+{
+  VipsAsyncSource *self = (VipsAsyncSource *) source;
+
+  gint64 read_length = asyncReaderRead(self->readerHandle, buffer, length);
+  if (read_length < 0) {
+    vips_error("vips_async_source_read", "failed to read from async source");
+  }
+  return read_length;
+}
+
+// seek function for vips async source. whence can be SEEK_SET (0), SEEK_CUR (1), or SEEK_END (2).
+static gint64
+vips_async_source_seek(VipsSource *source, gint64 offset, int whence)
+{
+  VipsAsyncSource *self = (VipsAsyncSource *) source;
+
+  gint64 actual_offset = asyncReaderSeek(self->readerHandle, offset, whence);
+
+  if (actual_offset < 0) {
+    vips_error("vips_async_source_seek", "failed to seek in async source");
+  }
+
+  return actual_offset;
+}
+
+static void
+vips_async_source_dispose(GObject *gobject)
+{
+  VipsAsyncSource *source = (VipsAsyncSource *) gobject;
+
+  closeAsyncReader(source->readerHandle);
+
+  G_OBJECT_CLASS(vips_async_source_parent_class)->dispose(gobject);
+}
+
+// attaches seek/read handlers to the async source class
+static void
+vips_async_source_class_init(VipsAsyncSourceClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+  VipsObjectClass *object_class = VIPS_OBJECT_CLASS(klass);
+  VipsSourceClass *source_class = VIPS_SOURCE_CLASS(klass);
+
+  object_class->nickname = "async_source";
+  object_class->description = "async input source";
+
+  gobject_class->dispose = vips_async_source_dispose;
+
+  source_class->read = vips_async_source_read;
+  source_class->seek = vips_async_source_seek;
+}
+
+// initializes the async source (nothing to do here yet)
+static void
+vips_async_source_init(VipsAsyncSource *source)
+{
+}
+
+// creates a new async source with the given reader handle
+VipsAsyncSource *
+vips_new_async_source(uintptr_t readerHandle)
+{
+  VipsAsyncSource *source = g_object_new(VIPS_TYPE_ASYNC_SOURCE, NULL);
+  source->readerHandle = readerHandle;
+  return source;
+}

+ 65 - 0
vips/source.go

@@ -0,0 +1,65 @@
+package vips
+
+/*
+#cgo pkg-config: vips
+#cgo CFLAGS: -O3
+#cgo LDFLAGS: -lm
+#include "source.h"
+*/
+import "C"
+import (
+	"io"
+	"runtime/cgo"
+	"unsafe"
+)
+
+//export closeAsyncReader
+func closeAsyncReader(handle C.uintptr_t) {
+	h := cgo.Handle(handle)
+	h.Delete()
+}
+
+// calls seek() on the async reader via it's handle from the C side
+//
+//export asyncReaderSeek
+func asyncReaderSeek(handle C.uintptr_t, offset C.int64_t, whence int) C.int64_t {
+	h := cgo.Handle(handle)
+	reader, ok := h.Value().(io.ReadSeeker)
+	if !ok {
+		return -1
+	}
+
+	pos, err := reader.Seek(int64(offset), whence)
+	if err != nil {
+		return -1
+	}
+
+	return C.int64_t(pos)
+}
+
+// calls read() on the async reader via it's handle from the C side
+//
+//export asyncReaderRead
+func asyncReaderRead(handle C.uintptr_t, pointer unsafe.Pointer, size C.int64_t) C.int64_t {
+	h := cgo.Handle(handle)
+	reader, ok := h.Value().(io.ReadSeeker)
+	if !ok {
+		return -1
+	}
+
+	buf := unsafe.Slice((*byte)(pointer), size)
+	n, err := reader.Read(buf)
+	if err == io.EOF {
+		return 0
+	} else if err != nil {
+		return -1
+	}
+
+	return C.int64_t(n)
+}
+
+// newVipsSource creates a new VipsAsyncSource from an io.ReadSeeker.
+func newVipsAsyncSource(r io.ReadSeeker) *C.VipsAsyncSource {
+	handler := cgo.NewHandle(r)
+	return C.vips_new_async_source(C.uintptr_t(handler))
+}

+ 25 - 0
vips/source.h

@@ -0,0 +1,25 @@
+#include <stdlib.h>
+#include <stdint.h> // uintptr_t
+
+#include <vips/vips.h>
+#include <vips/connection.h>
+
+// vips async source
+typedef struct _VipsAsyncSource {
+  VipsSource source;      // class designator
+  uintptr_t readerHandle; // async reader handler
+} VipsAsyncSource;
+
+// glib class for vips async source
+typedef struct _VipsAsyncSourceClass {
+  VipsSourceClass parent_class;
+} VipsAsyncSourceClass;
+
+// vips async source read function
+int vips_jpegloadsource_go(VipsAsyncSource *source, int shrink, VipsImage **out);
+
+// creates new vips async source from a reader handle
+VipsAsyncSource *vips_new_async_source(uintptr_t readerHandle);
+
+// unreferences the source, which leads to reader close
+void unref_source(VipsAsyncSource *source);

+ 0 - 84
vips/vips.c

@@ -1116,87 +1116,3 @@ vips_cleanup()
   vips_error_clear();
   vips_thread_shutdown();
 }
-
-// --- async source ----------------------------------------------------------------------
-
-// define glib subtype for vips async source
-#define VIPS_TYPE_ASYNC_SOURCE (vips_async_source_get_type())
-G_DEFINE_FINAL_TYPE(VipsAsyncSource, vips_async_source, VIPS_TYPE_SOURCE)
-
-extern void closeAsyncReader(uintptr_t handle);
-extern gint64 asyncReaderSeek(uintptr_t handle, gint64 offset, int whence);
-extern gint64 asyncReaderRead(uintptr_t handle, gpointer buffer, gint64 size);
-
-// loads jpeg from a source
-int
-vips_jpegloadsource_go(VipsAsyncSource *source, int shrink, VipsImage **out)
-{
-  if (shrink > 1)
-    return vips_jpegload_source(VIPS_SOURCE(source), out, "shrink", shrink,
-        NULL);
-
-  return vips_jpegload_source(VIPS_SOURCE(source), out, NULL);
-}
-
-// dereferences source
-void
-close_source(VipsImage **in, VipsAsyncSource *source)
-{
-  uintptr_t readerHandle = source->readerHandle;
-  VIPS_UNREF(source);
-  closeAsyncReader(readerHandle);
-}
-
-// attaches close signals to the image. first signal closes it's source, second closes the reader.
-void
-vips_attach_image_close_signals(VipsImage **in, uintptr_t handle, VipsAsyncSource *source)
-{
-  g_signal_connect(*in, "close", G_CALLBACK(close_source), (void *) source);
-}
-
-// read function for vips async source
-static gint64
-vips_async_source_read(VipsSource *source, void *buffer, size_t length)
-{
-  VipsAsyncSource *self = (VipsAsyncSource *) source;
-
-  return asyncReaderRead(self->readerHandle, buffer, length);
-}
-
-// seek function for vips async source. whence can be SEEK_SET (0), SEEK_CUR (1), or SEEK_END (2).
-static gint64
-vips_async_source_seek(VipsSource *source, gint64 offset, int whence)
-{
-  VipsAsyncSource *self = (VipsAsyncSource *) source;
-
-  return asyncReaderSeek(self->readerHandle, offset, whence);
-}
-
-// attaches seek/read handlers to the async source class
-static void
-vips_async_source_class_init(VipsAsyncSourceClass *klass)
-{
-  VipsObjectClass *object_class = VIPS_OBJECT_CLASS(klass);
-  VipsSourceClass *source_class = VIPS_SOURCE_CLASS(klass);
-
-  object_class->nickname = "async_source";
-  object_class->description = "async input source";
-
-  source_class->read = vips_async_source_read;
-  source_class->seek = vips_async_source_seek;
-}
-
-// initializes the async source (nothing to do here yet)
-static void
-vips_async_source_init(VipsAsyncSource *source)
-{
-}
-
-// creates a new async source with the given reader handle
-VipsAsyncSource *
-vips_new_async_source(uintptr_t readerHandle)
-{
-  VipsAsyncSource *source = g_object_new(vips_async_source_get_type(), NULL);
-  source->readerHandle = readerHandle;
-  return source;
-}

+ 4 - 49
vips/vips.go

@@ -5,6 +5,7 @@ package vips
 #cgo CFLAGS: -O3
 #cgo LDFLAGS: -lm
 #include "vips.h"
+#include "source.h"
 */
 import "C"
 import (
@@ -15,7 +16,6 @@ import (
 	"os"
 	"regexp"
 	"runtime"
-	"runtime/cgo"
 	"strings"
 	"sync"
 	"time"
@@ -331,49 +331,6 @@ func (img *Image) Pages() int {
 	return p
 }
 
-//export closeAsyncReader
-func closeAsyncReader(handle C.uintptr_t) {
-	h := cgo.Handle(handle)
-	h.Delete()
-}
-
-// calls seek() on the async reader via it's handle from the C side
-//
-//export asyncReaderSeek
-func asyncReaderSeek(handle C.uintptr_t, offset C.int64_t, whence int) C.int64_t {
-	h := cgo.Handle(handle)
-	reader, ok := h.Value().(*bytes.Reader)
-	if !ok {
-		return -1
-	}
-
-	pos, err := reader.Seek(int64(offset), whence)
-	if err != nil {
-		return -1
-	}
-
-	return C.int64_t(pos)
-}
-
-// calls read() on the async reader via it's handle from the C side
-//
-//export asyncReaderRead
-func asyncReaderRead(handle C.uintptr_t, pointer unsafe.Pointer, size C.int64_t) C.int64_t {
-	h := cgo.Handle(handle)
-	reader, ok := h.Value().(*bytes.Reader)
-	if !ok {
-		return -1
-	}
-
-	buf := unsafe.Slice((*byte)(pointer), size)
-	n, err := reader.Read(buf)
-	if err != nil {
-		return -1
-	}
-
-	return C.int64_t(n)
-}
-
 func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64, pages int) error {
 	if imgdata.Type == imagetype.ICO {
 		return img.loadIco(imgdata.Data, shrink, scale, pages)
@@ -390,8 +347,7 @@ func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64,
 	err := C.int(0)
 
 	reader := bytes.NewReader(imgdata.Data)
-	handler := cgo.NewHandle(reader)
-	source := C.vips_new_async_source(C.uintptr_t(handler))
+	source := newVipsAsyncSource(reader)
 
 	switch imgdata.Type {
 	case imagetype.JPEG:
@@ -411,15 +367,14 @@ func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64,
 	case imagetype.TIFF:
 		err = C.vips_tiffload_go(data, dataSize, &tmp)
 	default:
-		C.close_source(nil, source)
+		C.unref_source(source)
 		return newVipsError("Usupported image type to load")
 	}
 	if err != 0 {
-		C.close_source(nil, source)
+		C.unref_source(source)
 		return Error()
 	}
 
-	C.vips_attach_image_close_signals(&tmp, C.uintptr_t(handler), source)
 	C.swap_and_clear(&img.VipsImage, tmp)
 
 	if imgdata.Type == imagetype.TIFF {

+ 0 - 24
vips/vips.h

@@ -2,7 +2,6 @@
 #include <stdint.h> // uintptr_t
 
 #include <vips/vips.h>
-#include <vips/connection.h>
 #include <vips/vips7compat.h>
 #include <vips/vector.h>
 
@@ -12,17 +11,6 @@ typedef struct _RGB {
   double b;
 } RGB;
 
-// vips async source
-typedef struct _VipsAsyncSource {
-  VipsSourceCustom source; // class designator
-  uintptr_t readerHandle;  // async reader handler
-} VipsAsyncSource;
-
-// glib class for vips async source
-typedef struct _VipsAsyncSourceClass {
-  VipsSourceCustomClass parent_class;
-} VipsAsyncSourceClass;
-
 int vips_initialize();
 
 void clear_image(VipsImage **in);
@@ -112,15 +100,3 @@ int vips_avifsave_go(VipsImage *in, void **buf, size_t *len, int quality, int sp
 int vips_tiffsave_go(VipsImage *in, void **buf, size_t *len, int quality);
 
 void vips_cleanup();
-
-// vips async source read function
-int vips_jpegloadsource_go(VipsAsyncSource *source, int shrink, VipsImage **out);
-
-// creates new vips async source from a reader handle
-VipsAsyncSource *vips_new_async_source(uintptr_t readerHandle);
-
-// attaches "close" signal to the vips image: closes reader and unrefs vips source
-void vips_attach_image_close_signals(VipsImage **in, uintptr_t handle, VipsAsyncSource *source);
-
-// closes source and corresponding reader
-void close_source(VipsImage **in, VipsAsyncSource *source);