diff --git a/.gitignore b/.gitignore index c876e1d4..6b2869c8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ */obj/* target/ build/ +robovm-build *.o *.so *.class diff --git a/settings.gradle b/settings.gradle index e475db29..3d9573e1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,4 +14,4 @@ include ':vtm-android-gdx' //include ':vtm-web-js' include ':vtm-jeo' include ':vtm-playground' -//include ':vtm-ios' +include ':vtm-ios' diff --git a/vtm-ios/build.gradle b/vtm-ios/build.gradle index 39f54e1b..1a334a98 100644 --- a/vtm-ios/build.gradle +++ b/vtm-ios/build.gradle @@ -1,69 +1,72 @@ buildscript { repositories { + mavenLocal() mavenCentral() + maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + jcenter() } - dependencies { - classpath 'com.github.jtakakura:gradle-robovm-plugin:0.0.4' + classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.1.0' } } -repositories { - maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } -} +apply plugin: "java" +apply plugin: "robovm" -apply plugin: 'java' -apply plugin: 'robovm' +sourceSets.main.java.srcDirs = ["src/"] + +sourceCompatibility = '1.7' +[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' ext { // Configure your application main class mainClassName = "org.oscim.ios.RoboVmLauncher" - //roboVMVersion = "0.0.9" + roboVMVersion = "2.1.0" } +launchIPhoneSimulator.dependsOn build +launchIPadSimulator.dependsOn build +launchIOSDevice.dependsOn build +createIPA.dependsOn build + dependencies { + compile project(':vtm') compile project(':vtm-gdx') compile project(':vtm-themes') compile 'org.slf4j:slf4j-simple:1.7.5' + compile "com.mobidevelop.robovm:robovm-rt:$roboVMVersion" + compile "com.mobidevelop.robovm:robovm-cocoatouch:$roboVMVersion" compile "com.badlogicgames.gdx:gdx-backend-robovm:$gdxVersion" + compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-ios" } -sourceCompatibility = '1.7' -//[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' -robovm { - // Configure robovm - iosSignIdentity = "" - iosProvisioningProfile = "" + + +task copyLibs(type: Copy){ + from (zipTree("vtm-natives-ios.jar")) + into ("${buildDir}/natives") } -sourceSets { - main { - java.srcDirs = ['src/'] - //resources.srcDirs = ['src/', 'data'] - } - output.resourcesDir = 'assets' +task copyVtmResources(type: Copy){ + from ("../vtm/resources") + into ("${buildDir}") } -// compile bytecode to llvm and run in the ios simulator -// task run (dependsOn: compileJava){ -// doFirst { -// println(">> Running RoboVM") -// String cmd = "$project.robovm_home/bin/robovm -verbose -arch x86 -os ios -cp $project.robovm_home/lib/robovm-objc.jar:$project.robovm_home/lib/robovm-cocoatouch.jar:$projectDir/build/classes/main/ -run $mainClass" -// def proc = cmd.execute() - -// proc.in.eachLine {line -> println line} -// proc.err.eachLine {line -> System.err.println( 'ERROR: ' + line)} -// proc.waitFor() -// } -// } - - -eclipse { - project { - natures = [ 'org.eclipse.jdt.core.javanature', - 'org.robovm.eclipse.RoboVMNature'] - buildCommand 'org.robovm.eclipse.RoboVMClassBuilder' - } +task copyVtmThemesResources(type: Copy){ + from ("../vtm-themes/resources") + into ("${buildDir}") +} + +tasks.withType(org.gradle.api.tasks.compile.JavaCompile){ + compileTask -> compileTask.dependsOn copyLibs +} + +tasks.withType(org.gradle.api.tasks.compile.JavaCompile){ + compileTask -> compileTask.dependsOn copyVtmResources +} + +tasks.withType(org.gradle.api.tasks.compile.JavaCompile){ + compileTask -> compileTask.dependsOn copyVtmThemesResources } diff --git a/vtm-ios/robovm.properties b/vtm-ios/robovm.properties index b94925cd..d7bff069 100644 --- a/vtm-ios/robovm.properties +++ b/vtm-ios/robovm.properties @@ -1,7 +1,7 @@ # #Fri May 31 13:01:40 CEST 2013 app.version=1.0 -app.id=com.noxymo.opensciencemap +app.id=de.longri.libgdx.mapsforge app.mainclass=org.oscim.ios.RobovmLauncher app.executable=VtmApp app.build=1 diff --git a/vtm-ios/robovm.xml b/vtm-ios/robovm.xml index d6e6a9f4..8180d96b 100644 --- a/vtm-ios/robovm.xml +++ b/vtm-ios/robovm.xml @@ -1,37 +1,47 @@ - ${app.executable} - ${app.mainclass} - ios - thumbv7 - ios - Info.plist.xml - - - ../vtm-themes/resources/assets - - ** - - true - - - data - - - - com.badlogic.gdx.scenes.scene2d.ui.* - - - ../vtm-ext-libs/ios/libgdx.a - ../vtm-ext-libs/ios/libObjectAL.a - ../vtm-ext-libs/ios/libvtm-jni.a - - - UIKit - OpenGLES - QuartzCore - CoreGraphics - OpenAL - AudioToolbox - AVFoundation - + ${app.executable} + ${app.mainclass} + ios + thumbv7 + ios + Info.plist.xml + + + ./build/assets + + ** + + true + + + data + + + + com.badlogic.gdx.scenes.scene2d.ui.* + com.badlogic.gdx.graphics.g3d.particles.** + com.android.okhttp.HttpHandler + com.android.okhttp.HttpsHandler + com.android.org.conscrypt.** + com.android.org.bouncycastle.jce.provider.BouncyCastleProvider + com.android.org.bouncycastle.jcajce.provider.keystore.BC$Mappings + com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi + com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi$Std + com.android.org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi + com.android.org.bouncycastle.crypto.digests.AndroidDigestFactoryOpenSSL + org.apache.harmony.security.provider.cert.DRLCertFactory + org.apache.harmony.security.provider.crypto.CryptoProvider + + + build/natives/libvtm-jni.a + + + UIKit + OpenGLES + QuartzCore + CoreGraphics + OpenAL + AudioToolbox + AVFoundation + \ No newline at end of file diff --git a/vtm-ios/src/org/oscim/ios/IOSMapApp.java b/vtm-ios/src/org/oscim/ios/IOSMapApp.java new file mode 100644 index 00000000..4a232a1a --- /dev/null +++ b/vtm-ios/src/org/oscim/ios/IOSMapApp.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013 Hannes Janetzek + * Copyright 2016 Longri + * + * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.ios; + + +import org.oscim.backend.GLAdapter; +import org.oscim.gdx.GdxAssets; +import org.oscim.gdx.GdxMap; +import org.oscim.ios.backend.IosGL; +import org.oscim.ios.backend.IosGraphics; + + +public class IOSMapApp extends GdxMap { + + public static void init() { + + // init globals + IosGraphics.init(); + GdxAssets.init("assets/"); + GLAdapter.init(new IosGL()); + } +} diff --git a/vtm-ios/src/org/oscim/ios/RobovmLauncher.java b/vtm-ios/src/org/oscim/ios/RobovmLauncher.java index 7b7d541a..1b157a34 100644 --- a/vtm-ios/src/org/oscim/ios/RobovmLauncher.java +++ b/vtm-ios/src/org/oscim/ios/RobovmLauncher.java @@ -1,58 +1,70 @@ package org.oscim.ios; -import org.oscim.backend.GLAdapter; -import org.oscim.gdx.GdxMap; -import org.oscim.ios.backend.IosGLAdapter; -import org.oscim.ios.backend.IosGraphics; -import org.oscim.layers.tile.buildings.BuildingLayer; -import org.oscim.layers.tile.vector.VectorTileLayer; -import org.oscim.layers.tile.vector.labeling.LabelLayer; -import org.oscim.theme.VtmThemes; -import org.oscim.tiling.TileSource; -import org.oscim.tiling.source.oscimap4.OSciMap4TileSource; -import org.robovm.apple.glkit.GLKViewDrawableStencilFormat; -import org.robovm.cocoatouch.foundation.NSAutoreleasePool; -import org.robovm.cocoatouch.uikit.UIApplication; - import com.badlogic.gdx.backends.iosrobovm.IOSApplication; import com.badlogic.gdx.backends.iosrobovm.IOSApplicationConfiguration; +import org.oscim.backend.CanvasAdapter; +import org.oscim.layers.tile.buildings.BuildingLayer; +import org.oscim.layers.tile.vector.VectorTileLayer; +import org.oscim.layers.tile.vector.labeling.LabelLayer; +import org.oscim.map.Map; +import org.oscim.theme.VtmThemes; +import org.oscim.tiling.source.oscimap4.OSciMap4TileSource; +import org.robovm.apple.foundation.NSAutoreleasePool; +import org.robovm.apple.glkit.GLKViewDrawableStencilFormat; +import org.robovm.apple.uikit.UIApplication; +import org.robovm.apple.uikit.UIDevice; +import org.robovm.apple.uikit.UIScreen; public class RobovmLauncher extends IOSApplication.Delegate { - @Override - protected IOSApplication createApplication() { - IOSApplicationConfiguration config = new IOSApplicationConfiguration(); - config.orientationLandscape = true; - config.orientationPortrait = true; - config.stencilFormat = GLKViewDrawableStencilFormat._8; - return new IOSApplication(new GdxMap() { - @Override - public void createLayers() { - TileSource tileSource = new OSciMap4TileSource(); + @Override + protected IOSApplication createApplication() { - //initDefaultLayers(tileSource, false,true, false); - VectorTileLayer l = mMap.setBaseMap(tileSource); - mMap.setTheme(VtmThemes.NEWTRON); - mMap.layers().add(new BuildingLayer(mMap, l)); - mMap.layers().add(new LabelLayer(mMap, l)); + IOSApplicationConfiguration config = new IOSApplicationConfiguration(); + config.orientationLandscape = true; + config.orientationPortrait = true; + config.stencilFormat = GLKViewDrawableStencilFormat._8; - // mMap.getLayers().add(new GenericLayer(mMap, new - // GridRenderer(1,new Line(Color.LTGRAY, 1.2f),null))); + float scale = (float)(getIosVersion() >= 8 ? UIScreen.getMainScreen().getNativeScale() : UIScreen.getMainScreen() + .getScale()); - mMap.setMapPosition(53.1, 8.8, 1 << 14); - } + CanvasAdapter.dpi *= scale; - }, config); - } + IOSMapApp iosMapApp = new IOSMapApp() { + @Override + public void createLayers() { + Map map = getMap(); - public static void main(String[] argv) { - NSAutoreleasePool pool = new NSAutoreleasePool(); - System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "TRACE"); - IosGraphics.init(); - GLAdapter.init(new IosGLAdapter()); + VectorTileLayer l = map.setBaseMap(new OSciMap4TileSource()); - UIApplication.main(argv, null, RobovmLauncher.class); - pool.drain(); - } + map.layers().add(new BuildingLayer(map, l)); + map.layers().add(new LabelLayer(map, l)); + + map.setTheme(VtmThemes.DEFAULT); + map.setMapPosition(53.075, 8.808, 1 << 17); + } + + }; + + IOSMapApp.init(); + + return new IOSApplication(iosMapApp, config); + } + + + private int getIosVersion () { + String systemVersion = UIDevice.getCurrentDevice().getSystemVersion(); + return Integer.parseInt(systemVersion.split("\\.")[0]); + } + + + public static void main(String[] argv) { + NSAutoreleasePool pool = new NSAutoreleasePool(); + System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "TRACE"); + IOSMapApp.init(); + + UIApplication.main(argv, null, RobovmLauncher.class); + pool.drain(); + } } diff --git a/vtm-ios/src/org/oscim/ios/backend/IosBitmap.java b/vtm-ios/src/org/oscim/ios/backend/IosBitmap.java index 71fee475..8394145c 100644 --- a/vtm-ios/src/org/oscim/ios/backend/IosBitmap.java +++ b/vtm-ios/src/org/oscim/ios/backend/IosBitmap.java @@ -1,77 +1,219 @@ +/* + * Copyright 2016 Longri + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ package org.oscim.ios.backend; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Pixmap; +import org.oscim.backend.AssetAdapter; +import org.oscim.backend.GL; +import org.oscim.backend.canvas.Bitmap; +import org.oscim.backend.canvas.Color; +import org.robovm.apple.coregraphics.*; +import org.robovm.apple.foundation.NSData; +import org.robovm.apple.uikit.UIColor; +import org.robovm.apple.uikit.UIImage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import org.oscim.backend.GL20; -import org.oscim.backend.canvas.Bitmap; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.g2d.Gdx2DPixmap; - +/** + * iOS specific implementation of {@link Bitmap}
+ *
+ * Created by Longri on 25.06.16. + */ public class IosBitmap implements Bitmap { - Pixmap pixmap; - boolean disposable; + static final Logger log = LoggerFactory.getLogger(IosBitmap.class); - /** always argb8888 */ - public IosBitmap(int width, int height, int format) { - pixmap = new Pixmap(width, height, Pixmap.Format.RGBA8888); - } + final CGBitmapContext cgBitmapContext; + final int width; + final int height; + Pixmap pixmap; - public IosBitmap(String fileName) { - FileHandle handle = Gdx.files.internal(fileName); - pixmap = new Pixmap(handle); - disposable = true; - } + /** + * Constructor
+ * Create a IosBitmap with given width and height.
+ * The format is ignored and set always to ARGB8888 + * + * @param width + * @param height + * @param format ignored always ARGB8888 + */ + public IosBitmap(int width, int height, int format) { + this.width = width; + this.height = height; + this.cgBitmapContext = CGBitmapContext.create(width, height, 8, 4 * width, + CGColorSpace.createDeviceRGB(), CGImageAlphaInfo.PremultipliedLast); + } - public IosBitmap(InputStream inputStream) throws IOException { - pixmap = new Pixmap(new Gdx2DPixmap(inputStream, Gdx2DPixmap.GDX2D_FORMAT_RGBA8888)); - } + /** + * Constructor
+ * Create a IosBitmap from given InputStream + * + * @param inputStream + * @throws IOException + */ + public IosBitmap(InputStream inputStream) throws IOException { + NSData data = new NSData(toByteArray(inputStream)); + CGImage image = new UIImage(data).getCGImage(); + this.width = (int) image.getWidth(); + this.height = (int) image.getHeight(); + this.cgBitmapContext = CGBitmapContext.create(width, height, 8, 4 * width, + CGColorSpace.createDeviceRGB(), CGImageAlphaInfo.PremultipliedLast); - @Override - public int getWidth() { - return pixmap.getWidth(); - } + this.cgBitmapContext.drawImage(new CGRect(0, 0, width, height), image); + image.dispose(); + } - @Override - public int getHeight() { - return pixmap.getHeight(); - } + /** + * Constructor
+ * Load a IosBitmap from Asset with given FilePath + * + * @param fileName + * @throws IOException + */ + public IosBitmap(String fileName) throws IOException { + if (fileName == null || fileName.length() == 0) { + // no image source defined + this.cgBitmapContext = null; + this.width = 0; + this.height = 0; + return; + } - @Override - public void recycle() { - // FIXME this should be called at some point in time - pixmap.dispose(); + InputStream inputStream = AssetAdapter.readFileAsStream(fileName); + if (inputStream == null) { + log.error("invalid bitmap source: " + fileName); + // no image source defined + this.cgBitmapContext = null; + this.width = 0; + this.height = 0; + return; + } - } + NSData data = new NSData(toByteArray(inputStream)); + CGImage image = new UIImage(data).getCGImage(); + this.width = (int) image.getWidth(); + this.height = (int) image.getHeight(); + this.cgBitmapContext = CGBitmapContext.create(width, height, 8, 4 * width, + CGColorSpace.createDeviceRGB(), CGImageAlphaInfo.PremultipliedLast); - @Override - public int[] getPixels() { - return null; - } + this.cgBitmapContext.drawImage(new CGRect(0, 0, width, height), image); + image.dispose(); + } - @Override - public void eraseColor(int color) { - } - @Override - public void uploadToTexture(boolean replace) { + @Override + public int getWidth() { + return this.width; + } - Gdx.gl.glTexImage2D(GL20.TEXTURE_2D, 0, pixmap.getGLInternalFormat(), - pixmap.getWidth(), pixmap.getHeight(), 0, - pixmap.getGLFormat(), pixmap.getGLType(), - pixmap.getPixels()); + @Override + public int getHeight() { + return this.height; + } - if (disposable) { - pixmap.dispose(); - } - } + @Override + public void recycle() { + if (this.cgBitmapContext != null) this.cgBitmapContext.release(); + if (this.pixmap != null) this.pixmap.dispose(); + } - @Override - public boolean isValid() { - return true; - } + @Override + public int[] getPixels() { + //Todo fill a int[] with pixmap.getPixel(x,y) + return new int[0]; + } + + @Override + public void eraseColor(int color) { + + //delete all pixels and fill with given color + + CGRect rect = new CGRect(0, 0, this.width, this.height); + this.cgBitmapContext.setFillColor(getCGColor(color)); + this.cgBitmapContext.setBlendMode(CGBlendMode.Clear); + this.cgBitmapContext.fillRect(rect); + this.cgBitmapContext.setBlendMode(CGBlendMode.Normal); + this.cgBitmapContext.fillRect(rect); + } + + @Override + public void uploadToTexture(boolean replace) { + + //create Pixmap from cgBitmapContext + UIImage uiImage = new UIImage(cgBitmapContext.toImage()); + NSData data = uiImage.toPNGData(); + byte[] encodedData = data.getBytes(); + + if (pixmap != null) { + // release outdated native pixel buffer + pixmap.dispose(); + } + + pixmap = new Pixmap(encodedData, 0, encodedData.length); + + Gdx.gl.glTexImage2D(GL.TEXTURE_2D, 0, pixmap.getGLInternalFormat(), + pixmap.getWidth(), pixmap.getHeight(), 0, + pixmap.getGLFormat(), pixmap.getGLType(), + pixmap.getPixels()); + + data.dispose(); + uiImage.dispose(); + encodedData = null; + + } + + @Override + public boolean isValid() { + return this.cgBitmapContext != null; + } + + + /** + * Returns a ByteArray from InputStream + * + * @param in InputStream + * @return + * @throws IOException + */ + static byte[] toByteArray(InputStream in) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buff = new byte[8192]; + while (in.read(buff) > 0) { + out.write(buff); + } + out.close(); + return out.toByteArray(); + } + + /** + * Returns the CGColor from given int + * + * @param color + * @return + */ + static CGColor getCGColor(int color) { + return UIColor.fromRGBA( + Color.a(color), + Color.g(color), + Color.b(color), + Color.r(color)) + .getCGColor(); + } } diff --git a/vtm-ios/src/org/oscim/ios/backend/IosCanvas.java b/vtm-ios/src/org/oscim/ios/backend/IosCanvas.java index 7587f028..952f005f 100644 --- a/vtm-ios/src/org/oscim/ios/backend/IosCanvas.java +++ b/vtm-ios/src/org/oscim/ios/backend/IosCanvas.java @@ -1,78 +1,64 @@ +/* + * Copyright 2016 Longri + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ package org.oscim.ios.backend; import org.oscim.backend.canvas.Bitmap; import org.oscim.backend.canvas.Canvas; import org.oscim.backend.canvas.Paint; +import org.robovm.apple.coregraphics.CGBitmapContext; +import org.robovm.apple.coregraphics.CGRect; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.TextureData; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.BitmapFont.Glyph; - +/** + * iOS specific implementation of {@link Canvas}
+ *
+ * Created by Longri on 25.06.16. + */ public class IosCanvas implements Canvas { - IosBitmap bitmap; - static BitmapFont font = new BitmapFont(); + static final Logger log = LoggerFactory.getLogger(IosCanvas.class); - public IosCanvas() { - // canvas comes with gdx pixmap - } + CGBitmapContext cgBitmapContext; - @Override - public void setBitmap(Bitmap bitmap) { - this.bitmap = (IosBitmap) bitmap; - this.bitmap.pixmap.setColor(0); - this.bitmap.pixmap.fill(); - } + @Override + public void setBitmap(Bitmap bitmap) { + cgBitmapContext = ((IosBitmap) bitmap).cgBitmapContext; + } - @Override - public void drawText(String string, float x, float y, Paint paint) { - if (bitmap == null) { - // log.debug("no bitmap set"); - return; - } + @Override + public void drawText(String string, float x, float y, Paint fill, Paint stroke) { - // IosPaint p = (IosPaint) paint; + //flip Y-axis + y = this.cgBitmapContext.getHeight() - y; - Pixmap pixmap = bitmap.pixmap; + IosPaint iosFill = (IosPaint) fill; + if (stroke != null) { + IosPaint iosStroke = (IosPaint) stroke; + iosFill.setStrokeWidth(iosStroke.strokeWidth); + iosFill.setStrokeColor(iosStroke.getColor()); + } + iosFill.drawLine(this.cgBitmapContext, string, x, y); + } - TextureData td = font.getRegion().getTexture().getTextureData(); - if (!td.isPrepared()) - td.prepare(); - - Pixmap f = td.consumePixmap(); - - int adv = (int) x; - Glyph last = null; - - int ch = (int) font.getCapHeight(); - int h = (int) font.getLineHeight(); - int yy = (int) (y - font.getLineHeight()); - if (y < 0) - y = 0; - - // pixmap.setColor(0xff0000ff); - // int w = (int) font.getBounds(string).width; - // pixmap.drawRectangle((int) x - 4, (int) y - 4, w + 8, h + 8); - - for (int i = 0; i < string.length(); i++) { - char c = string.charAt(i); - Glyph g = font.getData().getGlyph(c); - if (g == null) - g = font.getData().getGlyph(' '); - - if (i > 0) - adv += last.getKerning(c); - pixmap.drawPixmap(f, adv, //- g.xoffset, - yy - (g.height + g.yoffset) - (h - ch), - g.srcX, g.srcY, - g.width, g.height); - adv += g.width; - last = g; - } - } - - @Override - public void drawBitmap(Bitmap bitmap, float x, float y) { - } + @Override + public void drawBitmap(Bitmap bitmap, float x, float y) { + this.cgBitmapContext.saveGState(); + this.cgBitmapContext.translateCTM(x, y); + this.cgBitmapContext.drawImage(new CGRect(0, 0, bitmap.getWidth(), bitmap.getHeight()), + ((IosBitmap) bitmap).cgBitmapContext.toImage()); + this.cgBitmapContext.restoreGState(); + } } diff --git a/vtm-ios/src/org/oscim/ios/backend/IosGL.java b/vtm-ios/src/org/oscim/ios/backend/IosGL.java new file mode 100644 index 00000000..568f51a0 --- /dev/null +++ b/vtm-ios/src/org/oscim/ios/backend/IosGL.java @@ -0,0 +1,745 @@ +/* + * Copyright 2016 Longri + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.ios.backend; + +import com.badlogic.gdx.backends.iosrobovm.IOSGLES20; + +import org.oscim.backend.GL; + +import java.nio.Buffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +/** + * iOS specific implementation of {@link GL}
+ *
+ * Created by Longri on 25.06.16. + */ +public class IosGL implements GL { + + private static final IOSGLES20 iOSGL = new IOSGLES20(); + + public void activeTexture(int texture) { + iOSGL.glActiveTexture(texture); + } + + public void bindTexture(int target, int texture) { + iOSGL.glBindTexture(target, texture); + } + + public void blendFunc(int sfactor, int dfactor) { + iOSGL.glBlendFunc(sfactor, dfactor); + } + + public void clear(int mask) { + iOSGL.glClear(mask); + } + + public void clearColor(float red, float green, float blue, float alpha) { + iOSGL.glClearColor(red, green, blue, alpha); + } + + public void clearDepthf(float depth) { + iOSGL.glClearDepthf(depth); + } + + public void clearStencil(int s) { + iOSGL.glClearStencil(s); + } + + public void colorMask(boolean red, boolean green, boolean blue, boolean alpha) { + iOSGL.glColorMask(red, green, blue, alpha); + } + + public void compressedTexImage2D(int target, int level, int internalformat, int width, + int height, int border, + int imageSize, Buffer data) { + iOSGL.glCompressedTexImage2D( + target, + level, + internalformat, + width, + height, + border, + imageSize, + data); + } + + public void compressedTexSubImage2D(int target, int level, int xoffset, int yoffset, + int width, int height, int format, + int imageSize, Buffer data) { + iOSGL.glCompressedTexSubImage2D( + target, + level, + xoffset, + yoffset, + width, + height, + format, + imageSize, + data); + } + + public void copyTexImage2D(int target, int level, int internalformat, int x, int y, + int width, int height, int border) { + iOSGL.glCopyTexImage2D( + target, + level, + internalformat, + x, + y, + width, + height, + border); + } + + public void copyTexSubImage2D(int target, int level, int xoffset, int yoffset, int x, int y, + int width, int height) { + iOSGL.glCopyTexSubImage2D( + target, + level, + xoffset, + yoffset, + x, + y, + width, + height); + } + + public void cullFace(int mode) { + iOSGL.glCullFace(mode); + } + + public void deleteTextures(int n, IntBuffer textures) { + iOSGL.glDeleteTextures(n, textures); + } + + public void depthFunc(int func) { + iOSGL.glDepthFunc(func); + } + + public void depthMask(boolean flag) { + iOSGL.glDepthMask(flag); + } + + public void depthRangef(float zNear, float zFar) { + iOSGL.glDepthRangef(zNear, zFar); + } + + public void disable(int cap) { + iOSGL.glDisable(cap); + } + + public void drawArrays(int mode, int first, int count) { + iOSGL.glDrawArrays(mode, first, count); + } + + public void drawElements(int mode, int count, int type, Buffer indices) { + iOSGL.glDrawElements(mode, count, type, indices); + } + + public void enable(int cap) { + iOSGL.glEnable(cap); + } + + public void finish() { + iOSGL.glFinish(); + } + + public void flush() { + iOSGL.glFlush(); + } + + public void frontFace(int mode) { + iOSGL.glFrontFace(mode); + } + + public void genTextures(int n, IntBuffer textures) { + iOSGL.glGenTextures(n, textures); + } + + public int getError() { + return iOSGL.glGetError(); + } + + public void getIntegerv(int pname, IntBuffer params) { + iOSGL.glGetIntegerv(pname, params); + } + + public String getString(int name) { + return iOSGL.glGetString(name); + } + + public void hint(int target, int mode) { + iOSGL.glHint(target, mode); + } + + public void lineWidth(float width) { + iOSGL.glLineWidth(width); + } + + public void pixelStorei(int pname, int param) { + iOSGL.glPixelStorei(pname, param); + } + + public void polygonOffset(float factor, float units) { + iOSGL.glPolygonOffset(factor, units); + } + + public void readPixels(int x, int y, int width, int height, int format, int type, + Buffer pixels) { + iOSGL.glReadPixels( + x, + y, + width, + height, + format, + type, + pixels); + } + + public void scissor(int x, int y, int width, int height) { + iOSGL.glScissor(x, y, width, height); + } + + public void stencilFunc(int func, int ref, int mask) { + iOSGL.glStencilFunc(func, ref, mask); + } + + public void stencilMask(int mask) { + iOSGL.glStencilMask(mask); + } + + public void stencilOp(int fail, int zfail, int zpass) { + iOSGL.glStencilOp(fail, zfail, zpass); + } + + public void texImage2D(int target, int level, int internalFormat, int width, int height, + int border, int format, int type, + Buffer pixels) { + iOSGL.glTexImage2D( + target, + level, + internalFormat, + width, + height, + border, + format, + type, + pixels); + } + + public void texParameterf(int target, int pname, float param) { + iOSGL.glTexParameterf(target, pname, param); + } + + public void texSubImage2D(int target, int level, int xoffset, int yoffset, int width, + int height, int format, int type, + Buffer pixels) { + iOSGL.glTexSubImage2D( + target, + level, + xoffset, + yoffset, + width, + height, + format, + type, + pixels); + } + + public void viewport(int x, int y, int width, int height) { + iOSGL.glViewport(x, y, width, height); + } + + public void getFloatv(int pname, FloatBuffer params) { + iOSGL.glGetFloatv(pname, params); + } + + public void getTexParameterfv(int target, int pname, FloatBuffer params) { + iOSGL.glGetTexParameterfv(target, pname, params); + } + + public void texParameterfv(int target, int pname, FloatBuffer params) { + iOSGL.glTexParameterfv(target, pname, params); + } + + public void bindBuffer(int target, int buffer) { + iOSGL.glBindBuffer(target, buffer); + } + + public void bufferData(int target, int size, Buffer data, int usage) { + iOSGL.glBufferData(target, size, data, usage); + } + + public void bufferSubData(int target, int offset, int size, Buffer data) { + iOSGL.glBufferSubData(target, offset, size, data); + } + + public void deleteBuffers(int n, IntBuffer buffers) { + iOSGL.glDeleteBuffers(n, buffers); + } + + public void getBufferParameteriv(int target, int pname, IntBuffer params) { + iOSGL.glGetBufferParameteriv(target, pname, params); + } + + public void genBuffers(int n, IntBuffer buffers) { + iOSGL.glGenBuffers(n, buffers); + } + + public void getTexParameteriv(int target, int pname, IntBuffer params) { + iOSGL.glGetTexParameteriv(target, pname, params); + } + + public boolean isBuffer(int buffer) { + return iOSGL.glIsBuffer(buffer); + } + + public boolean isEnabled(int cap) { + return iOSGL.glIsEnabled(cap); + } + + public boolean isTexture(int texture) { + return iOSGL.glIsTexture(texture); + } + + public void texParameteri(int target, int pname, int param) { + iOSGL.glTexParameteri(target, pname, param); + } + + public void texParameteriv(int target, int pname, IntBuffer params) { + iOSGL.glTexParameteriv(target, pname, params); + } + + public void drawElements(int mode, int count, int type, int indices) { + iOSGL.glDrawElements(mode, count, type, indices); + } + + public void attachShader(int program, int shader) { + iOSGL.glAttachShader(program, shader); + } + + public void bindAttribLocation(int program, int index, String name) { + iOSGL.glBindAttribLocation(program, index, name); + } + + public void bindFramebuffer(int target, int framebuffer) { + iOSGL.glBindFramebuffer(target, framebuffer); + } + + public void bindRenderbuffer(int target, int renderbuffer) { + iOSGL.glBindRenderbuffer(target, renderbuffer); + } + + public void blendColor(float red, float green, float blue, float alpha) { + iOSGL.glBlendColor(red, green, blue, alpha); + } + + public void blendEquation(int mode) { + iOSGL.glBlendEquation(mode); + } + + public void blendEquationSeparate(int modeRGB, int modeAlpha) { + iOSGL.glBlendEquationSeparate(modeRGB, modeAlpha); + } + + public void blendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) { + iOSGL.glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); + } + + public int checkFramebufferStatus(int target) { + return iOSGL.glCheckFramebufferStatus(target); + } + + public void compileShader(int shader) { + iOSGL.glCompileShader(shader); + } + + public int createProgram() { + return iOSGL.glCreateProgram(); + } + + public int createShader(int type) { + return iOSGL.glCreateShader(type); + } + + public void deleteFramebuffers(int n, IntBuffer framebuffers) { + iOSGL.glDeleteFramebuffers(n, framebuffers); + } + + public void deleteProgram(int program) { + iOSGL.glDeleteProgram(program); + } + + public void deleteRenderbuffers(int n, IntBuffer renderbuffers) { + iOSGL.glDeleteRenderbuffers( + n, + renderbuffers); + } + + public void deleteShader(int shader) { + iOSGL.glDeleteShader(shader); + } + + public void detachShader(int program, int shader) { + iOSGL.glDetachShader(program, shader); + } + + public void disableVertexAttribArray(int index) { + iOSGL.glDisableVertexAttribArray(index); + } + + public void enableVertexAttribArray(int index) { + iOSGL.glEnableVertexAttribArray(index); + } + + public void framebufferRenderbuffer(int target, int attachment, int renderbuffertarget, + int renderbuffer) { + iOSGL.glFramebufferRenderbuffer( + target, + attachment, + renderbuffertarget, + renderbuffer); + } + + public void framebufferTexture2D(int target, int attachment, int textarget, int texture, + int level) { + iOSGL.glFramebufferTexture2D( + target, + attachment, + textarget, + texture, + level); + } + + public void generateMipmap(int target) { + iOSGL.glGenerateMipmap(target); + } + + public void genFramebuffers(int n, IntBuffer framebuffers) { + iOSGL.glGenFramebuffers(n, framebuffers); + } + + public void genRenderbuffers(int n, IntBuffer renderbuffers) { + iOSGL + .glGenRenderbuffers(n, renderbuffers); + } + + public String getActiveAttrib(int program, int index, IntBuffer size, Buffer type) { + return iOSGL.glGetActiveAttrib( + program, + index, + size, + type); + } + + public String getActiveUniform(int program, int index, IntBuffer size, Buffer type) { + return iOSGL.glGetActiveUniform( + program, + index, + size, + type); + } + + public void getAttachedShaders(int program, int maxcount, Buffer count, IntBuffer shaders) { + iOSGL.glGetAttachedShaders( + program, + maxcount, + count, + shaders); + } + + public int getAttribLocation(int program, String name) { + return iOSGL.glGetAttribLocation(program, name); + } + + public void getBooleanv(int pname, Buffer params) { + iOSGL.glGetBooleanv(pname, params); + } + + public void getFramebufferAttachmentParameteriv(int target, int attachment, int pname, + IntBuffer params) { + iOSGL.glGetFramebufferAttachmentParameteriv( + target, + attachment, + pname, + params); + } + + public void getProgramiv(int program, int pname, IntBuffer params) { + iOSGL.glGetProgramiv(program, pname, params); + } + + public String getProgramInfoLog(int program) { + return iOSGL.glGetProgramInfoLog(program); + } + + public void getRenderbufferParameteriv(int target, int pname, IntBuffer params) { + iOSGL.glGetRenderbufferParameteriv( + target, + pname, + params); + } + + public void getShaderiv(int shader, int pname, IntBuffer params) { + iOSGL.glGetShaderiv(shader, pname, params); + } + + public String getShaderInfoLog(int shader) { + return iOSGL.glGetShaderInfoLog(shader); + } + + public void getShaderPrecisionFormat(int shadertype, int precisiontype, IntBuffer range, + IntBuffer precision) { + iOSGL.glGetShaderPrecisionFormat( + shadertype, + precisiontype, + range, + precision); + } + + public void getShaderSource(int shader, int bufsize, Buffer length, String source) { + throw new UnsupportedOperationException("Not implemented"); + } + + public void getUniformfv(int program, int location, FloatBuffer params) { + iOSGL.glGetUniformfv(program, location, params); + } + + public void getUniformiv(int program, int location, IntBuffer params) { + iOSGL.glGetUniformiv(program, location, params); + } + + public int getUniformLocation(int program, String name) { + return iOSGL.glGetUniformLocation(program, name); + } + + public void getVertexAttribfv(int index, int pname, FloatBuffer params) { + iOSGL.glGetVertexAttribfv(index, pname, params); + } + + public void getVertexAttribiv(int index, int pname, IntBuffer params) { + iOSGL.glGetVertexAttribiv(index, pname, params); + } + + public void getVertexAttribPointerv(int index, int pname, Buffer pointer) { + iOSGL.glGetVertexAttribPointerv( + index, + pname, + pointer); + } + + public boolean isFramebuffer(int framebuffer) { + return iOSGL.glIsFramebuffer(framebuffer); + } + + public boolean isProgram(int program) { + return iOSGL.glIsProgram(program); + } + + public boolean isRenderbuffer(int renderbuffer) { + return iOSGL.glIsRenderbuffer(renderbuffer); + } + + public boolean isShader(int shader) { + return iOSGL.glIsShader(shader); + } + + public void linkProgram(int program) { + iOSGL.glLinkProgram(program); + } + + public void releaseShaderCompiler() { + iOSGL.glReleaseShaderCompiler(); + } + + public void renderbufferStorage(int target, int internalformat, int width, int height) { + iOSGL.glRenderbufferStorage(target, internalformat, width, height); + } + + public void sampleCoverage(float value, boolean invert) { + iOSGL.glSampleCoverage(value, invert); + } + + public void shaderBinary(int n, IntBuffer shaders, int binaryformat, Buffer binary, int length) { + iOSGL.glShaderBinary( + n, + shaders, + binaryformat, + binary, + length); + } + + public void shaderSource(int shader, String string) { + iOSGL.glShaderSource(shader, string); + } + + public void stencilFuncSeparate(int face, int func, int ref, int mask) { + iOSGL.glStencilFuncSeparate(face, func, ref, mask); + } + + public void stencilMaskSeparate(int face, int mask) { + iOSGL.glStencilMaskSeparate(face, mask); + } + + public void stencilOpSeparate(int face, int fail, int zfail, int zpass) { + iOSGL.glStencilOpSeparate(face, fail, zfail, zpass); + } + + public void uniform1f(int location, float x) { + iOSGL.glUniform1f(location, x); + } + + public void uniform1fv(int location, int count, FloatBuffer v) { + iOSGL.glUniform1fv(location, count, v); + } + + public void uniform1i(int location, int x) { + iOSGL.glUniform1i(location, x); + } + + public void uniform1iv(int location, int count, IntBuffer v) { + iOSGL.glUniform1iv(location, count, v); + } + + public void uniform2f(int location, float x, float y) { + iOSGL.glUniform2f(location, x, y); + } + + public void uniform2fv(int location, int count, FloatBuffer v) { + iOSGL.glUniform2fv(location, count, v); + } + + public void uniform2i(int location, int x, int y) { + iOSGL.glUniform2i(location, x, y); + } + + public void uniform2iv(int location, int count, IntBuffer v) { + iOSGL.glUniform2iv(location, count, v); + } + + public void uniform3f(int location, float x, float y, float z) { + iOSGL.glUniform3f(location, x, y, z); + } + + public void uniform3fv(int location, int count, FloatBuffer v) { + iOSGL.glUniform3fv(location, count, v); + } + + public void uniform3i(int location, int x, int y, int z) { + iOSGL.glUniform3i(location, x, y, z); + } + + public void uniform3iv(int location, int count, IntBuffer v) { + iOSGL.glUniform3iv(location, count, v); + } + + public void uniform4f(int location, float x, float y, float z, float w) { + iOSGL.glUniform4f(location, x, y, z, w); + } + + public void uniform4fv(int location, int count, FloatBuffer v) { + iOSGL.glUniform4fv(location, count, v); + } + + public void uniform4i(int location, int x, int y, int z, int w) { + iOSGL.glUniform4i(location, x, y, z, w); + } + + public void uniform4iv(int location, int count, IntBuffer v) { + iOSGL.glUniform4iv(location, count, v); + } + + public void uniformMatrix2fv(int location, int count, boolean transpose, FloatBuffer value) { + iOSGL.glUniformMatrix2fv( + location, + count, + transpose, + value); + } + + public void uniformMatrix3fv(int location, int count, boolean transpose, FloatBuffer value) { + iOSGL.glUniformMatrix3fv( + location, + count, + transpose, + value); + } + + public void uniformMatrix4fv(int location, int count, boolean transpose, FloatBuffer value) { + iOSGL.glUniformMatrix4fv( + location, + count, + transpose, + value); + } + + public void useProgram(int program) { + iOSGL.glUseProgram(program); + } + + public void validateProgram(int program) { + iOSGL.glValidateProgram(program); + } + + public void vertexAttrib1f(int indx, float x) { + iOSGL.glVertexAttrib1f(indx, x); + } + + public void vertexAttrib1fv(int indx, FloatBuffer values) { + iOSGL.glVertexAttrib1fv(indx, values); + } + + public void vertexAttrib2f(int indx, float x, float y) { + iOSGL.glVertexAttrib2f(indx, x, y); + } + + public void vertexAttrib2fv(int indx, FloatBuffer values) { + iOSGL.glVertexAttrib2fv(indx, values); + } + + public void vertexAttrib3f(int indx, float x, float y, float z) { + iOSGL.glVertexAttrib3f(indx, x, y, z); + } + + public void vertexAttrib3fv(int indx, FloatBuffer values) { + iOSGL.glVertexAttrib3fv(indx, values); + } + + public void vertexAttrib4f(int indx, float x, float y, float z, float w) { + iOSGL.glVertexAttrib4f(indx, x, y, z, w); + } + + public void vertexAttrib4fv(int indx, FloatBuffer values) { + iOSGL.glVertexAttrib4fv(indx, values); + } + + public void vertexAttribPointer(int indx, int size, int type, boolean normalized, int stride, + Buffer ptr) { + iOSGL.glVertexAttribPointer( + indx, + size, + type, + normalized, + stride, + ptr); + } + + public void vertexAttribPointer(int indx, int size, int type, boolean normalized, int stride, + int ptr) { + iOSGL.glVertexAttribPointer(indx, size, type, normalized, stride, ptr); + } +} diff --git a/vtm-ios/src/org/oscim/ios/backend/IosGLAdapter.java b/vtm-ios/src/org/oscim/ios/backend/IosGLAdapter.java deleted file mode 100644 index 68b9c893..00000000 --- a/vtm-ios/src/org/oscim/ios/backend/IosGLAdapter.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.oscim.ios.backend; - -import org.oscim.backend.GL20; - -import com.badlogic.gdx.backends.iosrobovm.IOSGLES20; - -public class IosGLAdapter extends IOSGLES20 implements GL20 { - -} diff --git a/vtm-ios/src/org/oscim/ios/backend/IosGraphics.java b/vtm-ios/src/org/oscim/ios/backend/IosGraphics.java index b06b7dfd..18ffc3f4 100644 --- a/vtm-ios/src/org/oscim/ios/backend/IosGraphics.java +++ b/vtm-ios/src/org/oscim/ios/backend/IosGraphics.java @@ -1,3 +1,17 @@ +/* + * Copyright 2016 Longri + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ package org.oscim.ios.backend; import java.io.IOException; @@ -8,53 +22,54 @@ import org.oscim.backend.canvas.Bitmap; import org.oscim.backend.canvas.Canvas; import org.oscim.backend.canvas.Paint; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * iOS specific implementation of {@link CanvasAdapter}
+ *
+ * Created by Longri on 25.06.16. + */ public class IosGraphics extends CanvasAdapter { - private static final IosGraphics INSTANCE = new IosGraphics(); - - public static CanvasAdapter get() { - return INSTANCE; - } + static final Logger log = LoggerFactory.getLogger(IosGraphics.class); public static void init() { - g = INSTANCE; + CanvasAdapter.init(new IosGraphics()); } @Override - public Canvas getCanvas() { + protected Canvas newCanvasImpl() { return new IosCanvas(); } @Override - public Paint getPaint() { + protected Paint newPaintImpl() { return new IosPaint(); } @Override - public Bitmap getBitmap(int width, int height, int format) { + protected Bitmap newBitmapImpl(int width, int height, int format) { return new IosBitmap(width, height, format); } @Override - public Bitmap decodeBitmap(InputStream inputStream) { + protected Bitmap decodeBitmapImpl(InputStream inputStream) { try { return new IosBitmap(inputStream); } catch (IOException e) { - e.printStackTrace(); + log.error("decodeBitmapImpl",e); return null; } } @Override - public Bitmap loadBitmapAsset(String fileName) { - return new IosBitmap(fileName); - - // try { - // return createBitmap(fileName); - // } catch (IOException e) { - // e.printStackTrace(); - // } - // return null; + protected Bitmap loadBitmapAssetImpl(String fileName) { + try { + return new IosBitmap(fileName); + } catch (IOException e) { + log.error("loadBitmapAssetImpl",e); + return null; + } } - } diff --git a/vtm-ios/src/org/oscim/ios/backend/IosPaint.java b/vtm-ios/src/org/oscim/ios/backend/IosPaint.java index 53f7e701..b580115c 100644 --- a/vtm-ios/src/org/oscim/ios/backend/IosPaint.java +++ b/vtm-ios/src/org/oscim/ios/backend/IosPaint.java @@ -1,55 +1,326 @@ +/* + * Copyright 2016 Longri + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ package org.oscim.ios.backend; import org.oscim.backend.canvas.Paint; +import org.robovm.apple.coregraphics.CGAffineTransform; +import org.robovm.apple.coregraphics.CGBitmapContext; +import org.robovm.apple.coregraphics.CGBlendMode; +import org.robovm.apple.coregraphics.CGLineCap; +import org.robovm.apple.coretext.CTFont; +import org.robovm.apple.coretext.CTLine; +import org.robovm.apple.foundation.NSAttributedString; +import org.robovm.apple.uikit.NSAttributedStringAttributes; +import org.robovm.apple.uikit.UIColor; +import org.robovm.apple.uikit.UIFont; +import org.robovm.apple.uikit.UIFontWeight; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; + + +/** + * iOS specific implementation of {@link Paint}
+ *
+ * Created by Longri on 25.06.16. + */ public class IosPaint implements Paint { + private static final Logger log = LoggerFactory.getLogger(IosPaint.class); - @Override - public int getColor() { - return 0; - } + private static final String DEFAULT_FONT_NAME = UIFont.getSystemFont(1, UIFontWeight.Semibold).getFontDescriptor().getPostscriptName(); + private static final String DEFAULT_FONT_NAME_BOLD = UIFont.getSystemFont(1, UIFontWeight.Bold).getFontDescriptor().getPostscriptName(); + private static final String DEFAULT_FONT_NAME_ITALIC = UIFont.getItalicSystemFont(1).getFontDescriptor().getPostscriptName(); - @Override - public void setColor(int color) { - } + private final NSAttributedStringAttributes attribs = new NSAttributedStringAttributes(); + private CGLineCap cap = CGLineCap.Butt; + private Style style; + private float textSize; + private FontFamily fontFamily; + private FontStyle fontStyle; + private int colorInt; + private int strokeColorInt; + private CTLine ctLine; + private boolean ctLineIsDirty = true; + private String lastText = ""; + private float descent; + private float fontHeight; + private final static HashMap fontHashMap = new HashMap<>(); - @Override - public void setStrokeCap(Cap cap) { - } + float strokeWidth; - @Override - public void setStrokeWidth(float width) { - } + @Override + public int getColor() { + return this.colorInt; + } - @Override - public void setStyle(Style style) { - } + @Override + public void setColor(int color) { + if (colorInt == color) return; + this.colorInt = color; + synchronized (attribs) { + attribs.setForegroundColor(getUiColor(color)); + } + ctLineIsDirty = true; + } - @Override - public void setTextAlign(Align align) { - } + public void setStrokeColor(int color) { + if (strokeColorInt == color) return; + this.strokeColorInt = color; + synchronized (attribs) { + attribs.setStrokeColor(getUiColor(color)); + } + ctLineIsDirty = true; + } - @Override - public void setTextSize(float textSize) { - } + private UIColor getUiColor(int color) { + float colorA = ((color & 0xff000000) >>> 24) / 255f; + float colorR = ((color & 0xff0000) >>> 16) / 255f; + float colorG = ((color & 0xff00) >>> 8) / 255f; + float colorB = (color & 0xff) / 255f; + return new UIColor(colorR, colorG, colorB, colorA); + } - @Override - public void setTypeface(FontFamily fontFamily, FontStyle fontStyle) { - } + @Override + public void setStrokeCap(Cap cap) { + this.cap = getLineCap(cap); + } - @Override - public float measureText(String text) { - return IosCanvas.font.getBounds(text).width; - } - @Override - public float getFontHeight() { - return IosCanvas.font.getLineHeight(); - } + @Override + public void setStrokeWidth(float width) { + if (this.strokeWidth == width) return; + this.strokeWidth = width; + this.ctLineIsDirty = true; + } - @Override - public float getFontDescent() { - return IosCanvas.font.getDescent(); - } + @Override + public void setStyle(Style style) { + this.style = style; + } + @Override + public void setTextAlign(Align align) { +// TODO: set Align + } + + @Override + public void setTextSize(float textSize) { + if (this.textSize != textSize) { + this.textSize = textSize; + createIosFont(); + ctLineIsDirty = true; + } + } + + @Override + public void setTypeface(FontFamily fontFamily, FontStyle fontStyle) { + if (fontFamily != this.fontFamily + || fontStyle != this.fontStyle) { + + this.fontFamily = fontFamily; + this.fontStyle = fontStyle; + createIosFont(); + ctLineIsDirty = true; + } + } + + + @Override + public float measureText(String text) { + if (ctLineIsDirty || !text.equals(lastText)) { + ctLineIsDirty = true; + createCTLine(text); + } + return (float) ctLine.getWidth(); + } + + + private void createCTLine(String text) { + if (ctLineIsDirty) { + synchronized (attribs) { + /* + The sign of the value for NSStrokeWidthAttributeName is interpreted as a mode; + it indicates whether the attributed string is to be filled, stroked, or both. + Specifically, a zero value displays a fill only, while a positive value displays a stroke only. + A negative value allows displaying both a fill and stroke. + + !!!!! + NOTE: The value of NSStrokeWidthAttributeName is interpreted as a percentage of the font point size. + */ + float strokeWidthPercent = -(this.strokeWidth / this.textSize * 50); + attribs.setStrokeWidth(strokeWidthPercent); + + NSAttributedString attributedString = new NSAttributedString(text, attribs); + ctLine = CTLine.create(attributedString); + attributedString.dispose(); + } + lastText = text; + ctLineIsDirty = false; + } + } + + + private void createIosFont() { + + /* + DEVICE_DEFAULT = [iOS == getDeviceDefault()], [Android == 'Roboto'] + MONOSPACE = [iOS == 'Courier'], [Android == 'Droid Sans Mono'] + SANS_SERIF = [iOS == 'Verdena'], [Android == 'Droid Sans'] + SERIF = [iOS == 'Georgia'], [Android == 'Droid Serif'] + */ + + + String fontname = DEFAULT_FONT_NAME; + switch (this.fontFamily) { + case DEFAULT: + // set Style + switch (this.fontStyle) { + case NORMAL: + fontname = DEFAULT_FONT_NAME; + break; + case BOLD: + fontname = DEFAULT_FONT_NAME_BOLD; + break; + case BOLD_ITALIC: + fontname = DEFAULT_FONT_NAME_BOLD; + break; + case ITALIC: + fontname = DEFAULT_FONT_NAME_ITALIC; + break; + } + break; + case DEFAULT_BOLD: + // ignore style + fontname = DEFAULT_FONT_NAME_BOLD; + break; + case MONOSPACE: + // set Style + switch (this.fontStyle) { + case NORMAL: + fontname = "CourierNewPS-BoldMT"; + break; + case BOLD: + fontname = "CourierNewPS-BoldMT"; + break; + case BOLD_ITALIC: + fontname = "CourierNewPS-BoldMT"; + break; + case ITALIC: + fontname = "CourierNewPS-BoldMT"; + break; + } + break; + case SANS_SERIF: + // set Style + switch (this.fontStyle) { + case NORMAL: + fontname = "Verdana"; + break; + case BOLD: + fontname = "Verdana-Bold"; + break; + case BOLD_ITALIC: + fontname = "Verdana-BoldItalic"; + break; + case ITALIC: + fontname = "Verdana-Italic"; + break; + } + break; + case SERIF: + // set Style + switch (this.fontStyle) { + case NORMAL: + fontname = "Georgia"; + break; + case BOLD: + fontname = "Georgia-Bold"; + break; + case BOLD_ITALIC: + fontname = "Georgia-BoldItalic"; + break; + case ITALIC: + fontname = "Georgia-Italic"; + break; + } + break; + } + + synchronized (attribs) { + String key = fontname + this.textSize; + + //try to get buffered font + UIFont font = fontHashMap.get(key); + + if (font == null) { + CTFont ctFont = CTFont.create(fontname, this.textSize, CGAffineTransform.Identity()); + + descent = (float) ctFont.getDescent(); + fontHeight = (float) ctFont.getBoundingBox().getHeight(); + + font = ctFont.as(UIFont.class); + log.debug("Put Font to buffer :" + key); + fontHashMap.put(key, font); + } + + CTFont ctFont = font.as(CTFont.class); + descent = (float) ctFont.getDescent(); + fontHeight = (float) ctFont.getBoundingBox().getHeight(); + + attribs.setFont(font); + } + } + + + public void drawLine(CGBitmapContext cgBitmapContext, String text, float x, float y) { + if (ctLineIsDirty || !text.equals(lastText)) { + ctLineIsDirty = true; + createCTLine(text); + } + cgBitmapContext.saveGState(); + cgBitmapContext.setShouldAntialias(true); + cgBitmapContext.setTextPosition(x, y + descent); + cgBitmapContext.setBlendMode(CGBlendMode.Overlay); + + ctLine.draw(cgBitmapContext); + + cgBitmapContext.restoreGState(); + } + + @Override + public float getFontHeight() { + return fontHeight; + } + + @Override + public float getFontDescent() { + return descent; + } + + private CGLineCap getLineCap(Cap cap) { + switch (cap) { + case BUTT: + return CGLineCap.Butt; + case ROUND: + return CGLineCap.Round; + case SQUARE: + return CGLineCap.Square; + } + return CGLineCap.Butt; + } } diff --git a/vtm-ios/vtm-natives-ios.jar b/vtm-ios/vtm-natives-ios.jar new file mode 100644 index 00000000..a6590d2b Binary files /dev/null and b/vtm-ios/vtm-natives-ios.jar differ