Chinese character printed not corrected in SourceHanSansSC-Medium.otf - javascript

Description:
I've encountered a problem that a chinese character (胸) displays normally in html with 'SourceHanSansSC-Medium.otf' font but printed in a quite strange position while the html is printed by pdf reactor service.
If i replace it with SourceHanSansSC-Norml.otf, then both the html preview and the generated pdf by pdf-reacor are going well, only the SourceHanSansSC-Medium.otf useage will lead to this issue.
My environment :
System: Mac os 10.12.6, Java 8 Pdf reactor version: 10.0.
Preparation:
I pulled the pdf reactor image from docker hub and run it as a local docker container, that my app could visit it by http://localhost:9423/service/rest.
I write an very simple html contains the the error character in both SourceHanSansSC-Medium.otf and SourceHanSansSC-Medium.otf, just to compare the result of two fonts. They both display correctly in html preview, and only the medium font character would be printed in an incorrect position.
I mapped my html local parent path to pdf-reactor /ro/config to ensure the pdf-reactor is able to get the html to print.
HTML code:
This is My html code 'print_sc_font.html' (I attached the html the fonts in a zip):
<html>
<head>
<style type="text/css">
#font-face {
font-family: shssc-normal;
src: url("./SourceHanSansSC-Normal.otf");
}
#font-face {
font-family: shssc-medium;
src: url("./SourceHanSansSC-Medium.otf");
}
</style>
</head>
<body>
<div style="font-family: shssc-normal;">Print by SC Normal Font: 肺癌</div>
<div style="font-family: shssc-medium;">Print by SC Medium Font: 肺癌</div>
</body>
</html>
Html Preview is ok
Java Print Code (PdfReactorTest.java):
package com.gc.dev;
import com.realobjects.pdfreactor.webservice.client.Configuration;
import com.realobjects.pdfreactor.webservice.client.PDFreactor;
import com.realobjects.pdfreactor.webservice.client.PDFreactorWebserviceException;
import com.realobjects.pdfreactor.webservice.client.Result;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class PDFReactorTest {
public static void main(String[] args) {
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
String timeStamp = dateFormat.format(date);
// Create new PDFreactor instance
PDFreactor pdfReactor = new PDFreactor("http://localhost:9423/service/rest");
// Create a new configuration object
Configuration config = new Configuration()
// Specify the input document for Mac systems (adapt path if necessary) .setDocument("file:///ro/config/html/test/print_sc_font.html")
// Enable javaScriptSettings
.setJavaScriptMode(Configuration.JavaScriptMode.ENABLED)
// Set an appropriate log level
.setLogLevel(Configuration.LogLevel.DEBUG)
// Sets the title of the created PDF
.setTitle("Demonstration of PDFreactor Java API")
// Sets the author of the created PDF
.setAuthor("Myself")
// Enables links in the PDF document.
.setAddLinks(true)
// Enable bookmarks in the PDF document
.setAddBookmarks(true)
// Set some viewer preferences
.setViewerPreferences(
Configuration.ViewerPreferences.FIT_WINDOW,
Configuration.ViewerPreferences.PAGE_MODE_USE_THUMBS)
// Add user style sheets
.setUserStyleSheets(
new Configuration.Resource().setContent("#page {" +
"#top-center {" +
"content: 'PDFreactor Java API demonstration';" +
"}" +
" #bottom-center {" +
"content: \"Created on " + timeStamp + "\";" +
"}" +
"}"),
new Configuration.Resource().setUri("common.css"));
FileOutputStream fos = null;
try {
// Render document and save result to result
Result result = pdfReactor.convert(config);
if (result != null) {
byte[] pdf = result.getDocument();
//Save the pdf at the desired location
fos = new FileOutputStream("result.pdf");
fos.write(pdf);
fos.close();
}
} catch (PDFreactorWebserviceException exception) {
Result result = exception.getResult();
System.err.println(result.getError());
} catch (Exception e) {
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
}
}
}
}
}
Result pdf:
I haved attach my code and screen snapshot.
the SourceHanSansSC-Normal.otf is too large to attach, so two font files SourceHanSansSC-Normal and SourceHanSansSC-Medium.otf could be downloaded from https://github.com/adobe-fonts/source-han-sans/tree/release/OTF/SimplifiedChinese,

We can replicate this behavior using your fonts. This is a known issue, which is reported as #7530 in our internal tracker. The issue appears to be that the font subset containing certain characters is not embedded properly. As a workaround, you could make sure the entire font is embedded by adding the property "-ro-font-embedding-type: all;" to the "#font-face" rule declaration for this font, e.g.:
#font-face {
​font-family: shssc-medium;
-ro-font-embedding-type: all;
src: url("./SourceHanSansSC-Medium.otf");
}

