Java: заменить текст на середину строки изображения и выровнять с переносом слов - PullRequest
0 голосов
/ 01 сентября 2018

Я все еще немного новичок в программировании на Java, так что извините за огромный дамп текста. Я очень ценю, что вы нашли время, чтобы прочитать мою текущую проблему!

Я работаю над программным обеспечением, которое поможет ускорить процесс разработки настольных игр с использованием Java Swing. Он берет файл карточек CSV для игры, позволяет вам создать фиктивную карточку, поместив туда, где каждый столбец будет отображаться на карточке, и затем автоматически сгенерировать все карточки в CSV из этих позиций.

Во многих карточных играх есть символы, которые представляют что-то в игре, и я хочу иметь возможность вставлять их в середину строк. В настоящее время я могу заменить всю строку символом; так как он проверяет, если string == a known rule, нарисуйте символ вместо этого. Однако я не знаю, как бы я искал строку для определенного набора символов. Если он их найдет, удалите их из строки и нарисуйте соответствующий символ на его месте. Прекрасный пример можно увидеть с символами маны на магических картах: https://cdn0.vox -cdn.com / uploads / chorus_asset / file / 8039357 / C0cIVZ5.png

Таким образом, строка может быть: Gain 1 {GOLD} at the start of each tun. И нужно будет заменить {GOLD} изображением золота, используя класс Rule, содержащий строку для поиска и буферизованное изображение для замены.

Я бы хотел, чтобы это работало без жесткого ограничения размера символа, но это не является жестким требованием. Лучшее решение - масштабировать символ, чтобы его высота соответствовала тексту.

Этот метод берет буферизованное изображение (карту без текста) и накладывает текст поверх карты.

//Will modify the buffered image with the placeables
static public BufferedImage buildCard(BufferedImage start, int whichCardID) {
    //Copy so we don't lose our template
    BufferedImage ni = deepCopy(start); //ni = new image

    //The headers of the document
    String[] headers = MainWindow.loadedCards.get(0);

    //For each placeable, write down it's text
    for(int i=0; i<headers.length; i++) {
        //get current header
        String currentHeader = headers[i];

        //The Text
        String theText = MainWindow.loadedCards.get(whichCardID)[i];

        //The Settings
        PlaceableSettings theSettings = MainWindow.placeableSettings.get(currentHeader);

        //Make the change to the image
        //ni = writeToImage(ni, theText, theSettings);

        ///////New below
        boolean foundRule = false;

        //see if we have a rule to draw a graphic instead
        for(RuleMaster.Rule r : RuleMaster.rules) {
            if(r.keyword.equals(theText)) {
                //there is a rule for this!
                ni = drawRuleToImage(ni, r, theSettings);
                foundRule = true; //so we don't draw the current text
            }
        }
        //No rules for this

        //Make the change to the image if there are no rules
        if(foundRule == false)
            ni = writeToImage(ni, theText, theSettings);
    }
    return ni;
}

