1 /*
   2  * Copyright (c) 2010, 2018, 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.pipe.*;
  33 
  34 import static sun.java2d.xr.XRUtils.XDoubleToFixed;
  35 
  36 /**
  37  * Native implementation of XRBackend.
  38  * Almost direct 1:1 binding to libX11.
  39  *
  40  * @author Clemens Eisserer
  41  */
  42 
  43 public class XRBackendNative implements XRBackend {
  44     private static long FMTPTR_A8;
  45     private static long FMTPTR_ARGB32;
  46     private static long ximgPtr;
  47     
  48     private static final int AA_MASK_WIDTH = 128;
  49     private static final int AA_MASK_HEIGHT = 64;
  50     
  51     static {
  52         initIDs();
  53     } 
  54 
  55     int maskPicture;
  56     int maskPixmap;
  57     long maskGC;
  58     
  59     public XRBackendNative() {
  60 
  61     }
  62     
  63     public void initResources(int parentXID) {
  64         ximgPtr = initDefaultAAXImg(AA_MASK_WIDTH, AA_MASK_HEIGHT);
  65         if(ximgPtr == 0) {
  66             throw new OutOfMemoryError("failed to allocate ximg");
  67         }
  68         
  69         maskPixmap = createPixmap(parentXID, 8, AA_MASK_WIDTH, AA_MASK_HEIGHT);
  70         maskPicture = createPicture(maskPixmap, XRUtils.PictStandardA8);
  71         maskGC = createGC(maskPixmap);
  72         setGCExposures(maskGC, false);
  73     }
  74     
  75     private static native void initIDs();
  76     
  77     private static native long initDefaultAAXImg(int maxAATileWidth, int maxAATileHeight);
  78 
  79     public native long createGC(int drawable);
  80 
  81     public native void freeGC(long gc);
  82 
  83     public native int createPixmap(int drawable, int depth,
  84                                    int width, int height);
  85 
  86     private native int createPictureNative(int drawable, long formatID);
  87 
  88     public native void freePicture(int picture);
  89 
  90     public native void freePixmap(int pixmap);
  91 
  92     public native void setGCExposures(long gc, boolean exposure);
  93 
  94     public native void setGCForeground(long gc, int pixel);
  95 
  96     public native void setPictureRepeat(int picture, int repeat);
  97 
  98     public native void copyArea(int src, int dst, long gc,
  99                                 int srcx, int srcy, int width, int height,
 100                                  int dstx, int dsty);
 101 
 102     public native void setGCMode(long gc, boolean copy);
 103 
 104     private static native void GCRectanglesNative(int drawable, long gc,
 105                                                   int[] rectArray, int rectCnt);
 106 
 107     public native void renderComposite(byte op, int src, int mask,
 108                                        int dst, int srcX, int srcY,
 109                                        int maskX, int maskY, int dstX, int dstY,
 110                                        int width, int height);
 111 
 112     private native void renderRectangle(int dst, byte op,
 113                                         short red, short green,
 114                                         short blue, short alpha,
 115                                         int x, int y, int width, int height);
 116 
 117     private static native void
 118          XRenderRectanglesNative(int dst, byte op,
 119                                  short red, short green,
 120                                  short blue, short alpha,
 121                                  int[] rects, int rectCnt);
 122 
 123     private native void XRSetTransformNative(int pic,
 124                                              int m00, int m01, int m02,
 125                                              int m10, int m11, int m12);
 126 
 127     private static native int
 128         XRCreateLinearGradientPaintNative(float[] fractionsArray,
 129                                           short[] pixelsArray,
 130                                           int x1, int y1, int x2, int y2,
 131                                           int numStops, int repeat);
 132 
 133     private static native int
 134         XRCreateRadialGradientPaintNative(float[] fractionsArray,
 135                                           short[] pixelsArray, int numStops,
 136                                           int centerX, int centerY,
 137                                           int innerRadius, int outerRadius,
 138                                           int repeat);
 139 
 140     public native void setFilter(int picture, int filter);
 141 
 142     private static native void XRSetClipNative(long dst,
 143                                                int x1, int y1, int x2, int y2,
 144                                                Region clip, boolean isGC);
 145 
 146     public void GCRectangles(int drawable, long gc, GrowableRectArray rects) {
 147         GCRectanglesNative(drawable, gc, rects.getArray(), rects.getSize());
 148     }
 149 
 150     public int createPicture(int drawable, int formatID) {
 151         return createPictureNative(drawable, getFormatPtr(formatID));
 152     }
 153 
 154     public void setPictureTransform(int picture, AffineTransform transform) {
 155         XRSetTransformNative(picture,
 156                              XDoubleToFixed(transform.getScaleX()),
 157                              XDoubleToFixed(transform.getShearX()),
 158                              XDoubleToFixed(transform.getTranslateX()),
 159                              XDoubleToFixed(transform.getShearY()),
 160                              XDoubleToFixed(transform.getScaleY()),
 161                              XDoubleToFixed(transform.getTranslateY()));
 162     }
 163 
 164     public void renderRectangle(int dst, byte op, XRColor color,
 165                                 int x, int y, int width, int height) {
 166         renderRectangle(dst, op, (short)color.red, (short)color.green,
 167                        (short)color.blue, (short)color.alpha,
 168                         x, y, width, height);
 169     }
 170 
 171     private short[] getRenderColors(int[] pixels) {
 172         short[] renderColors = new short[pixels.length * 4];
 173 
 174         XRColor c = new XRColor();
 175         for (int i = 0; i < pixels.length; i++) {
 176             c.setColorValues(pixels[i]);
 177             renderColors[i * 4 + 0] = (short) c.alpha;
 178             renderColors[i * 4 + 1] = (short) c.red;
 179             renderColors[i * 4 + 2] = (short) c.green;
 180             renderColors[i * 4 + 3] = (short) c.blue;
 181         }
 182 
 183         return renderColors;
 184     }
 185 
 186     private static long getFormatPtr(int formatID) {
 187         switch (formatID) {
 188         case XRUtils.PictStandardA8:
 189             return FMTPTR_A8;
 190         case XRUtils.PictStandardARGB32:
 191             return FMTPTR_ARGB32;
 192         }
 193 
 194         return 0L;
 195     }
 196 
 197     public int createLinearGradient(Point2D p1, Point2D p2, float[] fractions,
 198                               int[] pixels,  int repeat) {
 199 
 200         short[] colorValues = getRenderColors(pixels);
 201         int gradient =
 202            XRCreateLinearGradientPaintNative(fractions, colorValues,
 203                 XDoubleToFixed(p1.getX()), XDoubleToFixed(p1.getY()),
 204                 XDoubleToFixed(p2.getX()), XDoubleToFixed(p2.getY()),
 205                 fractions.length, repeat);
 206         return gradient;
 207     }
 208 
 209     public int createRadialGradient(float centerX, float centerY,
 210                                    float innerRadius, float outerRadius,
 211                                    float[] fractions, int[] pixels, int repeat) {
 212 
 213         short[] colorValues = getRenderColors(pixels);
 214         return XRCreateRadialGradientPaintNative
 215              (fractions, colorValues, fractions.length,
 216               XDoubleToFixed(centerX),
 217               XDoubleToFixed(centerY),
 218               XDoubleToFixed(innerRadius),
 219               XDoubleToFixed(outerRadius),
 220               repeat);
 221     }
 222 
 223     public void setGCClipRectangles(long gc, Region clip) {
 224         XRSetClipNative(gc, clip.getLoX(), clip.getLoY(),
 225                         clip.getHiX(), clip.getHiY(),
 226                         clip.isRectangular() ? null : clip, true);
 227     }
 228 
 229     public void setClipRectangles(int picture, Region clip) {
 230         if (clip != null) {
 231             XRSetClipNative(picture, clip.getLoX(), clip.getLoY(),
 232                             clip.getHiX(), clip.getHiY(),
 233                             clip.isRectangular() ? null : clip, false);
 234         } else {
 235             XRSetClipNative(picture, 0, 0, 32767, 32767, null, false);
 236         }
 237     }
 238 
 239     public void renderRectangles(int dst, byte op, XRColor color,
 240                                  GrowableRectArray rects) {
 241         XRenderRectanglesNative(dst, op,
 242                                 (short) color.red, (short) color.green,
 243                                 (short) color.blue, (short) color.alpha,
 244                                 rects.getArray(), rects
 245                 .getSize());
 246     }
 247 
 248     private static long[] getGlyphInfoPtrs(List<XRGlyphCacheEntry> cacheEntries) {
 249         long[] glyphInfoPtrs = new long[cacheEntries.size()];
 250         for (int i = 0; i < cacheEntries.size(); i++) {
 251             glyphInfoPtrs[i] = cacheEntries.get(i).getGlyphInfoPtr();
 252         }
 253         return glyphInfoPtrs;
 254     }
 255 
 256     public void XRenderAddGlyphs(int glyphSet, GlyphList gl,
 257                                  List<XRGlyphCacheEntry> cacheEntries,
 258                                  byte[] pixelData) {
 259         long[] glyphInfoPtrs = getGlyphInfoPtrs(cacheEntries);
 260         XRAddGlyphsNative(glyphSet, glyphInfoPtrs,
 261                           glyphInfoPtrs.length, pixelData, pixelData.length);
 262     }
 263 
 264     public void XRenderFreeGlyphs(int glyphSet, int[] gids) {
 265         XRFreeGlyphsNative(glyphSet, gids, gids.length);
 266     }
 267 
 268     private static native void XRAddGlyphsNative(int glyphSet,
 269                                                  long[] glyphInfoPtrs,
 270                                                  int glyphCnt,
 271                                                  byte[] pixelData,
 272                                                  int pixelDataLength);
 273 
 274     private static native void XRFreeGlyphsNative(int glyphSet,
 275                                                   int[] gids, int idCnt);
 276 
 277     private static native void
 278         XRenderCompositeTextNative(int op, int src, int dst,
 279                                    int srcX, int srcY, long maskFormat,
 280                                    int[] eltArray, int[] glyphIDs, int eltCnt,
 281                                    int glyphCnt);
 282 
 283     public int XRenderCreateGlyphSet(int formatID) {
 284         return XRenderCreateGlyphSetNative(getFormatPtr(formatID));
 285     }
 286 
 287     private static native int XRenderCreateGlyphSetNative(long format);
 288 
 289     public void XRenderCompositeText(byte op, int src, int dst,
 290                                      int maskFormatID,
 291                                      int sx, int sy, int dx, int dy,
 292                                      int glyphset, GrowableEltArray elts) {
 293 
 294         GrowableIntArray glyphs = elts.getGlyphs();
 295         XRenderCompositeTextNative(op, src, dst, sx, sy, 0, elts.getArray(),
 296                                    glyphs.getArray(), elts.getSize(),
 297                                    glyphs.getSize());
 298     }
 299     
 300     public void maskedComposite(byte op, int src, int eaMask, int dst, 
 301             int srcX, int srcY, int dstX, int dstY, int width, 
 302             int height, int maskScan, int maskOff, byte[] mask, float ea) {
 303         if(mask == null) {
 304               renderComposite(op, src, eaMask, dst, srcX, srcY, 0, 0, dstX, dstY, width, height);
 305         } else {
 306             putMaskImage(maskPixmap, maskGC, mask, 0, 0, 0, 0, width, height, maskOff, maskScan, ea);
 307             renderComposite(op, src, maskPicture, dst, srcX, srcY, 0, 0, dstX, dstY, width, height);
 308         }
 309     }
 310 
 311     public void putMaskImage(int drawable, long gc, byte[] imageData,
 312                              int sx, int sy, int dx, int dy,
 313                              int width, int height, int maskOff,
 314                              int maskScan, float ea) {
 315         putMaskNative(drawable, gc, imageData, sx, sy, dx, dy,
 316                       width, height, maskOff, maskScan, ea, ximgPtr);
 317     }
 318 
 319     private static native void putMaskNative(int drawable, long gc,
 320                                              byte[] imageData,
 321                                              int sx, int sy, int dx, int dy,
 322                                              int width, int height,
 323                                              int maskOff, int maskScan,
 324                                              float ea, long xImg);
 325 
 326     public void padBlit(byte op, int srcPict, int maskPict, int dstPict,
 327                         AffineTransform maskTrx, int maskWidth, int maskHeight,
 328                         int lastMaskWidth, int lastMaskHeight,
 329                         int sx, int sy, int dx, int dy, int w, int h) {
 330 
 331         padBlitNative(op, srcPict, maskPict, dstPict,
 332                       XDoubleToFixed(maskTrx.getScaleX()),
 333                       XDoubleToFixed(maskTrx.getShearX()),
 334                       XDoubleToFixed(maskTrx.getTranslateX()),
 335                       XDoubleToFixed(maskTrx.getShearY()),
 336                       XDoubleToFixed(maskTrx.getScaleY()),
 337                       XDoubleToFixed(maskTrx.getTranslateY()),
 338                       maskWidth, maskHeight, lastMaskWidth, lastMaskHeight,
 339                       sx, sy, dx, dy, w, h);
 340     }
 341 
 342     private static native void padBlitNative(byte op, int srcPict,
 343                                              int maskPict, int dstPict,
 344                                              int m00, int m01, int m02,
 345                                              int m10, int m11, int m12,
 346                                              int maskWidth, int maskHeight,
 347                                              int lastMaskWidth,
 348                                              int lastMaskHeight,
 349                                              int sx, int sy, int dx, int dy,
 350                                              int w, int h);
 351 
 352 }