1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.java2d.xr;
  27 
  28 import java.awt.geom.*;
  29 import java.util.*;
  30 
  31 import sun.font.*;
  32 import sun.java2d.jules.*;
  33 import sun.java2d.pipe.*;
  34 
  35 import static sun.java2d.xr.XRUtils.XDoubleToFixed;
  36 
  37 /**
  38  * Native implementation of XRBackend.
  39  * Almost direct 1:1 binding to libX11.
  40  *
  41  * @author Clemens Eisserer
  42  */
  43 
  44 public class XRBackendNative implements XRBackend {
  45 
  46     static {
  47         initIDs();
  48     }
  49 
  50     private static long FMTPTR_A8;
  51     private static long FMTPTR_ARGB32;
  52     private static long MASK_XIMG;
  53 
  54     private static native void initIDs();
  55 
  56     public native long createGC(int drawable);
  57 
  58     public native void freeGC(long gc);
  59 
  60     public native int createPixmap(int drawable, int depth,
  61                                    int width, int height);
  62 
  63     private native int createPictureNative(int drawable, long formatID);
  64 
  65     public native void freePicture(int picture);
  66 
  67     public native void freePixmap(int pixmap);
  68 
  69     public native void setGCExposures(long gc, boolean exposure);
  70 
  71     public native void setGCForeground(long gc, int pixel);
  72 
  73     public native void setPictureRepeat(int picture, int repeat);
  74 
  75     public native void copyArea(int src, int dst, long gc,
  76                                 int srcx, int srcy, int width, int height,
  77                                  int dstx, int dsty);
  78 
  79     public native void setGCMode(long gc, boolean copy);
  80 
  81     private static native void GCRectanglesNative(int drawable, long gc,
  82                                                   int[] rectArray, int rectCnt);
  83 
  84     public native void renderComposite(byte op, int src, int mask,
  85                                        int dst, int srcX, int srcY,
  86                                        int maskX, int maskY, int dstX, int dstY,
  87                                        int width, int height);
  88 
  89     private native void renderRectangle(int dst, byte op,
  90                                         short red, short green,
  91                                         short blue, short alpha,
  92                                         int x, int y, int width, int height);
  93 
  94     private static native void
  95          XRenderRectanglesNative(int dst, byte op,
  96                                  short red, short green,
  97                                  short blue, short alpha,
  98                                  int[] rects, int rectCnt);
  99 
 100     private native void XRSetTransformNative(int pic,
 101                                              int m00, int m01, int m02,
 102                                              int m10, int m11, int m12);
 103 
 104     private static native int
 105         XRCreateLinearGradientPaintNative(float[] fractionsArray,
 106                                           short[] pixelsArray,
 107                                           int x1, int y1, int x2, int y2,
 108                                           int numStops, int repeat);
 109 
 110     private static native int
 111         XRCreateRadialGradientPaintNative(float[] fractionsArray,
 112                                           short[] pixelsArray, int numStops,
 113                                           int centerX, int centerY,
 114                                           int innerRadius, int outerRadius,
 115                                           int repeat);
 116 
 117     public native void setFilter(int picture, int filter);
 118 
 119     private static native void XRSetClipNative(long dst,
 120                                                int x1, int y1, int x2, int y2,
 121                                                Region clip, boolean isGC);
 122 
 123     public void GCRectangles(int drawable, long gc, GrowableRectArray rects) {
 124         GCRectanglesNative(drawable, gc, rects.getArray(), rects.getSize());
 125     }
 126 
 127     public int createPicture(int drawable, int formatID) {
 128         return createPictureNative(drawable, getFormatPtr(formatID));
 129     }
 130 
 131     public void setPictureTransform(int picture, AffineTransform transform) {
 132         XRSetTransformNative(picture,
 133                              XDoubleToFixed(transform.getScaleX()),
 134                              XDoubleToFixed(transform.getShearX()),
 135                              XDoubleToFixed(transform.getTranslateX()),
 136                              XDoubleToFixed(transform.getShearY()),
 137                              XDoubleToFixed(transform.getScaleY()),
 138                              XDoubleToFixed(transform.getTranslateY()));
 139     }
 140 
 141     public void renderRectangle(int dst, byte op, XRColor color,
 142                                 int x, int y, int width, int height) {
 143         renderRectangle(dst, op, (short)color.red, (short)color.green,
 144                        (short)color.blue, (short)color.alpha,
 145                         x, y, width, height);
 146     }
 147 
 148     private short[] getRenderColors(int[] pixels) {
 149         short[] renderColors = new short[pixels.length * 4];
 150 
 151         XRColor c = new XRColor();
 152         for (int i = 0; i < pixels.length; i++) {
 153             c.setColorValues(pixels[i], true);
 154             renderColors[i * 4 + 0] = (short) c.alpha;
 155             renderColors[i * 4 + 1] = (short) c.red;
 156             renderColors[i * 4 + 2] = (short) c.green;
 157             renderColors[i * 4 + 3] = (short) c.blue;
 158         }
 159 
 160         return renderColors;
 161     }
 162 
 163     private static long getFormatPtr(int formatID) {
 164         switch (formatID) {
 165         case XRUtils.PictStandardA8:
 166             return FMTPTR_A8;
 167         case XRUtils.PictStandardARGB32:
 168             return FMTPTR_ARGB32;
 169         }
 170 
 171         return 0L;
 172     }
 173 
 174     public int createLinearGradient(Point2D p1, Point2D p2, float[] fractions,
 175                               int[] pixels,  int repeat) {
 176 
 177         short[] colorValues = getRenderColors(pixels);
 178         int gradient =
 179            XRCreateLinearGradientPaintNative(fractions, colorValues,
 180                 XDoubleToFixed(p1.getX()), XDoubleToFixed(p1.getY()),
 181                 XDoubleToFixed(p2.getX()), XDoubleToFixed(p2.getY()),
 182                 fractions.length, repeat);
 183         return gradient;
 184     }
 185 
 186     public int createRadialGradient(float centerX, float centerY,
 187                                    float innerRadius, float outerRadius,
 188                                    float[] fractions, int[] pixels, int repeat) {
 189 
 190         short[] colorValues = getRenderColors(pixels);
 191         return XRCreateRadialGradientPaintNative
 192              (fractions, colorValues, fractions.length,
 193               XDoubleToFixed(centerX),
 194               XDoubleToFixed(centerY),
 195               XDoubleToFixed(innerRadius),
 196               XDoubleToFixed(outerRadius),
 197               repeat);
 198     }
 199 
 200     public void setGCClipRectangles(long gc, Region clip) {
 201         XRSetClipNative(gc, clip.getLoX(), clip.getLoY(),
 202                         clip.getHiX(), clip.getHiY(),
 203                         clip.isRectangular() ? null : clip, true);
 204     }
 205 
 206     public void setClipRectangles(int picture, Region clip) {
 207         if (clip != null) {
 208             XRSetClipNative(picture, clip.getLoX(), clip.getLoY(),
 209                             clip.getHiX(), clip.getHiY(),
 210                             clip.isRectangular() ? null : clip, false);
 211         } else {
 212             XRSetClipNative(picture, 0, 0, 32767, 32767, null, false);
 213         }
 214     }
 215 
 216     public void renderRectangles(int dst, byte op, XRColor color,
 217                                  GrowableRectArray rects) {
 218         XRenderRectanglesNative(dst, op,
 219                                 (short) color.red, (short) color.green,
 220                                 (short) color.blue, (short) color.alpha,
 221                                 rects.getArray(), rects
 222                 .getSize());
 223     }
 224 
 225     private static long[] getGlyphInfoPtrs(List<XRGlyphCacheEntry> cacheEntries) {
 226         long[] glyphInfoPtrs = new long[cacheEntries.size()];
 227         for (int i = 0; i < cacheEntries.size(); i++) {
 228             glyphInfoPtrs[i] = cacheEntries.get(i).getGlyphInfoPtr();
 229         }
 230         return glyphInfoPtrs;
 231     }
 232 
 233     public void XRenderAddGlyphs(int glyphSet, GlyphList gl,
 234                                  List<XRGlyphCacheEntry> cacheEntries,
 235                                  byte[] pixelData) {
 236         long[] glyphInfoPtrs = getGlyphInfoPtrs(cacheEntries);
 237         XRAddGlyphsNative(glyphSet, glyphInfoPtrs,
 238                           glyphInfoPtrs.length, pixelData, pixelData.length);
 239     }
 240 
 241     public void XRenderFreeGlyphs(int glyphSet, int[] gids) {
 242         XRFreeGlyphsNative(glyphSet, gids, gids.length);
 243     }
 244 
 245     private static native void XRAddGlyphsNative(int glyphSet,
 246                                                  long[] glyphInfoPtrs,
 247                                                  int glyphCnt,
 248                                                  byte[] pixelData,
 249                                                  int pixelDataLength);
 250 
 251     private static native void XRFreeGlyphsNative(int glyphSet,
 252                                                   int[] gids, int idCnt);
 253 
 254     private static native void
 255         XRenderCompositeTextNative(int op, int src, int dst,
 256                                    int srcX, int srcY, long maskFormat,
 257                                    int[] eltArray, int[] glyphIDs, int eltCnt,
 258                                    int glyphCnt);
 259 
 260     public int XRenderCreateGlyphSet(int formatID) {
 261         return XRenderCreateGlyphSetNative(getFormatPtr(formatID));
 262     }
 263 
 264     private static native int XRenderCreateGlyphSetNative(long format);
 265 
 266     public void XRenderCompositeText(byte op, int src, int dst,
 267                                      int maskFormatID,
 268                                      int sx, int sy, int dx, int dy,
 269                                      int glyphset, GrowableEltArray elts) {
 270 
 271         GrowableIntArray glyphs = elts.getGlyphs();
 272         XRenderCompositeTextNative(op, src, dst, sx, sy, 0, elts.getArray(),
 273                                    glyphs.getArray(), elts.getSize(),
 274                                    glyphs.getSize());
 275     }
 276 
 277     public void putMaskImage(int drawable, long gc, byte[] imageData,
 278                              int sx, int sy, int dx, int dy,
 279                              int width, int height, int maskOff,
 280                              int maskScan, float ea) {
 281         putMaskNative(drawable, gc, imageData, sx, sy, dx, dy,
 282                       width, height, maskOff, maskScan, ea, MASK_XIMG);
 283     }
 284 
 285     private static native void putMaskNative(int drawable, long gc,
 286                                              byte[] imageData,
 287                                              int sx, int sy, int dx, int dy,
 288                                              int width, int height,
 289                                              int maskOff, int maskScan,
 290                                              float ea, long xImg);
 291 
 292     public void padBlit(byte op, int srcPict, int maskPict, int dstPict,
 293                         AffineTransform maskTrx, int maskWidth, int maskHeight,
 294                         int lastMaskWidth, int lastMaskHeight,
 295                         int sx, int sy, int dx, int dy, int w, int h) {
 296 
 297         padBlitNative(op, srcPict, maskPict, dstPict,
 298                       XDoubleToFixed(maskTrx.getScaleX()),
 299                       XDoubleToFixed(maskTrx.getShearX()),
 300                       XDoubleToFixed(maskTrx.getTranslateX()),
 301                       XDoubleToFixed(maskTrx.getShearY()),
 302                       XDoubleToFixed(maskTrx.getScaleY()),
 303                       XDoubleToFixed(maskTrx.getTranslateY()),
 304                       maskWidth, maskHeight, lastMaskWidth, lastMaskHeight,
 305                       sx, sy, dx, dy, w, h);
 306     }
 307 
 308     private static native void padBlitNative(byte op, int srcPict,
 309                                              int maskPict, int dstPict,
 310                                              int m00, int m01, int m02,
 311                                              int m10, int m11, int m12,
 312                                              int maskWidth, int maskHeight,
 313                                              int lastMaskWidth,
 314                                              int lastMaskHeight,
 315                                              int sx, int sy, int dx, int dy,
 316                                              int w, int h);
 317 
 318     public void renderCompositeTrapezoids(byte op, int src, int maskFormat,
 319                                           int dst, int srcX, int srcY,
 320                                           TrapezoidList trapList) {
 321         renderCompositeTrapezoidsNative(op, src, getFormatPtr(maskFormat),
 322                                         dst, srcX, srcY,
 323                                         trapList.getTrapArray());
 324     }
 325 
 326     private static native void
 327         renderCompositeTrapezoidsNative(byte op, int src, long maskFormat,
 328                                         int dst, int srcX, int srcY,
 329                                         int[] trapezoids);
 330 }