Spec-Zone .ru
спецификации, руководства, описания, API
Содержание документации

Собственный Интерфейс AWT

Ключ к Рендерингу к Холсту AWT от Собственного Кода

Новый Java™ SE AWT Собственный Интерфейс позволяет представить библиотеки, скомпилированные в собственный код, чтобы потянуть непосредственно к Java поверхность рисования Canvas. Это означает, что такими библиотеками можно пользоваться, не будучи преобразованным в Java сначала и без существенного влияния на производительность. Пример, иллюстрирующий, как легкий это должно использовать Собственный Интерфейс AWT, представляется и обсуждается в этом техническом примечании.

Введение

Определение Java Standard Edition включает JNI, Java Собственный Интерфейс. Большинство разработчиков Java никогда не должно будет использовать это, но интерфейс неоценим в определенных ситуациях, потому что это обеспечивает единственный путь к Байт-коду Java, чтобы взаимодействовать непосредственно с кодом программы, который был скомпилирован в собственные машинные инструкции для микропроцессора узла. JNI чаще всего используется в качестве ``клапана escape'', чтобы включить доступу к функциональности платформы, еще поддерживаемой языком программирования Java. Например, Вы могли использовать JNI, чтобы интегрировать с собственным кодом, который связывается с периферийным устройством, таким как сканер, соединенный с системой через порт USB.

Конечно, JNI является достаточно общим, чтобы привыкнуть к доступу почти любой вид собственной библиотеки, независимо от того, могла ли бы задача, которая будет выполнена, также быть сделана, используя чистый Java. Главный штраф за использование этого - то, что переносимость кода страдает, но это может быть приемлемым или даже необходимым для деловых или технических причин.

Деловые причины? Рассмотрите ситуацию, где унаследованное программное обеспечение, которое Вы пытаетесь портировать на Java, пользуется сторонней библиотекой для критического набора операций. Если Вы не имеете исходных прав на эту библиотеку, и невозможно убедить владельца обеспечивать версию Java, Вы не можете быть в состоянии использовать ее. Даже если у Вас действительно есть источник, усилие должно было портировать стандартную библиотеку на Java и тест, который может быть слишком дорого рассмотреть.

Другая важная причина того, чтобы оставить собственный код в покое связывается с производительностью. Если Вы имеете дело с точно обработанной частью кода, тщательно настроенного для производительности в течение лет, Вы, вероятно, не хотите преобразовывать это в Java и рисковать потерей производительности. Обычно лучше сохранить это в целости, пока Вы не удовлетворяетесь, что преимущества мобильности Java и надежности кода перевешивают ожидаемое различие в производительности.

Библиотека рендеринга является хорошим примером части собственного кода, который большинство разработчиков так же, как скоро оставило бы в покое по причинам производительности. К сожалению, это - самый тип библиотеки, которую было самым трудным интегрировать с кодом Java через JNI. Основная проблема состояла в том, что код рендеринга не может идентифицировать, где потянуть. Это нуждается в доступе к информации о поверхности рисования Java (такой как дескриптор к базовой коллеге Canvas), но не может получить это.

До сих пор платформа Java сохранила доступ к этой информации частным — "частный" в смысле недокументированного, неподдерживаемого, и осудила. Хорошие новости - то, что эта ситуация будет исправлена с введением "AWT Собственный Интерфейс" в выпуске обновления Java ("пустельга"). Впервые будет официальный способ получить всю информацию, Вы должны знать о коллеге Java Canvas так, чтобы можно было потянуть непосредственно к Canvas от собственной библиотеки кода, используя подпрограммы рисунка, обеспеченные операционной системой.

Как Это Работает

В этом разделе мы опишем наиболее распространенное использование Собственного Интерфейса AWT — переопределение метода paint, чтобы направить операции рисования к собственной библиотеке рендеринга, которая тогда запрашивает Java VM, чтобы определить информацию, в которой это нуждается, чтобы представить. Отметьте, однако, что любой собственный код может использовать Собственный Интерфейс AWT, чтобы узнать о целевой поверхности рисования, не только кодируют в методе paint.

Первый шаг в присоединении собственная библиотека рендеринга к Java, Canvas должен определить новый класс, который расширяет Canvas и переопределяет метод paint. Система Java направляет все операции рисования для объекта Canvas через метод paint, как это делает для всех других объектов GUI.