Related

How to generate ICS file for different calender's dynamically in reactJS

I have event data and I want user to be able to download ICS file and save it in calender of his choice
This is the function I am using but the ics file generated is only supported in outlook calender. How can I generate dynamic ICS file for all calneder type
export const saveCallInvite = (event) => {
const newEvent = { ...event, address: event?.event_url ? event?.event_url : `${event?.address?.line_1} ${event?.address?.line_2}, ${event?.address?.city} ${event?.address?.state}, ${event?.address?.country} ${event?.address?.postal_code} ` }
// Create the .ics URL
let url = [
"BEGIN:VCALENDAR",
"VERSION:2.0",
"BEGIN:VEVENT",
"DTSTART:" + newEvent.date,
"DTEND:",
"SUMMARY:" + newEvent.name,
"DESCRIPTION:" + newEvent.description,
"LOCATION:" + newEvent.address,
"BEGIN:VALARM",
"TRIGGER:-PT15M",
"REPEAT:1",
"DURATION:PT15M",
"ACTION:DISPLAY",
"DESCRIPTION:Reminder",
"END:VALARM",
"END:VEVENT",
"END:VCALENDAR"
].join("\n");
let blob = new Blob([url], { type: 'text/calendar;charset=utf-8' });
if (/msie\s|trident\/|edge\//i.test(window.navigator.userAgent)) {
// Open/Save link in IE and Edge
window.navigator.msSaveBlob(blob, `.ics`);
} else {
// Open/Save link in Modern Browsers
window.open(encodeURI("data:text/calendar;charset=utf8," + url));
}
}
Check that you have the minimum requirements for a valid ics file according to RFC5545. I see you are at least missing some VCALENDAR minimum requirements. Some calendar applications are more fussy than others, so it is best if the file is as valid as possible. See https://stackoverflow.com/a/67698638/440290
Then check your output ics file with all the ics validators. They do not all check everything and so may give you different errors and warnings.

How to upload photo from library in webview in android app

