Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/java2d/SurfaceData.h
38829 views
/*1* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/**26* This include file contains information on how to use a SurfaceData27* object from native code.28*/2930#ifndef _Included_SurfaceData31#define _Included_SurfaceData3233#include <jni.h>3435#ifdef __cplusplus36extern "C" {37#endif3839/*40* This structure is used to represent a rectangular bounding box41* throughout various functions in the native SurfaceData API.42*43* All coordinates (x1 <= x < x2, y1 <= y < y2) are considered to44* be inside these bounds.45*/46typedef struct {47jint x1;48jint y1;49jint x2;50jint y2;51} SurfaceDataBounds;5253#define SD_RASINFO_PRIVATE_SIZE 645455/*56* The SurfaceDataRasInfo structure is used to pass in and return various57* pieces of information about the destination drawable. In particular:58*59* SurfaceDataBounds bounds;60* [Needed for SD_LOCK_READ or SD_LOCK_WRITE]61* The 2 dimensional bounds of the raster array that is needed. Valid62* memory locations are required at:63* *(pixeltype *) (((char *)rasBase) + y * scanStride + x * pixelStride)64* for each x, y pair such that (bounds.x1 <= x < bounds.x2) and65* (bounds.y1 <= y < bounds.y2).66*67* void *rasBase;68* [Requires SD_LOCK_READ or SD_LOCK_WRITE]69* A pointer to the device space origin (0, 0) of the indicated raster70* data. This pointer may point to a location that is outside of the71* allocated memory for the requested bounds and it may even point72* outside of accessible memory. Only the locations that fall within73* the coordinates indicated by the requested bounds are guaranteed74* to be accessible.75*76* jint pixelBitOffset;77* [Requires SD_LOCK_READ or SD_LOCK_WRITE]78* The number of bits offset from the beginning of the first byte79* of a scanline to the first bit of the first pixel on that scanline.80* The bit offset must be less than 8 and it must be the same for each81* scanline. This field is only needed by image types which pack82* multiple pixels into a byte, such as ByteBinary1Bit et al. For83* image types which use whole bytes (or shorts or ints) to store84* their pixels, this field will always be 0.85*86* jint pixelStride;87* [Requires SD_LOCK_READ or SD_LOCK_WRITE]88* The pixel stride is the distance in bytes from the data for one pixel89* to the data for the pixel at the next x coordinate (x, y) => (x+1, y).90* For data types that pack multiple pixels into a byte, such as91* ByteBinary1Bit et al, this field will be 0 and the loops which92* render to and from such data need to calculate their own offset93* from the beginning of the scanline using the absolute x coordinate94* combined with the pixelBitOffset field.95* Bugfix 6220829 - this field used to be unsigned int, but some96* primitives used negative pixel offsets and the corresponding97* unsigned stride values caused the resulting pixel offset to98* to always be a positive 32-bit quantity - causing problems on99* 64-bit architectures.100*101* jint scanStride;102* [Requires SD_LOCK_READ or SD_LOCK_WRITE]103* The scan stride is the distance in bytes from the data for one pixel104* to the data for the pixel at the next y coordinate (x, y) => (x, y+1).105* Bugfix 6220829 - this field used to be unsigned int, but some106* primitives used negative pixel offsets and the corresponding107* unsigned stride values caused the resulting pixel offset to108* to always be a positive 32-bit quantity - causing problems on109* 64-bit architectures.110*111* unsigned int lutSize;112* [Requires SD_LOCK_LUT]113* The number of entries in the color lookup table. The data beyond the114* end of the map will be undefined.115*116* jint *lutBase;117* [Requires SD_LOCK_LUT]118* A pointer to the beginning of the color lookup table for the colormap.119* The color lookup table is formatted as an array of jint values each120* representing the 32-bit ARGB color for the pixel representing by the121* corresponding index. The table is guaranteed to contain at least 256122* valid memory locations even if the size of the map is smaller than 256.123*124* unsigned char *invColorTable;125* [Requires SD_LOCK_INVCOLOR]126* A pointer to the beginning of the inverse color lookup table for the127* colormap. The inverse color lookup table is formatted as a 32x32x32128* array of bytes indexed by RxGxB where each component is reduced to 5129* bits of precision before indexing.130*131* char *redErrTable;132* char *grnErrTable;133* char *bluErrTable;134* [Requires SD_LOCK_INVCOLOR]135* Pointers to the beginning of the ordered dither color error tables136* for the colormap. The error tables are formatted as an 8x8 array137* of bytes indexed by coordinates using the formula [y & 7][x & 7].138*139* int *invGrayTable;140* [Requires SD_LOCK_INVGRAY]141* A pointer to the beginning of the inverse gray lookup table for the142* colormap. The inverse color lookup table is formatted as an array143* of 256 integers indexed by a byte gray level and storing an index144* into the colormap of the closest matching gray pixel.145*146* union priv {};147* A buffer of private data for the SurfaceData implementation.148* This field is a union of a data block of the desired default149* size (SD_RASINFO_PRIVATE_SIZE) and a (void *) pointer that150* ensures proper "strictest" alignment on all platforms.151*/152typedef struct {153SurfaceDataBounds bounds; /* bounds of raster array */154void *rasBase; /* Pointer to (0, 0) pixel */155jint pixelBitOffset; /* bit offset to (0, *) pixel */156jint pixelStride; /* bytes to next X pixel */157jint scanStride; /* bytes to next Y pixel */158unsigned int lutSize; /* # colors in colormap */159jint *lutBase; /* Pointer to colormap[0] */160unsigned char *invColorTable; /* Inverse color table */161char *redErrTable; /* Red ordered dither table */162char *grnErrTable; /* Green ordered dither table */163char *bluErrTable; /* Blue ordered dither table */164int *invGrayTable; /* Inverse gray table */165union {166void *align; /* ensures strict alignment */167char data[SD_RASINFO_PRIVATE_SIZE];168} priv;169} SurfaceDataRasInfo;170171typedef struct _SurfaceDataOps SurfaceDataOps;172173/*174* This function is used to lock a particular region of a particular175* destination. Once this method is called, no changes of any of the176* data returned by any of the other SurfaceData vectored functions177* may change until a corresponding call to Release is made.178*179* The env parameter should be the JNIEnv of the surrounding JNI context.180*181* The ops parameter should be a pointer to the ops object upon which182* this function is being invoked.183*184* The rasInfo parameter should be a pointer to a SurfaceDataRasInfo185* structure in which the bounds have been initialized to the maximum186* bounds of the raster data that will need to be accessed later.187*188* The lockflags parameter should indicate which information will be189* needed by the caller. The various flags which may be OR'd together190* may consist of any of the following:191* SD_LOCK_READ The caller needs to read pixels from the dest192* SD_LOCK_WRITE The caller needs to write pixels to the dest193* SD_LOCK_RD_WR A combination of (SD_LOCK_READ | SD_LOCK_WRITE)194* SD_LOCK_LUT The caller needs the colormap (Lut)195* SD_LOCK_INVCOLOR The caller needs the inverse color table196* SD_LOCK_INVGRAY The caller needs the inverse gray table197* SD_LOCK_FASTEST The caller only wants direct pixel access198* Note that the SD_LOCK_LUT, SD_LOCK_INVCOLOR, and SD_LOCK_INVGRAY flags199* are only valid for destinations with IndexColorModels.200* Also note that SD_LOCK_FASTEST will only succeed if the access to the201* pixels will occur just as fast regardless of the size of the bounds.202* This flag is used by the Text rendering routines to determine if it203* matters whether or not they have calculated a tight bounding box for204* the pixels they will be touching.205*206* Return value:207*208* If this function succeeds, it will return SD_SUCCESS (0).209*210* If this function is unable to honor the SD_LOCK_FASTEST flag,211* it will return SD_SLOWLOCK. The bounds parameter of the212* SurfaceDataRasInfo object should be intersected with a tighter213* bounding rectangle before calling the GetRasInfo function so214* as to minimize the amount pixel copying or conversion. Note215* that the Lock function may have already intersected the216* bounds with a tighter rectangle as it tried to honor the217* SD_SLOWLOCK flag and so the caller should only use intersection218* operations to further restrict the bounds.219*220* If this function fails for any reason that is not recoverable,221* it will throw an appropriate Java exception and return SD_FAILED.222*223* Operation:224*225* This function will intersect the bounds specified in the rasInfo226* parameter with the available raster data in the destination drawable227* and modify the contents of the bounds field to represent the maximum228* available raster data.229*230* If the available raster data in the destination drawable consists of231* a non-rectangular region of pixels, this method may throw an InvalidPipe232* exception (optionally the object may decide to provide a copy of the233* destination pixel data with undefined data in the inaccessible portions).234*235* Further processing by the caller may discover that a smaller region of236* data is actually needed and the call to GetRasData can be made with a237* still smaller bounds.238*239* Note to callers:240* This function may use JNI methods so it is important that the241* caller not have any outstanding GetPrimitiveArrayCritical or242* GetStringCritical locks which have not been released.243*244* Note to implementers:245* The caller may also continue to use JNI methods after this method246* is called so it is important that implementations of SurfaceData247* not return from this function with any outstanding JNI Critical248* locks that have not been released.249*/250typedef jint LockFunc(JNIEnv *env,251SurfaceDataOps *ops,252SurfaceDataRasInfo *rasInfo,253jint lockflags);254255/*256* This function returns information about the raster data for the drawable.257* The function will fill in or modify the contents of the SurfaceDataRasInfo258* structure that is passed in with various pieces of information depending259* on what was requested in the lockflags parameter that was handed into260* the LockFunc. For more information on which pieces of information are261* returned based upon the lock flags see the documentation for the262* RasInfo structure above.263*264* The env parameter should be the JNIEnv of the surrounding JNI context.265*266* The ops parameter should be a pointer to the ops object upon which267* this function is being invoked.268*269* The pRasInfo parameter should be a pointer to the same structure of type270* SurfaceDataRasInfo. The bounds member of that structure should be271* initialized to the bounding box of the raster data that is actually272* needed for reading or writing before calling this function. These273* bounds must be a subset of the raster bounds that were given to the274* LockFunc or the results will be undefined.275*276* If the surface was locked with the flag SD_LOCK_FASTEST then this277* function may reevaluate the bounds in the RasInfo structure and278* return a subset of what was requested. Callers that use that flag279* should be prepared to reevaluate their clipping after GetRasInfo280* returns. If the SD_LOCK_FASTEST flag was not specified, then this281* function will return a buffer containing all of the pixels in the282* requested bounds without reevaluating them.283*284* Any information that was requested in the lockflags of the LockFunc285* will be returned and NULL pointers will be returned for all other286* information.287*288* Note to callers:289* This function may use JNI Critical methods so it is important290* that the caller not call any other JNI methods after this function291* returns until the Release function is called.292*/293typedef void GetRasInfoFunc(JNIEnv *env,294SurfaceDataOps *ops,295SurfaceDataRasInfo *pRasInfo);296297/*298* This function releases all of the Critical data for the specified299* drawable.300*301* This function vector is allowed to be NULL if a given SurfaceData302* implementation does not require the use of JNI Critical array locks.303* Callers should use the "SurfaceData_InvokeRelease(env, ops)" macro304* to handle the conditional invocation of this function.305*306* In particular, this function will release any outstanding JNI Critical307* locks that the SurfaceData implementation may have used so that it308* will be safe for the caller to start using arbitrary JNI calls or309* return from its calling JNI function.310*311* The env parameter should be the JNIEnv of the surrounding JNI context.312*313* The ops parameter should be a pointer to the ops object upon which314* this function is being invoked.315*316* The pRasInfo parameter should be a pointer to the same structure of317* type SurfaceDataRasInfo that was passed to the GetRasInfo function.318* The bounds should be unchanged since that call.319*320* Note to callers:321* This function will release any outstanding JNI Critical locks so322* it will once again be safe to use arbitrary JNI calls or return323* to the enclosing JNI native context.324*325* Note to implementers:326* This function may not use any JNI methods other than to release327* outstanding JNI Critical array locks since there may be other328* nested SurfacData objects holding locks with their own outstanding329* JNI Critical locks. This restriction includes the use of the330* JNI monitor calls so that all MonitorExit invocations must be331* done in the Unlock function.332*/333typedef void ReleaseFunc(JNIEnv *env,334SurfaceDataOps *ops,335SurfaceDataRasInfo *pRasInfo);336337/*338* This function unlocks the specified drawable.339*340* This function vector is allowed to be NULL if a given SurfaceData341* implementation does not require any unlocking of the destination.342* Callers should use the "SurfaceData_InvokeUnlock(env, ops)" macro343* to handle the conditional invocation of this function.344*345* The env parameter should be the JNIEnv of the surrounding JNI context.346*347* The ops parameter should be a pointer to the ops object upon which348* this function is being invoked.349*350* The pRasInfo parameter should be a pointer to the same structure of351* type SurfaceDataRasInfo that was passed to the GetRasInfo function.352* The bounds should be unchanged since that call.353*354* Note to callers:355* This function may use JNI methods so it is important that the356* caller not have any outstanding GetPrimitiveArrayCritical or357* GetStringCritical locks which have not been released.358*359* Note to implementers:360* This function may be used to release any JNI monitors used to361* prevent the destination from being modified. It may also be362* used to perform operations which may require blocking (such as363* executing X11 operations which may need to flush data).364*/365typedef void UnlockFunc(JNIEnv *env,366SurfaceDataOps *ops,367SurfaceDataRasInfo *pRasInfo);368369/*370* This function sets up the specified drawable. Some surfaces may371* need to perform certain operations during Setup that cannot be372* done after later operations such as Lock. For example, on373* win9x systems, when any surface is locked we cannot make a call to374* the message-handling thread.375*376* This function vector is allowed to be NULL if a given SurfaceData377* implementation does not require any setup.378*379* The env parameter should be the JNIEnv of the surrounding JNI context.380*381* The ops parameter should be a pointer to the ops object upon which382* this function is being invoked.383*384* Note to callers:385* This function may use JNI methods so it is important that the386* caller not have any outstanding GetPrimitiveArrayCritical or387* GetStringCritical locks which have not been released.388*/389typedef void SetupFunc(JNIEnv *env,390SurfaceDataOps *ops);391392/*393* This function disposes the specified SurfaceDataOps structure394* and associated native resources.395* The implementation is SurfaceData-type specific.396*/397typedef void DisposeFunc(JNIEnv *env,398SurfaceDataOps *ops);399400/*401* Constants used for return values. Constants less than 0 are402* unrecoverable failures and indicate that a Java exception has403* already been thrown. Constants greater than 0 are conditional404* successes which warn the caller that various optional features405* were not available so that workarounds can be used.406*/407#define SD_FAILURE -1408#define SD_SUCCESS 0409#define SD_SLOWLOCK 1410411/*412* Constants for the flags used in the Lock function.413*/414#define SD_LOCK_READ (1 << 0)415#define SD_LOCK_WRITE (1 << 1)416#define SD_LOCK_RD_WR (SD_LOCK_READ | SD_LOCK_WRITE)417#define SD_LOCK_LUT (1 << 2)418#define SD_LOCK_INVCOLOR (1 << 3)419#define SD_LOCK_INVGRAY (1 << 4)420#define SD_LOCK_FASTEST (1 << 5)421#define SD_LOCK_PARTIAL (1 << 6)422#define SD_LOCK_PARTIAL_WRITE (SD_LOCK_WRITE | SD_LOCK_PARTIAL)423#define SD_LOCK_NEED_PIXELS (SD_LOCK_READ | SD_LOCK_PARTIAL)424425/*426* This structure provides the function vectors for manipulating427* and retrieving information about the destination drawable.428* There are also variables for the surface data object used by429* native code to track the state of the surface.430* The sdObject is a pointer to the Java SurfaceData object;431* this is set in SurfaceData_InitOps() and used by any object432* using the ops structure to refer to elements in the Java object433* (such as fields that we need to set from native code).434*/435struct _SurfaceDataOps {436LockFunc *Lock;437GetRasInfoFunc *GetRasInfo;438ReleaseFunc *Release;439UnlockFunc *Unlock;440SetupFunc *Setup;441DisposeFunc *Dispose;442jobject sdObject;443};444445#define _ClrReduce(c) (((unsigned char) c) >> 3)446447/*448* This macro performs a lookup in an inverse color table given 3 8-bit449* RGB primaries. It automates the process of reducing the primaries450* to 5-bits of precision and using them to index into the specified451* inverse color lookup table.452*/453#define SurfaceData_InvColorMap(invcolortbl, r, g, b) \454(invcolortbl)[(_ClrReduce(r)<<10) + (_ClrReduce(g)<<5) + _ClrReduce(b)]455456/*457* This macro invokes the SurfaceData Release function only if the458* function vector is not NULL.459*/460#define SurfaceData_InvokeRelease(env, ops, pRI) \461do { \462if ((ops)->Release != NULL) { \463(ops)->Release(env, ops, pRI); \464} \465} while(0)466467/*468* This macro invokes the SurfaceData Unlock function only if the469* function vector is not NULL.470*/471#define SurfaceData_InvokeUnlock(env, ops, pRI) \472do { \473if ((ops)->Unlock != NULL) { \474(ops)->Unlock(env, ops, pRI); \475} \476} while(0)477478/*479* This macro invokes both the SurfaceData Release and Unlock functions480* only if the function vectors are not NULL. It can be used in cases481* where only one surface has been accessed and where no other JNI482* Critical locks (which would need to be released after Release and483* before Unlock) are held by the calling function.484*/485#define SurfaceData_InvokeReleaseUnlock(env, ops, pRI) \486do { \487if ((ops)->Release != NULL) { \488(ops)->Release(env, ops, pRI); \489} \490if ((ops)->Unlock != NULL) { \491(ops)->Unlock(env, ops, pRI); \492} \493} while(0)494495/*496* This macro invokes both the SurfaceData Release and Unlock functions497* on two nested drawables only if the function vectors are not NULL.498* It can be used in cases where two surfaces have been accessed and499* where no other JNI Critical locks (which would need to be released500* after Release and before Unlock) are held by the calling function. The501* two ops vectors should be specified in the same order that they were502* locked. Both surfaces will be released and then both unlocked.503*/504#define SurfaceData_InvokeReleaseUnlock2(env, ops1, pRI1, ops2, pRI2) \505do { \506if ((ops2)->Release != NULL) { \507(ops2)->Release(env, ops2, pRI2); \508} \509if ((ops1)->Release != NULL) { \510(ops1)->Release(env, ops1, pRI1); \511} \512if ((ops2)->Unlock != NULL) { \513(ops2)->Unlock(env, ops2, pRI2); \514} \515if ((ops1)->Unlock != NULL) { \516(ops1)->Unlock(env, ops1, pRI1); \517} \518} while(0)519520#define SurfaceData_InvokeDispose(env, ops) \521do { \522if ((ops)->Dispose != NULL) { \523(ops)->Dispose(env, ops); \524} \525} while(0)526527#define SurfaceData_InvokeSetup(env, ops) \528do { \529if ((ops)->Setup != NULL) { \530(ops)->Setup(env, ops); \531} \532} while(0)533534/*535* This function returns a pointer to a native SurfaceDataOps536* structure for accessing the indicated SurfaceData Java object.537*538* Note to callers:539* This function uses JNI methods so it is important that the540* caller not have any outstanding GetPrimitiveArrayCritical or541* GetStringCritical locks which have not been released.542*543* The caller may continue to use JNI methods after this method544* is called since this function will not leave any outstanding545* JNI Critical locks unreleased.546*/547JNIEXPORT SurfaceDataOps * JNICALL548SurfaceData_GetOps(JNIEnv *env, jobject sData);549550/*551* Does the same as the above, but doesn't call Setup function552* even if it's set.553*/554JNIEXPORT SurfaceDataOps * JNICALL555SurfaceData_GetOpsNoSetup(JNIEnv *env, jobject sData);556557/*558* This function stores a pointer to a native SurfaceDataOps559* structure into the indicated Java SurfaceData object.560*561* Note to callers:562* This function uses JNI methods so it is important that the563* caller not have any outstanding GetPrimitiveArrayCritical or564* GetStringCritical locks which have not been released.565*566* The caller may continue to use JNI methods after this method567* is called since this function will not leave any outstanding568* JNI Critical locks unreleased.569*/570JNIEXPORT void JNICALL571SurfaceData_SetOps(JNIEnv *env, jobject sData, SurfaceDataOps *ops);572573/*574* This function throws an InvalidPipeException which will cause the575* calling SunGraphics2D object to revalidate its pipelines and call576* again. This utility method should be called from the SurfaceData577* native Lock routine when some attribute of the surface has changed578* that requires pipeline revalidation, including:579*580* The bit depth or pixel format of the surface.581* The surface (window) has been disposed.582* The device clip of the surface has been changed (resize, visibility, etc.)583*584* Note to callers:585* This function uses JNI methods so it is important that the586* caller not have any outstanding GetPrimitiveArrayCritical or587* GetStringCritical locks which have not been released.588*589* The caller may continue to use JNI methods after this method590* is called since this function will not leave any outstanding591* JNI Critical locks unreleased.592*/593JNIEXPORT void JNICALL594SurfaceData_ThrowInvalidPipeException(JNIEnv *env, const char *msg);595596/*597* This function intersects two bounds objects which exist in the same598* coordinate space. The contents of the first parameter (dst) are599* modified to contain the intersection of the two bounds while the600* contents of the second parameter (src) are untouched.601*/602JNIEXPORT void JNICALL603SurfaceData_IntersectBounds(SurfaceDataBounds *dst, SurfaceDataBounds *src);604605/*606* This function intersects a bounds object with a rectangle specified607* in lox, loy, hix, hiy format in the same coordinate space. The608* contents of the first parameter (bounds) are modified to contain609* the intersection of the two rectangular regions.610*/611JNIEXPORT void JNICALL612SurfaceData_IntersectBoundsXYXY(SurfaceDataBounds *bounds,613jint lox, jint loy, jint hix, jint hiy);614615/*616* This function intersects a bounds object with a rectangle specified617* in XYWH format in the same coordinate space. The contents of the618* first parameter (bounds) are modified to contain the intersection619* of the two rectangular regions.620*/621JNIEXPORT void JNICALL622SurfaceData_IntersectBoundsXYWH(SurfaceDataBounds *bounds,623jint x, jint y, jint w, jint h);624625/*626* This function intersects two bounds objects which exist in different627* coordinate spaces. The coordinate spaces of the two objects are628* related such that a given coordinate in the space of the A bounds629* is related to the analogous coordinate in the space of the B bounds630* by the formula: (AX + BXminusAX, AY + BYminusAY) == (BX, BY).631* The contents of both bounds objects are modified to represent their632* mutual intersection.633*/634JNIEXPORT void JNICALL635SurfaceData_IntersectBlitBounds(SurfaceDataBounds *Abounds,636SurfaceDataBounds *Bbounds,637jint BXminusAX, jint BYminusAY);638639640/*641* This function creates and initializes the ops structure. The function642* is called by "subclasses" of SurfaceData (e.g., BufImgSurfaceData)643* which pass in the size of the structure to allocate (subclasses generally644* need additional fields in the ops structure particular to their usage645* of the structure). The structure is allocated and initialized646* and is stored in the SurfaceData java object for later retrieval.647* Subclasses of SurfaceData should call this function instead of allocating648* the memory directly.649*/650SurfaceDataOps *SurfaceData_InitOps(JNIEnv *env, jobject sData, int opsSize);651652/*653* This function invokes the ops-specific disposal function.654* It is a part of the finalizers-free disposal mechanism.655* (see Disposer and DefaultDisposerRecord classes for more information)656* It also destroys the ops structure created in SurfaceData_InitOps.657*/658void SurfaceData_DisposeOps(JNIEnv *env, jlong ops);659660#ifdef __cplusplus661};662#endif663664#endif665666667