aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/utils/SkTextBox.h10
-rw-r--r--resources/slides.lua26
-rw-r--r--src/utils/SkLua.cpp52
-rw-r--r--src/utils/SkTextBox.cpp72
4 files changed, 141 insertions, 19 deletions
diff --git a/include/utils/SkTextBox.h b/include/utils/SkTextBox.h
index e217076fed..d4372d1b6a 100644
--- a/include/utils/SkTextBox.h
+++ b/include/utils/SkTextBox.h
@@ -60,6 +60,14 @@ public:
int countLines() const;
SkScalar getTextHeight() const;
+ SkTextBlob* snapshotTextBlob(SkScalar* computedBottom) const;
+
+ class Visitor {
+ public:
+ virtual ~Visitor() {}
+ virtual void operator()(const char*, size_t, SkScalar x, SkScalar y, const SkPaint&) = 0;
+ };
+
private:
SkRect fBox;
SkScalar fSpacingMul, fSpacingAdd;
@@ -67,6 +75,8 @@ private:
const char* fText;
size_t fLen;
const SkPaint* fPaint;
+
+ SkScalar visit(Visitor&, const char text[], size_t len, const SkPaint&) const;
};
class SkTextLineBreaker {
diff --git a/resources/slides.lua b/resources/slides.lua
index e96182c2bd..f706a29659 100644
--- a/resources/slides.lua
+++ b/resources/slides.lua
@@ -1,3 +1,4 @@
+gShowBounds = false
gPath = "/skia/trunk/resources/"
@@ -37,6 +38,13 @@ function draw_bullet(canvas, x, y, paint, indent)
canvas:drawCircle(cx, cy, radius, paint)
end
+function stroke_rect(canvas, rect, color)
+ local paint = Sk.newPaint()
+ paint:setStroke(true);
+ paint:setColor(color)
+ canvas:drawRect(rect, paint)
+end
+
function drawSlide(canvas, slide, master_template)
template = master_template.slide -- need to sniff the slide to know if we're title or slide
@@ -65,10 +73,18 @@ function drawSlide(canvas, slide, master_template)
local fm = paint:getFontMetrics()
local x_offset = -fm.ascent * node.indent * 1.25
- y = y - fm.ascent * scale
- draw_bullet(canvas, x + x_offset, y, paint, node.indent)
- canvas:drawText(node.text, x + x_offset, y, paint)
- y = y + fm.descent * scale + extra_dy
+ local bounds = make_rect(x + x_offset, y, 620, 640)
+ local blob, newBottom = Sk.newTextBlob(node.text, bounds, paint)
+ draw_bullet(canvas, x + x_offset, y - fm.ascent, paint, node.indent)
+ canvas:drawTextBlob(blob, 0, 0, paint)
+ y = newBottom + paint:getTextSize() * .5
+
+ if gShowBounds then
+ bounds.bottom = newBottom
+ stroke_rect(canvas, bounds, {a=1,r=0,g=1,b=0})
+ stroke_rect(canvas, blob:bounds(), {a=1,r=1,g=0,b=0})
+ end
+
end
end
@@ -305,6 +321,8 @@ local keyProcs = {
s = spawn_scale_animation,
["="] = function () scale_text_delta(gTemplate, 1) end,
["-"] = function () scale_text_delta(gTemplate, -1) end,
+
+ b = function () gShowBounds = not gShowBounds end,
}
function onCharHandler(uni)
diff --git a/src/utils/SkLua.cpp b/src/utils/SkLua.cpp
index 4fdb71404d..12e2dd8ddf 100644
--- a/src/utils/SkLua.cpp
+++ b/src/utils/SkLua.cpp
@@ -556,6 +556,15 @@ static int lcanvas_drawText(lua_State* L) {
return 0;
}
+static int lcanvas_drawTextBlob(lua_State* L) {
+ const SkTextBlob* blob = get_ref<SkTextBlob>(L, 2);
+ SkScalar x = lua2scalar(L, 3);
+ SkScalar y = lua2scalar(L, 4);
+ const SkPaint& paint = *get_obj<SkPaint>(L, 5);
+ get_ref<SkCanvas>(L, 1)->drawTextBlob(blob, x, y, paint);
+ return 0;
+}
+
static int lcanvas_getSaveCount(lua_State* L) {
lua_pushnumber(L, get_ref<SkCanvas>(L, 1)->getSaveCount());
return 1;
@@ -681,6 +690,7 @@ const struct luaL_Reg gSkCanvas_Methods[] = {
{ "drawPath", lcanvas_drawPath },
{ "drawPicture", lcanvas_drawPicture },
{ "drawText", lcanvas_drawText },
+ { "drawTextBlob", lcanvas_drawTextBlob },
{ "getSaveCount", lcanvas_getSaveCount },
{ "getTotalMatrix", lcanvas_getTotalMatrix },
{ "getClipStack", lcanvas_getClipStack },
@@ -1697,6 +1707,24 @@ static const struct luaL_Reg gSkPicture_Methods[] = {
///////////////////////////////////////////////////////////////////////////////
+static int ltextblob_bounds(lua_State* L) {
+ SkLua(L).pushRect(get_ref<SkTextBlob>(L, 1)->bounds());
+ return 1;
+}
+
+static int ltextblob_gc(lua_State* L) {
+ SkSafeUnref(get_ref<SkTextBlob>(L, 1));
+ return 0;
+}
+
+static const struct luaL_Reg gSkTextBlob_Methods[] = {
+ { "bounds", ltextblob_bounds },
+ { "__gc", ltextblob_gc },
+ { NULL, NULL }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
static int ltypeface_gc(lua_State* L) {
SkSafeUnref(get_ref<SkTypeface>(L, 1));
return 0;
@@ -1809,6 +1837,26 @@ static int lsk_newRRect(lua_State* L) {
return 1;
}
+#include "SkTextBox.h"
+// Sk.newTextBlob(text, rect, paint)
+static int lsk_newTextBlob(lua_State* L) {
+ const char* text = lua_tolstring(L, 1, NULL);
+ SkRect bounds;
+ lua2rect(L, 2, &bounds);
+ const SkPaint& paint = *get_obj<SkPaint>(L, 3);
+
+ SkTextBox box;
+ box.setMode(SkTextBox::kLineBreak_Mode);
+ box.setBox(bounds);
+ box.setText(text, strlen(text), paint);
+
+ SkScalar newBottom;
+ SkAutoTUnref<SkTextBlob> blob(box.snapshotTextBlob(&newBottom));
+ push_ref<SkTextBlob>(L, blob);
+ SkLua(L).pushScalar(newBottom);
+ return 2;
+}
+
static int lsk_newTypeface(lua_State* L) {
const char* name = NULL;
int style = SkTypeface::kNormal;
@@ -1877,6 +1925,7 @@ static void register_Sk(lua_State* L) {
setfield_function(L, "newPictureRecorder", lsk_newPictureRecorder);
setfield_function(L, "newRRect", lsk_newRRect);
setfield_function(L, "newRasterSurface", lsk_newRasterSurface);
+ setfield_function(L, "newTextBlob", lsk_newTextBlob);
setfield_function(L, "newTypeface", lsk_newTypeface);
lua_pop(L, 1); // pop off the Sk table
}
@@ -1896,6 +1945,7 @@ void SkLua::Load(lua_State* L) {
REG_CLASS(L, SkDocument);
REG_CLASS(L, SkImage);
REG_CLASS(L, SkImageFilter);
+ REG_CLASS(L, SkMatrix);
REG_CLASS(L, SkPaint);
REG_CLASS(L, SkPath);
REG_CLASS(L, SkPathEffect);
@@ -1904,8 +1954,8 @@ void SkLua::Load(lua_State* L) {
REG_CLASS(L, SkRRect);
REG_CLASS(L, SkShader);
REG_CLASS(L, SkSurface);
+ REG_CLASS(L, SkTextBlob);
REG_CLASS(L, SkTypeface);
- REG_CLASS(L, SkMatrix);
}
extern "C" int luaopen_skia(lua_State* L);
diff --git a/src/utils/SkTextBox.cpp b/src/utils/SkTextBox.cpp
index 55d75a64da..0bb7a6bf5a 100644
--- a/src/utils/SkTextBox.cpp
+++ b/src/utils/SkTextBox.cpp
@@ -165,14 +165,13 @@ void SkTextBox::setSpacing(SkScalar mul, SkScalar add)
/////////////////////////////////////////////////////////////////////////////////////////////
-void SkTextBox::draw(SkCanvas* canvas, const char text[], size_t len, const SkPaint& paint)
-{
- SkASSERT(canvas && (text || len == 0));
-
+SkScalar SkTextBox::visit(Visitor& visitor, const char text[], size_t len,
+ const SkPaint& paint) const {
SkScalar marginWidth = fBox.width();
- if (marginWidth <= 0 || len == 0)
- return;
+ if (marginWidth <= 0 || len == 0) {
+ return fBox.top();
+ }
const char* textStop = text + len;
@@ -200,8 +199,7 @@ void SkTextBox::draw(SkCanvas* canvas, const char text[], size_t len, const SkPa
{
SkScalar textHeight = fontHeight;
- if (fMode == kLineBreak_Mode && fSpacingAlign != kStart_SpacingAlign)
- {
+ if (fMode == kLineBreak_Mode && fSpacingAlign != kStart_SpacingAlign) {
int count = SkTextLineBreaker::CountLines(text, textStop - text, paint, marginWidth);
SkASSERT(count > 0);
textHeight += scaledSpacing * (count - 1);
@@ -222,29 +220,48 @@ void SkTextBox::draw(SkCanvas* canvas, const char text[], size_t len, const SkPa
y += fBox.fTop - metrics.fAscent;
}
- for (;;)
- {
+ for (;;) {
size_t trailing;
len = linebreak(text, textStop, paint, marginWidth, &trailing);
- if (y + metrics.fDescent + metrics.fLeading > 0)
- canvas->drawText(text, len - trailing, x, y, paint);
+ if (y + metrics.fDescent + metrics.fLeading > 0) {
+ visitor(text, len - trailing, x, y, paint);
+ }
text += len;
- if (text >= textStop)
+ if (text >= textStop) {
break;
+ }
y += scaledSpacing;
- if (y + metrics.fAscent >= fBox.fBottom)
+ if (y + metrics.fAscent >= fBox.fBottom) {
break;
+ }
}
+ return y + metrics.fDescent + metrics.fLeading;
}
///////////////////////////////////////////////////////////////////////////////
+class CanvasVisitor : public SkTextBox::Visitor {
+ SkCanvas* fCanvas;
+public:
+ CanvasVisitor(SkCanvas* canvas) : fCanvas(canvas) {}
+
+ virtual void operator()(const char text[], size_t length, SkScalar x, SkScalar y,
+ const SkPaint& paint) SK_OVERRIDE {
+ fCanvas->drawText(text, length, x, y, paint);
+ }
+};
+
void SkTextBox::setText(const char text[], size_t len, const SkPaint& paint) {
fText = text;
fLen = len;
fPaint = &paint;
}
+void SkTextBox::draw(SkCanvas* canvas, const char text[], size_t len, const SkPaint& paint) {
+ CanvasVisitor sink(canvas);
+ this->visit(sink, text, len, paint);
+}
+
void SkTextBox::draw(SkCanvas* canvas) {
this->draw(canvas, fText, fLen, *fPaint);
}
@@ -257,3 +274,30 @@ SkScalar SkTextBox::getTextHeight() const {
SkScalar spacing = SkScalarMul(fPaint->getTextSize(), fSpacingMul) + fSpacingAdd;
return this->countLines() * spacing;
}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkTextBlob.h"
+
+class TextBlobVisitor : public SkTextBox::Visitor {
+public:
+ SkTextBlobBuilder fBuilder;
+
+ virtual void operator()(const char text[], size_t length, SkScalar x, SkScalar y,
+ const SkPaint& paint) SK_OVERRIDE {
+ SkPaint p(paint);
+ p.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ const int count = paint.countText(text, length);
+ paint.textToGlyphs(text, length, fBuilder.allocRun(p, count, x, y).glyphs);
+ }
+};
+
+SkTextBlob* SkTextBox::snapshotTextBlob(SkScalar* computedBottom) const {
+ TextBlobVisitor visitor;
+ SkScalar newB = this->visit(visitor, fText, fLen, *fPaint);
+ if (computedBottom) {
+ *computedBottom = newB;
+ }
+ return (SkTextBlob*)visitor.fBuilder.build();
+}
+