Новый метод paint, чтобы быть реализованным в собственной библиотеке рендеринга, должен быть объявлен как public native void, и сама собственная библиотека загружается во время выполнения включением звонка в System.loadLibrary( "myRenderingLib") в блоке static класса. Имя myRenderingLib используется для собственной совместно используемой библиотеки; для операционной среды Соляриса подлинным именем для файла библиотеки на диске является libmyRenderingLib.so.

Вот простой пример такого класса:

import java.awt.*;
import java.awt.event.*;

public class MyCanvas extends Canvas {
    static {
        System.loadLibrary("myRenderingLib");
    }
    public native void paint(Graphics g);

    public static void main(String[] args) {
        Frame f = new Frame();
        f.setBounds(0, 0, 500, 110);
        f.add( new MyCanvas() );
        f.addWindowListener( new WindowAdapter() {
            public void windowClosing(WindowEvent ev) {
                System.exit(0);
            }
        } );
        f.show();
    }
}

Отметьте, что у этого класса есть метод main, который может быть используемой Торунью этот код как приложение для тестирования.

Следующий шаг должен выполнить инструмент javah на файле класса MyCanvas выше, чтобы генерировать заголовочный файл C/C++, который описывает интерфейс к собственному методу paint, что Java ожидает использоваться. javah является стандартным инструментом, включенным с SDK Java.

Заключительный шаг - самый интересный - должен записать собственный метод рендеринга с интерфейсом, который соответствует заголовочному файлу, что javah, сгенерированный, и, создает это как стандарт совместно использованная библиотека (призвал myRenderingLib вышеупомянутый пример), соединяя это, для операционной среды Соляриса, против библиотеки jre/lib/sparc/libjawt.so. (Для Microsoft Windows соединитесь против библиотеки jre/bin/jawt.dll.) Этот код перезвонит к виртуальной машине Java, чтобы получить информацию поверхности рисунка, это должно получить доступ к коллеге MyCanvas. Как только эта информация доступна, код может потянуть непосредственно к MyCanvas, используя стандартные подпрограммы рисунка, предоставленные базовой операционной системой.

Вот является демонстрационный исходный код для собственного метода paint, разработанного для использования в Солярисе X11-на-основе средой рисунка и Java VM, где Собственный Интерфейс AWT присутствует:

/*
 * Copyright (c) 1999 Oracle and/or its affiliates.  All rights reserved.
 * 
 */

#include "MyCanvas.h"
#include "jawt_md.h"

/*
 * Class:     MyCanvas
 * Method:    paint
 * Signature: (Ljava/awt/Graphics;)V
 */
JNIEXPORT void JNICALL Java_MyCanvas_paint
(JNIEnv* env, jobject canvas, jobject graphics)
{
    JAWT awt;
    JAWT_DrawingSurface* ds;
    JAWT_DrawingSurfaceInfo* dsi;
    JAWT_X11DrawingSurfaceInfo* dsi_x11;
    jboolean result;
    jint lock;
    GC gc;
    
    short       i;
    char        *testString = "^^^ rendered from native code ^^^";

    /* Get the AWT */
    awt.version = JAWT_VERSION_1_3;
    if (JAWT_GetAWT(env, &awt) == JNI_FALSE) {
        printf("AWT Not found\n");
        return;
    }

    /* Get the drawing surface */
    ds = awt.GetDrawingSurface(env, canvas);
    if (ds == NULL) {
        printf("NULL drawing surface\n");
        return;
    }

    /* Lock the drawing surface */
    lock = ds->Lock(ds);
    if((lock & JAWT_LOCK_ERROR) != 0) {
        printf("Error locking surface\n");
        awt.FreeDrawingSurface(ds);
        return;
    }

    /* Get the drawing surface info */
    dsi = ds->GetDrawingSurfaceInfo(ds);
    if (dsi == NULL) {
        printf("Error getting surface info\n");
        ds->Unlock(ds);
        awt.FreeDrawingSurface(ds);
        return;
    }

    /* Get the platform-specific drawing info */
    dsi_x11 = (JAWT_X11DrawingSurfaceInfo*)dsi->platformInfo;


    /* Now paint */
    gc = XCreateGC(dsi_x11->display, dsi_x11->drawable, 0, 0);
    XSetBackground(dsi_x11->display, gc, 0);
    for (i=0; i<36;i++)
    {
        XSetForeground(dsi_x11->display, gc, 10*i);
        XFillRectangle(dsi_x11->display, dsi_x11->drawable, gc,
                        10*i, 5, 90, 90);
    }
    XSetForeground(dsi_x11->display, gc, 155);
    XDrawImageString(dsi_x11->display, dsi_x11->drawable, gc,
                        100, 110, testString, strlen(testString));
    XFreeGC(dsi_x11->display, gc);


    /* Free the drawing surface info */
    ds->FreeDrawingSurfaceInfo(dsi);

    /* Unlock the drawing surface */
    ds->Unlock(ds);

    /* Free the drawing surface */
    awt.FreeDrawingSurface(ds);
}

