1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: drawing.h,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
39 * frog - Jan 11, 1999: Created.
40 * frog - Nov 20, 2000: remove display function, only needed loading object from binary
42 #include "precompile.h"
62 BEGIN_GRADATION
= 0, LINEAR
, RADIAL
, CONICAL
, SQUARE
,
63 END_GRADATION
, BITMAP_PATTERN
66 #define OBJRET_FILE_OK 0
67 #define OBJRET_FILE_ERROR (-1)
68 #define OBJRET_FILE_NO_PRIVATE_BLOCK (-2)
69 #define OBJRET_FILE_NO_PRIVATE_BLOCK_2 (-3)
71 typedef int (*HWPDOFuncType
) (int, HWPDrawingObject
*, int, void *, int);
73 #define HWPDOFunc(hdo, cmd, argp, argv) \
74 (HWPDOFuncTbl[(hdo)->type]((hdo)->type, (hdo), (cmd), (argp), (argv)))
75 #define HWPDOFunc2(type, cmd, argp, argv) \
76 (HWPDOFuncTbl[(type)]((type), NULL, (cmd), (argp), (argv)))
78 static int HWPDOLineFunc(int, HWPDrawingObject
*, int, void *, int);
79 static int HWPDORectFunc(int, HWPDrawingObject
*, int, void *, int);
80 static int HWPDOEllipseFunc(int, HWPDrawingObject
*, int, void *, int);
81 static int HWPDOArcFunc(int, HWPDrawingObject
*, int, void *, int);
82 static int HWPDOFreeFormFunc(int, HWPDrawingObject
*, int, void *, int);
83 static int HWPDOTextBoxFunc(int, HWPDrawingObject
*, int, void *, int);
84 static int HWPDOEllipse2Func(int, HWPDrawingObject
*, int, void *, int);
85 static int HWPDOArc2Func(int, HWPDrawingObject
*, int, void *, int);
86 static int HWPDOContainerFunc(int, HWPDrawingObject
*, int, void *, int);
87 static HWPPara
*LoadParaList();
89 HWPDOFuncType HWPDOFuncTbl
[] =
104 static HMemIODev
*hmem
= 0;
106 static int count
= 0;
108 inline bool HAVE_FCOLOR(HWPDrawingObject
* hdo
)
110 return hdo
->property
.fill_color
!= HWPDO_COLOR_NONE
;
114 inline bool HAVE_PATTERN(HWPDrawingObject
* hdo
)
116 return (hdo
->property
.pattern_type
& HWPDO_PAT_TYPE_BITS
)
117 != HWPDO_PAT_SOLID
&& hdo
->property
.pattern_color
!= HWPDO_COLOR_NONE
;
121 inline bool HAVE_GRADATION(HWPDrawingObject
* hdo
)
123 return hdo
->property
.gstyle
> BEGIN_GRADATION
&&
124 hdo
->property
.gstyle
< END_GRADATION
&&
125 hdo
->property
.fromcolor
!= HWPDO_COLOR_NONE
&&
126 hdo
->property
.tocolor
!= HWPDO_COLOR_NONE
;
130 inline bool HAVE_BITMAP_PATTERN(HWPDrawingObject
* hdo
)
132 return hdo
->property
.gstyle
== BITMAP_PATTERN
&&
133 hdo
->property
.szPatternFile
[0];
137 inline bool HAS_PAT(HWPDrawingObject
* hdo
)
139 return HAVE_FCOLOR(hdo
) || HAVE_PATTERN(hdo
) ||
140 HAVE_GRADATION(hdo
) || HAVE_BITMAP_PATTERN(hdo
);
144 static void SetHdoParallRgn(HWPDrawingObject
* hdo
, int width
, int height
)
146 hdo
->property
.parall
.pt
[0].x
= 0;
147 hdo
->property
.parall
.pt
[0].y
= 0;
148 hdo
->property
.parall
.pt
[1].x
= width
;
149 hdo
->property
.parall
.pt
[1].y
= 0;
150 hdo
->property
.parall
.pt
[2].x
= width
;
151 hdo
->property
.parall
.pt
[2].y
= height
;
155 static bool SkipPrivateBlock(int type
)
159 if (type
== OBJRET_FILE_NO_PRIVATE_BLOCK
)
162 if (hmem
->state() || hmem
->skipBlock(n
) != n
)
168 return hmem
->skipBlock(n
) == n
;
172 static int SizeExpected
;
175 static int ReadSizeField(int size
)
178 SizeRead
= hmem
->read4b();
185 static bool SkipUnusedField(void)
187 return (SizeExpected
< SizeRead
) ?
188 hmem
->skipBlock(SizeRead
- SizeExpected
) != 0 : true;
192 #define HDOFILE_HEADER_SIZE (2*4+16) // 16=sizeof(ZZRect)
193 #define HDOFILE_COMMON_SIZE (7*4+16+44)
195 #define HDOFILE_HAS_NEXT 0x01
196 #define HDOFILE_HAS_CHILD 0x02
199 * °øÅë Çì´õ¸¦ Àоîµå¸°´Ù.
200 * °³Ã¼Á¾·ù/¿¬°áÁ¤º¸/»ó´ëÀ§Ä¡/°³Ã¼Å©±â/Àý´ëÀ§Ä¡/Â÷Áö¿µ¿ª/±âº»¼Ó¼º/ȸÀü¼Ó¼º/±×¶óµ¥À̼Ç/ºñÆ®¸ÊÆÐÅÏ
202 static bool LoadCommonHeader(HWPDrawingObject
* hdo
, WORD
* link_info
)
204 uint size
, property_size
, common_size
;
208 size
= hmem
->read4b();
213 if (size
< HDOFILE_COMMON_SIZE
)
218 common_size
= HDOFILE_COMMON_SIZE
;
220 hdo
->type
= hmem
->read2b();
221 *link_info
= sal::static_int_cast
<WORD
>(hmem
->read2b());
222 hdo
->offset
.x
= hmem
->read4b();
223 hdo
->offset
.y
= hmem
->read4b();
224 hdo
->extent
.w
= hmem
->read4b();
225 hdo
->extent
.h
= hmem
->read4b();
226 hdo
->offset2
.x
= hmem
->read4b();
227 hdo
->offset2
.y
= hmem
->read4b();
232 hdo
->vrect
.x
= hmem
->read4b();
233 hdo
->vrect
.y
= hmem
->read4b();
234 hdo
->vrect
.w
= hmem
->read4b();
235 hdo
->vrect
.h
= hmem
->read4b();
237 // read bare property 44 bytes
238 hdo
->property
.line_pstyle
= hmem
->read4b();
239 hdo
->property
.line_hstyle
= hmem
->read4b();
240 hdo
->property
.line_tstyle
= hmem
->read4b();
241 hdo
->property
.line_color
= hmem
->read4b();
242 hdo
->property
.line_width
= (hunit
) hmem
->read4b();
243 hdo
->property
.fill_color
= hmem
->read4b();
244 hdo
->property
.pattern_type
= hmem
->read4b();
245 hdo
->property
.pattern_color
= hmem
->read4b();
246 hdo
->property
.hmargin
= (hunit
) hmem
->read4b();
247 hdo
->property
.vmargin
= (hunit
) hmem
->read4b();
248 hdo
->property
.flag
= hmem
->read4b();
249 // read ratation property 32 bytes
250 if ((size
>= common_size
+ 32)
251 && (hdo
->property
.flag
& HWPDO_FLAG_ROTATION
))
253 hdo
->property
.rot_originx
= hmem
->read4b();
254 hdo
->property
.rot_originy
= hmem
->read4b();
255 for (int ii
= 0; ii
< 3; ii
++)
257 hdo
->property
.parall
.pt
[ii
].x
= hmem
->read4b();
258 hdo
->property
.parall
.pt
[ii
].y
= hmem
->read4b();
263 SetHdoParallRgn(hdo
, hdo
->extent
.w
, hdo
->extent
.h
);
265 // read gradient property 28 bytes
266 if ((size
>= common_size
+ 28) &&
267 (hdo
->property
.flag
& HWPDO_FLAG_GRADATION
))
269 hdo
->property
.fromcolor
= hmem
->read4b();
270 hdo
->property
.tocolor
= hmem
->read4b();
271 hdo
->property
.gstyle
= hmem
->read4b();
272 hdo
->property
.angle
= hmem
->read4b();
273 hdo
->property
.center_x
= hmem
->read4b();
274 hdo
->property
.center_y
= hmem
->read4b();
275 hdo
->property
.nstep
= hmem
->read4b();
279 // read bitmap property 278 bytes
280 if ((size
>= common_size
+ 278) && \
281 (hdo
->property
.flag
& HWPDO_FLAG_BITMAP
))
283 hdo
->property
.offset1
.x
= hmem
->read4b();
284 hdo
->property
.offset1
.y
= hmem
->read4b();
285 hdo
->property
.offset2
.x
= hmem
->read4b();
286 hdo
->property
.offset2
.y
= hmem
->read4b();
287 if (!hmem
->readBlock(hdo
->property
.szPatternFile
, 261))
289 hdo
->property
.pictype
= sal::static_int_cast
<char>(hmem
->read1b());
292 if( ( size
>= common_size
+ 3 ) && ( hdo
->property
.flag
& HWPDO_FLAG_WATERMARK
) )
293 //if( ( size >= common_size ) && ( hdo->property.flag >> 20 & 0x01 ) )
295 if( size
- common_size
>= 5 )
296 hmem
->skipBlock( 2 );
297 hdo
->property
.luminance
= hmem
->read1b();
298 hdo
->property
.contrast
= hmem
->read1b();
299 hdo
->property
.greyscale
= hmem
->read1b();
303 hdo
->property
.luminance
= 0;
304 hdo
->property
.contrast
= 0;
305 hdo
->property
.greyscale
= 0;
307 hdo
->property
.pPara
= 0L;
309 if( ( size
> common_size
) && (hdo
->property
.flag
& HWPDO_FLAG_AS_TEXTBOX
) )
312 hdo
->property
.pPara
= LoadParaList();
313 if( hdo
->property
.pPara
)
319 if( size
<= common_size
)
321 return hmem
->skipBlock(size
- common_size
) != 0;
325 static HWPDrawingObject
*LoadDrawingObject(void)
327 HWPDrawingObject
*hdo
, *head
, *prev
;
335 if ((hdo
= new HWPDrawingObject
) == NULL
)
339 if (!LoadCommonHeader(hdo
, &link_info
))
343 if (hdo
->type
< 0 || hdo
->type
>= HWPDO_NITEMS
)
345 hdo
->type
= HWPDO_RECT
;
346 if (!SkipPrivateBlock(OBJRET_FILE_NO_PRIVATE_BLOCK
))
353 switch (res
= HWPDOFunc(hdo
, OBJFUNC_LOAD
, NULL
, 0))
355 case OBJRET_FILE_ERROR
:
359 case OBJRET_FILE_NO_PRIVATE_BLOCK
:
360 case OBJRET_FILE_NO_PRIVATE_BLOCK_2
:
361 if (!SkipPrivateBlock(res
))
366 if (link_info
& HDOFILE_HAS_CHILD
)
368 hdo
->child
= LoadDrawingObject();
369 if (hdo
->child
== NULL
)
379 while (link_info
& HDOFILE_HAS_NEXT
);
383 // drawing object can be list.
384 // hdo = current item, head = list;
388 HWPDOFunc(hdo
, OBJFUNC_FREE
, NULL
, 0);
401 static bool LoadDrawingObjectBlock(Picture
* pic
)
403 int size
= hmem
->read4b();
405 if (hmem
->state() || size
< HDOFILE_HEADER_SIZE
)
408 pic
->picinfo
.picdraw
.zorder
= hmem
->read4b();
409 pic
->picinfo
.picdraw
.mbrcnt
= hmem
->read4b();
410 pic
->picinfo
.picdraw
.vrect
.x
= hmem
->read4b();
411 pic
->picinfo
.picdraw
.vrect
.y
= hmem
->read4b();
412 pic
->picinfo
.picdraw
.vrect
.w
= hmem
->read4b();
413 pic
->picinfo
.picdraw
.vrect
.h
= hmem
->read4b();
415 if (size
> HDOFILE_HEADER_SIZE
&&
416 !hmem
->skipBlock(size
- HDOFILE_HEADER_SIZE
))
419 pic
->picinfo
.picdraw
.hdo
= LoadDrawingObject();
420 if (pic
->picinfo
.picdraw
.hdo
== 0)
426 // object manipulation function
429 HWPDODefaultFunc(int , HWPDrawingObject
* , int cmd
, void *, int)
431 if (cmd
== OBJFUNC_LOAD
)
432 return OBJRET_FILE_NO_PRIVATE_BLOCK
;
439 /* os 06.09.2005: unused function
441 calcArrowPolygonPts(long lWidth, ZZPoint * arrowPt,
442 ZZPoint * boxPt, int x1, int y1, int x2, int y2)
444 long lLength = lWidth;
448 if (gc->lineWidth > ONE_MILI)
449 lWidth = lLength = DRPX2(gc->lineWidth) * 2;
451 lWidth = lLength = DRPX2(ARROW_WIDTH);
460 boxPt[3].x = boxPt[0].x = arrowPt[1].x = x1 + lWidth;
461 boxPt[2].x = boxPt[1].x = arrowPt[2].x = x1 - lWidth;
464 boxPt[2].y = boxPt[3].y = y1 + lLength * 2 / 3;
465 arrowPt[0].y = y1 + lLength * 3 / 2;
466 boxPt[0].y = boxPt[1].y = arrowPt[1].y = arrowPt[2].y = y1 - lLength;
470 boxPt[0].y = boxPt[1].y = y1 - lLength * 2 / 3;
471 arrowPt[0].y = y1 - lLength * 3 / 2;
472 boxPt[2].y = boxPt[3].y = arrowPt[1].y = arrowPt[2].y = y1 + lLength;
477 double rSlope, rRadians;
478 long DX1, DY1, DX2, DY2;
480 rSlope = (double) dy / (double) dx;
481 rRadians = atan(rSlope);
482 DX1 = (long) (lLength * cos(rRadians) + 0.5);
483 DY1 = (long) (lLength * sin(rRadians) + 0.5);
484 DX2 = (long) (lWidth * sin(rRadians) + 0.5);
485 DY2 = (long) (lWidth * cos(rRadians) + 0.5);
489 arrowPt[0].x = (int) (x1 + cos(rRadians) * lLength * 3 / 2);
490 arrowPt[0].y = (int) (y1 + sin(rRadians) * lLength * 3 / 2);
491 boxPt[0].x = arrowPt[1].x = x1 - DX1 - DX2;
492 boxPt[0].y = arrowPt[1].y = y1 - DY1 + DY2;
493 boxPt[1].x = arrowPt[2].x = x1 - DX1 + DX2;
494 boxPt[1].y = arrowPt[2].y = y1 - DY1 - DY2;
495 boxPt[2].x = arrowPt[0].x - DX1 + DX2;
496 boxPt[2].y = arrowPt[0].y - DY1 - DY2;
497 boxPt[3].x = arrowPt[0].x - DX1 - DX2;
498 boxPt[3].y = arrowPt[0].y - DY1 + DY2;
502 arrowPt[0].x = (int) (x1 - cos(rRadians) * lLength * 3 / 2);
503 arrowPt[0].y = (int) (y1 - sin(rRadians) * lLength * 3 / 2);
504 boxPt[0].x = arrowPt[1].x = x1 + DX1 - DX2;
505 boxPt[0].y = arrowPt[1].y = y1 + DY1 + DY2;
506 boxPt[1].x = arrowPt[2].x = x1 + DX1 + DX2;
507 boxPt[1].y = arrowPt[2].y = y1 + DY1 - DY2;
508 boxPt[3].x = arrowPt[0].x + DX1 - DX2;
509 boxPt[3].y = arrowPt[0].y + DY1 + DY2;
510 boxPt[2].x = arrowPt[0].x + DX1 + DX2;
511 boxPt[2].y = arrowPt[0].y + DY1 - DY2;
517 HWPDOLineFunc(int type
, HWPDrawingObject
* hdo
, int cmd
, void *argp
, int argv
)
522 if (ReadSizeField(4) < 4)
523 return OBJRET_FILE_ERROR
;
524 hdo
->u
.line_arc
.flip
= hmem
->read4b();
526 return OBJRET_FILE_ERROR
;
527 if (!SkipUnusedField())
528 return OBJRET_FILE_ERROR
;
529 return OBJRET_FILE_NO_PRIVATE_BLOCK_2
;
531 return HWPDODefaultFunc(type
, hdo
, cmd
, argp
, argv
);
540 HWPDORectFunc(int type
, HWPDrawingObject
* hdo
, int cmd
, void *argp
, int argv
)
542 return HWPDODefaultFunc(type
, hdo
, cmd
, argp
, argv
);
549 HWPDOEllipseFunc(int type
, HWPDrawingObject
* hdo
,
550 int cmd
, void *argp
, int argv
)
552 return HWPDODefaultFunc(type
, hdo
, cmd
, argp
, argv
);
555 #define WTMM(x) ((double)(x) / 1800. * 25.4)
557 HWPDOEllipse2Func(int type
, HWPDrawingObject
* hdo
,
558 int cmd
, void *argp
, int argv
)
563 if (ReadSizeField(16) < 16)
564 return OBJRET_FILE_ERROR
;
565 hdo
->u
.arc
.radial
[0].x
= hmem
->read4b();
566 hdo
->u
.arc
.radial
[0].y
= hmem
->read4b();
567 hdo
->u
.arc
.radial
[1].x
= hmem
->read4b();
568 hdo
->u
.arc
.radial
[1].y
= hmem
->read4b();
570 if (ReadSizeField(0) < 0)
571 return OBJRET_FILE_ERROR
;
574 return HWPDODefaultFunc(type
, hdo
, cmd
, argp
, argv
);
583 HWPDOArcFunc(int type
, HWPDrawingObject
* hdo
, int cmd
, void *argp
, int argv
)
589 if (ReadSizeField(4) < 4)
590 return OBJRET_FILE_ERROR
;
591 hdo
->u
.line_arc
.flip
= hmem
->read4b();
593 return OBJRET_FILE_ERROR
;
594 if (!SkipUnusedField())
595 return OBJRET_FILE_ERROR
;
598 return HWPDODefaultFunc(type
, hdo
, cmd
, argp
, argv
);
605 HWPDOArc2Func(int type
, HWPDrawingObject
* hdo
, int cmd
, void *argp
, int argv
)
611 return OBJRET_FILE_NO_PRIVATE_BLOCK
;
613 return HWPDODefaultFunc(type
, hdo
, cmd
, argp
, argv
);
621 #define SPLINE_NSTEP 100
622 #define SPLINE_UNIT 20
623 #define SPLINE_UNIT2 40
624 #define SPLINE_UNIT3 60
626 /* os 06.09.2005: unused function
627 static int getBlend(int alpha)
629 static bool first = true;
630 static char isCached[SPLINE_NSTEP];
631 static int blend[SPLINE_NSTEP];
636 memset(isCached, 0, sizeof(char) * SPLINE_NSTEP);
640 if ((alpha < -SPLINE_UNIT2) || (alpha > SPLINE_UNIT2))
643 if (!isCached[alpha + SPLINE_UNIT2])
645 isCached[alpha + SPLINE_UNIT2] = TRUE;
646 ntheta = (double) alpha / SPLINE_UNIT;
648 if ((alpha < -SPLINE_UNIT) || (alpha > SPLINE_UNIT))
650 ntheta = (ntheta > 1) ? (2 - ntheta) : (2 + ntheta);
651 blend[alpha + SPLINE_UNIT2] =
652 (int) (1000 * ntheta * ntheta * ntheta / 6.);
655 blend[alpha + SPLINE_UNIT2] =
657 (4 - 6 * ntheta * ntheta -
658 3 * ntheta * ntheta * ntheta) / 6);
660 blend[alpha + SPLINE_UNIT2] =
662 (4 - 6 * ntheta * ntheta +
663 3 * ntheta * ntheta * ntheta) / 6);
665 return blend[alpha + SPLINE_UNIT2];
670 HWPDOFreeFormFunc(int type
, HWPDrawingObject
* hdo
,
671 int cmd
, void *argp
, int argv
)
677 hdo
->u
.freeform
.pt
= 0;
678 if (ReadSizeField(4) < 4)
679 return OBJRET_FILE_ERROR
;
680 hdo
->u
.freeform
.npt
= hmem
->read4b();
682 return OBJRET_FILE_ERROR
;
683 if (!SkipUnusedField())
684 return OBJRET_FILE_ERROR
;
686 int size
= hdo
->u
.freeform
.npt
* sizeof(ZZPoint
);
688 if (ReadSizeField(size
) < size
)
689 return OBJRET_FILE_ERROR
;
690 if (hdo
->u
.freeform
.npt
)
692 hdo
->u
.freeform
.pt
= new ZZPoint
[hdo
->u
.freeform
.npt
];
693 if (hdo
->u
.freeform
.pt
== NULL
)
695 hdo
->u
.freeform
.npt
= 0;
696 return OBJRET_FILE_ERROR
;
698 for (int ii
= 0; ii
< hdo
->u
.freeform
.npt
; ii
++)
700 hdo
->u
.freeform
.pt
[ii
].x
= hmem
->read4b();
701 hdo
->u
.freeform
.pt
[ii
].y
= hmem
->read4b();
704 delete[]hdo
->u
.freeform
.pt
;
705 hdo
->u
.freeform
.npt
= 0;
706 return OBJRET_FILE_ERROR
;
710 if (!SkipUnusedField())
711 return OBJRET_FILE_ERROR
;
712 return OBJRET_FILE_OK
;
715 if (hdo
->u
.freeform
.pt
)
716 delete[]hdo
->u
.freeform
.pt
;
719 return HWPDODefaultFunc(type
, hdo
, cmd
, argp
, argv
);
727 static void FreeParaList(HWPPara
* para
)
730 FreeParaList(para
->Next());
735 static HWPPara
*LoadParaList()
740 HWPFile
*hwpf
= GetCurrentDoc();
741 HIODev
*hio
= hwpf
->SetIODevice(hmem
);
743 LinkedList
< HWPPara
> plist
;
745 hwpf
->ReadParaList(plist
);
746 hwpf
->SetIODevice(hio
);
748 return plist
.count()? plist
.first() : 0;
753 HWPDOTextBoxFunc(int type
, HWPDrawingObject
* hdo
,
754 int cmd
, void *argp
, int argv
)
757 // hunit sx, sy, xs, ys;
762 if (ReadSizeField(0) < 0 || !SkipUnusedField())
763 return OBJRET_FILE_ERROR
;
764 if (ReadSizeField(0) < 0)
765 return OBJRET_FILE_ERROR
;
766 hdo
->u
.textbox
.h
= LoadParaList();
767 return hdo
->u
.textbox
.h
? OBJRET_FILE_OK
: OBJRET_FILE_ERROR
;
769 if (hdo
->u
.textbox
.h
)
771 FreeParaList(hdo
->u
.textbox
.h
);
772 hdo
->u
.textbox
.h
= NULL
;
776 return HWPDODefaultFunc(type
, hdo
, cmd
, argp
, argv
);
783 HWPDOContainerFunc(int type
, HWPDrawingObject
* hdo
,
784 int cmd
, void *argp
, int argv
)
786 return HWPDODefaultFunc(type
, hdo
, cmd
, argp
, argv
);
790 /* HWPDrawObject ¸â¹ö ÇÔ¼ö */
792 HWPDrawingObject::HWPDrawingObject()
794 memset(this, 0, sizeof(HWPDrawingObject
));
799 HWPDrawingObject::~HWPDrawingObject()
802 if (hdo
->property
.pictype
== PICTYP_EMBED
)
803 RemoveEmbeddedPic(hdo
->property
.szPatternFile
);
804 hdo
->property
.szPatternFile
[0] = 0;
812 HWPDOFunc(this, OBJFUNC_FREE
, NULL
, 0);