alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (JulesAATileGenerator.java)

This example Java source code file (JulesAATileGenerator.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

awt, basicstroke, cpu_cnt, enable_threading, geometry, growableintarray, idletilecache, julesaatilegenerator, julespathbuf, julestile, thread_begin, thread_min, threading, threads, tile_size, tile_size_fp, tiletrapcontainer, tileworker

The JulesAATileGenerator.java Java example source code

/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.java2d.jules;

import java.awt.*;
import java.awt.geom.*;
import java.util.concurrent.*;
import sun.java2d.pipe.*;
import sun.java2d.xr.*;

public class JulesAATileGenerator implements AATileGenerator {
    /* Threading stuff */
    final static ExecutorService rasterThreadPool =
                                          Executors.newCachedThreadPool();
    final static int CPU_CNT = Runtime.getRuntime().availableProcessors();

    final static boolean ENABLE_THREADING = false;
    final static int THREAD_MIN = 16;
    final static int THREAD_BEGIN = 16;

    IdleTileCache tileCache;
    TileWorker worker;
    boolean threaded = false;
    int rasterTileCnt;

    /* Tiling */
    final static int TILE_SIZE = 32;
    final static int TILE_SIZE_FP = 32 << 16;
    int left, right, top, bottom, width, height;
    int leftFP, topFP;
    int tileCnt, tilesX, tilesY;
    int currTilePos = 0;
    TrapezoidList traps;
    TileTrapContainer[] tiledTrapArray;
    JulesTile mainTile;

    public JulesAATileGenerator(Shape s, AffineTransform at, Region clip,
                                BasicStroke bs, boolean thin,
                                boolean normalize, int[] bbox) {
        JulesPathBuf buf = new JulesPathBuf();

        if (bs == null) {
            traps = buf.tesselateFill(s, at, clip);
        } else {
            traps = buf.tesselateStroke(s, bs, thin, false, true, at, clip);
        }

        calculateArea(bbox);
        bucketSortTraps();
        calculateTypicalAlpha();

        threaded = ENABLE_THREADING &&
                   rasterTileCnt >= THREAD_MIN && CPU_CNT >= 2;
        if (threaded) {
            tileCache = new IdleTileCache();
            worker = new TileWorker(this, THREAD_BEGIN, tileCache);
            rasterThreadPool.execute(worker);
        }

        mainTile = new JulesTile();
    }

    private static native long
        rasterizeTrapezoidsNative(long pixmanImagePtr, int[] traps,
                                  int[] trapPos, int trapCnt,
                                  byte[] buffer, int xOff, int yOff);

    private static native void freePixmanImgPtr(long pixmanImgPtr);

    private void calculateArea(int[] bbox) {
        tilesX = 0;
        tilesY = 0;
        tileCnt = 0;
        bbox[0] = 0;
        bbox[1] = 0;
        bbox[2] = 0;
        bbox[3] = 0;

        if (traps.getSize() > 0) {
            left = traps.getLeft();
            right = traps.getRight();
            top = traps.getTop();
            bottom = traps.getBottom();
            leftFP = left << 16;
            topFP = top << 16;

            bbox[0] = left;
            bbox[1] = top;
            bbox[2] = right;
            bbox[3] = bottom;

            width = right - left;
            height = bottom - top;

            if (width > 0 && height > 0) {
                tilesX = (int) Math.ceil(((double) width) / TILE_SIZE);
                tilesY = (int) Math.ceil(((double) height) / TILE_SIZE);
                tileCnt = tilesY * tilesX;
                tiledTrapArray = new TileTrapContainer[tileCnt];
            } else {
                // If there is no area touched by the traps, don't
                // render them.
                traps.setSize(0);
            }
        }
    }


    private void bucketSortTraps() {

        for (int i = 0; i < traps.getSize(); i++) {
            int top = traps.getTop(i) - XRUtils.XDoubleToFixed(this.top);
            int bottom = traps.getBottom(i) - topFP;
            int p1xLeft = traps.getP1XLeft(i) - leftFP;
            int p2xLeft = traps.getP2XLeft(i) - leftFP;
            int p1xRight = traps.getP1XRight(i) - leftFP;
            int p2xRight = traps.getP2XRight(i) - leftFP;

            int minLeft = Math.min(p1xLeft, p2xLeft);
            int maxRight = Math.max(p1xRight, p2xRight);

            maxRight = maxRight > 0 ? maxRight - 1 : maxRight;
            bottom = bottom > 0 ? bottom - 1 : bottom;

            int startTileY = top / TILE_SIZE_FP;
            int endTileY = bottom / TILE_SIZE_FP;
            int startTileX = minLeft / TILE_SIZE_FP;
            int endTileX = maxRight / TILE_SIZE_FP;

            for (int n = startTileY; n <= endTileY; n++) {

                for (int m = startTileX; m <= endTileX; m++) {
                    int trapArrayPos = n * tilesX + m;
                    TileTrapContainer trapTileList = tiledTrapArray[trapArrayPos];
                    if (trapTileList == null) {
                        trapTileList = new TileTrapContainer(new GrowableIntArray(1, 16));
                        tiledTrapArray[trapArrayPos] = trapTileList;
                    }

                    trapTileList.getTraps().addInt(i);
                }
            }
        }
    }

    public void getAlpha(byte[] tileBuffer, int offset, int rowstride) {
        JulesTile tile = null;

        if (threaded) {
            tile = worker.getPreRasterizedTile(currTilePos);
        }

        if (tile != null) {
            System.arraycopy(tile.getImgBuffer(), 0,
                             tileBuffer, 0, tileBuffer.length);
            tileCache.releaseTile(tile);
        } else {
            mainTile.setImgBuffer(tileBuffer);
            rasterizeTile(currTilePos, mainTile);
        }

        nextTile();
    }

    public void calculateTypicalAlpha() {
        rasterTileCnt = 0;

        for (int index = 0; index < tileCnt; index++) {

            TileTrapContainer trapCont = tiledTrapArray[index];
            if (trapCont != null) {
                GrowableIntArray trapList = trapCont.getTraps();

                int tileAlpha = 127;
                if (trapList == null || trapList.getSize() == 0) {
                    tileAlpha = 0;
                } else if (doTrapsCoverTile(trapList, index)) {
                    tileAlpha = 0xff;
                }

                if (tileAlpha == 127 || tileAlpha == 0xff) {
                    rasterTileCnt++;
                }

                trapCont.setTileAlpha(tileAlpha);
            }
        }
    }

    /*
     * Optimization for large fills. Foutunatly cairo does generate an y-sorted
     * list of trapezoids. This makes it quite simple to check whether a tile is
     * fully covered by traps by: - Checking whether the tile is fully covered by
     * traps vertically (trap 2 starts where trap 1 ended) - Checking whether all
     * traps cover the tile horizontally This also works, when a single tile
     * coveres the whole tile.
     */
    protected boolean doTrapsCoverTile(GrowableIntArray trapList, int tileIndex) {

        // Don't bother optimizing tiles with lots of traps, usually it won't
        // succeed anyway.
        if (trapList.getSize() > TILE_SIZE) {
            return false;
        }

        int tileStartX = getXPos(tileIndex) * TILE_SIZE_FP + leftFP;
        int tileStartY = getYPos(tileIndex) * TILE_SIZE_FP + topFP;
        int tileEndX = tileStartX + TILE_SIZE_FP;
        int tileEndY = tileStartY + TILE_SIZE_FP;

        // Check whether first tile covers the beginning of the tile vertically
        int firstTop = traps.getTop(trapList.getInt(0));
        int firstBottom = traps.getBottom(trapList.getInt(0));
        if (firstTop > tileStartY || firstBottom < tileStartY) {
            return false;
        }

        // Initialize lastBottom with top, in order to pass the checks for the
        // first iteration
        int lastBottom = firstTop;

        for (int i = 0; i < trapList.getSize(); i++) {
            int trapPos = trapList.getInt(i);
            if (traps.getP1XLeft(trapPos) > tileStartX ||
                traps.getP2XLeft(trapPos) > tileStartX ||
                traps.getP1XRight(trapPos) < tileEndX  ||
                traps.getP2XRight(trapPos) < tileEndX  ||
                 traps.getTop(trapPos) != lastBottom)
            {
                return false;
            }
            lastBottom = traps.getBottom(trapPos);
        }

        // When the last trap covered the tileEnd vertically, the tile is fully
        // covered
        return lastBottom >= tileEndY;
    }

    public int getTypicalAlpha() {
        if (tiledTrapArray[currTilePos] == null) {
            return 0;
        } else {
            return tiledTrapArray[currTilePos].getTileAlpha();
        }
    }

    public void dispose() {
        freePixmanImgPtr(mainTile.getPixmanImgPtr());

        if (threaded) {
            tileCache.disposeConsumerResources();
            worker.disposeConsumerResources();
        }
    }

    protected JulesTile rasterizeTile(int tileIndex, JulesTile tile) {
        int tileOffsetX = left + getXPos(tileIndex) * TILE_SIZE;
        int tileOffsetY = top + getYPos(tileIndex) * TILE_SIZE;
        TileTrapContainer trapCont = tiledTrapArray[tileIndex];
        GrowableIntArray trapList = trapCont.getTraps();

        if (trapCont.getTileAlpha() == 127) {
            long pixmanImgPtr =
                 rasterizeTrapezoidsNative(tile.getPixmanImgPtr(),
                                           traps.getTrapArray(),
                                           trapList.getArray(),
                                           trapList.getSize(),
                                           tile.getImgBuffer(),
                                           tileOffsetX, tileOffsetY);
            tile.setPixmanImgPtr(pixmanImgPtr);
        }

        tile.setTilePos(tileIndex);
        return tile;
    }

    protected int getXPos(int arrayPos) {
        return arrayPos % tilesX;
    }

    protected int getYPos(int arrayPos) {
        return arrayPos / tilesX;
    }

    public void nextTile() {
        currTilePos++;
    }

    public int getTileHeight() {
        return TILE_SIZE;
    }

    public int getTileWidth() {
        return TILE_SIZE;
    }

    public int getTileCount() {
        return tileCnt;
    }

    public TileTrapContainer getTrapContainer(int index) {
        return tiledTrapArray[index];
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java JulesAATileGenerator.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.