mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-13 17:28:52 -04:00
Added proper code formatting renderer (using font renderer used for screens). Closes #1054.
Fixed text wrapping, strings without "wrap points" caused an infinite loop.
This commit is contained in:
parent
a1283c9aa2
commit
c7dfddd009
@ -22,7 +22,14 @@ over two* lines. But *this ... no *this is* **_bold italic_** *text*.
|
||||
|
||||
`test for code`
|
||||
`that's not code yet`
|
||||
this is some `code` that's inline.
|
||||
`function f(a)`
|
||||
` testingIndent(a)`
|
||||
` do`
|
||||
` lalala()`
|
||||
` end`
|
||||
`end`
|
||||
yeah, line spacing is a bit low, but otherwise too little text fits on one screen.
|
||||
this is some `code` that's inline. then `some more CODE that` line wraps and so on.
|
||||
|
||||
isn't*.
|
||||
|
||||
@ -35,3 +42,7 @@ And finally, [this is a link!](https://avatars1.githubusercontent.com/u/514903).
|
||||

|
||||

|
||||

|
||||
|
||||
wrap testing
|
||||
12345678901234567890.1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
`123456789012345678901234567890.12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890`
|
@ -112,6 +112,33 @@ abstract class TextureFontRenderer {
|
||||
RenderState.checkError(getClass.getName + ".drawBuffer: leaving")
|
||||
}
|
||||
|
||||
def drawString(s: String, x: Int, y: Int): Unit = {
|
||||
GL11.glPushMatrix()
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
|
||||
|
||||
GL11.glTranslatef(x, y, 0)
|
||||
GL11.glScalef(0.5f, 0.5f, 1)
|
||||
GL11.glDepthMask(false)
|
||||
|
||||
for (i <- 0 until textureCount) {
|
||||
bindTexture(i)
|
||||
GL11.glBegin(GL11.GL_QUADS)
|
||||
var tx = 0f
|
||||
for (n <- 0 until s.length) {
|
||||
val ch = s.charAt(n)
|
||||
// Don't render whitespace.
|
||||
if (ch != ' ') {
|
||||
drawChar(tx, 0, ch)
|
||||
}
|
||||
tx += charWidth
|
||||
}
|
||||
GL11.glEnd()
|
||||
}
|
||||
|
||||
GL11.glPopAttrib()
|
||||
GL11.glPopMatrix()
|
||||
}
|
||||
|
||||
protected def charWidth: Int
|
||||
|
||||
protected def charHeight: Int
|
||||
|
@ -106,6 +106,8 @@ object Document {
|
||||
|
||||
private def HeaderSegment(s: Segment, m: Regex.Match) = new segment.HeaderSegment(s, m.group(2), m.group(1).length)
|
||||
|
||||
private def CodeSegment(s: Segment, m: Regex.Match) = new segment.CodeSegment(s, m.group(2))
|
||||
|
||||
private def LinkSegment(s: Segment, m: Regex.Match) = new segment.LinkSegment(s, m.group(1), m.group(2))
|
||||
|
||||
private def BoldSegment(s: Segment, m: Regex.Match) = new segment.BoldSegment(s, m.group(2))
|
||||
@ -127,7 +129,7 @@ object Document {
|
||||
|
||||
private val segmentTypes = Array(
|
||||
"""^(#+)\s(.*)""".r -> HeaderSegment _, // headers: # ...
|
||||
"""(`)(\S.*?\S|$)\1""".r -> ItalicSegment _, // code: `...`
|
||||
"""(`)(.*?)\1""".r -> CodeSegment _, // code: `...`
|
||||
"""!\[([^\[]*)\]\(([^\)]+)\)""".r -> ImageSegment _, // images: 
|
||||
"""\[([^\[]+)\]\(([^\)]+)\)""".r -> LinkSegment _, // links: [...](...)
|
||||
"""(\*\*|__)(\S.*?\S|$)\1""".r -> BoldSegment _, // bold: **...** | __...__
|
||||
|
@ -0,0 +1,84 @@
|
||||
package li.cil.oc.client.renderer.markdown.segment
|
||||
|
||||
import li.cil.oc.client.renderer.TextBufferRenderCache
|
||||
import li.cil.oc.client.renderer.markdown.Document
|
||||
import net.minecraft.client.gui.FontRenderer
|
||||
import org.lwjgl.opengl.GL11
|
||||
|
||||
private[markdown] class CodeSegment(protected val parent: Segment, val text: String) extends Segment {
|
||||
override def height(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = {
|
||||
var lines = 0
|
||||
var chars = text
|
||||
var lineChars = maxChars(chars, maxWidth - indent)
|
||||
while (chars.length > lineChars) {
|
||||
lines += 1
|
||||
chars = chars.drop(lineChars).dropWhile(_.isWhitespace)
|
||||
lineChars = maxChars(chars, maxWidth)
|
||||
}
|
||||
lines * Document.lineHeight(renderer)
|
||||
}
|
||||
|
||||
override def width(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = {
|
||||
var currentX = indent
|
||||
var chars = text
|
||||
if (indent == 0) chars = chars.dropWhile(_.isWhitespace)
|
||||
var lineChars = maxChars(chars, maxWidth - indent)
|
||||
while (chars.length > lineChars) {
|
||||
chars = chars.drop(lineChars).dropWhile(_.isWhitespace)
|
||||
lineChars = maxChars(chars, maxWidth)
|
||||
currentX = 0
|
||||
}
|
||||
currentX + stringWidth(chars)
|
||||
}
|
||||
|
||||
override def render(x: Int, y: Int, indent: Int, maxWidth: Int, minY: Int, maxY: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = {
|
||||
TextBufferRenderCache.renderer.generateChars(text.toCharArray)
|
||||
|
||||
var currentX = x + indent
|
||||
var currentY = y
|
||||
var chars = text
|
||||
var numChars = maxChars(chars, maxWidth - indent)
|
||||
while (chars.length > 0 && (currentY - y) < maxY) {
|
||||
val part = chars.take(numChars).reverse.dropWhile(_.isWhitespace).reverse
|
||||
GL11.glColor4f(0.75f, 0.8f, 1, 1)
|
||||
TextBufferRenderCache.renderer.drawString(part, currentX, currentY)
|
||||
currentX = x
|
||||
currentY += Document.lineHeight(renderer)
|
||||
chars = chars.drop(numChars).dropWhile(_.isWhitespace)
|
||||
numChars = maxChars(chars, maxWidth)
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
private def drawBox(x: Int, y: Int, width: Int, height: Int): Unit = {
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D)
|
||||
GL11.glBegin(GL11.GL_QUADS)
|
||||
GL11.glVertex2f(x, y)
|
||||
GL11.glVertex2f(x, y + height)
|
||||
GL11.glVertex2f(x + width, y + height)
|
||||
GL11.glVertex2f(x + width, y)
|
||||
GL11.glEnd()
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D)
|
||||
}
|
||||
|
||||
private def stringWidth(s: String): Int = s.length * TextBufferRenderCache.renderer.charRenderWidth
|
||||
|
||||
private def maxChars(s: String, maxWidth: Int): Int = {
|
||||
val breaks = Set(' ', '-', '.', '+', '*', '_', '/')
|
||||
var pos = 0
|
||||
var lastBreak = -1
|
||||
while (pos < s.length) {
|
||||
pos += 1
|
||||
val width = stringWidth(s.take(pos))
|
||||
if (width >= maxWidth) {
|
||||
if (lastBreak > 0 || stringWidth(s) <= maxWidth) return lastBreak + 1
|
||||
else return pos - 1
|
||||
}
|
||||
if (pos < s.length && breaks.contains(s.charAt(pos))) lastBreak = pos
|
||||
}
|
||||
pos
|
||||
}
|
||||
|
||||
override def toString: String = s"{CodeSegment: text = $text}"
|
||||
}
|
@ -127,7 +127,10 @@ private[markdown] class TextSegment(protected val parent: Segment, val text: Str
|
||||
while (pos < s.length) {
|
||||
pos += 1
|
||||
val width = (stringWidth(s.take(pos), renderer) * fontScale).toInt
|
||||
if (width >= maxWidth) return lastBreak + 1
|
||||
if (width >= maxWidth) {
|
||||
if (lastBreak > 0 || stringWidth(s, renderer) <= maxWidth) return lastBreak + 1
|
||||
else return pos - 1
|
||||
}
|
||||
if (pos < s.length && breaks.contains(s.charAt(pos))) lastBreak = pos
|
||||
}
|
||||
pos
|
||||
|
@ -209,7 +209,7 @@ object ModOpenComputers extends ModProxy {
|
||||
api.Manual.addProvider("oredict", OreDictImageProvider)
|
||||
|
||||
api.Manual.addTab(new ItemStackTabIconRenderer(api.Items.get("case1").createItemStack(1)), "oc:gui.Manual.Blocks", "%LANGUAGE%/block/index.md")
|
||||
api.Manual.addTab(new ItemStackTabIconRenderer(api.Items.get("chip1").createItemStack(1)), "oc:gui.Manual.Items", "%LANGUAGE%/item/index.md")
|
||||
api.Manual.addTab(new ItemStackTabIconRenderer(api.Items.get("cpu1").createItemStack(1)), "oc:gui.Manual.Items", "%LANGUAGE%/item/index.md")
|
||||
}
|
||||
|
||||
private def blacklistHost(host: Class[_], itemNames: String*) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user