Canvas:Text

From MozillaWiki
Jump to: navigation, search

Text in Canvas

This page contains archived design discussion of a feature that was implemented in Firefox 3. See bug 339553 where the feature was implemented and mdc:Canvas:Text for documentation.


The <canvas> spec currently lacks any methods for drawing text; this was done to simplify initial implementation.

API

string textStyle;
void drawText(in string textToDraw);
void pathText(in string textToDraw);

Do we need measureText? (myk: yes, so that you can resize the canvas to the size of the text, which is useful when you're using the canvas as an object representation of some text, f.e. in the microsummary editor, about which read more below)

textStyle: CSS 2.1 "font" shorthand, e.g. "12pt bold Helvetica". Reading textStyle just returns the last string that was passed in. Defaults to whatever the user's default sans serif font is (maybe serif font? what's the default for text if no font is specified?).

drawText: draws textToDraw relative to the current origin transformation matrix, and fills with the current fillStyle. The current origin is the origin of the text baseline.

pathText: adds the glyphs of the given text to the current path. They can then be stroked/filled/clipped as normal.

  • roc: You will be able to create a hidden IFRAME full of properly laid-out text with full CSS styling (plus MathML and whatever else), and draw that to a canvas --- but that won't use canvas fill/stroke.
  • vlad: Yeah, I think that's useful as well when you need to create a more complex text layout; but it seems overkill when you just want a simple string. Being able to use stroke/fill is also important (since you can do things like text with a gradient/pattern/etc).
  • roc: agree.
  • taken: In this case, user can select the texts ? IMHO, mozilla should not increase unselectable text.--Taken 01:53, 4 Mar 2006 (PST)
  • vlad: nope, this is an entirely un-accessability-non-graphical-browser-friendly way to draw text. The rationale, however, is that canvas as a whole has fallback when canvas isn't available, because even the graphics you draw may have just as much or more meaning than any text. There are plenty of ways to get around having a text-drawing API, they're just painful and annoying, but not impossible -- which means someone will wrap it in some JS and make it easy, just possibly slow. So if people are going to do it anyway, we may as well provide the API and make everyone happy.
  • myk: there are legitimate uses for non-selectable text. For example, the Microsummaries support I'm building for Firefox includes a microsummary editor that lets users mix snippets of text from a summarized page with arbitrary text.

    Snippet text isn't editable by the user, since it's really just a user-friendly representation of an XPath expression that pulls content from the page, so the editor needs to represent snippets as objects which can be added, deleted, or moved around, not character data that can be selected and manipulated as individual characters.

    My first thought was to use SVG to draw the text, but the SVG spec says that SVG text must be selectable. So now I'm rendering text in a hidden iframe and then drawing it onto a canvas, as roc suggests, and that works fine, but it's way overcomplicated for my simple needs.
    • roc: myk, -moz-user-select might be a much easier way to achieve that...
    • myk: roc, -moz-user-select gives me some of the behavior I want. Setting it to "none" makes the text non-selectable, and if I place the cursor on either end of the text and move it towards the text via the arrow keys, the cursor jumps to the other side of the text instead of moving into the text.

      But if I hit backspace to the right of the text (or delete to its left) I can remove characters from it, and once I do that the cursor is inside the text element, at which point I can scroll within it with the arrow keys and add characters by typing. Plus I can't select the element, which I do want to be able to do (but as a whole, not character-by-character). So it's not quite the behavior I want.
    • roc: Please file a bug to extend or fix -moz-user-select to do what you want. Canvas text is not appropriate for this IMHO ... for one thing, it won't reflow with other content across lines.
    • myk: roc, it looks like I can get what I want (albeit with some bugs) by using -moz-user-select: all.
  • hixie: IMHO fontStyle should be an object, not a string, because in future we'll almost certainly want to add things to it other than what CSS font shorthand can express. It could be set from a string and stringify to a string, though, to preserve the illusion in the common case.
  • hixie: is drawing-text-along-a-path a requirement?
  • taken: IMHO, if implements this as not a part of spec, mozilla should use custom context like opera, such as moz-2dtext. --Taken 04:56, 22 April 2006 (PDT)
  • gerv: I think we should sidestep the complexity problem by implementing drawElement(), to match drawWindow(). This way we can leverage all of the text styling and handling capabilities of Gecko (left-to-right, kerning, line breaking, CSS text properties etc. etc.), encourage people to provide fallback accessible content (because the divs they are filling with text and using for drawElement() can be inside the canvas tag). It's easy enough to use, as well, and far less heavyweight than doing the same thing using drawWindow(). And I doubt you can have a transparent background on a window, anyway. You can also get the metrics you need to fit the text to wherever you want to put it, just be reading the width and height of the div. And it leverages existing code in drawWindow().
    • shaustein: I do not think drawElement alone would be sufficient. Applications for drawString() will be labels on maps, in games, graphs, diagrams. There you need to measure the actual size of the text box. For a more detailed list of arguments, see http://rhino-canvas.sourceforge.net/www/drawstring.html.