diff options
Diffstat (limited to 'app/gfx/canvas_linux.cc')
-rw-r--r-- | app/gfx/canvas_linux.cc | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/app/gfx/canvas_linux.cc b/app/gfx/canvas_linux.cc new file mode 100644 index 0000000..feb5b7f --- /dev/null +++ b/app/gfx/canvas_linux.cc @@ -0,0 +1,141 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "app/gfx/canvas.h" + +#include <pango/pango.h> + +#include "app/gfx/font.h" +#include "base/gfx/rect.h" +#include "base/logging.h" +#include "base/string_util.h" + +namespace { + +// Returns a new pango font, free with pango_font_description_free(). +PangoFontDescription* PangoFontFromGfxFont(const gfx::Font& gfx_font) { + gfx::Font font = gfx_font; // Copy so we can call non-const methods. + PangoFontDescription* pfd = pango_font_description_new(); + pango_font_description_set_family(pfd, WideToUTF8(font.FontName()).c_str()); + pango_font_description_set_size(pfd, font.FontSize() * PANGO_SCALE); + + switch (font.style()) { + case gfx::Font::NORMAL: + // Nothing to do, should already be PANGO_STYLE_NORMAL. + break; + case gfx::Font::BOLD: + pango_font_description_set_weight(pfd, PANGO_WEIGHT_BOLD); + break; + case gfx::Font::ITALIC: + pango_font_description_set_style(pfd, PANGO_STYLE_ITALIC); + break; + case gfx::Font::UNDERLINED: + // TODO(deanm): How to do underlined? Where do we use it? Probably have + // to paint it ourselves, see pango_font_metrics_get_underline_position. + break; + } + + return pfd; +} + +} // namespace + +namespace gfx { + +Canvas::Canvas(int width, int height, bool is_opaque) + : skia::PlatformCanvasLinux(width, height, is_opaque) { +} + +Canvas::Canvas() : skia::PlatformCanvasLinux() { +} + +Canvas::~Canvas() { +} + +// static +void Canvas::SizeStringInt(const std::wstring& text, + const gfx::Font& font, + int* width, int* height, int flags) { + NOTIMPLEMENTED(); +} + +void Canvas::ApplySkiaMatrixToCairoContext(cairo_t* cr) { + const SkMatrix& skia_matrix = getTotalMatrix(); + cairo_matrix_t cairo_matrix; + cairo_matrix_init(&cairo_matrix, + SkScalarToFloat(skia_matrix.getScaleX()), + SkScalarToFloat(skia_matrix.getSkewY()), + SkScalarToFloat(skia_matrix.getSkewX()), + SkScalarToFloat(skia_matrix.getScaleY()), + SkScalarToFloat(skia_matrix.getTranslateX()), + SkScalarToFloat(skia_matrix.getTranslateY())); + cairo_set_matrix(cr, &cairo_matrix); +} + +void Canvas::DrawStringInt(const std::wstring& text, + const gfx::Font& font, + const SkColor& color, int x, int y, int w, int h, + int flags) { + cairo_surface_t* surface = beginPlatformPaint(); + cairo_t* cr = cairo_create(surface); + // We're going to draw onto the surface directly. This circumvents the matrix + // installed by Skia. Apply the matrix from skia to cairo so they align and + // we draw at the right place. + ApplySkiaMatrixToCairoContext(cr); + PangoLayout* layout = pango_cairo_create_layout(cr); + + cairo_set_source_rgb(cr, + SkColorGetR(color) / 255.0, + SkColorGetG(color) / 255.0, + SkColorGetB(color) / 255.0); + + // TODO(deanm): Implement the rest of the Canvas flags. + if (!(flags & Canvas::NO_ELLIPSIS)) + pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); + + pango_layout_set_width(layout, w * PANGO_SCALE); + pango_layout_set_height(layout, h * PANGO_SCALE); + + if (flags & TEXT_ALIGN_CENTER) { + pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); + } else if (flags & TEXT_ALIGN_RIGHT) { + pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT); + } + + if (flags & MULTI_LINE) { + pango_layout_set_wrap(layout, + (flags & CHARACTER_BREAK) ? PANGO_WRAP_WORD_CHAR : PANGO_WRAP_WORD); + } + + if (flags & NO_ELLIPSIS) + pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); + + std::string utf8 = WideToUTF8(text); + pango_layout_set_text(layout, utf8.data(), utf8.size()); + + PangoFontDescription* desc = PangoFontFromGfxFont(font); + pango_layout_set_font_description(layout, desc); + pango_font_description_free(desc); + + int width, height; + pango_layout_get_size(layout, &width, &height); + + if (flags & Canvas::TEXT_VALIGN_TOP) { + // Cairo should draw from the top left corner already. + } else if (flags & Canvas::TEXT_VALIGN_BOTTOM) { + y = y + (h - (height / PANGO_SCALE)); + } else { + // Vertically centered. + y = y + ((h - (height / PANGO_SCALE)) / 2); + } + + cairo_move_to(cr, x, y); + pango_cairo_show_layout(cr, layout); + + g_object_unref(layout); + cairo_destroy(cr); + // NOTE: beginPlatformPaint returned its surface, we shouldn't destroy it. +} + +} // namespace gfx |