1 /* 2 * Copyright (c) 2010, 2016, 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 com.sun.prism.impl.shape; 27 28 import com.sun.javafx.geom.Path2D; 29 import com.sun.javafx.geom.RectBounds; 30 import com.sun.javafx.geom.Rectangle; 31 import com.sun.javafx.geom.Shape; 32 import com.sun.javafx.geom.transform.BaseTransform; 33 import com.sun.marlin.DMarlinRenderer; 34 import com.sun.marlin.DMarlinRenderingEngine; 35 import com.sun.marlin.MaskMarlinAlphaConsumer; 36 import com.sun.marlin.DRendererContext; 37 import com.sun.prism.BasicStroke; 38 import com.sun.prism.impl.PrismSettings; 39 40 /** 41 * Thread-safe Marlin rasterizer (TL or CLQ storage) 42 */ 43 public final class DMarlinRasterizer implements ShapeRasterizer { 44 private static final MaskData EMPTY_MASK = MaskData.create(new byte[1], 0, 0, 1, 1); 45 46 @Override 47 public MaskData getMaskData(Shape shape, 48 BasicStroke stroke, 49 RectBounds xformBounds, 50 BaseTransform xform, 51 boolean close, boolean antialiasedShape) 52 { 53 if (stroke != null && stroke.getType() != BasicStroke.TYPE_CENTERED) { 54 // RT-27427 55 // TODO: Optimize the combinatorial strokes for simple 56 // shapes and/or teach the rasterizer to be able to 57 // do a "differential fill" between two shapes. 58 // Note that most simple shapes will use a more optimized path 59 // than this method for the INNER/OUTER strokes anyway. 60 shape = stroke.createStrokedShape(shape); 61 stroke = null; 62 } 63 if (xformBounds == null) { 64 if (stroke != null) { 65 // Note that all places that pass null for xformbounds also 66 // pass null for stroke so that the following is not typically 67 // executed, but just here as a safety net. 68 shape = stroke.createStrokedShape(shape); 69 stroke = null; 70 } 71 72 xformBounds = new RectBounds(); 73 //TODO: Need to verify that this is a safe cast ... (RT-27427) 74 xformBounds = (RectBounds) xform.transform(shape.getBounds(), xformBounds); 75 } 76 if (xformBounds.isEmpty()) { 77 return EMPTY_MASK; 78 } 79 80 final DRendererContext rdrCtx = DMarlinRenderingEngine.getRendererContext(); 81 DMarlinRenderer renderer = null; 82 try { 83 final Rectangle rclip = rdrCtx.clip; 84 rclip.setBounds(xformBounds); 85 86 if (shape instanceof Path2D) { 87 renderer = DMarlinPrismUtils.setupRenderer(rdrCtx, (Path2D) shape, stroke, xform, rclip, 88 antialiasedShape); 89 } 90 if (renderer == null) { 91 renderer = DMarlinPrismUtils.setupRenderer(rdrCtx, shape, stroke, xform, rclip, 92 antialiasedShape); 93 } 94 final int outpix_xmin = renderer.getOutpixMinX(); 95 final int outpix_xmax = renderer.getOutpixMaxX(); 96 final int outpix_ymin = renderer.getOutpixMinY(); 97 final int outpix_ymax = renderer.getOutpixMaxY(); 98 final int w = outpix_xmax - outpix_xmin; 99 final int h = outpix_ymax - outpix_ymin; 100 if ((w <= 0) || (h <= 0)) { 101 return EMPTY_MASK; 102 } 103 104 MaskMarlinAlphaConsumer consumer = rdrCtx.consumer; 105 if (consumer == null || (w * h) > consumer.getAlphaLength()) { 106 final int csize = (w * h + 0xfff) & (~0xfff); 107 rdrCtx.consumer = consumer = new MaskMarlinAlphaConsumer(csize); 108 if (PrismSettings.verbose) { 109 System.out.println("new alphas with length = " + csize); 110 } 111 } 112 consumer.setBoundsNoClone(outpix_xmin, outpix_ymin, w, h); 113 renderer.produceAlphas(consumer); 114 return consumer.getMaskData(); 115 } finally { 116 if (renderer != null) { 117 renderer.dispose(); 118 } 119 // recycle the RendererContext instance 120 DMarlinRenderingEngine.returnRendererContext(rdrCtx); 121 } 122 } 123 }