Ключевой структурой данных здесь является JAWT, который определяется в jawt.h (включенный jawt_md.h); это обеспечивает доступ ко всей информации, собственный код должен был сделать задание. Первая часть собственного метода является шаблоном: это заполняет структуру JAWT, получает структуру JAWT_DrawingSurface, блокирует поверхность (только один механизм рисунка за один раз, пожалуйста!), затем получает структуру JAWT_DrawingSurfaceInfo, которая содержит указатель (в поле platformInfo) к необходимой специфичной для платформы информации о рисунке. Это также включает ограничительный прямоугольник поверхности рисунка и текущей области отсечения.

Структура информации, на которую указывает platformInfo, определяется в машинно-зависимом заголовочном файле под названием jawt_md.h. Для рисунка Solaris/X11 это включает информацию о дисплее X11 и X11 drawable связанный с MyCanvas. После того, как операции рисования завершаются, есть больше шаблонного кода, поскольку JAWT_DrawingSurfaceInfo освобождается, и JAWT_DrawingSurface разблокирован и освобожден.

Соответствующий код для платформы Microsoft Windows был бы структурирован точно так же, но будет включать версию jawt_md.h для Microsoft Windows, и структура, расположенная в поле platformInfo рисования поверхностной информации, была бы снята как JAWT_Win32DrawingSurfaceInfo*. И, конечно, фактические операции рисования должны были бы быть изменены на тех, приспосабливают для платформы Microsoft Windows.

Сводка

Возможность потянуть непосредственно в Java, Canvas от собственной библиотеки кода чрезвычайно полезен для разработчиков, планирующих переместить систему унаследованного программного обеспечения на Java, особенно тот, который включает высокоэффективный механизм рендеринга. Это делает намного легче перейти шаг за шагом, оставляя чувствительный к производительности код рендеринга в покое, в то время как другой менее - чувствительные части кода преобразовываются в Java. Результатом может быть современное центральное Java приложение, предоставляя преимущество мобильности и эффективности разработки, но того, который не жертвует инвестициями в производительности основной части собственного кода.

Ссылки

Категорическая ссылка на Java Собственный Интерфейс является Java Собственный Интерфейс: Руководство Программиста и Спецификация Sheng Liang Sun Microsystems. Эта книга была опубликована в июне 1999 Аддисоном-Уэсли. ISBN 0-201-32577-2.

Приложение

Заголовочные файлы для jawt.h и jawt_md.h

jawt.h

/*
 * @(#)jawt.h   1.2 99/05/27
 *
 * Copyright (c) 1999 Oracle and/or its affiliates.  All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Sun Microsystems, Inc. ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Sun.
 */

#ifndef _JAVASOFT_JAWT_H_
#define _JAVASOFT_JAWT_H_

#include "jni.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * AWT native interface (new in JDK 1.3)
 *
 * The AWT native interface allows a native C or C++ application a means
 * by which to access native structures in AWT.  This is to facilitate moving
 * legacy C and C++ applications to Java and to target the needs of the
 * community who, at present, wish to do their own native rendering to canvases
 * for performance reasons.  Standard extensions such as Java3D also require a
 * means to access the underlying native data structures of AWT.
 *
 * There may be future extensions to this API depending on demand.
 *
 * A VM does not have to implement this API in order to pass the JCK.
 * It is recommended, however, that this API is implemented on VMs that support
 * standard extensions, such as Java3D.
 *
 * Since this is a native API, any program which uses it cannot be considered
 * 100% pure java.
 */

