Kaynağa Gözat

Merge pull request #109 from viest/dev

Feat Format And Image
viest 6 yıl önce
ebeveyn
işleme
c2535e094f

+ 24 - 0
.appveyor.yml

@@ -123,6 +123,30 @@ environment:
                   PHP_VER: 7.2.3
                   ZLIB_VER: 1.2.11
                   TS: 1
+                - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+                  ARCH: x64
+                  VC: vc15
+                  PHP_VER: 7.3.0
+                  ZLIB_VER: 1.2.11
+                  TS: 0
+                - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+                  ARCH: x64
+                  VC: vc15
+                  PHP_VER: 7.3.0
+                  ZLIB_VER: 1.2.11
+                  TS: 1
+                - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+                  ARCH: x86
+                  VC: vc15
+                  PHP_VER: 7.3.0
+                  ZLIB_VER: 1.2.11
+                  TS: 0
+                - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+                  ARCH: x86
+                  VC: vc15
+                  PHP_VER: 7.3.0
+                  ZLIB_VER: 1.2.11
+                  TS: 1
 
 build_script:
         ps: |

+ 17 - 4
README_zh.md

@@ -206,7 +206,7 @@ $freeFile->output();
 #### 语法
 
 ```php
-insertImage(int $row, int $column, string $localImagePath)
+insertImage(int $row, int $column, string $localImagePath[, double $widthScale, double $heightScale])
 ```
 
 ##### int $row
@@ -221,6 +221,16 @@ insertImage(int $row, int $column, string $localImagePath)
 
 > 图片路径
 
