summaryrefslogtreecommitdiff
path: root/examples/text
diff options
context:
space:
mode:
authorJonathon Jongsma <jjongsma@gnome.org>2008-12-11 22:28:53 -0600
committerJonathon Jongsma <jjongsma@gnome.org>2008-12-11 22:28:53 -0600
commitbfe3e94977430d4f564bfe006578e4ea9104a566 (patch)
tree8481c7d4d981b852d7e81abb4b495e3496827b75 /examples/text
parent5f35a1ce44f635da2cfeec24fd1720be85843f0f (diff)
Enhance the UserFontFace example
* examples/text/user-font.cc: enhanced the UserFontFace example quite a bit so that it shows a few different virtual functions and actually draws different sized boxes for different characters
Diffstat (limited to 'examples/text')
-rw-r--r--examples/text/user-font.cc112
1 files changed, 94 insertions, 18 deletions
diff --git a/examples/text/user-font.cc b/examples/text/user-font.cc
index 8e5dae9..7836f5b 100644
--- a/examples/text/user-font.cc
+++ b/examples/text/user-font.cc
@@ -1,36 +1,98 @@
#include <cairomm/cairomm.h>
#include <iostream>
+#include <map>
const double HEIGHT = 200.0;
const double WIDTH = 400.0;
const double FONT_SIZE = 64.0;
const double TEXT_ORIGIN_Y = (HEIGHT / 2.0) + (FONT_SIZE / 2.0);
const double TEXT_ORIGIN_X = 50.0; // arbitrary
+const double GLYPH_SPACING = 0.1;
+
+struct GlyphBounds
+{
+ unsigned long glyph;
+ double width;
+ double height;
+};
+
+// an array that stores the bounds of the glyphs that we're going to draw
+static const GlyphBounds glyphs[] =
+{
+ { 'c', 0.45, 0.5 },
+ { 'a', 0.45, 0.5 },
+ { 'i', 0.2, 0.75 },
+ { 'r', 0.4, 0.5 },
+ { 'o', 0.44, 0.5 },
+ { 'm', 0.75, 0.5 },
+ { '!', 0.2, 0.75 }
+};
// A *very* simple font that just draws a box for every glyph
class BoxFontFace : public Cairo::UserFontFace
{
public:
+ // Derived user font classes should have a factory method to create an object
+ // and return it with a RefPtr
static Cairo::RefPtr<BoxFontFace> create()
{
return Cairo::RefPtr<BoxFontFace>(new BoxFontFace());
}
virtual Cairo::ErrorStatus
- render_glyph(const Cairo::RefPtr<Cairo::ScaledFont>& /*scaled_font*/,
- unsigned long glyph,
- const Cairo::RefPtr<Cairo::Context>& cr,
- Cairo::TextExtents& /*metrics*/)
+ init(const Cairo::RefPtr<Cairo::ScaledFont>& /*scaled_font*/,
+ const Cairo::RefPtr<Cairo::Context>& /*cr*/,
+ Cairo::FontExtents &extents)
{
- std::cout << "Rendering glyph " << glyph << std::endl;
- cr->set_line_width(0.05);
- // FIXME: is the negative Y value correct?
- cr->rectangle(0.0, 0.0, 1.0, -1.0);
- cr->stroke();
+ double max = 0;
+ for (unsigned int i = 0; i < sizeof (glyphs) / sizeof (GlyphBounds); ++i) {
+ if (glyphs[i].width > max)
+ max = glyphs[i].width;
+ }
+ // add some spacing between characters
+ max += GLYPH_SPACING;
+ extents.max_x_advance = max;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ virtual Cairo::ErrorStatus
+ unicode_to_glyph (const Cairo::RefPtr<Cairo::ScaledFont>& /*scaled_font*/,
+ unsigned long unicode, unsigned long& glyph)
+ {
+ glyph = 0;
+ // yes this is a stupid an ineffienct way to do this but we only have a few
+ // glyphs and this is just demonstration code
+ for (unsigned int i = 0; i < sizeof (glyphs) / sizeof (GlyphBounds); ++i) {
+ if (glyphs[i].glyph == unicode) {
+ // glyph 0 is often a special glyph-not-found value, so offset it by 1
+ glyph = i+1;
+ break;
+ }
+ }
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ virtual Cairo::ErrorStatus
+ render_glyph(const Cairo::RefPtr<Cairo::ScaledFont>& /*scaled_font*/,
+ unsigned long glyph,
+ const Cairo::RefPtr<Cairo::Context>& cr,
+ Cairo::TextExtents& metrics)
+ {
+ // check that the glyph is in our table
+ if (glyph >= 1 && glyph <= sizeof(glyphs)/sizeof(GlyphBounds)) {
+ cr->set_line_width(0.05);
+ // Need a negative Y value since the text origin is at the bottom left point
+ // and cairo's positive Y axis is down and we want to draw up
+ cr->rectangle(0.0, 0.0, glyphs[glyph-1].width, -glyphs[glyph-1].height);
+ cr->stroke();
+ metrics.x_advance = glyphs[glyph-1].width + GLYPH_SPACING;
+ }
return CAIRO_STATUS_SUCCESS;
}
protected:
+ // FontFace is a ref-counted object, so the constructor should be protected so
+ // it is not created without a refptr to manage it. See the create() method
BoxFontFace() : UserFontFace() { }
};
@@ -51,16 +113,30 @@ int main(int, char**)
// draw the text
cr->move_to(TEXT_ORIGIN_X, TEXT_ORIGIN_Y);
cr->set_source_rgb(0.8, 0.2, 0.2);
+ Cairo::RefPtr<BoxFontFace> font = BoxFontFace::create();
+ cr->set_font_face(font);
+ cr->set_font_size(FONT_SIZE);
+ cr->show_text("cairomm!");
- // this scope block is simply to test that the user font can still be
- // drawn even after the UserFont wrapper object has been de-referenced
- {
- Cairo::RefPtr<BoxFontFace> font = BoxFontFace::create();
- cr->set_font_face(font);
- }
-
+ // Now show it with the toy text API to demonstrate how the glyphs match up
+ cr->move_to(TEXT_ORIGIN_X, TEXT_ORIGIN_Y);
+ cr->set_source_rgba(0.2, 0.2, 0.2, 0.3);
+ Cairo::RefPtr<Cairo::ToyFontFace> toy_font =
+ Cairo::ToyFontFace::create("Bitstream Charter",
+ Cairo::FONT_SLANT_NORMAL,
+ Cairo::FONT_WEIGHT_BOLD);
+ cr->set_font_face(toy_font);
cr->set_font_size(FONT_SIZE);
cr->show_text("cairomm!");
- surface->write_to_png("user-font.png");
- return 0;
+
+ const char* filename = "user-font.png";
+ try {
+ surface->write_to_png(filename);
+ std::cout << "Wrote Image " << filename << std::endl;
+ return 0;
+ } catch (const std::exception& e)
+ {
+ std::cout << "** Unable to write Image " << filename << std::endl;
+ return 1;
+ }
}