2370N/A/*
2685N/A * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2370N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2370N/A *
2370N/A * This code is free software; you can redistribute it and/or modify it
2370N/A * under the terms of the GNU General Public License version 2 only, as
2685N/A * published by the Free Software Foundation. Oracle designates this
2370N/A * particular file as subject to the "Classpath" exception as provided
2685N/A * by Oracle in the LICENSE file that accompanied this code.
2370N/A *
2370N/A * This code is distributed in the hope that it will be useful, but WITHOUT
2370N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2370N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2370N/A * version 2 for more details (a copy is included in the LICENSE file that
2370N/A * accompanied this code).
2370N/A *
2370N/A * You should have received a copy of the GNU General Public License version
2370N/A * 2 along with this work; if not, write to the Free Software Foundation,
2370N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2370N/A *
2685N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2685N/A * or visit www.oracle.com if you need additional information or have any
2685N/A * questions.
2370N/A */
2370N/A
2370N/Apackage sun.font;
2370N/A
2370N/Aimport java.io.*;
2370N/A
2370N/A/**
2370N/A * Stores glyph-related data, used in the pure-java glyphcache.
2370N/A *
2370N/A * @author Clemens Eisserer
2370N/A */
2370N/A
2370N/Apublic class XRGlyphCacheEntry {
2370N/A long glyphInfoPtr;
2370N/A
2370N/A int lastUsed;
2370N/A boolean pinned;
2370N/A
2370N/A int xOff;
2370N/A int yOff;
2370N/A
2370N/A int glyphSet;
2370N/A
2370N/A public XRGlyphCacheEntry(long glyphInfoPtr, GlyphList gl) {
2370N/A this.glyphInfoPtr = glyphInfoPtr;
2370N/A
2370N/A /* TODO: Does it make sence to cache results? */
2370N/A xOff = (int) Math.round(getXAdvance());
2370N/A yOff = (int) Math.round(getYAdvance());
2370N/A }
2370N/A
2370N/A public int getXOff() {
2370N/A return xOff;
2370N/A }
2370N/A
2370N/A public int getYOff() {
2370N/A return yOff;
2370N/A }
2370N/A
2370N/A public void setGlyphSet(int glyphSet) {
2370N/A this.glyphSet = glyphSet;
2370N/A }
2370N/A
2370N/A public int getGlyphSet() {
2370N/A return glyphSet;
2370N/A }
2370N/A
2370N/A public static int getGlyphID(long glyphInfoPtr) {
6133N/A // We need to access the GlyphID with Unsafe.getAddress() because the
6133N/A // corresponding field in the underlying C data-structure is of type
6133N/A // 'void*' (see field 'cellInfo' of struct 'GlyphInfo'
6133N/A // in src/share/native/sun/font/fontscalerdefs.h).
6133N/A // On 64-bit Big-endian architectures it would be wrong to access this
6133N/A // field with Unsafe.getInt().
6133N/A return (int) StrikeCache.unsafe.getAddress(glyphInfoPtr +
6133N/A StrikeCache.cacheCellOffset);
2370N/A }
2370N/A
2370N/A public static void setGlyphID(long glyphInfoPtr, int id) {
6133N/A // We need to access the GlyphID with Unsafe.putAddress() because the
6133N/A // corresponding field in the underlying C data-structure is of type
6133N/A // 'void*' (see field 'cellInfo' of struct 'GlyphInfo' in
6133N/A // src/share/native/sun/font/fontscalerdefs.h).
6133N/A // On 64-bit Big-endian architectures it would be wrong to write this
6133N/A // field with Unsafe.putInt() because it is also accessed from native
6133N/A // code as a 'long'.
6133N/A // See Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative()
6133N/A // in src/solaris/native/sun/java2d/x11/XRBackendNative.c
6133N/A StrikeCache.unsafe.putAddress(glyphInfoPtr +
6133N/A StrikeCache.cacheCellOffset, (long)id);
2370N/A }
2370N/A
2370N/A public int getGlyphID() {
2370N/A return getGlyphID(glyphInfoPtr);
2370N/A }
2370N/A
2370N/A public void setGlyphID(int id) {
2370N/A setGlyphID(glyphInfoPtr, id);
2370N/A }
2370N/A
2370N/A public float getXAdvance() {
2370N/A return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.xAdvanceOffset);
2370N/A }
2370N/A
2370N/A public float getYAdvance() {
2370N/A return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.yAdvanceOffset);
2370N/A }
2370N/A
2370N/A public int getSourceRowBytes() {
2370N/A return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.rowBytesOffset);
2370N/A }
2370N/A
2370N/A public int getWidth() {
2370N/A return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.widthOffset);
2370N/A }
2370N/A
2370N/A public int getHeight() {
2370N/A return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.heightOffset);
2370N/A }
2370N/A
2370N/A public void writePixelData(ByteArrayOutputStream os, boolean uploadAsLCD) {
6133N/A long pixelDataAddress =
6133N/A StrikeCache.unsafe.getAddress(glyphInfoPtr +
6133N/A StrikeCache.pixelDataOffset);
2370N/A if (pixelDataAddress == 0L) {
2370N/A return;
2370N/A }
2370N/A
2370N/A int width = getWidth();
2370N/A int height = getHeight();
2370N/A int rowBytes = getSourceRowBytes();
2370N/A int paddedWidth = getPaddedWidth(uploadAsLCD);
2370N/A
2370N/A if (!uploadAsLCD) {
2370N/A for (int line = 0; line < height; line++) {
2370N/A for(int x = 0; x < paddedWidth; x++) {
2370N/A if(x < width) {
2370N/A os.write(StrikeCache.unsafe.getByte(pixelDataAddress + (line * rowBytes + x)));
2370N/A }else {
2370N/A /*pad to multiple of 4 bytes per line*/
2370N/A os.write(0);
2370N/A }
2370N/A }
2370N/A }
2370N/A } else {
2370N/A for (int line = 0; line < height; line++) {
2370N/A int rowStart = line * rowBytes;
2370N/A int rowBytesWidth = width * 3;
2370N/A int srcpix = 0;
2370N/A while (srcpix < rowBytesWidth) {
2370N/A os.write(StrikeCache.unsafe.getByte
2370N/A (pixelDataAddress + (rowStart + srcpix + 2)));
2370N/A os.write(StrikeCache.unsafe.getByte
2370N/A (pixelDataAddress + (rowStart + srcpix + 1)));
2370N/A os.write(StrikeCache.unsafe.getByte
2370N/A (pixelDataAddress + (rowStart + srcpix + 0)));
2370N/A os.write(255);
2370N/A srcpix += 3;
2370N/A }
2370N/A }
2370N/A }
2370N/A }
2370N/A
2370N/A public float getTopLeftXOffset() {
2370N/A return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.topLeftXOffset);
2370N/A }
2370N/A
2370N/A public float getTopLeftYOffset() {
2370N/A return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.topLeftYOffset);
2370N/A }
2370N/A
2370N/A public long getGlyphInfoPtr() {
2370N/A return glyphInfoPtr;
2370N/A }
2370N/A
2370N/A public boolean isGrayscale(boolean listContainsLCDGlyphs) {
2370N/A return getSourceRowBytes() == getWidth() && !(getWidth() == 0 && getHeight() == 0 && listContainsLCDGlyphs);
2370N/A }
2370N/A
2370N/A public int getPaddedWidth(boolean listContainsLCDGlyphs) {
2370N/A int width = getWidth();
2370N/A return isGrayscale(listContainsLCDGlyphs) ? (int) Math.ceil(width / 4.0) * 4 : width;
2370N/A }
2370N/A
2370N/A public int getDestinationRowBytes(boolean listContainsLCDGlyphs) {
2370N/A boolean grayscale = isGrayscale(listContainsLCDGlyphs);
2370N/A return grayscale ? getPaddedWidth(grayscale) : getWidth() * 4;
2370N/A }
2370N/A
2370N/A public int getGlyphDataLenth(boolean listContainsLCDGlyphs) {
2370N/A return getDestinationRowBytes(listContainsLCDGlyphs) * getHeight();
2370N/A }
2370N/A
2370N/A public void setPinned() {
2370N/A pinned = true;
2370N/A }
2370N/A
2370N/A public void setUnpinned() {
2370N/A pinned = false;
2370N/A }
2370N/A
2370N/A public int getLastUsed() {
2370N/A return lastUsed;
2370N/A }
2370N/A
2370N/A public void setLastUsed(int lastUsed) {
2370N/A this.lastUsed = lastUsed;
2370N/A }
2370N/A
2370N/A public int getPixelCnt() {
2370N/A return getWidth() * getHeight();
2370N/A }
2370N/A
2370N/A public boolean isPinned() {
2370N/A return pinned;
2370N/A }
2370N/A}