All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.codename1.designer.css.WebviewSnapshotter Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Codename One designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *  
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 * 
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 * 
 * Please contact Codename One through http://www.codenameone.com/ if you 
 * need additional information or have any questions.
 */
package com.codename1.designer.css;

import com.codename1.io.Log;
import com.codename1.processing.Result;
import com.codename1.ui.BrowserComponent;
import com.codename1.ui.CN;
import com.codename1.ui.Image;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 *
 * @author shannah
 */
public class WebviewSnapshotter {
    private int x, y, w, h;
    private BrowserComponent web;
    final LinkedList eventQueue = new LinkedList();
    Thread eventThread;
    Runnable onDone;
    boolean done;
    BufferedImage image;
    Graphics2D imageGraphics;
    
    
    public WebviewSnapshotter(BrowserComponent web) {
        this.web = web;
    }
    
    public void setBounds(int x, int y, int w, int h) {
        this.x = x;
        this.y =y;
        this.w = w;
        this.h = h;
    }
    
    private void fireJSSnap(int x, int y, int w, int h) {
        //System.out.println("[WebviewSnapshotter::fireJSSnap("+x+","+y+","+w+","+h);
        if (!CN.isEdt()) {
            CN.callSerially(()-> {
                fireJSSnap(x, y, w, h);
            });
            return;
        } 
        
        web.execute("window.snapper = window.snapper || {}; "
                + "window.snapper.handleJSSnap = function(scrollX, scrollY, x, y, w, h) {"
                + "  callback.onSuccess(JSON.stringify({scrollX:scrollX, scrollY:scrollY, x:x, y:y, w:w, h:h}));"
                + "}; window.getRectSnapshot("+x+","+y+","+w+","+h+");", res -> {
                    try {
                        Result data = Result.fromContent(res.toString(), Result.JSON);
                        handleJSSnap(
                                data.getAsInteger("scrollX"),
                                data.getAsInteger("scrollY"),
                                data.getAsInteger("x"),
                                data.getAsInteger("y"),
                                data.getAsInteger("w"),
                                data.getAsInteger("h")
                        );
                    } catch (Exception ex) {
                        Log.p("Failed to parse callback in fireJSSnap");
                        Log.e(ex);
                    }
                });
    }
    
    private boolean isEventThread() {
        return Thread.currentThread() == eventThread;
    }
    
    private void runLater(Runnable r) {
        synchronized(eventQueue) {
            eventQueue.add(r);
            eventQueue.notify();
        }
    }
    
    public void log(String msg) {
        System.out.println(msg);
    }
    
    public final void handleJSSnap(int scrollX, int scrollY, int x, int y, int w, int h) {
        //System.out.println("[WebviewSnapshotter::handleJSSnap("+scrollX+","+scrollY+","+x+","+y+","+w+","+h+")");
        if (!isEventThread()) {
            runLater(()-> {
                handleJSSnap(scrollX, scrollY, x, y, w, h);
            });
            return;
        }
        CN.callSerially(()-> {
            Image wi = web.captureScreenshot().get();
            BufferedImage img = (BufferedImage)wi.getImage();
            
            runLater(()-> {
                int remw = Math.min(w, 320);
                int remh = Math.min(h, 480);
                //remw = Math.min(remw, 320);
                //remh = Math.min(remh, 480);
                BufferedImage img2 = img.getSubimage(20,20, remw, remh);
                //System.out.println("Writing image at "+(x-20)+", "+(y-20)+" with width "+remw+" and height "+remh);
                imageGraphics.drawImage(img2, null, x-20, y-20);
                if (x+remw < this.x+this.w || y+remh < this.y+this.h) {
                    if (x+remw < this.x+this.w) {
                        fireJSSnap(x+remw, y, w, h);
                    } else {
                        fireJSSnap(this.x, y+remh, w, h);
                    }
                } else {
                    fireDone();
                }
            });

        });

    }
    
    public final void fireDone() {
        //System.out.println("[WebViewSnapshotter::fireDone()]");
        if (!isEventThread()) {
            runLater(()-> {
                fireDone();
            });
            return;
        } 
        //System.out.println("In fireDone()");
        imageGraphics.dispose();
        
        // Now do the fireDone
        if (onDone != null) {
            onDone.run();
        }
        done = true;
    }
    
    public void snapshot(Runnable onDone) {
        //System.out.println("[WebviewSnapshotter::snapshot()]");
        if (eventThread != null) {
            throw new RuntimeException("Snapshot event thread already created");
        }
        eventThread = new Thread(()-> {
            while (!done) {
                Runnable evt = null;
                synchronized(eventQueue) {
                    if (eventQueue.isEmpty()) {
                        try {
                            eventQueue.wait();
                        } catch (InterruptedException ex) {
                            Logger.getLogger(WebviewSnapshotter.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                    evt = eventQueue.remove();
                }
                evt.run();
            }
        });
        this.onDone = onDone;
        int x = this.x;
        int y = this.y;
        int width = Math.min(this.w, 320);
        int height = Math.min(this.h, 480);
        this.image = new BufferedImage(this.w, this.h, BufferedImage.TYPE_INT_ARGB);
        this.imageGraphics = this.image.createGraphics();
        fireJSSnap(x, y, width, height);
        eventThread.start();
        
    }
    
    public void snapshotSync() {
        Object lock = new Object();
        boolean[] complete = new boolean[1];
        snapshot(()-> {
            complete[0] = true;
            synchronized(lock) {
                lock.notify();
            }
        });
        CN.invokeAndBlock(new Runnable() {
            public void run() {
                while (!complete[0]) {
                    synchronized(lock) {
                        try {
                            lock.wait();
                        } catch (InterruptedException ex) {
                            Logger.getLogger(WebviewSnapshotter.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }
        });
        
    }
    
    public BufferedImage getImage() {
        return image;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy