CreateFont() from String

旧城冷巷雨未停 提交于 2020-03-26 04:49:31

问题


It is posible to make a variable in Processing or Java that self contain the typography (ttf or otf) in format of String to be able to load it in the same way that you can do it with images, since LoadImage () works from an array of integers. I can do it with the Images. Is there any way to do it for the case of typography? Thanks!

int[][] var = {
     // R    G    B    A
     {255,   0,   0, 128},
     {  0, 255,   0, 128}
};  

PImage loadPixelsArray(int xDiv, int yDiv, float[][] dots) {

   PImage img = createImage(xDiv, yDiv, ARGB);
   img.loadPixels();
   int size = img.pixels.length;
   for (int i = 0; i < size; i++) {
          img.pixels[i] = color(dots[i][0], dots[i][1], dots[i][2], dots[i][3]);
   }
   img.updatePixels();
   return img;
}

ps: returns PImage of 2 pixels. I need the same for PFont.


回答1:


There isn't a way to do this without resorting to some pretty gross hacks.

If you're curious, the way you might approach this is by first creating a .vlw font using George's answer. Then you'd need to write a utility program that reads in the bytes of the file as a byte array, then outputs some syntax that lets you store this as a variable. Copy that variable into your target sketch, and then you could then use a ByteArrayInputStream to pass the bytes into the PFont constructor that takes an InputStream.

So sure, it's possible to do this. But this is very hacky and you should definitely not bother trying it.

Instead, I encourage you to take a step back and think about exactly what you're trying to do. It sounds like you're trying to export a single .exe file from Processing. Note that this is not possible, even if you use the above hack to get rid of the font file!

Processing exports itself as a directory of run scripts and .jar files. It is not a single packaged executable file. To convert your Processing sketch into a .exe file, you're going to have to use something like Launch4J or JWrapper.

Note that these kinds of applications all offer support for packaging external files, which is how you should deal with your font file.

Also note that you could just store your font on the web, and then pass the URL into the loadFont() function. But again, you'll still have to deal with the multiple .jar files that Processing exports.




回答2:


