Navigation

    KorGE

    • Register
    • Login
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    1. Home
    2. Saiful Anwar
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Saiful Anwar

    @Saiful Anwar

    2
    Reputation
    2
    Posts
    1
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online

    Saiful Anwar Follow

    Best posts made by Saiful Anwar

    • Text Wrapping

      How to perform text auto wrapping with predefined width?

      Calling

      text.setTextBounds(Rectangle(0.0, 0.0, 300.0, 200.0))
      

      doesn't seem to solve the issue.
      Thanks

      posted in General
      Saiful Anwar
      Saiful Anwar
    • RE: Text Wrapping

      I ended up doing this.
      In KorGE version 2 we can pass custom TextRenderer when creating Text.
      This is my "quick" implementation in case anyone want to use it.

      package view
      
      import com.soywiz.korge.view.Container
      import com.soywiz.korge.view.Text
      import com.soywiz.korge.view.ViewDslMarker
      import com.soywiz.korge.view.addTo
      import com.soywiz.korim.color.Colors
      import com.soywiz.korim.color.RGBA
      import com.soywiz.korim.font.DefaultTtfFont
      import com.soywiz.korim.font.Font
      import com.soywiz.korim.font.getTextBounds
      import com.soywiz.korim.text.TextAlignment
      import com.soywiz.korim.text.TextRenderer
      import com.soywiz.korim.text.TextRendererActions
      import com.soywiz.korio.resources.Resourceable
      
      enum class Gravity {
          LEFT, CENTER, RIGHT
      }
      
      inline fun Container.wrappableText(
          text: String,
          wrapWidth: Double,
          textSize: Double = 16.0,
          color: RGBA = Colors.WHITE,
          font: Resourceable<out Font> = DefaultTtfFont,
          gravity: Gravity = Gravity.CENTER,
          callback: @ViewDslMarker WrappableText.() -> Unit = {}
      ) = WrappableText(
          text,
          textSize = textSize,
          color = color,
          font = font,
          wrapWidth = wrapWidth,
          renderer = WrappableTextRenderer(wrapWidth, gravity)
      ).addTo(this, callback)
      
      
      class WrappableText(
          text: String, textSize: Double = DEFAULT_TEXT_SIZE,
          color: RGBA = Colors.WHITE, font: Resourceable<out Font> = DefaultTtfFont,
          alignment: TextAlignment = TextAlignment.TOP_LEFT,
          wrapWidth: Double,
          renderer: TextRenderer<String>,
          autoScaling: Boolean = true
      ) : Text(text, textSize, color, font, alignment, renderer, autoScaling) {
          init {
              val f = this.font.getOrNull()
      
              if (f is Font) {
                  val metrics = f.getTextBounds(textSize, text, renderer = renderer)
                  metrics.bounds.x = 0.0
                  metrics.bounds.y = 0.0
                  metrics.bounds.width = wrapWidth
                  setTextBounds(metrics.bounds)
              }
          }
      }
      
      class WrappableTextRenderer(val wrapWidth: Double, val gravity: Gravity) : TextRenderer<String> {
          override fun TextRendererActions.run(text: String, size: Double, defaultFont: Font) {
              reset()
              setFont(defaultFont, size)
      
              val lines = mutableListOf(Line())
              var curX = 0.0
      
              val spaceWidth = getGlyphMetrics(' '.toInt()).xadvance + getKerning(' '.toInt(), 'A'.toInt())
      
              for (word in text.split(' ')) {
                  var wordWidth = 0.0
                  var curWord = ""
      
                  for (n in word.indices) {
                      val c = word[n].toInt()
                      val c1 = word.getOrElse(n + 1) { '\u0000' }.toInt()
      
                      val g = getGlyphMetrics(c)
                      val kerning = getKerning(c, c1)
      
                      if (c == '\n'.toInt()) {
                          curX = 0.0
                          lines.last().words.add(Word(curWord, wordWidth))
                          curWord = ""
                          wordWidth = 0.0
                          lines.add(Line())
                      }
                      else {
                          wordWidth += g.xadvance + kerning
                          curWord += c.toChar()
                      }
                  }
      
                  curX += wordWidth + spaceWidth
      
                  if (curX > wrapWidth) {
                      lines.add(Line())
                      curX = wordWidth + spaceWidth
                  }
      
                  lines.last().words.add(Word(curWord, wordWidth))
              }
      
              for (line in lines) {
                  var start =
                      when (gravity) {
                          Gravity.LEFT -> 0.0
                          Gravity.CENTER -> (wrapWidth - line.calculateWidth(spaceWidth)) / 2
                          Gravity.RIGHT -> wrapWidth - line.calculateWidth(spaceWidth)
                      }
      
                  for (word in line.words) {
                      x = start
      
                      for (n in word.text.indices) {
                          val c = word.text[n].toInt()
                          val c1 = word.text.getOrElse(n + 1) { '\u0000' }.toInt()
      
                          val g = getGlyphMetrics(c)
                          transform.identity()
      
                          val advance = g.xadvance + getKerning(c, c1)
      
                          put(c)
                          advance(advance)
                      }
      
                      start += word.width + spaceWidth
                  }
      
                  newLine(lineHeight)
              }
      
              put(0)
          }
      
          data class Line(
              val words: MutableList<Word> = mutableListOf()
          ) {
              fun calculateWidth(spaceWidth: Double): Double {
                  return words.sumByDouble { it.width } + (words.size - 1) * spaceWidth
              }
          }
      
          data class Word(val text: String, val width: Double)
      }
      
      posted in General
      Saiful Anwar
      Saiful Anwar

    Latest posts made by Saiful Anwar

    • RE: Text Wrapping

      I ended up doing this.
      In KorGE version 2 we can pass custom TextRenderer when creating Text.
      This is my "quick" implementation in case anyone want to use it.

      package view
      
      import com.soywiz.korge.view.Container
      import com.soywiz.korge.view.Text
      import com.soywiz.korge.view.ViewDslMarker
      import com.soywiz.korge.view.addTo
      import com.soywiz.korim.color.Colors
      import com.soywiz.korim.color.RGBA
      import com.soywiz.korim.font.DefaultTtfFont
      import com.soywiz.korim.font.Font
      import com.soywiz.korim.font.getTextBounds
      import com.soywiz.korim.text.TextAlignment
      import com.soywiz.korim.text.TextRenderer
      import com.soywiz.korim.text.TextRendererActions
      import com.soywiz.korio.resources.Resourceable
      
      enum class Gravity {
          LEFT, CENTER, RIGHT
      }
      
      inline fun Container.wrappableText(
          text: String,
          wrapWidth: Double,
          textSize: Double = 16.0,
          color: RGBA = Colors.WHITE,
          font: Resourceable<out Font> = DefaultTtfFont,
          gravity: Gravity = Gravity.CENTER,
          callback: @ViewDslMarker WrappableText.() -> Unit = {}
      ) = WrappableText(
          text,
          textSize = textSize,
          color = color,
          font = font,
          wrapWidth = wrapWidth,
          renderer = WrappableTextRenderer(wrapWidth, gravity)
      ).addTo(this, callback)
      
      
      class WrappableText(
          text: String, textSize: Double = DEFAULT_TEXT_SIZE,
          color: RGBA = Colors.WHITE, font: Resourceable<out Font> = DefaultTtfFont,
          alignment: TextAlignment = TextAlignment.TOP_LEFT,
          wrapWidth: Double,
          renderer: TextRenderer<String>,
          autoScaling: Boolean = true
      ) : Text(text, textSize, color, font, alignment, renderer, autoScaling) {
          init {
              val f = this.font.getOrNull()
      
              if (f is Font) {
                  val metrics = f.getTextBounds(textSize, text, renderer = renderer)
                  metrics.bounds.x = 0.0
                  metrics.bounds.y = 0.0
                  metrics.bounds.width = wrapWidth
                  setTextBounds(metrics.bounds)
              }
          }
      }
      
      class WrappableTextRenderer(val wrapWidth: Double, val gravity: Gravity) : TextRenderer<String> {
          override fun TextRendererActions.run(text: String, size: Double, defaultFont: Font) {
              reset()
              setFont(defaultFont, size)
      
              val lines = mutableListOf(Line())
              var curX = 0.0
      
              val spaceWidth = getGlyphMetrics(' '.toInt()).xadvance + getKerning(' '.toInt(), 'A'.toInt())
      
              for (word in text.split(' ')) {
                  var wordWidth = 0.0
                  var curWord = ""
      
                  for (n in word.indices) {
                      val c = word[n].toInt()
                      val c1 = word.getOrElse(n + 1) { '\u0000' }.toInt()
      
                      val g = getGlyphMetrics(c)
                      val kerning = getKerning(c, c1)
      
                      if (c == '\n'.toInt()) {
                          curX = 0.0
                          lines.last().words.add(Word(curWord, wordWidth))
                          curWord = ""
                          wordWidth = 0.0
                          lines.add(Line())
                      }
                      else {
                          wordWidth += g.xadvance + kerning
                          curWord += c.toChar()
                      }
                  }
      
                  curX += wordWidth + spaceWidth
      
                  if (curX > wrapWidth) {
                      lines.add(Line())
                      curX = wordWidth + spaceWidth
                  }
      
                  lines.last().words.add(Word(curWord, wordWidth))
              }
      
              for (line in lines) {
                  var start =
                      when (gravity) {
                          Gravity.LEFT -> 0.0
                          Gravity.CENTER -> (wrapWidth - line.calculateWidth(spaceWidth)) / 2
                          Gravity.RIGHT -> wrapWidth - line.calculateWidth(spaceWidth)
                      }
      
                  for (word in line.words) {
                      x = start
      
                      for (n in word.text.indices) {
                          val c = word.text[n].toInt()
                          val c1 = word.text.getOrElse(n + 1) { '\u0000' }.toInt()
      
                          val g = getGlyphMetrics(c)
                          transform.identity()
      
                          val advance = g.xadvance + getKerning(c, c1)
      
                          put(c)
                          advance(advance)
                      }
      
                      start += word.width + spaceWidth
                  }
      
                  newLine(lineHeight)
              }
      
              put(0)
          }
      
          data class Line(
              val words: MutableList<Word> = mutableListOf()
          ) {
              fun calculateWidth(spaceWidth: Double): Double {
                  return words.sumByDouble { it.width } + (words.size - 1) * spaceWidth
              }
          }
      
          data class Word(val text: String, val width: Double)
      }
      
      posted in General
      Saiful Anwar
      Saiful Anwar
    • Text Wrapping

      How to perform text auto wrapping with predefined width?

      Calling

      text.setTextBounds(Rectangle(0.0, 0.0, 300.0, 200.0))
      

      doesn't seem to solve the issue.
      Thanks

      posted in General
      Saiful Anwar
      Saiful Anwar