//Takes a buffered image and writes text into it at the location given
static public BufferedImage writeToImage(BufferedImage old, String text, PlaceableSettings setts) {
    //make new blank graphics
    BufferedImage bi = new BufferedImage(old.getWidth(), old.getHeight(), BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = bi.createGraphics();

    //write old image to it
    g2d.drawImage(old, 0, 0, null); //null was set to "this" when this was not static | Note ion case this breaks

    //write text on it
    g2d.setPaint(setts.getColor());
    g2d.setFont(setts.getFont());

    //Setup word wrap
    FontMetrics fm = g2d.getFontMetrics(setts.getFont());
    //    int rightSideBuffer = bi.getWidth() - 10;
    //Rectangle2D rect = fm.getStringBounds(text, setts.getX(), rightSideBuffer, g2d); // try just -'ing the x slot from the width below
    Rectangle2D rect = fm.getStringBounds(text, g2d); //this gets you the bounds for the entire image, need to remove space for x,y position


    //TODO: Problem: this is always length 1
    //Solution! No auto wrap, let the person define it as a setting
    @SuppressWarnings("unchecked")
    List<String> textList=StringUtils.wrap(text, fm, setts.getPixelsTillWrap() ); //width counted in # of characters

    //g2d.drawString(text, setts.getX(), setts.getY()); //old draw with no wrap



    for(int i=0; i< textList.size(); i++) {
        g2d.drawString(textList.get(i), setts.getX(), setts.getY() + ( i*(setts.getFont().getSize() + 2/*Buffer*/)));
    }

    //!!DEBUG
    if(EntryPoint.DEBUG) {
        Random r = new Random();
        g2d.setPaint(Color.RED);
        g2d.drawString(Integer.toString(textList.size()), 100, 50+r.nextInt(250));
        g2d.setPaint(Color.GREEN);
        g2d.drawString(Double.toString(rect.getWidth()), 200, 50+r.nextInt(250));
        g2d.setPaint(Color.PINK);
        //g2d.drawString(Integer.toString(( ((int) rect.getWidth()) - setts.getX())), 100, 250+r.nextInt(100));

    }

    //cleanup
    g2d.dispose();

    return bi;
}

//Takes a buffered image and draws an image on it at the location given
static public BufferedImage drawRuleToImage(BufferedImage old, RuleMaster.Rule rule, PlaceableSettings theSettings) {
    //make new blank graphics
    BufferedImage bi = new BufferedImage(old.getWidth(), old.getHeight(), BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = bi.createGraphics();

    //write old image to it
    g2d.drawImage(old, 0, 0, null); //null was set to "this" when this was not static | Note ion case this breaks

    g2d.drawImage(rule.image, theSettings.getX(), theSettings.getY(), null);

    //cleanup
    g2d.dispose();

    //System.exit(1);

    return bi;
}

Каждое правило содержит строку для замены и изображение для ее замены.

static public class Rule{
    //Text to look for
    String keyword;
    //image to replace it with
    BufferedImage image;

    public Rule (String key, BufferedImage img) {
        keyword = key;
        image = img;
    }
}

Я пытаюсь спроектировать это как инструмент для многих людей, чтобы текст мог соответствовать тому, что добавляет пользователь; хотя мой текущий процесс состоял в том, чтобы использовать строки, такие как "{M}", и это могло бы быть стандартом.

Еще одно большое препятствие в этом заключается в том, что текст может переноситься на карточках, а это означает, что строки и изображение необходимо переносить в предусмотренные рамки.

Редактировать 1: Были некоторые мысли, и я собираюсь попробовать этот подход. Все еще видите возможную проблему с границами при получении «следующей» половины нарисованной строки; но я верю, что это может сработать.

//If found a rule mid text:

            //Split string in 2 at the rule match: strings 'start', and 'next'
            //Calculate x and y for symbol
            //x is the # of characters in ('start' % the word wrap width) +1 as the symbol is the next character, then multiply that by the character size of the font
            //y is the integer of dividing the # of characters in 'start' by word wrap width multiplied by the font height
            //Draw Start of String
            //Draw symbol

            //next x = sym.x + sym width //TODO next (x,y) math

1 Ответ

0 голосов
/ 04 сентября 2018

Мне удалось решить проблему, искажая заранее, основываясь на размере текста. Используя известный размер изображения, можно заранее знать, как правильно сделать обтекание.

Затем я перебрал каждую строку. Я посмотрел сделал раскол в строке по тексту, который будет заменен. Я их нарисовал первую часть строки как обычно. Рассчитал ширину строки, используя int pixelWidth = ni.getGraphics().getFontMetrics().stringWidth(splitString[j]);. Затем нарисовал изображение в том же Y, но добавил ширину предыдущей строки к X. Затем добавил текущую ширину изображения к X и продолжил цикл; Рисование изображений и строк по мере необходимости.

...