In the Processing editor go to Tools > Create Font.. to create a .vlw file (Processing's font format) then in your code simply use loadFont() instead of createFont()

Be sure to run some tests in terms of the right font size and characters (especially if using special characters). In terms of rendering text Processing can do bitmaps or shapes using textMode() depending on the renderer.

Additionally, if you need to create images/pixels of text you can use PGraphics (which extends PImage)

Update It is still unclear what is that you're asking:

  • loading a font from a string(font filename) ?
  • render text to an image ?
  • get all the gyphs in a font as pixels ? something else ?

If you want to render text to an image, as mentioned above you can use PGraphics:

noSmooth();

PGraphics textImage = createGraphics(25,25);
textImage.beginDraw();
textImage.text("O!",10,15);
textImage.endDraw();

image(textImage,0,0);
image(textImage,0,0,textImage.width * 2.1,textImage.height * 2.1);
image(textImage,0,0,textImage.width * 4.5,textImage.height * 4.5);

For more details on PFont use the PFont javadoc. Notice you can get glyphs (which have images):

String[] fontNames = {"Monospaced","ProcessingSansPro-Regular"};
int NUM_FONTS = fontNames.length;
PFont[] fonts = new PFont[NUM_FONTS];
PFont font;

int FONT_SIZE = 30;
String message = "Hello World";

ArrayList<PImage> glyphImages;

void setup(){
  size(300,300);
  textAlign(CENTER);
  fill(0);

  // load fonts
  for(int i = 0 ; i < NUM_FONTS; i++){
    fonts[i] = createFont(fontNames[i],FONT_SIZE);
  }

  // set first font
  setFont(0);

}

void draw(){
  background(255);
  text(message,width * 0.5,height * 0.5);

  drawGlyphImages();

}

void keyPressed(){
  if(key == '1'){
    setFont(0);
  }
  if(key == '2'){
    setFont(1);
  }
}

void setFont(int fontIndex){
  // check font data is accessible
  if(fonts != null){

    if(fontIndex >= 0 && fontIndex < fonts.length){

      // update global reference to currently set font
      font = fonts[fontIndex];
      // tell Processing to use this font
      textFont(font,FONT_SIZE);
      // create glyph images
      glyphImages = getGlyphImages(font,message);

    }else{
      println("error: invalid array index",fontIndex,"valid range is",0,fonts.length-1);
    }

  }else{
    println("error: null fonts array");
  } 
}

ArrayList<PImage> getGlyphImages(PFont font,String message){

  ArrayList<PImage> result = new ArrayList<PImage>();

  // access font glyph images
  for(int i = 0 ; i < message.length(); i++){

    // get the each character
    char currentChar = message.charAt(i);
    // get the glyph
    PFont.Glyph glyph = font.getGlyph(currentChar);
    // if there is a glyph (space or other special character might not be encoded in the font file)
    if(glyph != null){
      // get a copy of the glyph image
      PImage glyphImage = glyph.image.get();
      // glyph PImages are in ALPHA format: for demo purposes we use a GRAY filter to set the format to RGB  
      glyphImage.filter(GRAY);
      // append the glyph image to the list
      result.add(glyphImage);
    }

  }

  return result;
}

ArrayList<PShape> getGlyphShapes(PFont font,String message){

  ArrayList<PShape> result = new ArrayList<PShape>();

  // access font glyph images
  for(int i = 0 ; i < message.length(); i++){

    // get the each character
    char currentChar = message.charAt(i);
    // get the glyph shape
    PShape glyphShape = font.getShape(currentChar);
    // if there is a glyph (space or other special character might not be encoded in the font file)
    if(glyphShape != null){
      // add the shape to the list
      result.add(glyphShape);
    }

  }

  return result;
}

void drawGlyphImages(){
  float previousGlyphsHeight = 0;
  for(int i = 0; i < glyphImages.size(); i++){
    PImage glyphImage = glyphImages.get(i);
    image(glyphImage,10,glyphImage.height + previousGlyphsHeight,glyphImage.width * 2,glyphImage.height * 2);
    previousGlyphsHeight += (glyphImage.height * 2) + 3;
  }
}

Additionally you can get the shapes via PFont's [getShape()][9]:

String[] fontNames = {"Monospaced","ProcessingSansPro-Regular"};
int NUM_FONTS = fontNames.length;
PFont[] fonts = new PFont[NUM_FONTS];
PFont font;

int FONT_SIZE = 30;
String message = "Hello World";

ArrayList<PShape> glyphShapes;

void setup(){
  size(345,345);
  textAlign(CENTER);
  fill(0);

  // load fonts
  for(int i = 0 ; i < NUM_FONTS; i++){
    fonts[i] = createFont(fontNames[i],FONT_SIZE);
  }

  // set first font
  setFont(0);

}

void draw(){
  background(255);
  text(message,width * 0.5,height * 0.5);

  drawGlyphShapes();

}

void keyPressed(){
  if(key == '1'){
    setFont(0);
  }
  if(key == '2'){
    setFont(1);
  }
}

void setFont(int fontIndex){
  // check font data is accessible
  if(fonts != null){

    if(fontIndex >= 0 && fontIndex < fonts.length){

      // update global reference to currently set font
      font = fonts[fontIndex];
      // tell Processing to use this font
      textFont(font,FONT_SIZE);
      // update glyph shapes
      glyphShapes = getGlyphShapes(font,message);
    }else{
      println("error: invalid array index",fontIndex,"valid range is",0,fonts.length-1);
    }

  }else{
    println("error: null fonts array");
  } 
}

ArrayList<PShape> getGlyphShapes(PFont font,String message){

  ArrayList<PShape> result = new ArrayList<PShape>();

  // access font glyph images
  for(int i = 0 ; i < message.length(); i++){

    // get the each character
    char currentChar = message.charAt(i);
    // get the glyph shape
    PShape glyphShape = font.getShape(currentChar);
    // if there is a glyph (space or other special character might not be encoded in the font file)
    if(glyphShape != null){
      // add the shape to the list
      result.add(glyphShape);
    }

  }

  return result;
}

void drawGlyphShapes(){
  float maxGlyphHeight = 30;
  for(int i = 0; i < glyphShapes.size(); i++){
    PShape glyphShape = glyphShapes.get(i);
    glyphShape.disableStyle();
    noFill();
    beginShape();
    for(int j = 0 ; j < glyphShape.getVertexCount(); j++){
      PVector vertex = glyphShape.getVertex(j);
      vertex(10 + vertex.x,vertex.y + 30 + glyphShape.getHeight() + (maxGlyphHeight * i));
    }
    endShape(CLOSE);
  }
}

If you want to draw your own glyphs you can always use beginShape(), createShape(), etc. and wrap it in a function that takes the string you want to render and draws the correct shapes for each character.

If you want to create your own ttf font file you may need an external library. Have a look at the Typography Processing libraries for extended functionality.



来源:https://stackoverflow.com/questions/52818958/createfont-from-string

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!