Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > de.comp.lang.javascript > #4922

Re: "Optische" Zeichenhöhe berechnen

From Christian Zimmermann <ch.zim@web.de>
Newsgroups de.comp.lang.javascript
Subject Re: "Optische" Zeichenhöhe berechnen
Date 2017-11-20 09:36 +0100
Organization albasani.net
Message-ID <ouu45o$v5o$1@news.albasani.net> (permalink)
References <ouk8ir$ed9$1@news.albasani.net>

Show all headers | View raw


Hi,

erstmal zum Code. Ich habe mir nun folgende Lösung für mein Problem
erstellt. Das hat etwas "länger" gedauert, weil ich zufälligerweise auch
mit "Comic Sans MS" getestet und dabei festgestellt habe, dass der
Firefox bei dieser Schriftart über den unteren Canvas-Rand
hinausschreiben kann. Dies bedarf in diesem Fall noch einer kleinen
Korrektur.

************* Code *************
<!DOCTYPE html>
<html>
<meta charset ="utf-8">
<body style="background-color:steelblue">

<canvas id="myCanvas" width="1000" height="140"
style="background-color:white">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>
// test cases
var i,x,tw;
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var txt = ['g','a','A','Ä','Â','Âj','"'], h=0, fontStyle="bold 90px Arial";
var txtMet;

ctx.moveTo(0,c.height/2);
ctx.lineTo(c.width,c.height/2);
ctx.stroke();
ctx.font = fontStyle;
x = 0;
for (i = 0; i < txt.length; i++) {
    txtMet = getVisualTextMetricsInPixel(txt[i], fontStyle);
    tw = ctx.measureText(txt[i]).width;
    ctx.textBaseline = "bottom";
    ctx.fillText(txt[i], x , c.height/2 + txtMet.textHeight/2
                                        +
txtMet.distBottomTextToBottomLine - txtMet.adjust);
    ctx.textBaseline = "middle";
    ctx.fillText(txt[i], x + tw + 5, c.height/2);
    x = x + 2 * tw + 15;
}

function getVisualTextMetricsInPixel (text, fontStyle) {
  var i;
  var img, flag, lines;
  var canvas, ctx;
  var txtMet = {textHeight: 0, fontMaxHeight: 0,
                distTopTextToBottomLine: 0,
                adjust: 0};

  if (text === "") return txtMet;

  var body = document.getElementsByTagName("body")[0];
  var div = document.createElement("div");
  var textNode = document.createTextNode("jÂ");

  //retrieve maximum font height
  div.appendChild(textNode);
  div.setAttribute("style", "font:" + fontStyle);
  body.appendChild(div);
  txtMet.fontMaxHeight = div.offsetHeight;
  body.removeChild(div);

  //retrieve "visual" font height and distance from bottom line
  canvas = document.createElement("canvas");
  canvas.style.visibility = "hidden";
  body.appendChild(canvas);
  ctx = canvas.getContext("2d");

  // set the width
  ctx.font = fontStyle;
  canvas.width = Math.ceil(ctx.measureText(text).width);
  canvas.height = txtMet.fontMaxHeight;
  ctx.font = fontStyle;
  ctx.textBaseline = "bottom";
  ctx.fillText(text, 0, canvas.height - 1);
  // check if part of the text is drawn below the bottom of the canvas rect,
  // because in Firefox sometimes .fillText() with textBaseline =
"bottom" and
  // font "Comic Sans MS" does
  img = ctx.getImageData(0, canvas.height - 1, canvas.width, canvas.height);
  i=0;
  while (!isRowEmpty(img)) {
        i++;
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillText(text, 0, canvas.height - i);
        img = ctx.getImageData(0, canvas.height - 1, canvas.width,
canvas.height);
  }
  if (i > 0) txtMet.adjust = i - 1;
  // retrieve the text height
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillText(text, 0, canvas.height - txtMet.adjust);
  img = ctx.getImageData(0, 0, canvas.width, canvas.height);
  lines = getTopBottomLine(img, canvas.width, canvas.height - 1);
  txtMet.textHeight = lines.bottom - lines.top + 1;
  txtMet.distBottomTextToBottomLine = canvas.height - lines.bottom - 1;

  body.removeChild(canvas);
  return txtMet;
}

function isRowEmpty (img) {
  for (var i = 0; i <= img.data.length; i+=4) {
      if (img.data[i+3] > 0) { return false; }
  }
  return true;
}

function getTopBottomLine (img, width, height) {
  var lines = {top: -1, bottom: -1};
  var i,j,flag;

  // Approach from top
  // (to the first non-transparent pixel that belongs to the top of the
character)
  flag = false;
  for (j = 0; j <= height; j++) {
      for (i = 0; i < width; i++) {
          if (img.data[(j*width+i)*4+3] > 0) {
             lines.top = j;
             flag = true;
             break;
          }
      }
      if (flag) break;
  }
  // Approach from bottom
  // (to the first non-transparent pixel that belongs to the bottom of
the character)
  flag = false;
  for (j = height; j >= 0; j--) {
      for (i = 0; i < width; i++) {
          if (img.data[(j*width+i)*4+3]>0) {
             lines.bottom = j;
             flag = true;
             break;
          }
      }
      if (flag) break;
  }

  return lines;
}
</script>

</body>
</html>

************* Code *************

Getestet habe ich mit

Firefox 52.4.0 (32bit)
Firefox 52.5.0 (32bit)
Firefox 58.0b4 (64-Bit)
IE 11.15.15299.0
Edge 41.16299.15.0
Chrome 61.0.3163.100 (32-Bit)
Chrome 62.0.3202.94 (32-Bit)

Gruß,
Christian

Back to de.comp.lang.javascript | Previous | NextPrevious in thread | Next in thread | Find similar


Thread

"Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-16 15:50 +0100
  Re: "Optische" Zeichenhöhe berechnen Arno Welzel <usenet@arnowelzel.de> - 2017-11-16 19:50 +0100
    Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-16 20:07 +0100
      Re: "Optische" Zeichenhöhe berechnen "Peter J. Holzer" <hjp-usenet3@hjp.at> - 2017-11-16 23:33 +0100
        Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-17 00:00 +0100
          Re: "Optische" Zeichenhöhe berechnen Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-11-17 02:35 +0100
            Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-17 08:06 +0100
              Re: "Optische" Zeichenhöhe berechnen Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-11-17 14:00 +0100
                Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-20 09:54 +0100
      Re: "Optische" Zeichenhöhe berechnen Arno Welzel <usenet@arnowelzel.de> - 2017-11-18 19:52 +0100
        Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-20 09:46 +0100
  Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-20 09:36 +0100
    Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-20 10:31 +0100

csiph-web