+##### double $widthScale
+
+> 对图像X轴进行缩放处理;
+> 默认为1,保持图像原始宽度;值为0.5时,图像宽度为原图的1/2;
+
+##### double $heightScale
+
+> 对图像轴进行缩放处理;
+> 默认为1,保持图像原始高度;值为0.5时,图像高度为原图的1/2;
+
 ##### 实例
 
 ```php
@@ -308,7 +318,8 @@ $excel  = new \Vtiful\Kernel\Excel($config);
 $fileObject = $excel->fileName('tutorial01.xlsx');
 $fileHandle = $fileObject->getHandle();
 
-$boldStyle = \Vtiful\Kernel\Format::bold($fileHandle);
+$format    = new \Vtiful\Kernel\Format($fileHandle);
+$boldStyle = $format->bold()->toResource();
 
 $fileObject->header(['name', 'age'])
     ->data([['viest', 21]])
@@ -345,7 +356,8 @@ $excel  = new \Vtiful\Kernel\Excel($config);
 $fileObject = $excel->fileName('tutorial01.xlsx');
 $fileHandle = $fileObject->getHandle();
 
-$boldStyle = \Vtiful\Kernel\Format::bold($fileHandle);
+$format    = new \Vtiful\Kernel\Format($fileHandle);
+$boldStyle = $format->bold()->toResource();
 
 $fileObject->header(['name', 'age'])
     ->data([['viest', 21]])
@@ -374,7 +386,8 @@ $excel  = new \Vtiful\Kernel\Excel($config);
 $fileObject = $excel->constMemory('tutorial01.xlsx');
 $fileHandle = $fileObject->getHandle();
 
-$boldStyle = \Vtiful\Kernel\Format::bold($fileHandle);
+$format    = new \Vtiful\Kernel\Format($fileHandle);
+$boldStyle = $format->bold()->toResource();
 
 $fileObject->header(['name', 'age'])
     ->data([['viest', 21]])

+ 8 - 2
kernel/excel.c

@@ -90,6 +90,8 @@ ZEND_BEGIN_ARG_INFO_EX(xls_insert_image_arginfo, 0, 0, 3)
                 ZEND_ARG_INFO(0, row)
                 ZEND_ARG_INFO(0, column)
                 ZEND_ARG_INFO(0, image)
+                ZEND_ARG_INFO(0, width)
+                ZEND_ARG_INFO(0, height)
 ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_INFO_EX(xls_insert_formula_arginfo, 0, 0, 3)
@@ -362,18 +364,22 @@ PHP_METHOD(vtiful_xls, insertImage)
 {
     zval *image;
     zend_long row, column;
+    double width = 1, height = 1;
 
-    ZEND_PARSE_PARAMETERS_START(3, 3)
+    ZEND_PARSE_PARAMETERS_START(3, 5)
             Z_PARAM_LONG(row)
             Z_PARAM_LONG(column)
             Z_PARAM_ZVAL(image)
+            Z_PARAM_OPTIONAL
+            Z_PARAM_DOUBLE(width)
+            Z_PARAM_DOUBLE(height)
     ZEND_PARSE_PARAMETERS_END();
 
     ZVAL_COPY(return_value, getThis());
 
     xls_object *obj = Z_XLS_P(getThis());
 
-    image_writer(image, row, column, &obj->ptr);
+    image_writer(image, row, column, width, height,  &obj->ptr);
 }
 /* }}} */
 

+ 95 - 55
kernel/format.c

@@ -11,70 +11,105 @@
 */
 
 #include "include.h"
-#include "ext/standard/php_var.h"
 
 zend_class_entry *vtiful_format_ce;
 
-/* {{{ ARG_INFO
+/* {{{ format_objects_new
  */
-ZEND_BEGIN_ARG_INFO_EX(format_bold_arginfo, 0, 0, 1)
-                ZEND_ARG_INFO(0, handle)
-ZEND_END_ARG_INFO()
+static zend_object_handlers format_handlers;
+
+static zend_always_inline void *vtiful_format_object_alloc(size_t obj_size, zend_class_entry *ce) {
+    void *obj = emalloc(obj_size);
+    memset(obj, 0, obj_size);
+    return obj;
+}
+
+PHP_VTIFUL_API zend_object *format_objects_new(zend_class_entry *ce)
+{
+    format_object *format = vtiful_format_object_alloc(sizeof(format_object), ce);
+
+    zend_object_std_init(&format->zo, ce);
+    object_properties_init(&format->zo, ce);
 
-ZEND_BEGIN_ARG_INFO_EX(format_italic_arginfo, 0, 0, 1)
+    format->ptr.format  = NULL;
+    format->zo.handlers = &format_handlers;
+
+    return &format->zo;
+}
+/* }}} */
+
+/* {{{ format_objects_free
+ */
+static void format_objects_free(zend_object *object)
+{
+    format_object *intern = php_vtiful_format_fetch_object(object);
+
+    if (intern->ptr.format != NULL) {
+        // free by workbook
+        intern->ptr.format = NULL;
+    }
+
+    zend_object_std_dtor(&intern->zo);
+}
+/* }}} */
+
+/* {{{ ARG_INFO
+ */
+ZEND_BEGIN_ARG_INFO_EX(format_construct_arginfo, 0, 0, 1)
                 ZEND_ARG_INFO(0, handle)
 ZEND_END_ARG_INFO()
 
-ZEND_BEGIN_ARG_INFO_EX(format_underline_arginfo, 0, 0, 2)
-                ZEND_ARG_INFO(0, handle)
+ZEND_BEGIN_ARG_INFO_EX(format_underline_arginfo, 0, 0, 1)
                 ZEND_ARG_INFO(0, style)
 ZEND_END_ARG_INFO()
 
-ZEND_BEGIN_ARG_INFO_EX(format_align_arginfo, 0, 0, 2)
-                ZEND_ARG_INFO(0, handle)
+ZEND_BEGIN_ARG_INFO_EX(format_align_arginfo, 0, 0, 1)
                 ZEND_ARG_INFO(0, style)
 ZEND_END_ARG_INFO()
 /* }}} */
 
-/** {{{ \Vtiful\Kernel\Format::bold()
+/** {{{ \Vtiful\Kernel\Format::__construct()
  */
-PHP_METHOD(vtiful_format, bold)
+PHP_METHOD(vtiful_format, __construct)
 {
     zval *handle;
-    lxw_format *bold_format;
+    format_object *obj;
     xls_resource_t *xls_res;
 
     ZEND_PARSE_PARAMETERS_START(1, 1)
             Z_PARAM_RESOURCE(handle)
     ZEND_PARSE_PARAMETERS_END();
 
-    xls_res   = zval_get_resource(handle);
-    bold_format = workbook_add_format(xls_res->workbook);
+    ZVAL_COPY(return_value, getThis());
 
-    format_set_bold(bold_format);
+    xls_res = zval_get_resource(handle);
+    obj     = Z_FORMAT_P(getThis());
 
-    RETURN_RES(zend_register_resource(bold_format, le_xls_writer));
+    if (obj->ptr.format == NULL) {
+        obj->ptr.format = workbook_add_format(xls_res->workbook);
+    }
 }
 /* }}} */
 
-/** {{{ \Vtiful\Kernel\Format::italic()
+/** {{{ \Vtiful\Kernel\Format::bold()
  */
-PHP_METHOD(vtiful_format, italic)
+PHP_METHOD(vtiful_format, bold)
 {
-    zval *handle;
-    lxw_format *italic_format;
-    xls_resource_t *xls_res;
-
-    ZEND_PARSE_PARAMETERS_START(1, 1)
-            Z_PARAM_RESOURCE(handle)
-    ZEND_PARSE_PARAMETERS_END();
+    ZVAL_COPY(return_value, getThis());
 
-    xls_res   = zval_get_resource(handle);
-    italic_format = workbook_add_format(xls_res->workbook);
+    format_object *obj = Z_FORMAT_P(getThis());
+    format_set_bold(obj->ptr.format);
+}
+/* }}} */
 
-    format_set_italic(italic_format);
+/** {{{ \Vtiful\Kernel\Format::italic()
+ */
+PHP_METHOD(vtiful_format, italic)
+{
+    ZVAL_COPY(return_value, getThis());
 
-    RETURN_RES(zend_register_resource(italic_format, le_xls_writer));
+    format_object *obj = Z_FORMAT_P(getThis());
+    format_set_italic(obj->ptr.format);
 }
 /* }}} */
 
@@ -82,22 +117,16 @@ PHP_METHOD(vtiful_format, italic)
  */
 PHP_METHOD(vtiful_format, underline)
 {
-    zval *handle;
     zend_long style;
-    lxw_format *underline_format;
-    xls_resource_t *xls_res;
 
-    ZEND_PARSE_PARAMETERS_START(2, 2)
-            Z_PARAM_RESOURCE(handle)
+    ZEND_PARSE_PARAMETERS_START(1, 1)
             Z_PARAM_LONG(style)
     ZEND_PARSE_PARAMETERS_END();
 
-    xls_res = zval_get_resource(handle);
-    underline_format = workbook_add_format(xls_res->workbook);
-
-    format_set_underline(underline_format, style);
+    ZVAL_COPY(return_value, getThis());
 
-    RETURN_RES(zend_register_resource(underline_format, le_xls_writer));
+    format_object *obj = Z_FORMAT_P(getThis());
+    format_set_underline(obj->ptr.format, style);
 }
 /* }}} */
 
@@ -105,19 +134,16 @@ PHP_METHOD(vtiful_format, underline)
  */
 PHP_METHOD(vtiful_format, align)
 {
-    zval *handle = NULL, *args = NULL;
+    zval *args = NULL;
     int argc, i;
 
-    lxw_format *align_format;
-    xls_resource_t *xls_res;
-
-    ZEND_PARSE_PARAMETERS_START(2, -1)
-            Z_PARAM_RESOURCE(handle)
+    ZEND_PARSE_PARAMETERS_START(1, -1)
             Z_PARAM_VARIADIC('+', args, argc)
     ZEND_PARSE_PARAMETERS_END();
 
-    xls_res = zval_get_resource(handle);
-    align_format = workbook_add_format(xls_res->workbook);
+    ZVAL_COPY(return_value, getThis());
+
+    format_object *obj = Z_FORMAT_P(getThis());
 
     for (i = 0; i < argc; ++i) {
         zval *arg = args + i;
@@ -126,10 +152,18 @@ PHP_METHOD(vtiful_format, align)
             zend_throw_exception(vtiful_exception_ce, "Format exception, please view the manual", 150);
         }
 
-        format_set_align(align_format, Z_LVAL_P(arg));
+        format_set_align(obj->ptr.format, Z_LVAL_P(arg));
     }
+}
+/* }}} */
 
-    RETURN_RES(zend_register_resource(align_format, le_xls_writer));
+/** {{{ \Vtiful\Kernel\Format::toResource()
+ */
+PHP_METHOD(vtiful_format, toResource)
+{
+    format_object *obj = Z_FORMAT_P(getThis());
+
+    RETURN_RES(zend_register_resource(obj->ptr.format, le_xls_writer));
 }
 /* }}} */
 
@@ -137,10 +171,12 @@ PHP_METHOD(vtiful_format, align)
 /** {{{ xls_methods
 */
 zend_function_entry format_methods[] = {
-        PHP_ME(vtiful_format, bold,      format_bold_arginfo,      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-        PHP_ME(vtiful_format, italic,    format_italic_arginfo,    ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-        PHP_ME(vtiful_format, underline, format_underline_arginfo, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-        PHP_ME(vtiful_format, align,     format_align_arginfo,     ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+        PHP_ME(vtiful_format, __construct, format_construct_arginfo, ZEND_ACC_PUBLIC)
+        PHP_ME(vtiful_format, bold,        NULL,                     ZEND_ACC_PUBLIC)
+        PHP_ME(vtiful_format, italic,      NULL,                     ZEND_ACC_PUBLIC)
+        PHP_ME(vtiful_format, underline,   format_underline_arginfo, ZEND_ACC_PUBLIC)
+        PHP_ME(vtiful_format, align,       format_align_arginfo,     ZEND_ACC_PUBLIC)
+        PHP_ME(vtiful_format, toResource,  NULL,                     ZEND_ACC_PUBLIC)
         PHP_FE_END
 };
 /* }}} */
@@ -151,9 +187,13 @@ VTIFUL_STARTUP_FUNCTION(format) {
     zend_class_entry ce;
 
     INIT_NS_CLASS_ENTRY(ce, "Vtiful\\Kernel", "Format", format_methods);
-
+    ce.create_object = format_objects_new;
     vtiful_format_ce = zend_register_internal_class(&ce);
 
+    memcpy(&format_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+    format_handlers.offset   = XtOffsetOf(format_object, zo);
+    format_handlers.free_obj = format_objects_free;
+
     REGISTER_CLASS_CONST_LONG(vtiful_format_ce, "UNDERLINE_SINGLE",            LXW_UNDERLINE_SINGLE)
     REGISTER_CLASS_CONST_LONG(vtiful_format_ce, "UNDERLINE_DOUBLE ",           LXW_UNDERLINE_DOUBLE)
     REGISTER_CLASS_CONST_LONG(vtiful_format_ce, "UNDERLINE_SINGLE_ACCOUNTING", LXW_UNDERLINE_SINGLE_ACCOUNTING)

+ 16 - 2
kernel/include.h

@@ -38,23 +38,37 @@ typedef struct {
     lxw_worksheet *worksheet;
 } xls_resource_t;
 
+typedef struct {
+    lxw_format  *format;
+} xls_resource_format_t;
+
 typedef struct _vtiful_xls_object {
     xls_resource_t ptr;
     zend_long      line;
     zend_object    zo;
 } xls_object;
 
+typedef struct _vtiful_format_object {
+    xls_resource_format_t ptr;
+    zend_object zo;
+} format_object;
+
 static inline xls_object *php_vtiful_xls_fetch_object(zend_object *obj) {
     return (xls_object *)((char *)(obj) - XtOffsetOf(xls_object, zo));
 }
 
+static inline format_object *php_vtiful_format_fetch_object(zend_object *obj) {
+    return (format_object *)((char *)(obj) - XtOffsetOf(format_object, zo));
+}
+
 #define REGISTER_CLASS_CONST_LONG(class_name, const_name, value) \
     zend_declare_class_constant_long(class_name, const_name, sizeof(const_name)-1, (zend_long)value);
 
 #define REGISTER_CLASS_PROPERTY_NULL(class_name, property_name, acc) \
     zend_declare_property_null(class_name, ZEND_STRL(property_name), acc);
 
-#define Z_XLS_P(zv) php_vtiful_xls_fetch_object(Z_OBJ_P(zv));
+#define Z_XLS_P(zv)    php_vtiful_xls_fetch_object(Z_OBJ_P(zv));
+#define Z_FORMAT_P(zv) php_vtiful_format_fetch_object(Z_OBJ_P(zv));
 
 #define ROW(range) \
     lxw_name_to_row(range)
@@ -83,7 +97,7 @@ STATIC void _populate_range(lxw_workbook *self, lxw_series_range *range);
 STATIC void _populate_range_dimensions(lxw_workbook *self, lxw_series_range *range);
 
 void type_writer(zval *value, zend_long row, zend_long columns, xls_resource_t *res, zend_string *format);
-void image_writer(zval *value, zend_long row, zend_long columns, xls_resource_t *res);
+void image_writer(zval *value, zend_long row, zend_long columns, double width, double height, xls_resource_t *res);
 void formula_writer(zval *value, zend_long row, zend_long columns, xls_resource_t *res);
 void auto_filter(zend_string *range, xls_resource_t *res);
 void merge_cells(zend_string *range, zend_string *value, xls_resource_t *res);

+ 4 - 2
kernel/write.c

@@ -47,9 +47,11 @@ void type_writer(zval *value, zend_long row, zend_long columns, xls_resource_t *
 /*
  * Write the image to the file
  */
-void image_writer(zval *value, zend_long row, zend_long columns, xls_resource_t *res)
+void image_writer(zval *value, zend_long row, zend_long columns, double width, double height, xls_resource_t *res)
 {
-    worksheet_insert_image(res->worksheet, row, columns, ZSTR_VAL(zval_get_string(value)));
+    lxw_image_options options = {.x_scale = width, .y_scale = height};
+
+    worksheet_insert_image_opt(res->worksheet, row, columns, ZSTR_VAL(zval_get_string(value)), &options);
 }
 
 /*

+ 8 - 5
tests/007.phpt

@@ -5,11 +5,14 @@ Check for vtiful presence
 --FILE--
 <?php
 $config = ['path' => './tests'];
-$excel = new \Vtiful\Kernel\Excel($config);
-$handle = $excel->fileName('tutorial01.xlsx')
-    ->getHandle();
-$boldStyle = \Vtiful\Kernel\Format::bold($handle);
-var_dump($boldStyle);
+
+$excel  = new \Vtiful\Kernel\Excel($config);
+$handle = $excel->fileName('tutorial01.xlsx')->getHandle();
+
+$format     = new \Vtiful\Kernel\Format($handle);
+$boldFormat = $format->bold()->toResource();
+
+var_dump($boldFormat);
 ?>
 --EXPECT--
 resource(5) of type (xlsx)

+ 7 - 4
tests/008.phpt

@@ -5,10 +5,13 @@ Check for vtiful presence
 --FILE--
 <?php
 $config = ['path' => './tests'];
-$excel = new \Vtiful\Kernel\Excel($config);
-$handle = $excel->fileName('tutorial01.xlsx')
-    ->getHandle();
-$italicStyle = \Vtiful\Kernel\Format::italic($handle);
+
+$excel  = new \Vtiful\Kernel\Excel($config);
+$handle = $excel->fileName('tutorial01.xlsx')->getHandle();
+
+$format      = new \Vtiful\Kernel\Format($handle);
+$italicStyle = $format->italic()->toResource();
+
 var_dump($italicStyle);
 ?>
 --EXPECT--

+ 7 - 4
tests/009.phpt

@@ -5,10 +5,13 @@ Check for vtiful presence
 --FILE--
 <?php
 $config = ['path' => './tests'];
-$excel = new \Vtiful\Kernel\Excel($config);
-$handle = $excel->fileName('tutorial01.xlsx')
-    ->getHandle();
-$underlineStyle = \Vtiful\Kernel\Format::underline($handle, \Vtiful\Kernel\Format::UNDERLINE_SINGLE);
+
+$excel  = new \Vtiful\Kernel\Excel($config);
+$handle = $excel->fileName('tutorial01.xlsx')->getHandle();
+
+$format         = new \Vtiful\Kernel\Format($handle);
+$underlineStyle = $format->underline(\Vtiful\Kernel\Format::UNDERLINE_SINGLE)->toResource();
+
 var_dump($underlineStyle);
 ?>
 --EXPECT--

+ 2 - 1
tests/011.phpt

@@ -10,7 +10,8 @@ $excel  = new \Vtiful\Kernel\Excel($config);
 $fileObject = $excel->fileName('tutorial01.xlsx');
 $fileHandle = $fileObject->getHandle();
 
-$boldStyle = \Vtiful\Kernel\Format::bold($fileHandle);
+$format    = new \Vtiful\Kernel\Format($fileHandle);
+$boldStyle = $format->bold()->toResource();
 
 $filePath = $fileObject->header(['name', 'age'])
     ->data([['viest', 21]])

+ 2 - 1
tests/012.phpt

@@ -10,7 +10,8 @@ $excel  = new \Vtiful\Kernel\Excel($config);
 $fileObject = $excel->fileName('tutorial01.xlsx');
 $fileHandle = $fileObject->getHandle();
 
-$boldStyle = \Vtiful\Kernel\Format::bold($fileHandle);
+$format    = new \Vtiful\Kernel\Format($fileHandle);
+$boldStyle = $format->bold()->toResource();
 
 $filePath = $fileObject->header(['name', 'age'])
     ->data([

+ 3 - 3
tests/format_align.phpt

@@ -13,11 +13,11 @@ $fileObject  = new \Vtiful\Kernel\Excel($config);
 $fileObject = $fileObject->fileName('tutorial.xlsx');
 $fileHandle = $fileObject->getHandle();
 
-$alignStyle = \Vtiful\Kernel\Format::align(
-    $fileHandle,
+$format     = new \Vtiful\Kernel\Format($fileHandle);
+$alignStyle = $format->align(
     \Vtiful\Kernel\Format::FORMAT_ALIGN_CENTER,
     \Vtiful\Kernel\Format::FORMAT_ALIGN_VERTICAL_CENTER
-);
+)->toResource();
 
 $filePath = $fileObject->header(['name', 'age'])
     ->data([

+ 29 - 0
tests/image_no_styles.phpt

@@ -0,0 +1,29 @@
+--TEST--
+Check for vtiful presence
+--SKIPIF--
+<?php if (!extension_loaded("xlswriter")) print "skip"; ?>
+--FILE--
+<?php
+$config = [
+    'path' => './tests'
+];
+
+$fileObject = new \Vtiful\Kernel\Excel($config);
+$fileObject = $fileObject->fileName('tutorial.xlsx');
+
+$filePath = $fileObject->header(['name', 'age'])
+    ->data([
+        ['viest', 21],
+        ['wjx',   21]
+    ])
+    ->insertImage(3, 0, __DIR__ . '/../resource/pecl.png')
+    ->output();
+
+var_dump($filePath);
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/tutorial.xlsx');
+?>
+--EXPECT--
+string(21) "./tests/tutorial.xlsx"

+ 29 - 0
tests/image_width_height_styles.phpt

@@ -0,0 +1,29 @@
+--TEST--
+Check for vtiful presence
+--SKIPIF--
+<?php if (!extension_loaded("xlswriter")) print "skip"; ?>
+--FILE--
+<?php
+$config = [
+    'path' => './tests'
+];
+
+$fileObject = new \Vtiful\Kernel\Excel($config);
+$fileObject = $fileObject->fileName('tutorial.xlsx');
+
+$filePath = $fileObject->header(['name', 'age'])
+    ->data([
+        ['viest', 21],
+        ['wjx',   21]
+    ])
+    ->insertImage(3, 0, __DIR__ . '/../resource/pecl.png', 10, 20)
+    ->output();
+
+var_dump($filePath);
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/tutorial.xlsx');
+?>
+--EXPECT--
+string(21) "./tests/tutorial.xlsx"