/*
 * AWT Native Drawing Surface (JAWT_DrawingSurface).
 *
 * For each platform, there is a native drawing surface structure.  This
 * platform-specific structure can be found in jawt_md.h.  It is recommended
 * that additional platforms follow the same model.  It is also recommended
 * that VMs on Microsoft Windows platforms and Solaris operating environment 
 * support the existing structures in jawt_md.h.
 *
 *******************
 * EXAMPLE OF USAGE:
 *******************
 *
 * In Miscrosoft Windows, a programmer wishes to access the HWND of a canvas 
 * to perform native rendering into it.  The programmer has declared the 
 * paint() method for their canvas subclass to be native:
 *
 *
 * MyCanvas.java:
 *
 * import java.awt.*;
 *
 * public class MyCanvas extends Canvas {
 *
 *     static {
 *         System.loadLibrary("mylib");
 *     }
 *
 *     public native void paint(Graphics g);
 * }
 *
 *
 * myfile.c:
 *
 * #include "jawt_md.h"
 * #include <assert.h>
 *
 * JNIEXPORT void JNICALL
 * Java_MyCanvas_paint(JNIEnv* env, jobject canvas, jobject graphics)
 * {
 *     JAWT awt;
 *     JAWT_DrawingSurface* ds;
 *     JAWT_DrawingSurfaceInfo* dsi;
 *     JAWT_Win32DrawingSurfaceInfo* dsi_win;
 *     jboolean result;
 *     jint lock;
 *
 *     // Get the AWT
 *     awt.version = JAWT_VERSION_1_3;
 *     result = JAWT_GetAWT(env, &awt);
 *     assert(result != JNI_FALSE);
 *
 *     // Get the drawing surface
 *     ds = awt.GetDrawingSurface(env, canvas);
 *     assert(ds != NULL);
 *
 *     // Lock the drawing surface
 *     lock = ds->Lock(ds);
 *     assert((lock & JAWT_LOCK_ERROR) == 0);
 *
 *     // Get the drawing surface info
 *     dsi = ds->GetDrawingSurfaceInfo(ds);
 *
 *     // Get the platform-specific drawing info
 *     dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
 *
 *     //////////////////////////////
 *     // !!! DO PAINTING HERE !!! //
 *     //////////////////////////////
 *
 *     // Free the drawing surface info
 *     ds->FreeDrawingSurfaceInfo(dsi);
 *
 *     // Unlock the drawing surface
 *     ds->Unlock(ds);
 *
 *     // Free the drawing surface
 *     awt.FreeDrawingSurface(ds);
 * }
 *
 */

/*
 * JAWT_Rectangle
 * Structure for a native rectangle.
 */
typedef struct jawt_Rectangle {
    jint x;
    jint y;
    jint width;
    jint height;
} JAWT_Rectangle;

struct jawt_DrawingSurface;

/*
 * JAWT_DrawingSurfaceInfo
 * Structure for containing the underlying drawing information of a component.
 */
typedef struct jawt_DrawingSurfaceInfo {
    /*
     * Pointer to the platform-specific information.  This can be safely
     * cast to a JAWT_Win32DrawingSurfaceInfo on Microsoft Windows or a
     * JAWT_X11DrawingSurfaceInfo on Solaris operating environment.  
     * See jawt_md.h for details.
     */
    void* platformInfo;
    /* Cached pointer to the underlying drawing surface */
    struct jawt_DrawingSurface* ds;
    /* Bounding rectangle of the drawing surface */
    JAWT_Rectangle bounds;
    /* Number of rectangles in the clip */
    jint clipSize;
    /* Clip rectangle array */
    JAWT_Rectangle* clip;
} JAWT_DrawingSurfaceInfo;

#define JAWT_LOCK_ERROR                 0x00000001
#define JAWT_LOCK_CLIP_CHANGED          0x00000002
#define JAWT_LOCK_BOUNDS_CHANGED        0x00000004
#define JAWT_LOCK_SURFACE_CHANGED       0x00000008

/*
 * JAWT_DrawingSurface
 * Structure for containing the underlying drawing information of a component.
 * All operations on a JAWT_DrawingSurface MUST be performed from the same
 * thread as the call to GetDrawingSurface.
 */