I am using webview component on my android app. Users can load images from android photo library and show these images on a web page in the webview. How can I upload these image to my backend server from javascript?
Below is my java code to handle image chooser behavior:
setWebChromeClient(new WebChromeClient() {
#Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
Intent chooser = Intent.createChooser(intent, "Select Image");
activity.startActivityForResult(chooser, ResultCode.CHOOSE_PHOTO_REQUEST);
return false;
}
});
the above code will show image picker and when a user select an image, the onActivityResult will pass the selected image path to javascript as below:
if (resultCode == Activity.RESULT_OK) {
Uri imageUri = imageReturnedIntent.getData();
Log.d("IMAGE", "choose image uri " + imageUri);
String path = getRealPathFromURI(imageUri);
Log.d("IMAGE", "choose image real path " + path);
webView.loadUrl("javascript:choosePhotos('" + path + "')");
}
public String getRealPathFromURI(Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = {MediaStore.Images.Media.DATA};
cursor = mainActivity.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
in javascript, I can put the image path on a <img src=''/> tag to show the selected images. The path is something like this: '/storage/emulated/0/DCIM/Camera/IMG_20160808_200837.jpg'
It works fine here. But now I want to upload this image to my backend server. How can javascript handle this path: /storage/emulated/0/DCIM/Camera/IMG_20160808_200837.jpg.
You Can use filePathCallback to pass the selected file to webview.
Just create a global variable
ValueCallback filePathCallback;
and assign the parameter from onShowFileChooser() method to it.
then you can use this callback in onActivityResult() to pass the selected file to webview as :
Uri results[] = new Uri[]{imageUri};
filePathCallback.onReceiveValue(results);
then on html you will get file at

Need to parse a value from other webpage. First I need to call other webpage and parse the XML value from it

I am developing one project that should show currency exchange rate, so I planned to call another webpage to get the exchange rate values from that page. I tried in Angular-js but I couldn't get the response from webpage(in Angular JS: we can call only JSON/Rest url ).I tried in XMLHttpRequest but it won't call the webpage(url) if we call the webpage from otherdomain( Beacuse of CORS ).
Similarly, I tried in Java and I successfully called the webpages and got XML but I couldn't parse the value(getting error:"un-formatted XML").
Can someone please guide me, how i can get the value from any webpage. Please let me know is there anyway that i can implement by using API call or any webservice call. If I go with API or Webservice call then should I need to communicate with IT-vendor of moneyexchange website in order to get the API/webservice to consume particular values ??.
Please help me on the same(I am ready to implement on any technology)
Java code:
package webXMRead;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class webPageXMLRead
{
public static void main(String args[]) throws URISyntaxException,
ClientProtocolException, IOException, MalformedURLException {
//For study and example purpose I took url:http://www.google.com , need to parse this website, I am not using for any profit purpose
String url = "http://www.google.com";
System.out.println("Url is careated****");
URL url2 = new URL(url);
HttpGet httpGet = new HttpGet(url);
HttpClient httpClient = new DefaultHttpClient();
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity entity = httpResponse.getEntity();
System.out.println("Entity is*****" + entity);
try {
String xmlParseString = EntityUtils.toString(entity);
System.out.println("This Stirng ***" + xmlParseString);
HttpURLConnection connection = (HttpURLConnection) url2
.openConnection();
InputStream inputStream = connection.getInputStream();
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder documentBuilder = builderFactory
.newDocumentBuilder();
Document document = documentBuilder.parse(inputStream);
document.getDocumentElement().normalize();
NodeList nodeList = document.getElementsByTagName("rss");
System.out.println("This is firstnode" + nodeList);
for (int getChild = 0; getChild < nodeList.getLength(); getChild++) {
Node Listnode = nodeList.item(getChild);
System.out.println("Into the for loop"
+ Listnode.getAttributes().getLength());
Element firstnoderss = (Element) Listnode;
System.out.println("ListNodes" + Listnode.getAttributes());
System.out.println("This is node list length"
+ nodeList.getLength());
Node Subnode = nodeList.item(getChild);
System.out.println("This is list node" + Subnode);
}
} catch (Exception exception) {
System.out.println("Exception is" + exception);
}
}
Angular-JS: (I just tried to check whether it return any any value, but no success. But I faced CORS problem in XMLHttpRequest(javascript) when i tried in different domain)
Angular-JS code:
<!DOCTYPE html>
<html>
<head>
<title>test your webservice</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article ng-app="webpage">
<section ng-controller="booksCtrl">
<h2 >{{data}} </h2>
</section>
</article>
<script type="text/javascript">
var app = angular.module('webpage', []);
app.controller('booksCtrl', function($scope, $http) {
/* $httpProvider.defaults.useXDomain = true;*/
/*delete $http.defaults.headers.common['X-Requested-With'];*/
/*just for study purpose, not for any profit usage, so for example purpose I used URL:http://www.google.com, */
$http.get("http://www.google.com")
.then(function(response) {
$scope.data=response.data;
},
function(errresponse) {
alert("err"+errresponse.status);
});
});
</script>
</body>
</html>
Basically you need to parse a HTML document. For that please use JSoup. This would be an ideal fit four your use case. Once you have the Document object in java, you can parse and get desired value from it.
String html = "<html><head><title>First parse</title></head>"
+ "<body><p>Parsed HTML into a doc.</p></body></html>";
Document doc = Jsoup.parse(html);

Is there an easy way to add the struts 1.3 html styleId attribute without touching every element?

I am currently working with legacy code to attempt to get it to work correctly in newer browsers. The code is written with Struts 1.3 and makes use of the html tag library extensively in the following manner:
<html:text property="myTextInput" maxlength="10"/>
Which produces the following html when rendered:
<input name="myTextInput" type="text" maxlength="10" value="">
In old versions of IE, one could use document.getElementById('myTextInput') to get a reference even if the element only had a name attribute and didn't have an id attribute. When using the jsp html tags, the name property generates the name attribute in the html code but doesn't generate the id attribute.
I found adding styleId to the html tag in the jsp does add the id attribute to the resulting xml, but this means I would have to touch every single html tag element in all the jsp's and change it similar to:
<html:text property="myTextInput" styleId="myTextInput" maxlength="10"/>
I also found document.getElementByName(), but this results in touching a lot of javascript and also (due to bad code), I don't know if it really is referring to an element by the id or name so this could cause some issues.
Is there an easy way to add the styleId attribute without touching every element?
I ended up writing a small java main method to deal with this. I use regex to find the html elements (select,option. text, hidden, textarea) that don't already have a styleId attribute and then add the styleId attribute with the same value as the property attribute. This could be expanded to do a bunch of files at once but right now I just wanted something to do individual files so I could easily check them against source control and make sure it worked correctly. It's a quick and dirty solution to a problem so I wouldn't have to comb through tons of jsp files manually so I'm sure there are some edge cases it doesn't deal with. With that said:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class JspModifierStyleId {
public static void main(String[] args) throws IOException {
String lineEnding = "\r\n";
String baseDir= "C:/path/to/your/directory/"; //Change this to suit your directory
String origFileName= "OriginalFile.jsp"; //Change this to suit your original file that needs the attribute added
File origFile = new File(baseDir + origFileName);
String tempFileName = "TemporaryFile.jsp";
File tempFile = new File(baseDir + tempFileName);
Pattern p = Pattern.compile("^(?!.*styleId)\\s*<html:(?:select|option|text|hidden|textarea)\\s.*property=\"([a-zA-Z1-9.]*)\".+");
FileReader in = new FileReader(origFile);
FileWriter out = new FileWriter(tempFile);
BufferedReader br = new BufferedReader(in);
BufferedWriter bw = new BufferedWriter(out);
String line;
while ((line = br.readLine()) != null) {
Matcher m = p.matcher(line);
if(m.matches()){
String strWithStyleId = line.substring(0, m.start(1)) + m.group(1) + "\" styleId=\"" + line.substring(m.start(1));
bw.write(strWithStyleId + lineEnding);
System.out.println(strWithStyleId);
}else {
bw.write(line + lineEnding);
}
}
br.close();
bw.close();
//copies back to original file, BE CAREFUL!!!
copyFile(tempFile, origFile);
}
public static void copyFile(File sourceFile, File destFile) throws IOException {
if(!destFile.exists()) {
destFile.createNewFile();
}
FileChannel source = null;
FileChannel destination = null;
try {
source = new FileInputStream(sourceFile).getChannel();
destination = new FileOutputStream(destFile).getChannel();
destination.transferFrom(source, 0, source.size());
}
finally {
if(source != null) {
source.close();
}
if(destination != null) {
destination.close();
}
}
}
}

amcharts not showing theme background in Android webview

I am using a webview to host amcharts in an android application. The basic setup for the code is that I form an HTML document programatically and load it hosted in my assets folder. The amcharts libraries are located in a subdirectory of the assets folder. So far, this setup has allowed me to generate charts in a webview with locally provided data. In order to change the chart's theme, I have been following a tutorial from the amcharts websight http://www.amcharts.com/tutorials/working-with-themes/. The tutorial allowed me to change the way the bars in the chart look, but the background remains unchanged. I have also looked at some posts reporting that the themes of other users were not working. My problem differs in the sense that the way the graph is being drawn is correct according to the theme. It is only the background that is not being set.
This is the class I use to build the test chart data.
public class AmChartsUtils {
public static String getTestHtml(String chartData) {
chartData = chartData.replace("\n", "");
return "<HTML><HEAD>" + getHeadContent(chartData)+ "<BODY>"+ getBodyContent() + "</BODY></HTML>";
}
private static String getHeadContent(String chartData) {
return "<script src=\"js/amcharts.js\" type=\"text/javascript\"></script>"+
"<script src=\"js/serial.js\" type=\"text/javascript\"></script>" +
"<script src=\"js/themes/dark.js\" type=\"text/javascript\"></script>" +
"<script src=\"js/themes/chalk.js\" type=\"text/javascript\"></script>" +
// "<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">"
getChartData(chartData);
}
private static String getChartData(String chartData) {
StringBuilder sb = new StringBuilder();
sb.append("<script type=\"text/javascript\">");
sb.append("var chartData = [");
sb.append(chartData);
sb.append("];");
sb.append(buildStartCommand());
sb.append("</script>");
return sb.toString();
}
private static String buildStartCommand() {
StringBuilder sb = new StringBuilder();
sb.append("if(document.body){");
sb.append("document.body.style.backgroundColor = \"#282828\";");
// sb.append("document.body.style.backgroundImage = \"url(\" + bgImage + \")\";");
sb.append("}");
sb.append("AmCharts.ready(function() {");
sb.append("var chart = new AmCharts.AmSerialChart(AmCharts.themes.chalk);");
sb.append("chart.dataProvider = chartData;");
sb.append("chart.categoryField = \"country\";");
sb.append("chart.angle = 30;");
sb.append("chart.depth3D = 15;");
sb.append("chart.backgroundColor = \"#282828\";");
sb.append("chart.backgroundAloha = \"1.0\";");
sb.append("var graph = new AmCharts.AmGraph();");
sb.append("graph.valueField = \"visits\";");
sb.append("graph.type = \"column\";");
sb.append("chart.addGraph(graph);");
sb.append("chart.write('chartdiv');");
sb.append("});");
return sb.toString();
}
private static String getBodyContent() {
return "<div id=\"chartdiv\" style=\"width: 400px; height: 400px;\"></div>";
}
}
Here is how the chart apears on the screen.
The expected result is the same graph with a dark chalkboard background.
Does anyone know why the background is not coming in? Thanks in advance for any help recieved.
There is a typo in your code:
sb.append("chart.backgroundAloha = \"1.0\";");
It should read this instead:
sb.append("chart.backgroundAlpha = \"1.0\";");
Also, alpha is a numeric parameter. I strongly suggest you supply it as number.
I know you won't be displaying it in some old browsers that might be thrown off by this, but it's a good idea to keep your JavaScript apps as strongly typed as possible.

Categories