1 /*
   2  * Copyright (c) 2010, 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                                           int m00, int m01, int m02,
 110                                            int m10, int m11, int m12);
 111 
 112     private native static int
 113         XRCreateRadialGradientPaintNative(float[] fractionsArray,
 114                                           short[] pixelsArray, int numStops,
 115                                           int innerRadius, int outerRadius,
 116                                           int repeat,
 117                                           int m00, int m01, int m02,
 118                                           int m10, int m11, int m12);
 119 
 120     public native void setFilter(int picture, int filter);
 121 
 122     private static native void XRSetClipNative(long dst,
 123                                                int x1, int y1, int x2, int y2,
 124                                                Region clip, boolean isGC);
 125 
 126     public void GCRectangles(int drawable, long gc, GrowableRectArray rects) {
 127         GCRectanglesNative(drawable, gc, rects.getArray(), rects.getSize());
 128     }
 129 
 130     public int createPicture(int drawable, int formatID) {
 131         return createPictureNative(drawable, getFormatPtr(formatID));
 132     }
 133 
 134     public void setPictureTransform(int picture, AffineTransform transform) {
 135         XRSetTransformNative(picture,
 136                              XDoubleToFixed(transform.getScaleX()),
 137                              XDoubleToFixed(transform.getShearX()),
 138                              XDoubleToFixed(transform.getTranslateX()),
 139                              XDoubleToFixed(transform.getShearY()),
 140                              XDoubleToFixed(transform.getScaleY()),
 141                              XDoubleToFixed(transform.getTranslateY()));
 142     }
 143 
 144     public void renderRectangle(int dst, byte op, XRColor color,
 145                                 int x, int y, int width, int height) {
 146         renderRectangle(dst, op, (short)color.red, (short)color.green,
 147                        (short)color.blue, (short)color.alpha,
 148                         x, y, width, height);
 149     }
 150 
 151     private short[] getRenderColors(int[] pixels) {
 152         short[] renderColors = new short[pixels.length * 4];
 153 
 154         XRColor c = new XRColor();
 155         for (int i = 0; i < pixels.length; i++) {
 156             c.setColorValues(pixels[i], true);
 157             renderColors[i * 4 + 0] = (short) c.alpha;
 158             renderColors[i * 4 + 1] = (short) c.red;
 159             renderColors[i * 4 + 2] = (short) c.green;
 160             renderColors[i * 4 + 3] = (short) c.blue;
 161         }
 162 
 163         return renderColors;
 164     }
 165 
 166     private static long getFormatPtr(int formatID) {
 167         switch (formatID) {
 168         case XRUtils.PictStandardA8:
 169             return FMTPTR_A8;
 170         case XRUtils.PictStandardARGB32:
 171             return FMTPTR_ARGB32;
 172         }
 173 
 174         return 0L;
 175     }
 176 
 177     public int createLinearGradient(Point2D p1, Point2D p2, float[] fractions,
 178                               int[] pixels,  int repeat, AffineTransform trx) {
 179 
 180         short[] colorValues = getRenderColors(pixels);
 181         int gradient =
 182            XRCreateLinearGradientPaintNative(fractions, colorValues,
 183                 XDoubleToFixed(p1.getX()), XDoubleToFixed(p1.getY()),
 184                 XDoubleToFixed(p2.getX()), XDoubleToFixed(p2.getY()),
 185                 fractions.length, repeat,
 186                 XDoubleToFixed(trx.getScaleX()),
 187                 XDoubleToFixed(trx.getShearX()),
 188                 XDoubleToFixed(trx.getTranslateX()),
 189                 XDoubleToFixed(trx.getShearY()),
 190                 XDoubleToFixed(trx.getScaleY()),
 191                 XDoubleToFixed(trx.getTranslateY()));
 192         return gradient;
 193     }
 194 
 195     public int createRadialGradient(Point2D inner, Point2D outer,
 196                                    float innerRadius, float outerRadius,
 197                                    float[] fractions, int[] pixels, int repeat,
 198                                    AffineTransform trx) {
 199 
 200         short[] colorValues = getRenderColors(pixels);
 201         return XRCreateRadialGradientPaintNative
 202              (fractions, colorValues, fractions.length,
 203               XDoubleToFixed(innerRadius),
 204               XDoubleToFixed(outerRadius),
 205               repeat,
 206               XDoubleToFixed(trx.getScaleX()),
 207               XDoubleToFixed(trx.getShearX()),
 208               XDoubleToFixed(trx.getTranslateX()),
 209               XDoubleToFixed(trx.getShearY()),
 210               XDoubleToFixed(trx.getScaleY()),
 211               XDoubleToFixed(trx.getTranslateY()));
 212     }
 213 
 214     public void setGCClipRectangles(long gc, Region clip) {
 215         XRSetClipNative(gc, clip.getLoX(), clip.getLoY(),
 216                         clip.getHiX(), clip.getHiY(),
 217                         clip.isRectangular() ? null : clip, true);
 218     }
 219 
 220     public void setClipRectangles(int picture, Region clip) {
 221         if (clip != null) {
 222             XRSetClipNative(picture, clip.getLoX(), clip.getLoY(),
 223                             clip.getHiX(), clip.getHiY(),
 224                             clip.isRectangular() ? null : clip, false);
 225         } else {
 226             XRSetClipNative(picture, 0, 0, 32767, 32767, null, false);
 227         }
 228     }
 229 
 230     public void renderRectangles(int dst, byte op, XRColor color,
 231                                  GrowableRectArray rects) {
 232         XRenderRectanglesNative(dst, op,
 233                                 (short) color.red, (short) color.green,
 234                                 (short) color.blue, (short) color.alpha,
 235                                 rects.getArray(), rects
 236                 .getSize());
 237     }
 238 
 239     private static long[] getGlyphInfoPtrs(List<XRGlyphCacheEntry> cacheEntries) {
 240         long[] glyphInfoPtrs = new long[cacheEntries.size()];
 241         for (int i = 0; i < cacheEntries.size(); i++) {
 242             glyphInfoPtrs[i] = cacheEntries.get(i).getGlyphInfoPtr();
 243         }
 244         return glyphInfoPtrs;
 245     }
 246 
 247     public void XRenderAddGlyphs(int glyphSet, GlyphList gl,
 248                                  List<XRGlyphCacheEntry> cacheEntries,
 249                                  byte[] pixelData) {
 250         long[] glyphInfoPtrs = getGlyphInfoPtrs(cacheEntries);
 251         XRAddGlyphsNative(glyphSet, glyphInfoPtrs,
 252                           glyphInfoPtrs.length, pixelData, pixelData.length);
 253     }
 254 
 255     public void XRenderFreeGlyphs(int glyphSet, int[] gids) {
 256         XRFreeGlyphsNative(glyphSet, gids, gids.length);
 257     }
 258 
 259     private static native void XRAddGlyphsNative(int glyphSet,
 260                                                  long[] glyphInfoPtrs,
 261                                                  int glyphCnt,
 262                                                  byte[] pixelData,
 263                                                  int pixelDataLength);
 264 
 265     private static native void XRFreeGlyphsNative(int glyphSet,
 266                                                   int[] gids, int idCnt);
 267 
 268     private static native void
 269         XRenderCompositeTextNative(int op, int src, int dst,
 270                                    int srcX, int srcY, long maskFormat,
 271                                    int[] eltArray, int[] glyphIDs, int eltCnt,
 272                                    int glyphCnt);
 273 
 274     public int XRenderCreateGlyphSet(int formatID) {
 275         return XRenderCreateGlyphSetNative(getFormatPtr(formatID));
 276     }
 277 
 278     private static native int XRenderCreateGlyphSetNative(long format);
 279 
 280     public void XRenderCompositeText(byte op, int src, int dst,
 281                                      int maskFormatID,
 282                                      int sx, int sy, int dx, int dy,
 283                                      int glyphset, GrowableEltArray elts) {
 284 
 285         GrowableIntArray glyphs = elts.getGlyphs();
 286         XRenderCompositeTextNative(op, src, dst, sx, sy, 0, elts.getArray(),
 287                                    glyphs.getArray(), elts.getSize(),
 288                                    glyphs.getSize());
 289     }
 290 
 291     public void putMaskImage(int drawable, long gc, byte[] imageData,
 292                              int sx, int sy, int dx, int dy,
 293                              int width, int height, int maskOff,
 294                              int maskScan, float ea) {
 295         putMaskNative(drawable, gc, imageData, sx, sy, dx, dy,
 296                       width, height, maskOff, maskScan, ea, MASK_XIMG);
 297     }
 298 
 299     private static native void putMaskNative(int drawable, long gc,
 300                                              byte[] imageData,
 301                                              int sx, int sy, int dx, int dy,
 302                                              int width, int height,
 303                                              int maskOff, int maskScan,
 304                                              float ea, long xImg);
 305 
 306     public void padBlit(byte op, int srcPict, int maskPict, int dstPict,
 307                         AffineTransform maskTrx, int maskWidth, int maskHeight,
 308                         int lastMaskWidth, int lastMaskHeight,
 309                         int sx, int sy, int dx, int dy, int w, int h) {
 310 
 311         padBlitNative(op, srcPict, maskPict, dstPict,
 312                       XDoubleToFixed(maskTrx.getScaleX()),
 313                       XDoubleToFixed(maskTrx.getShearX()),
 314                       XDoubleToFixed(maskTrx.getTranslateX()),
 315                       XDoubleToFixed(maskTrx.getShearY()),
 316                       XDoubleToFixed(maskTrx.getScaleY()),
 317                       XDoubleToFixed(maskTrx.getTranslateY()),
 318                       maskWidth, maskHeight, lastMaskWidth, lastMaskHeight,
 319                       sx, sy, dx, dy, w, h);
 320     }
 321 
 322     private static native void padBlitNative(byte op, int srcPict,
 323                                              int maskPict, int dstPict,
 324                                              int m00, int m01, int m02,
 325                                              int m10, int m11, int m12,
 326                                              int maskWidth, int maskHeight,
 327                                              int lastMaskWidth,
 328                                              int lastMaskHeight,
 329                                              int sx, int sy, int dx, int dy,
 330                                              int w, int h);
 331 
 332     public void renderCompositeTrapezoids(byte op, int src, int maskFormat,
 333                                           int dst, int srcX, int srcY,
 334                                           TrapezoidList trapList) {
 335         renderCompositeTrapezoidsNative(op, src, getFormatPtr(maskFormat),
 336                                         dst, srcX, srcY,
 337                                         trapList.getTrapArray());
 338     }
 339 
 340     private static native void
 341         renderCompositeTrapezoidsNative(byte op, int src, long maskFormat,
 342                                         int dst, int srcX, int srcY,
 343                                         int[] trapezoids);
 344 }