typedef struct jawt_DrawingSurface {
    /* Cached reference to the Java environment of the calling thread */
    JNIEnv* env;
    /* Cached reference to the target object */
    jobject target;
    /*
     * Lock the surface of the target component for native rendering.
     * When finished drawing, the surface must be unlocked with
     * Unlock().  This function returns a bitmask with one or more of the
     * following values:
     *
     * JAWT_LOCK_ERROR - When an error has occurred and the surface could not
     * be locked.
     *
     * JAWT_LOCK_CLIP_CHANGED - When the clip region has changed.
     *
     * JAWT_LOCK_BOUNDS_CHANGED - When the bounds of the surface have changed.
     *
     * JAWT_LOCK_SURFACE_CHANGED - When the surface itself has changed
     */
    jint (JNICALL *Lock)
        (struct jawt_DrawingSurface* ds);
    /*
     * Get the drawing surface info.
     * The value returned may be cached, but the values may change if
     * additional calls to Lock() or Unlock() are made.
     * Lock() must be called before this can return a valid value.
     * Returns NULL if an error has occurred.
     * When finished with the returned value, FreeDrawingSurfaceInfo must be
     * called.
     */
    JAWT_DrawingSurfaceInfo* (JNICALL *GetDrawingSurfaceInfo)
        (struct jawt_DrawingSurface* ds);
    /*
     * Free the drawing surface info.
     */
    void (JNICALL *FreeDrawingSurfaceInfo)
        (JAWT_DrawingSurfaceInfo* dsi);
    /* 
     * Unlock the drawing surface of the target component for native rendering.
     */
    void (JNICALL *Unlock)
        (struct jawt_DrawingSurface* ds);
} JAWT_DrawingSurface;

/*
 * JAWT
 * Structure for containing native AWT functions.
 */
typedef struct jawt {
    /*
     * Version of this structure.  This must always be set before
     * calling JAWT_GetAWT()
     */
    jint version;
    /*
     * Return a drawing surface from a target jobject.  This value
     * may be cached.
     * Returns NULL if an error has occurred.
     * Target must be a java.awt.Canvas.
     * FreeDrawingSurface() must be called when finished with the
     * returned JAWT_DrawingSurface.
     */
    JAWT_DrawingSurface* (JNICALL *GetDrawingSurface)
        (JNIEnv* env, jobject target);
    /*
     * Free the drawing surface allocated in GetDrawingSurface.
     */
    void (JNICALL *FreeDrawingSurface)
        (JAWT_DrawingSurface* ds);
} JAWT;

/*
 * Get the AWT native structure.  This function returns JNI_FALSE if
 * an error occurs.
 */
_JNI_IMPORT_OR_EXPORT_
jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt);

#define JAWT_VERSION_1_3 0x00010003

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* !_JAVASOFT_JAWT_H_ */

jawt_md.h (версия операционной среды Solaris/X11)

/*
 * @(#)jawt_md.h        1.2 99/05/27
 *
 * Copyright (c) 1999 Oracle and/or its affiliates.  All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Sun Microsystems, Inc. ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Sun.
 */

#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>
#include "jawt.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * X11-specific declarations for AWT native interface.
 * See notes in jawt.h for an example of use.
 */
typedef struct jawt_X11DrawingSurfaceInfo {
    Drawable drawable;
    Display* display;
    VisualID visualID;
    Colormap colormapID;
    int depth;
} JAWT_X11DrawingSurfaceInfo;

#ifdef __cplusplus
}
#endif

#endif /* !_JAVASOFT_JAWT_MD_H_ */

jawt_md.h (версия Microsoft Windows)

/*
 * @(#)jawt_md.h        1.2 99/05/27
 *
 * Copyright (c) 1999 Oracle and/or its affiliates.  All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Sun Microsystems, Inc. ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Sun.
 */

#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_

#include <windows.h>
#include "jawt.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Microsoft Windows specific declarations for AWT native interface.
 * See notes in jawt.h for an example of use.
 */
typedef struct jawt_Win32DrawingSurfaceInfo {
    /* Native window, DDB, or DIB handle */
    union {
        HWND hwnd;
        HBITMAP hbitmap;
        void* pbits;
    };
    /*
     * This HDC should always be used instead of the HDC returned from
     * BeginPaint() or any calls to GetDC().
     */
    HDC hdc;
    HPALETTE hpalette;
} JAWT_Win32DrawingSurfaceInfo;

#ifdef __cplusplus
}
#endif

#endif /* !_JAVASOFT_JAWT_MD_H_ */

Oracle и/или его филиалы Авторское право © 1993, 2011, Oracle и/или его филиалы. Все права защищены.
Свяжитесь с Нами