Obsah
1. Pohled pod kapotu JVM – práce s TTF fonty v knihovně SDLJava
2. Vykreslení textu vybraným fontem do samostatné bitmapy
3. Demonstrační příklad SDLTest40: vykreslení textu vybraným fontem do samostatné bitmapy
4. Pozadí textu: využití průhlednosti či vybrané konstantní barvy
5. Demonstrační příklad SDLTest41: vykreslení textu přes již dříve vykreslenou bitmapu
6. Demonstrační příklad SDLTest42: volba barvy pozadí textu
8. Demonstrační příklad SDLTest43: vykreslení textu s využitím antialiasingu
9. Repositář se zdrojovými kódy všech čtyř dnešních demonstračních příkladů
1. Práce s TTF fonty v knihovně SDLJava
Při programování grafických aplikací a her se v naprosté většině případů setkáme s nutností vykreslit na obrazovku nějaký text, ať již se jedná o titulek hry či o součást grafického uživatelského rozhraní aplikace (hlavní menu, nápověda atd.). V knihovně SDLJava existuje podpora pro vykreslování znaků, přičemž veškerá funkcionalita je ve skutečnosti zajištěna nativní knihovnou SDL_ttf verze 1.2 či 2.0, která navíc při své činnosti využívá další nativní knihovnu pojmenovanou (lib)FreeType (http://www.freetype.org/).
Obrázek 1: Hra Luola využívá knihovnu SDL i SDL_ttf.
Při instalaci knihovny SDLJava se kromě vlastního javovského archivu sdljava.jar vytvoří v pracovním adresáři i několik souborů obsahujících nativní části této knihovny. Jedním z těchto souborů je i libsdljava_ttf.so popř. sdljava_ttf.dll obsahující tenkou mezivrstvu mezi knihovnou SDLJava a nativní knihovnou libSDL_ttf. Pokud vám tedy nebudou dnešní demonstrační příklady pracovat korektně, je nutné zjistit, zda jsou všechny potřebné (nativní) knihovny skutečně nainstalovány. Pro běh demonstračních příkladů je taktéž nutné mít v pracovním adresáři umístěn font freesans.ttf dostupný na adrese http://www.fontspace.com/gnu-freefont/freesans (postačuje jen jediný uvedený soubor freesans.ttf či FreeSans.ttf – pozor na správné použití velkých a malých písmen v demonstračních příkladech v konstantě FONT_NAME!).
Obrázek 2: Scéna vykreslená dnešním prvním demonstračním příkladem.
2. Vykreslení textu vybraným fontem do samostatné bitmapy
Jak jsme si již řekli v předchozí kapitole, dokáže knihovna SDLJava pracovat s fonty typu TTF (True Type Font), v nichž jsou tvary jednotlivých znaků uloženy ve formě obrysů složených ze sekvence na sebe navazujících úseček a kvadratických Bézierových křivek. Ve skutečnosti se však v naprosté většině případů programátoři nemusí zabývat přesným algoritmem vykreslování jednotlivých znaků, což je ostatně dosti komplikované, především při menších velikostech znaků a použití tzv. hintingu. Díky třídám nabízených knihovnou SDLJava je možné jednoduše načíst vybraný soubor typu TTF s uvedením velikosti výsledného písma. Knihovna SDLJava se s využitím nativních částí SDL_ttf a FreeType sama postará o rasterizaci jednotlivých znaků, tj. o vykreslení a vyplnění již zmíněných úseček a Bézierových křivek představujících obrysy jednotlivých znaků. Základem při práci s písmy jsou třídy sdljava.ttf.SDLTTF a sdljava.ttf.SDLTrueTypeFont. Inicializace písma se provede následujícím způsobem:
// inicializace subsystemu SDL_ttf SDLTTF.init(); // instance tridy SDLTrueTypeFont nese jiz zpracovane informace fontu // vybrane velikosti final SDLTrueTypeFont font = SDLTTF.openFont("font.ttf", 36 /* velikost v pt */);
Následně je možné využít instanci třídy SDLTrueTypeFont pro vykreslení řetězce do samostatné (automaticky vytvořené) bitmapy, se kterou je možné pracovat jako s běžným spritem:
// vykreslit text do samostatne bitmapy SDLSurface bitmap = font.renderTextSolid("www.root.cz", new SDLColor(255, 95, 95)); // vypocitat umisteni bitmapy na obrazovce. final SDLRect rect = computePositionOnScreen(screen, bitmap); // provest operaci typu BitBLT bitmap.blitSurface(screen, rect); // nutno volat i v pripade, ze neni pouzit double buffering screen.updateRect(); screen.flip();
Při ukončování činnosti aplikace je vhodné provést i deinicializaci subsystému pro práci s fonty:
try { // uvolneni prostredku vyuzivanych subsytemem SDL_ttf. SDLTTF.quit(); } catch (SDLException e) { e.printStackTrace(); }
Obrázek 3: Scéna vykreslená dnešním prvním demonstračním příkladem (použit je odlišný font).
3. Demonstrační příklad SDLTest40: vykreslení textu vybraným fontem do samostatné bitmapy
Postup pro vykreslení řetězce popsaný v předchozí kapitole je použit v dnešním prvním demonstračním příkladu nazvaném SDLTest40, jehož zdrojový kód lze nalézt na této adrese. Nejprve je provedena inicializace knihovny SDLJava, posléze se inicializuje i systém pro práci s fonty a následně je vybraný font načten (měl by se nacházet v pracovním adresáři). Vykreslení celé scény (zde pouze jednořádkového textu) je realizováno v metodě drawOnScreen():
import sdljava.SDLMain; import sdljava.SDLException; import sdljava.event.SDLEvent; import sdljava.event.SDLKeyboardEvent; import sdljava.event.SDLKey; import sdljava.event.SDLQuitEvent; import sdljava.video.SDLColor; import sdljava.video.SDLRect; import sdljava.video.SDLSurface; import sdljava.video.SDLVideo; import sdljava.ttf.SDLTTF; import sdljava.ttf.SDLTrueTypeFont; import sdljava.x.swig.SDLPressedState; /** * Ctyricaty demonstracni priklad vyuzivajici knihovnu SDLjava. * * Ukazka vyuziti zakladnich moznosti tridy sdljava.ttf.SDLTTF. * * @author Pavel Tisnovsky */ public class SDLTest40 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 640; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 480; /** * Bitova hloubka vybraneho grafickeho rezimu. * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty) */ private static final int GFX_BPP = 0; /** * Jmeno souboru s fontem. */ private static final String FONT_NAME = "freesans.ttf"; //private static final String FONT_NAME = "mcgf.ttf"; //private static final String FONT_NAME = "aescr5b.ttf"; /** * Velikost pisma udavana v bodech. */ private static final int FONT_SIZE = 72; /** * Barva vykresleneho textu. */ private static final SDLColor FONT_COLOR = new SDLColor(255, 95, 95); /** * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani. */ private static SDLSurface initVideo() throws SDLException { final long flags = SDLVideo.SDL_DOUBLEBUF; return SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags); } /** * Smycka pro zpracovani udalosti. */ private static void eventLoop() throws SDLException { while (true) { // precist udalost z fronty SDLEvent event = SDLEvent.waitEvent(); // vyskok ze smycky pro zpracovani udalosti pri vyskytu // udalosti typu SDLQuitEvent if (event instanceof SDLQuitEvent) { return; } // stisk ci pusteni klavesy if (event instanceof SDLKeyboardEvent) { // pretypovani final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event; // symbol/kod klavesy final int symbol = keyEvent.getSym(); // ESC ukonci program if (symbol == SDLKey.SDLK_ESCAPE && keyEvent.getState() == SDLPressedState.PRESSED) { return; } } } } /** * Vykresleni bitmapy s textem na obrazovku (do okna aplikace). * * @param screen * framebuffer * @param font * font pouzity pri vykreslovani */ private static void drawOnScreen(SDLSurface screen, SDLTrueTypeFont font) throws SDLException { // vykreslit text do samostatne bitmapy SDLSurface bitmap = font.renderTextSolid("www.root.cz", FONT_COLOR); // vypocitat umisteni bitmapy na obrazovce. final SDLRect rect = computePositionOnScreen(screen, bitmap); // provest operaci typu BitBLT bitmap.blitSurface(screen, rect); // nutno volat i v pripade, ze neni pouzit double buffering screen.updateRect(); screen.flip(); } /** * Vypocitat umisteni bitmapy na obrazovce. * * @param screen * framebuffer * @param bitmap * bitmapa s pismem, ktera se ma na obrazovku vykreslit * @return obdelnik predstavujici pozici bitmapy na obrazovce */ private static SDLRect computePositionOnScreen(SDLSurface screen, SDLSurface bitmap) { // ziskat rozmery obrazovky i bitmapy final int screenWidth = screen.getWidth(); final int screenHeight = screen.getHeight(); final int bitmapWidth = bitmap.getWidth(); final int bitmapHeight = bitmap.getHeight(); // vypocitat umisteni bitmapy na obrazovce final int x = (screenWidth - bitmapWidth)>>1; final int y = (screenHeight - bitmapHeight)>>1; return new SDLRect(x, y, bitmapWidth, bitmapHeight); } /** * Spusteni ctyricateho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace knihovny SDLJava SDLMain.init(SDLMain.SDL_INIT_VIDEO); // inicializace subsystemu SDL_ttf SDLTTF.init(); // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani final SDLSurface screen = initVideo(); // instance tridy SDLTrueTypeFont nese jiz zpracovane informace fontu // vybrane velikosti final SDLTrueTypeFont font = SDLTTF.openFont(FONT_NAME, FONT_SIZE); // vykresleni sceny na obrazovku drawOnScreen(screen, font); // smycka pro zpracovani udalosti eventLoop(); } catch (Exception e) { e.printStackTrace(); } finally { try { // uvolneni prostredku vyuzivanych subsytemem SDL_ttf. SDLTTF.quit(); } catch (SDLException e) { e.printStackTrace(); } // musime obnovit puvodni graficky rezim // i v tom pripade, ze nastane nejaka vyjimka SDLMain.quit(); } } }
Obrázek 4: Scéna vykreslená dnešním prvním demonstračním příkladem (opět je použit odlišný font).
Skript pro překlad na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest40.java
Dávkový soubor pro překlad na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest40.java
Skript pro spuštění na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest40
Dávkový soubor pro spuštění na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest40
4. Pozadí textu: využití průhlednosti či vybrané konstantní barvy
Bitmapa, která je automaticky vytvořena při vykreslení fontu, může obsahovat buď průhlednou barvu pozadí (kde je průhlednost nastavena na 100%) nebo naopak zvolenou barvu. To, jaká možnost se při vykreslování využije, závisí na tom, zda se použije metoda SDLTrueTypeFont.renderTextSolid() nebo alternativní metoda SDLTrueTypeFont.renderTextShaded(). V prvním případě je vytvořena bitmapa s bitovou hloubkou 8bpp obsahující v místech, kde se nenachází žádný znak, zcela průhledné pixely. Při použití druhé metody jsou tyto pixely vyplněny zadanou barvou, ovšem vytvořená bitmapa bude mít stále shodnou bitovou hloubku 8bpp. Rozdíly mezi oběma vytvořenými bitmapami jsou patrné na následujících dvou obrázcích, u nichž byly texty (resp. přesněji řečeno bitmapy s texty) vykresleny přes již dříve vykreslenou bitmapu s načteným obrázkem:
Obrázek 5: Průhledné pozadí textu vykreslené demonstračním příkladem SDLTest41.
Obrázek 6: Neprůhledné pozadí textu vykreslené demonstračním příkladem SDLTest42.
5. Demonstrační příklad SDLTest41: vykreslení textu přes již dříve vykreslenou bitmapu
V dnešním druhém demonstračním příkladu pojmenovaném SDLTest41 je ukázáno, že se při zavolání metody SDLTrueTypeFont.renderTextSolid() skutečně vytvoří bitmapa obsahující průhledné pixely – pod textem je totiž zobrazen rastrový obrázek xscorch.bmp, který jsme již využili v několika předchozích demonstračních příkladech. Vlastní vykreslení obou bitmap je realizováno ve dvojici metod drawOnScreen() a drawBitmap():
/** * Vykresleni bitmapy na obrazovku. * * @param screen * framebuffer * @param bitmap * bitmapa, ktery se ma na obrazovku vykreslit */ private static void drawBitmap(SDLSurface screen, SDLSurface bitmap) throws SDLException { // vypocitat umisteni bitmapy na obrazovce. final SDLRect rect = computePositionOnScreen(screen, bitmap); // provest operaci typu BitBLT bitmap.blitSurface(screen, rect); } /** * Vykresleni podkladove bitmapy i bitmapy s textem na obrazovku (do okna aplikace). * * @param screen * framebuffer * @param font * font pouzity pri vykreslovani * @param bitmap * bitmapa, ktery se ma na obrazovku vykreslit */ private static void drawOnScreen(SDLSurface screen, SDLTrueTypeFont font, SDLSurface bitmap) throws SDLException { // vykreslit text do samostatne bitmapy SDLSurface textBitmap = font.renderTextSolid("www.root.cz", FONT_COLOR); // vykresleni podkladove bitmapy s obrazkem drawBitmap(screen, bitmap); // vykresleni bitmapy s textem drawBitmap(screen, textBitmap); // nutno volat i v pripade, ze neni pouzit double buffering screen.updateRect(); screen.flip(); }
Následuje výpis zdrojového kódu tohoto demonstračního příkladu:
import sdljava.SDLMain; import sdljava.SDLException; import sdljava.event.SDLEvent; import sdljava.event.SDLKeyboardEvent; import sdljava.event.SDLKey; import sdljava.event.SDLQuitEvent; import sdljava.video.SDLColor; import sdljava.video.SDLRect; import sdljava.video.SDLSurface; import sdljava.video.SDLVideo; import sdljava.ttf.SDLTTF; import sdljava.ttf.SDLTrueTypeFont; import sdljava.x.swig.SDLPressedState; /** * Ctyricaty prvni demonstracni priklad vyuzivajici knihovnu SDLjava. * * Ukazka vyuziti zakladnich moznosti tridy sdljava.ttf.SDLTTF. * Pod textem je vykreslena podkladova bitmapa s obrazkem. * Text je vykreslen metodou SDLTrueTypeFont.renderTextSolid() * * @author Pavel Tisnovsky */ public class SDLTest41 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 640; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 480; /** * Bitova hloubka vybraneho grafickeho rezimu. * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty) */ private static final int GFX_BPP = 0; /** * Jmeno souboru s fontem. */ private static final String FONT_NAME = "freesans.ttf"; //private static final String FONT_NAME = "mcgf.ttf"; //private static final String FONT_NAME = "aescr5b.ttf"; /** * Velikost pisma udavana v bodech. */ private static final int FONT_SIZE = 72; /** * Barva vykresleneho textu. */ private static final SDLColor FONT_COLOR = new SDLColor(95, 192, 95); /** * Nazev bitmapy, ktera se ma nacist a nasledne zobrazit. */ private static final String INPUT_IMAGE_NAME = "xscorch.bmp"; /** * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani. */ private static SDLSurface initVideo() throws SDLException { final long flags = SDLVideo.SDL_DOUBLEBUF; return SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags); } /** * Smycka pro zpracovani udalosti. */ private static void eventLoop() throws SDLException { while (true) { // precist udalost z fronty SDLEvent event = SDLEvent.waitEvent(); // vyskok ze smycky pro zpracovani udalosti pri vyskytu // udalosti typu SDLQuitEvent if (event instanceof SDLQuitEvent) { return; } // stisk ci pusteni klavesy if (event instanceof SDLKeyboardEvent) { // pretypovani final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event; // symbol/kod klavesy final int symbol = keyEvent.getSym(); // ESC ukonci program if (symbol == SDLKey.SDLK_ESCAPE && keyEvent.getState() == SDLPressedState.PRESSED) { return; } } } } /** * Vykresleni bitmapy na obrazovku. * * @param screen * framebuffer * @param bitmap * bitmapa, ktery se ma na obrazovku vykreslit */ private static void drawBitmap(SDLSurface screen, SDLSurface bitmap) throws SDLException { // vypocitat umisteni bitmapy na obrazovce. final SDLRect rect = computePositionOnScreen(screen, bitmap); // provest operaci typu BitBLT bitmap.blitSurface(screen, rect); } /** * Vykresleni podkladove bitmapy i bitmapy s textem na obrazovku (do okna aplikace). * * @param screen * framebuffer * @param font * font pouzity pri vykreslovani * @param bitmap * bitmapa, ktery se ma na obrazovku vykreslit */ private static void drawOnScreen(SDLSurface screen, SDLTrueTypeFont font, SDLSurface bitmap) throws SDLException { // vykreslit text do samostatne bitmapy SDLSurface textBitmap = font.renderTextSolid("www.root.cz", FONT_COLOR); // vykresleni podkladove bitmapy s obrazkem drawBitmap(screen, bitmap); // vykresleni bitmapy s textem drawBitmap(screen, textBitmap); // nutno volat i v pripade, ze neni pouzit double buffering screen.updateRect(); screen.flip(); } /** * Vypocitat umisteni bitmapy na obrazovce. * * @param screen * framebuffer * @param bitmap * bitmapa s pismem, ktera se ma na obrazovku vykreslit * @return obdelnik predstavujici pozici bitmapy na obrazovce */ private static SDLRect computePositionOnScreen(SDLSurface screen, SDLSurface bitmap) { // ziskat rozmery obrazovky i bitmapy final int screenWidth = screen.getWidth(); final int screenHeight = screen.getHeight(); final int bitmapWidth = bitmap.getWidth(); final int bitmapHeight = bitmap.getHeight(); // vypocitat umisteni bitmapy na obrazovce final int x = (screenWidth - bitmapWidth)>>1; final int y = (screenHeight - bitmapHeight)>>1; return new SDLRect(x, y, bitmapWidth, bitmapHeight); } /** * Spusteni ctyricateho prvniho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace knihovny SDLJava SDLMain.init(SDLMain.SDL_INIT_VIDEO); // inicializace subsystemu SDL_ttf SDLTTF.init(); // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani final SDLSurface screen = initVideo(); // nacteni bitmapy z externiho souboru final SDLSurface bitmap = SDLVideo.loadBMP(INPUT_IMAGE_NAME); // instance tridy SDLTrueTypeFont nese jiz zpracovane informace fontu // vybrane velikosti final SDLTrueTypeFont font = SDLTTF.openFont(FONT_NAME, FONT_SIZE); // vykresleni sceny na obrazovku drawOnScreen(screen, font, bitmap); // smycka pro zpracovani udalosti eventLoop(); } catch (Exception e) { e.printStackTrace(); } finally { try { // uvolneni prostredku vyuzivanych subsytemem SDL_ttf. SDLTTF.quit(); } catch (SDLException e) { e.printStackTrace(); } // musime obnovit puvodni graficky rezim // i v tom pripade, ze nastane nejaka vyjimka SDLMain.quit(); } } }
Skript pro překlad na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest41.java
Dávkový soubor pro překlad na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest41.java
Skript pro spuštění na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest41
Dávkový soubor pro spuštění na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest41
6. Demonstrační příklad SDLTest42: volba barvy pozadí textu
V demonstračním příkladu SDLTest42, jehož zdrojový kód je vypsán pod tímto odstavcem, se namísto metody SDLTrueTypeFont.renderTextSolid() používá pro výpis textu do bitmapy metoda SDLTrueTypeFont.renderTextShaded(); žádné další změny oproti předchozímu příkladu SDLTest41 zde nebyly provedeny:
import sdljava.SDLMain; import sdljava.SDLException; import sdljava.event.SDLEvent; import sdljava.event.SDLKeyboardEvent; import sdljava.event.SDLKey; import sdljava.event.SDLQuitEvent; import sdljava.video.SDLColor; import sdljava.video.SDLRect; import sdljava.video.SDLSurface; import sdljava.video.SDLVideo; import sdljava.ttf.SDLTTF; import sdljava.ttf.SDLTrueTypeFont; import sdljava.x.swig.SDLPressedState; /** * Ctyricaty druhy demonstracni priklad vyuzivajici knihovnu SDLjava. * * Ukazka vyuziti zakladnich moznosti tridy sdljava.ttf.SDLTTF. * Pod textem je vykreslena podkladova bitmapa s obrazkem. * Text je vykreslen metodou SDLTrueTypeFont.renderTextShaded(). * * @author Pavel Tisnovsky */ public class SDLTest42 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 640; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 480; /** * Bitova hloubka vybraneho grafickeho rezimu. * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty) */ private static final int GFX_BPP = 0; /** * Jmeno souboru s fontem. */ private static final String FONT_NAME = "freesans.ttf"; //private static final String FONT_NAME = "mcgf.ttf"; //private static final String FONT_NAME = "aescr5b.ttf"; /** * Velikost pisma udavana v bodech. */ private static final int FONT_SIZE = 72; /** * Barva vykresleneho textu. */ private static final SDLColor FONT_COLOR = new SDLColor(95, 192, 95); /** * Barva pozadi vykresleneho textu. */ private static final SDLColor BACKGROUND_COLOR = new SDLColor(32, 32, 32); /** * Nazev bitmapy, ktera se ma nacist a nasledne zobrazit. */ private static final String INPUT_IMAGE_NAME = "xscorch.bmp"; /** * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani. */ private static SDLSurface initVideo() throws SDLException { final long flags = SDLVideo.SDL_DOUBLEBUF; return SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags); } /** * Smycka pro zpracovani udalosti. */ private static void eventLoop() throws SDLException { while (true) { // precist udalost z fronty SDLEvent event = SDLEvent.waitEvent(); // vyskok ze smycky pro zpracovani udalosti pri vyskytu // udalosti typu SDLQuitEvent if (event instanceof SDLQuitEvent) { return; } // stisk ci pusteni klavesy if (event instanceof SDLKeyboardEvent) { // pretypovani final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event; // symbol/kod klavesy final int symbol = keyEvent.getSym(); // ESC ukonci program if (symbol == SDLKey.SDLK_ESCAPE && keyEvent.getState() == SDLPressedState.PRESSED) { return; } } } } /** * Vykresleni bitmapy na obrazovku. * * @param screen * framebuffer * @param bitmap * bitmapa, ktery se ma na obrazovku vykreslit */ private static void drawBitmap(SDLSurface screen, SDLSurface bitmap) throws SDLException { // vypocitat umisteni bitmapy na obrazovce. final SDLRect rect = computePositionOnScreen(screen, bitmap); // provest operaci typu BitBLT bitmap.blitSurface(screen, rect); } /** * Vykresleni podkladove bitmapy i bitmapy s textem na obrazovku (do okna aplikace). * * @param screen * framebuffer * @param font * font pouzity pri vykreslovani * @param bitmap * bitmapa, ktery se ma na obrazovku vykreslit */ private static void drawOnScreen(SDLSurface screen, SDLTrueTypeFont font, SDLSurface bitmap) throws SDLException { // vykreslit text do samostatne bitmapy SDLSurface textBitmap = font.renderTextShaded("www.root.cz", FONT_COLOR, BACKGROUND_COLOR); // vykresleni podkladove bitmapy s obrazkem drawBitmap(screen, bitmap); // vykresleni bitmapy s textem drawBitmap(screen, textBitmap); // nutno volat i v pripade, ze neni pouzit double buffering screen.updateRect(); screen.flip(); } /** * Vypocitat umisteni bitmapy na obrazovce. * * @param screen * framebuffer * @param bitmap * bitmapa s pismem, ktera se ma na obrazovku vykreslit * @return obdelnik predstavujici pozici bitmapy na obrazovce */ private static SDLRect computePositionOnScreen(SDLSurface screen, SDLSurface bitmap) { // ziskat rozmery obrazovky i bitmapy final int screenWidth = screen.getWidth(); final int screenHeight = screen.getHeight(); final int bitmapWidth = bitmap.getWidth(); final int bitmapHeight = bitmap.getHeight(); // vypocitat umisteni bitmapy na obrazovce final int x = (screenWidth - bitmapWidth)>>1; final int y = (screenHeight - bitmapHeight)>>1; return new SDLRect(x, y, bitmapWidth, bitmapHeight); } /** * Spusteni ctyricateho druheho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace knihovny SDLJava SDLMain.init(SDLMain.SDL_INIT_VIDEO); // inicializace subsystemu SDL_ttf SDLTTF.init(); // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani final SDLSurface screen = initVideo(); // nacteni bitmapy z externiho souboru final SDLSurface bitmap = SDLVideo.loadBMP(INPUT_IMAGE_NAME); // instance tridy SDLTrueTypeFont nese jiz zpracovane informace fontu // vybrane velikosti final SDLTrueTypeFont font = SDLTTF.openFont(FONT_NAME, FONT_SIZE); // vykresleni sceny na obrazovku drawOnScreen(screen, font, bitmap); // smycka pro zpracovani udalosti eventLoop(); } catch (Exception e) { e.printStackTrace(); } finally { try { // uvolneni prostredku vyuzivanych subsytemem SDL_ttf. SDLTTF.quit(); } catch (SDLException e) { e.printStackTrace(); } // musime obnovit puvodni graficky rezim // i v tom pripade, ze nastane nejaka vyjimka SDLMain.quit(); } } }
Skript pro překlad na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest42.java
Dávkový soubor pro překlad na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest42.java
Skript pro spuštění na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest42
Dávkový soubor pro spuštění na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest42
7. Fonty a antialiasing
Při vykreslování textu s využitím výše popsaných metod SDLTrueTypeFont.renderTextSolid() i SDLTrueTypeFont.renderTextShaded() se vždy vytvoří bitmapa s bitovou hloubkou 8bpp. Samotné vykreslování takového bitmapy s použitím nám již známé metody SDLSurface.blitSurface() je velmi rychlé a i samotný způsob uložení bitmapy v paměti je poměrně efektivní, ovšem na druhou stranu zde neexistuje podpora pro skutečný antialiasing textů, takže šikmé tahy znaků budou vykazovat typické „schody“. V případě, že je antialiasing nutné použít (což nemusí být případ hry, kde se většinou upřednostňuje rychlejší vykreslování před kvalitou!), použije se metoda SDLTrueTypeFont.renderTextBlended(), která vytvoří bitmapu s hloubkou 32bpp a tím pádem i s plnohodnotným osmibitovým alfa kanálem. A právě alfa kanál je využit při antialiasingu, zejména při rasterizaci okrajů písma (zde budou použity pixely s variabilní průhledností):
Obrázek 7: Text vykreslený bez použití antialiasingu.
Obrázek 8: Text vykreslený s využitím antialiasingu.
Nevýhody použití metody SDLTrueTypeFont.renderTextBlended() jsou tři: pomalejší vykreslování výsledné bitmapy metodou SDLSurface.blitSurface(), neboť je nutné provádět výpočet průhlednosti s každým pixelem (násobení!); větší paměťové nároky (projeví se při meziukládání bitmap) a taktéž problematická práce s těmito bitmapami ve chvíli, kdy není nastaven celoobrazovkový grafický režim s hloubkou 24bpp či 32bpp – a tyto režimy se v mnoha hrách nepoužívají, právě z důvodu větších nároků při práci s grafikou (přesun větších bitmap při operaci BitBlt atd.). Je tedy nutné pečlivě zvážit, kterou metodou se budou texty do (herních) scén vykreslovat a mnohdy převáží sice méně kvalitní, ale zato rychlejší rendering textů metodou SDLTrueTypeFont.renderTextSolid().
8. Demonstrační příklad SDLTest43: vykreslení textu s využitím antialiasingu
Vykreslení textu s využitím metody SDLTrueTypeFont.renderTextBlended() a tím pádem s využitím antialiasingu je použito v dnešním čtvrtém a současně i posledním demonstračním příkladu pojmenovaném SDLTest43. V tomto příkladu je pod vlastním textem (bitmapou s textem) opět zobrazena podkladová bitmapa, aby bylo patrné, jakým způsobem se průhledné a poloprůhledné pixely překreslí přes již dříve vykreslený obrázek na pozadí:
import sdljava.SDLMain; import sdljava.SDLException; import sdljava.event.SDLEvent; import sdljava.event.SDLKeyboardEvent; import sdljava.event.SDLKey; import sdljava.event.SDLQuitEvent; import sdljava.video.SDLColor; import sdljava.video.SDLRect; import sdljava.video.SDLSurface; import sdljava.video.SDLVideo; import sdljava.ttf.SDLTTF; import sdljava.ttf.SDLTrueTypeFont; import sdljava.x.swig.SDLPressedState; /** * Ctyricaty treti demonstracni priklad vyuzivajici knihovnu SDLjava. * * Ukazka vyuziti zakladnich moznosti tridy sdljava.ttf.SDLTTF. * Pod textem je vykreslena podkladova bitmapa s obrazkem. * Text je vykreslen metodou SDLTrueTypeFont.renderTextBlended(). * * @author Pavel Tisnovsky */ public class SDLTest43 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 640; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 480; /** * Bitova hloubka vybraneho grafickeho rezimu. * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty) */ private static final int GFX_BPP = 0; /** * Jmeno souboru s fontem. */ //private static final String FONT_NAME = "freesans.ttf"; //private static final String FONT_NAME = "mcgf.ttf"; private static final String FONT_NAME = "aescr5b.ttf"; /** * Velikost pisma udavana v bodech. */ private static final int FONT_SIZE = 72; /** * Barva vykresleneho textu. */ private static final SDLColor FONT_COLOR = new SDLColor(95, 192, 95); /** * Nazev bitmapy, ktera se ma nacist a nasledne zobrazit. */ private static final String INPUT_IMAGE_NAME = "xscorch.bmp"; /** * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani. */ private static SDLSurface initVideo() throws SDLException { final long flags = SDLVideo.SDL_DOUBLEBUF; return SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags); } /** * Smycka pro zpracovani udalosti. */ private static void eventLoop() throws SDLException { while (true) { // precist udalost z fronty SDLEvent event = SDLEvent.waitEvent(); // vyskok ze smycky pro zpracovani udalosti pri vyskytu // udalosti typu SDLQuitEvent if (event instanceof SDLQuitEvent) { return; } // stisk ci pusteni klavesy if (event instanceof SDLKeyboardEvent) { // pretypovani final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event; // symbol/kod klavesy final int symbol = keyEvent.getSym(); // ESC ukonci program if (symbol == SDLKey.SDLK_ESCAPE && keyEvent.getState() == SDLPressedState.PRESSED) { return; } } } } /** * Vykresleni bitmapy na obrazovku. * * @param screen * framebuffer * @param bitmap * bitmapa, ktery se ma na obrazovku vykreslit */ private static void drawBitmap(SDLSurface screen, SDLSurface bitmap) throws SDLException { // vypocitat umisteni bitmapy na obrazovce. final SDLRect rect = computePositionOnScreen(screen, bitmap); // provest operaci typu BitBLT bitmap.blitSurface(screen, rect); } /** * Vykresleni podkladove bitmapy i bitmapy s textem na obrazovku (do okna aplikace). * * @param screen * framebuffer * @param font * font pouzity pri vykreslovani * @param bitmap * bitmapa, ktery se ma na obrazovku vykreslit */ private static void drawOnScreen(SDLSurface screen, SDLTrueTypeFont font, SDLSurface bitmap) throws SDLException { // vykreslit text do samostatne bitmapy SDLSurface textBitmap = font.renderTextBlended("www.root.cz", FONT_COLOR); // vykresleni podkladove bitmapy s obrazkem drawBitmap(screen, bitmap); // vykresleni bitmapy s textem drawBitmap(screen, textBitmap); // nutno volat i v pripade, ze neni pouzit double buffering screen.updateRect(); screen.flip(); } /** * Vypocitat umisteni bitmapy na obrazovce. * * @param screen * framebuffer * @param bitmap * bitmapa s pismem, ktera se ma na obrazovku vykreslit * @return obdelnik predstavujici pozici bitmapy na obrazovce */ private static SDLRect computePositionOnScreen(SDLSurface screen, SDLSurface bitmap) { // ziskat rozmery obrazovky i bitmapy final int screenWidth = screen.getWidth(); final int screenHeight = screen.getHeight(); final int bitmapWidth = bitmap.getWidth(); final int bitmapHeight = bitmap.getHeight(); // vypocitat umisteni bitmapy na obrazovce final int x = (screenWidth - bitmapWidth)>>1; final int y = (screenHeight - bitmapHeight)>>1; return new SDLRect(x, y, bitmapWidth, bitmapHeight); } /** * Spusteni ctyricateho tretiho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace knihovny SDLJava SDLMain.init(SDLMain.SDL_INIT_VIDEO); // inicializace subsystemu SDL_ttf SDLTTF.init(); // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani final SDLSurface screen = initVideo(); // nacteni bitmapy z externiho souboru final SDLSurface bitmap = SDLVideo.loadBMP(INPUT_IMAGE_NAME); // instance tridy SDLTrueTypeFont nese jiz zpracovane informace fontu // vybrane velikosti final SDLTrueTypeFont font = SDLTTF.openFont(FONT_NAME, FONT_SIZE); // vykresleni sceny na obrazovku drawOnScreen(screen, font, bitmap); // smycka pro zpracovani udalosti eventLoop(); } catch (Exception e) { e.printStackTrace(); } finally { try { // uvolneni prostredku vyuzivanych subsytemem SDL_ttf. SDLTTF.quit(); } catch (SDLException e) { e.printStackTrace(); } // musime obnovit puvodni graficky rezim // i v tom pripade, ze nastane nejaka vyjimka SDLMain.quit(); } } }
Obrázek 9: Scéna vykreslená dnešním čtvrtým demonstračním příkladem.
Skript pro překlad na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest43.java
Dávkový soubor pro překlad na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest43.java
Skript pro spuštění na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest43
Dávkový soubor pro spuštění na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest43
Obrázek 10: Scéna vykreslená dnešním čtvrtým demonstračním příkladem.
9. Repositář se zdrojovými kódy všech čtyř dnešních demonstračních příkladů
Všechny čtyři dnes popsané demonstrační příklady byly společně s podpůrnými skripty určenými pro jejich překlad a následné spuštění uloženy do Mercurial repositáře dostupného na adrese http://icedtea.classpath.org/people/ptisnovs/jvm-tools/. Podobně jako tomu bylo i v předchozích devíti dílech tohoto seriálu, i ke dnešním příkladům jsou přiloženy skripty využitelné pro jejich překlad a spuštění. Navíc byly přidány i skripty využitelné ve Windows:
10. Odkazy na Internetu
- SDLJava: package sdljava.ttf
http://sdljava.sourceforge.net/docs/api/sdljava/ttf/package-summary.html#package_description - SDLJava: class sdljava.ttf.SDLTTF
http://sdljava.sourceforge.net/docs/api/sdljava/ttf/SDLTTF.html - SDLJava: class sdljava.ttf.SDLTrueTypeFont
http://sdljava.sourceforge.net/docs/api/sdljava/ttf/SDLTrueTypeFont.html - SDL_ttf Documentation
http://www.libsdl.org/projects/SDL_ttf/docs/ - SDL_ttf 2.0 (není prozatím součástí SDLJava)
http://www.libsdl.org/projects/SDL_ttf/ - SDL_ttf doc
http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_frame.html - SDL 1.2 Documentation: SDL_Surface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsurface.html - SDL 1.2 Documentation: SDL_PixelFormat
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlpixelformat.html - SDL 1.2 Documentation: SDL_LockSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdllocksurface.html - SDL 1.2 Documentation: SDL_UnlockSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlunlocksurface.html - SDL 1.2 Documentation: SDL_LoadBMP
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlloadbmp.html - SDL 1.2 Documentation: SDL_SaveBMP
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsavebmp.html - SDL 1.2 Documentation: SDL_BlitSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlblitsurface.html - SDL 1.2 Documentation: SDL_VideoInfo
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlvideoinfo.html - SDL 1.2 Documentation: SDL_GetVideoInfo
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlgetvideoinfo.html - glDrawArrays
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawArrays.xml - glDrawElements
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElements.xml - glDrawArraysInstanced
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawArraysInstanced.xml - glDrawElementsInstanced
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElementsInstanced.xml - Root.cz: Seriál Grafická knihovna OpenGL
http://www.root.cz/serialy/graficka-knihovna-opengl/ - Root.cz: Seriál Tvorba přenositelných grafických aplikací využívajících knihovnu GLUT
http://www.root.cz/serialy/tvorba-prenositelnych-grafickych-aplikaci-vyuzivajicich-knihovnu-glut/ - Best Practices for Working with Vertex Data
https://developer.apple.com/library/ios/documentation/3ddrawing/conceptual/opengles_programmingguide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html - Class BufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/image/BufferStrategy.html - Class Graphics
http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/Graphics.html - Double Buffering and Page Flipping
http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html - BufferStrategy and BufferCapabilities
http://docs.oracle.com/javase/tutorial/extra/fullscreen/bufferstrategy.html - Java:Tutorials:Double Buffering
http://content.gpwiki.org/index.php/Java:Tutorials:Double_Buffering - Double buffer in standard Java AWT
http://www.codeproject.com/Articles/2136/Double-buffer-in-standard-Java-AWT - Java 2D: Hardware Accelerating – Part 1 – Volatile Images
http://www.javalobby.org/forums/thread.jspa?threadID=16840&tstart=0 - Java 2D: Hardware Accelerating – Part 2 – Buffer Strategies
http://www.javalobby.org/java/forums/t16867.html - How does paintComponent work?
http://stackoverflow.com/questions/15544549/how-does-paintcomponent-work - A Swing Architecture Overview
http://www.oracle.com/technetwork/java/architecture-142923.html - Class javax.swing.JComponent
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html - Class java.awt.Component
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.html - Class java.awt.Component.BltBufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.BltBufferStrategy.html - Class java.awt.Component.FlipBufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.FlipBufferStrategy.html - Metoda java.awt.Component.isDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.html#isDoubleBuffered() - Metoda javax.swing.JComponent.isDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#isDoubleBuffered() - Metoda javax.swing.JComponent.setDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#setDoubleBuffered(boolean) - Javadoc – třída GraphicsDevice
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsDevice.html - Javadoc – třída GraphicsEnvironment
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsEnvironment.html - Javadoc – třída GraphicsConfiguration
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsConfiguration.html - Javadoc – třída DisplayMode
http://docs.oracle.com/javase/7/docs/api/java/awt/DisplayMode.html - Lesson: Full-Screen Exclusive Mode API
http://docs.oracle.com/javase/tutorial/extra/fullscreen/ - Full-Screen Exclusive Mode
http://docs.oracle.com/javase/tutorial/extra/fullscreen/exclusivemode.html - Display Mode
http://docs.oracle.com/javase/tutorial/extra/fullscreen/displaymode.html - Using the Full-Screen Exclusive Mode API in Java
http://www.developer.com/java/other/article.php/3609776/Using-the-Full-Screen-Exclusive-Mode-API-in-Java.htm - Java quick guide: JVM Instruction Set (tabulka všech instrukcí JVM)
http://www.mobilefish.com/tutorials/java/java_quickguide_jvm_instruction_set.html - The JVM Instruction Set
http://mpdeboer.home.xs4all.nl/scriptie/node14.html - MultiMedia eXtensions
http://softpixel.com/~cwright/programming/simd/mmx.phpi - SSE (Streaming SIMD Extentions)
http://www.songho.ca/misc/sse/sse.html - Timothy A. Chagnon: SSE and SSE2
http://www.cs.drexel.edu/~tc365/mpi-wht/sse.pdf - Intel corporation: Extending the Worldr's Most Popular Processor Architecture
http://download.intel.com/technology/architecture/new-instructions-paper.pdf - SIMD architectures:
http://arstechnica.com/old/content/2000/03/simd.ars/ - GC safe-point (or safepoint) and safe-region
http://xiao-feng.blogspot.cz/2008/01/gc-safe-point-and-safe-region.html - Safepoints in HotSpot JVM
http://blog.ragozin.info/2012/10/safepoints-in-hotspot-jvm.html - Java theory and practice: Synchronization optimizations in Mustang
http://www.ibm.com/developerworks/java/library/j-jtp10185/ - How to build hsdis
http://hg.openjdk.java.net/jdk7/hotspot/hotspot/file/tip/src/share/tools/hsdis/README - Java SE 6 Performance White Paper
http://www.oracle.com/technetwork/java/6-performance-137236.html - Lukas Stadler's Blog
http://classparser.blogspot.cz/2010/03/hsdis-i386dll.html - How to build hsdis-amd64.dll and hsdis-i386.dll on Windows
http://dropzone.nfshost.com/hsdis.htm - PrintAssembly
https://wikis.oracle.com/display/HotSpotInternals/PrintAssembly - The Java Virtual Machine Specification: 3.14. Synchronization
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.14 - The Java Virtual Machine Specification: 8.3.1.4. volatile Fields
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.4 - The Java Virtual Machine Specification: 17.4. Memory Model
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4 - The Java Virtual Machine Specification: 17.7. Non-atomic Treatment of double and long
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7 - Open Source ByteCode Libraries in Java
http://java-source.net/open-source/bytecode-libraries - ASM Home page
http://asm.ow2.org/ - Seznam nástrojů využívajících projekt ASM
http://asm.ow2.org/users.html - ObjectWeb ASM (Wikipedia)
http://en.wikipedia.org/wiki/ObjectWeb_ASM - Java Bytecode BCEL vs ASM
http://james.onegoodcookie.com/2005/10/26/java-bytecode-bcel-vs-asm/ - BCEL Home page
http://commons.apache.org/bcel/ - Byte Code Engineering Library (před verzí 5.0)
http://bcel.sourceforge.net/ - Byte Code Engineering Library (verze >= 5.0)
http://commons.apache.org/proper/commons-bcel/ - BCEL Manual
http://commons.apache.org/bcel/manual.html - Byte Code Engineering Library (Wikipedia)
http://en.wikipedia.org/wiki/BCEL - BCEL Tutorial
http://www.smfsupport.com/support/java/bcel-tutorial!/ - Bytecode Engineering
http://book.chinaunix.net/special/ebook/Core_Java2_Volume2AF/0131118269/ch13lev1sec6.html - Bytecode Outline plugin for Eclipse (screenshoty + info)
http://asm.ow2.org/eclipse/index.html - Javassist
http://www.jboss.org/javassist/ - Byteman
http://www.jboss.org/byteman - Java programming dynamics, Part 7: Bytecode engineering with BCEL
http://www.ibm.com/developerworks/java/library/j-dyn0414/ - The JavaTM Virtual Machine Specification, Second Edition
http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html - The class File Format
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html - javap – The Java Class File Disassembler
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/javap.html - javap-java-1.6.0-openjdk(1) – Linux man page
http://linux.die.net/man/1/javap-java-1.6.0-openjdk - Using javap
http://www.idevelopment.info/data/Programming/java/miscellaneous_java/Using_javap.html - Examine class files with the javap command
http://www.techrepublic.com/article/examine-class-files-with-the-javap-command/5815354 - aspectj (Eclipse)
http://www.eclipse.org/aspectj/ - Aspect-oriented programming (Wikipedia)
http://en.wikipedia.org/wiki/Aspect_oriented_programming - AspectJ (Wikipedia)
http://en.wikipedia.org/wiki/AspectJ - EMMA: a free Java code coverage tool
http://emma.sourceforge.net/ - Cobertura
http://cobertura.sourceforge.net/ - jclasslib bytecode viewer
http://www.ej-technologies.com/products/jclasslib/overview.html