From 82522511b7921e8c61742ebd80a4c674c56e7e48 Mon Sep 17 00:00:00 2001 From: "ben@chromium.org" Date: Fri, 15 May 2009 07:37:29 +0000 Subject: ChromeCanvas->gfx::Canvas Rename files too. TBR=brettw http://crbug.com/11387 Review URL: http://codereview.chromium.org/113443 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16148 0039d316-1c4b-4281-b951-d872f2087c98 --- app/DEPS | 8 +- app/app.vcproj | 16 +-- app/gfx/canvas.cc | 262 +++++++++++++++++++++++++++++++++++++++ app/gfx/canvas.h | 217 ++++++++++++++++++++++++++++++++ app/gfx/canvas_linux.cc | 141 +++++++++++++++++++++ app/gfx/canvas_win.cc | 268 ++++++++++++++++++++++++++++++++++++++++ app/gfx/chrome_canvas.cc | 265 --------------------------------------- app/gfx/chrome_canvas.h | 217 -------------------------------- app/gfx/chrome_canvas_linux.cc | 137 -------------------- app/gfx/chrome_canvas_win.cc | 264 --------------------------------------- app/gfx/chrome_font.h | 239 ----------------------------------- app/gfx/chrome_font_gtk.cc | 89 ------------- app/gfx/chrome_font_mac.mm | 90 -------------- app/gfx/chrome_font_skia.cc | 167 ------------------------- app/gfx/chrome_font_unittest.cc | 59 --------- app/gfx/chrome_font_win.cc | 214 -------------------------------- app/gfx/font.h | 239 +++++++++++++++++++++++++++++++++++ app/gfx/font_gtk.cc | 89 +++++++++++++ app/gfx/font_mac.mm | 90 ++++++++++++++ app/gfx/font_skia.cc | 167 +++++++++++++++++++++++++ app/gfx/font_unittest.cc | 59 +++++++++ app/gfx/font_win.cc | 213 +++++++++++++++++++++++++++++++ app/gfx/icon_util.h | 6 +- app/gfx/insets.h | 6 +- app/gfx/path.h | 6 +- app/gfx/text_elider.cc | 2 +- app/gfx/text_elider.h | 8 +- app/gfx/text_elider_unittest.cc | 2 +- app/l10n_util.cc | 6 +- app/l10n_util.h | 8 +- app/resource_bundle.cc | 2 +- app/resource_bundle_linux.cc | 2 +- app/resource_bundle_mac.mm | 2 +- app/resource_bundle_win.cc | 2 +- app/win_util.h | 2 +- 35 files changed, 1784 insertions(+), 1780 deletions(-) create mode 100644 app/gfx/canvas.cc create mode 100644 app/gfx/canvas.h create mode 100644 app/gfx/canvas_linux.cc create mode 100644 app/gfx/canvas_win.cc delete mode 100644 app/gfx/chrome_canvas.cc delete mode 100644 app/gfx/chrome_canvas.h delete mode 100644 app/gfx/chrome_canvas_linux.cc delete mode 100644 app/gfx/chrome_canvas_win.cc delete mode 100644 app/gfx/chrome_font.h delete mode 100644 app/gfx/chrome_font_gtk.cc delete mode 100644 app/gfx/chrome_font_mac.mm delete mode 100644 app/gfx/chrome_font_skia.cc delete mode 100644 app/gfx/chrome_font_unittest.cc delete mode 100644 app/gfx/chrome_font_win.cc create mode 100644 app/gfx/font.h create mode 100644 app/gfx/font_gtk.cc create mode 100644 app/gfx/font_mac.mm create mode 100644 app/gfx/font_skia.cc create mode 100644 app/gfx/font_unittest.cc create mode 100644 app/gfx/font_win.cc (limited to 'app') diff --git a/app/DEPS b/app/DEPS index a087ecf..cffa9e0 100644 --- a/app/DEPS +++ b/app/DEPS @@ -1,11 +1,11 @@ include_rules = [ - # TODO(beng): Modify this link to be more specific about what resource - # headers are included once app gets its own strings. - "+grit", + # TODO(beng): swap these with app/views specific generated resources. + "+grit/generated_resources.h", + "+grit/locale_settings.h", + "+grit/theme_resources.h", "+net", # TODO(beng): Sever these links once we have extracted all deps from # chrome/common. "+chrome/common/chrome_paths.h", - "+skia", ] diff --git a/app/app.vcproj b/app/app.vcproj index 37a051d..92b555c 100644 --- a/app/app.vcproj +++ b/app/app.vcproj @@ -125,35 +125,35 @@ Name="gfx" > + +#include "app/gfx/font.h" +#include "app/l10n_util.h" +#include "base/gfx/rect.h" +#include "base/logging.h" +#include "third_party/skia/include/core/SkShader.h" + +namespace gfx { + +bool Canvas::GetClipRect(gfx::Rect* r) { + SkRect clip; + if (!getClipBounds(&clip)) { + if (r) + r->SetRect(0, 0, 0, 0); + return false; + } + r->SetRect(SkScalarRound(clip.fLeft), SkScalarRound(clip.fTop), + SkScalarRound(clip.fRight - clip.fLeft), + SkScalarRound(clip.fBottom - clip.fTop)); + return true; +} + +bool Canvas::ClipRectInt(int x, int y, int w, int h) { + SkRect new_clip; + new_clip.set(SkIntToScalar(x), SkIntToScalar(y), + SkIntToScalar(x + w), SkIntToScalar(y + h)); + return clipRect(new_clip); +} + +bool Canvas::IntersectsClipRectInt(int x, int y, int w, int h) { + SkRect clip; + return getClipBounds(&clip) && + clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), + SkIntToScalar(y + h)); +} + +void Canvas::TranslateInt(int x, int y) { + translate(SkIntToScalar(x), SkIntToScalar(y)); +} + +void Canvas::ScaleInt(int x, int y) { + scale(SkIntToScalar(x), SkIntToScalar(y)); +} + +void Canvas::FillRectInt(const SkColor& color, int x, int y, int w, int h) { + SkPaint paint; + paint.setColor(color); + paint.setStyle(SkPaint::kFill_Style); + paint.setPorterDuffXfermode(SkPorterDuff::kSrcOver_Mode); + FillRectInt(x, y, w, h, paint); +} + +void Canvas::FillRectInt(int x, int y, int w, int h, const SkPaint& paint) { + SkIRect rc = {x, y, x + w, y + h}; + drawIRect(rc, paint); +} + +void Canvas::DrawRectInt(const SkColor& color, int x, int y, int w, int h) { + DrawRectInt(color, x, y, w, h, SkPorterDuff::kSrcOver_Mode); +} + +void Canvas::DrawRectInt(const SkColor& color, int x, int y, int w, int h, + SkPorterDuff::Mode mode) { + SkPaint paint; + paint.setColor(color); + paint.setStyle(SkPaint::kStroke_Style); + // Set a stroke width of 0, which will put us down the stroke rect path. If + // we set a stroke width of 1, for example, this will internally create a + // path and fill it, which causes problems near the edge of the canvas. + paint.setStrokeWidth(SkIntToScalar(0)); + paint.setPorterDuffXfermode(mode); + + SkIRect rc = {x, y, x + w, y + h}; + drawIRect(rc, paint); +} + +void Canvas::DrawLineInt(const SkColor& color, int x1, int y1, int x2, int y2) { + SkPaint paint; + paint.setColor(color); + paint.setStrokeWidth(SkIntToScalar(1)); + drawLine(SkIntToScalar(x1), SkIntToScalar(y1), SkIntToScalar(x2), + SkIntToScalar(y2), paint); +} + +void Canvas::DrawFocusRect(int x, int y, int width, int height) { + // Create a 2D bitmap containing alternating on/off pixels - we do this + // so that you never get two pixels of the same color around the edges + // of the focus rect (this may mean that opposing edges of the rect may + // have a dot pattern out of phase to each other). + static SkBitmap* dots = NULL; + if (!dots) { + int col_pixels = 32; + int row_pixels = 32; + + dots = new SkBitmap; + dots->setConfig(SkBitmap::kARGB_8888_Config, col_pixels, row_pixels); + dots->allocPixels(); + dots->eraseARGB(0, 0, 0, 0); + + uint32_t* dot = dots->getAddr32(0, 0); + for (int i = 0; i < row_pixels; i++) { + for (int u = 0; u < col_pixels; u++) { + if ((u % 2 + i % 2) % 2 != 0) { + dot[i * row_pixels + u] = SK_ColorGRAY; + } + } + } + } + + // First the horizontal lines. + + // Make a shader for the bitmap with an origin of the box we'll draw. This + // shader is refcounted and will have an initial refcount of 1. + SkShader* shader = SkShader::CreateBitmapShader( + *dots, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); + // Assign the shader to the paint & release our reference. The paint will + // now own the shader and the shader will be destroyed when the paint goes + // out of scope. + SkPaint paint; + paint.setShader(shader); + shader->unref(); + + SkRect rect; + rect.set(SkIntToScalar(x), SkIntToScalar(y), + SkIntToScalar(x + width), SkIntToScalar(y + 1)); + drawRect(rect, paint); + rect.set(SkIntToScalar(x), SkIntToScalar(y + height - 1), + SkIntToScalar(x + width), SkIntToScalar(y + height)); + drawRect(rect, paint); + + rect.set(SkIntToScalar(x), SkIntToScalar(y), + SkIntToScalar(x + 1), SkIntToScalar(y + height)); + drawRect(rect, paint); + rect.set(SkIntToScalar(x + width - 1), SkIntToScalar(y), + SkIntToScalar(x + width), SkIntToScalar(y + height)); + drawRect(rect, paint); +} + +void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int x, int y) { + drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y)); +} + +void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int x, int y, + const SkPaint& paint) { + drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), &paint); +} + +void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, + int src_w, int src_h, int dest_x, int dest_y, + int dest_w, int dest_h, + bool filter) { + SkPaint p; + DrawBitmapInt(bitmap, src_x, src_y, src_w, src_h, dest_x, dest_y, + dest_w, dest_h, filter, p); +} + +void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, + int src_w, int src_h, int dest_x, int dest_y, + int dest_w, int dest_h, + bool filter, const SkPaint& paint) { + DLOG_ASSERT(src_x + src_w < std::numeric_limits::max() && + src_y + src_h < std::numeric_limits::max()); + if (src_w <= 0 || src_h <= 0 || dest_w <= 0 || dest_h <= 0) { + NOTREACHED() << "Attempting to draw bitmap to/from an empty rect!"; + return; + } + + if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) + return; + + SkRect dest_rect = { SkIntToScalar(dest_x), + SkIntToScalar(dest_y), + SkIntToScalar(dest_x + dest_w), + SkIntToScalar(dest_y + dest_h) }; + + if (src_w == dest_w && src_h == dest_h) { + // Workaround for apparent bug in Skia that causes image to occasionally + // shift. + SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h }; + drawBitmapRect(bitmap, &src_rect, dest_rect, &paint); + return; + } + + // Make a bitmap shader that contains the bitmap we want to draw. This is + // basically what SkCanvas.drawBitmap does internally, but it gives us + // more control over quality and will use the mipmap in the source image if + // it has one, whereas drawBitmap won't. + SkShader* shader = SkShader::CreateBitmapShader(bitmap, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode); + SkMatrix shader_scale; + shader_scale.setScale(SkFloatToScalar(static_cast(dest_w) / src_w), + SkFloatToScalar(static_cast(dest_h) / src_h)); + shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y)); + shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y)); + shader->setLocalMatrix(shader_scale); + + // Set up our paint to use the shader & release our reference (now just owned + // by the paint). + SkPaint p(paint); + p.setFilterBitmap(filter); + p.setShader(shader); + shader->unref(); + + // The rect will be filled by the bitmap. + drawRect(dest_rect, p); +} + +void Canvas::DrawStringInt(const std::wstring& text, + const gfx::Font& font, + const SkColor& color, + int x, int y, int w, int h) { + DrawStringInt(text, font, color, x, y, w, h, + l10n_util::DefaultCanvasTextAlignment()); +} + +void Canvas::TileImageInt(const SkBitmap& bitmap, int x, int y, int w, int h) { + TileImageInt(bitmap, 0, 0, x, y, w, h); +} + +void Canvas::TileImageInt(const SkBitmap& bitmap, int src_x, int src_y, + int dest_x, int dest_y, int w, int h) { + if (!IntersectsClipRectInt(dest_x, dest_y, w, h)) + return; + + SkPaint paint; + + SkShader* shader = SkShader::CreateBitmapShader(bitmap, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode); + paint.setShader(shader); + paint.setPorterDuffXfermode(SkPorterDuff::kSrcOver_Mode); + + // CreateBitmapShader returns a Shader with a reference count of one, we + // need to unref after paint takes ownership of the shader. + shader->unref(); + save(); + translate(SkIntToScalar(dest_x - src_x), SkIntToScalar(dest_y - src_y)); + ClipRectInt(src_x, src_y, w, h); + drawPaint(paint); + restore(); +} + +SkBitmap Canvas::ExtractBitmap() { + const SkBitmap& device_bitmap = getDevice()->accessBitmap(false); + + // Make a bitmap to return, and a canvas to draw into it. We don't just want + // to call extractSubset or the copy constuctor, since we want an actual copy + // of the bitmap. + SkBitmap result; + device_bitmap.copyTo(&result, SkBitmap::kARGB_8888_Config); + return result; +} + +} // namespace gfx diff --git a/app/gfx/canvas.h b/app/gfx/canvas.h new file mode 100644 index 0000000..e1d20b8 --- /dev/null +++ b/app/gfx/canvas.h @@ -0,0 +1,217 @@ +// Copyright (c) 2006-2008 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. + +#ifndef APP_GFX_CANVAS_H_ +#define APP_GFX_CANVAS_H_ + +#if defined(OS_WIN) +#include +#endif + +#include + +#include "base/basictypes.h" +#include "skia/ext/platform_canvas.h" + +#if defined(OS_LINUX) +typedef struct _cairo cairo_t; +#endif + +namespace gfx { + +class Font; +class Rect; + +// Canvas is a SkCanvas subclass that provides a number of methods for common +// operations used throughout an application built using base/gfx and app/gfx. +// +// All methods that take integer arguments (as is used throughout views) +// end with Int. If you need to use methods provided by the superclass +// you'll need to do a conversion. In particular you'll need to use +// macro SkIntToScalar(xxx), or if converting from a scalar to an integer +// SkScalarRound. +// +// A handful of methods in this class are overloaded providing an additional +// argument of type SkPorterDuff::Mode. SkPorterDuff::Mode specifies how the +// source and destination colors are combined. Unless otherwise specified, +// the variant that does not take a SkPorterDuff::Mode uses a transfer mode +// of kSrcOver_Mode. +class Canvas : public skia::PlatformCanvas { + public: + // Specifies the alignment for text rendered with the DrawStringInt method. + enum { + TEXT_ALIGN_LEFT = 1, + TEXT_ALIGN_CENTER = 2, + TEXT_ALIGN_RIGHT = 4, + TEXT_VALIGN_TOP = 8, + TEXT_VALIGN_MIDDLE = 16, + TEXT_VALIGN_BOTTOM = 32, + + // Specifies the text consists of multiple lines. + MULTI_LINE = 64, + + // By default DrawStringInt does not process the prefix ('&') character + // specially. That is, the string "&foo" is rendered as "&foo". When + // rendering text from a resource that uses the prefix character for + // mnemonics, the prefix should be processed and can be rendered as an + // underline (SHOW_PREFIX), or not rendered at all (HIDE_PREFIX). + SHOW_PREFIX = 128, + HIDE_PREFIX = 256, + + // Prevent ellipsizing + NO_ELLIPSIS = 512, + + // Specifies if words can be split by new lines. + // This only works with MULTI_LINE. + CHARACTER_BREAK = 1024, + }; + + // Creates an empty Canvas. Callers must use initialize before using the + // canvas. + Canvas(); + + Canvas(int width, int height, bool is_opaque); + + virtual ~Canvas(); + + // Retrieves the clip rectangle and sets it in the specified rectangle if any. + // Returns true if the clip rect is non-empty. + bool GetClipRect(gfx::Rect* clip_rect); + + // Wrapper function that takes integer arguments. + // Returns true if the clip is non-empty. + // See clipRect for specifics. + bool ClipRectInt(int x, int y, int w, int h); + + // Test whether the provided rectangle intersects the current clip rect. + bool IntersectsClipRectInt(int x, int y, int w, int h); + + // Wrapper function that takes integer arguments. + // See translate() for specifics. + void TranslateInt(int x, int y); + + // Wrapper function that takes integer arguments. + // See scale() for specifics. + void ScaleInt(int x, int y); + + // Fills the given rectangle with the given paint's parameters. + void FillRectInt(int x, int y, int w, int h, const SkPaint& paint); + + // Fills the specified region with the specified color using a transfer + // mode of SkPorterDuff::kSrcOver_Mode. + void FillRectInt(const SkColor& color, int x, int y, int w, int h); + + // Draws a single pixel rect in the specified region with the specified + // color, using a transfer mode of SkPorterDuff::kSrcOver_Mode. + // + // NOTE: if you need a single pixel line, use DraLineInt. + void DrawRectInt(const SkColor& color, int x, int y, int w, int h); + + // Draws a single pixel rect in the specified region with the specified + // color and transfer mode. + // + // NOTE: if you need a single pixel line, use DraLineInt. + void DrawRectInt(const SkColor& color, int x, int y, int w, int h, + SkPorterDuff::Mode mode); + + // Draws a single pixel line with the specified color. + void DrawLineInt(const SkColor& color, int x1, int y1, int x2, int y2); + + // Draws a bitmap with the origin at the specified location. The upper left + // corner of the bitmap is rendered at the specified location. + void DrawBitmapInt(const SkBitmap& bitmap, int x, int y); + + // Draws a bitmap with the origin at the specified location, using the + // specified paint. The upper left corner of the bitmap is rendered at the + // specified location. + void DrawBitmapInt(const SkBitmap& bitmap, int x, int y, + const SkPaint& paint); + + // Draws a portion of a bitmap in the specified location. The src parameters + // correspond to the region of the bitmap to draw in the region defined + // by the dest coordinates. + // + // If the width or height of the source differs from that of the destination, + // the bitmap will be scaled. When scaling down, it is highly recommended + // that you call buildMipMap(false) on your bitmap to ensure that it has + // a mipmap, which will result in much higher-quality output. Set |filter| + // to use filtering for bitmaps, otherwise the nearest-neighbor algorithm + // is used for resampling. + // + // An optional custom SkPaint can be provided. + void DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, int src_w, + int src_h, int dest_x, int dest_y, int dest_w, int dest_h, + bool filter); + void DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, int src_w, + int src_h, int dest_x, int dest_y, int dest_w, int dest_h, + bool filter, const SkPaint& paint); + + // Draws text with the specified color, font and location. The text is + // aligned to the left, vertically centered, clipped to the region. If the + // text is too big, it is truncated and '...' is added to the end. + void DrawStringInt(const std::wstring& text, const gfx::Font& font, + const SkColor& color, int x, int y, int w, int h); + + // Draws text with the specified color, font and location. The last argument + // specifies flags for how the text should be rendered. It can be one of + // TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT or TEXT_ALIGN_LEFT. + void DrawStringInt(const std::wstring& text, const gfx::Font& font, + const SkColor& color, int x, int y, int w, int h, + int flags); + +#ifdef OS_WIN // Only implemented on Windows for now. + // Draws text with a 1-pixel halo around it of the given color. It allows + // ClearType to be drawn to an otherwise transparenct bitmap for drag images. + // Drag images have only 1-bit of transparency, so we don't do any fancy + // blurring. + void DrawStringWithHalo(const std::wstring& text, const gfx::Font& font, + const SkColor& text_color, const SkColor& halo_color, + int x, int y, int w, int h, int flags); +#endif + + // Draws a dotted gray rectangle used for focus purposes. + void DrawFocusRect(int x, int y, int width, int height); + + // Tiles the image in the specified region. + void TileImageInt(const SkBitmap& bitmap, int x, int y, int w, int h); + void TileImageInt(const SkBitmap& bitmap, int src_x, int src_y, + int dest_x, int dest_y, int w, int h); + + // Extracts a bitmap from the contents of this canvas. + SkBitmap ExtractBitmap(); + +#if defined(OS_LINUX) + // Applies current matrix on the canvas to the cairo context. This should be + // invoked anytime you plan on drawing directly to the cairo context. Be + // sure and set the matrix back to the identity when done. + void ApplySkiaMatrixToCairoContext(cairo_t* cr); +#endif + + // Compute the size required to draw some text with the provided font. + // Attempts to fit the text with the provided width and height. Increases + // height and then width as needed to make the text fit. This method + // supports multiple lines. + static void SizeStringInt(const std::wstring& test, const gfx::Font& font, + int *width, int* height, int flags); + + private: +#if defined(OS_WIN) + // Draws text with the specified color, font and location. The text is + // aligned to the left, vertically centered, clipped to the region. If the + // text is too big, it is truncated and '...' is added to the end. + void DrawStringInt(const std::wstring& text, HFONT font, + const SkColor& color, int x, int y, int w, int h, + int flags); +#endif + + DISALLOW_COPY_AND_ASSIGN(Canvas); +}; + +#if defined(OS_WIN) || defined(OS_LINUX) +typedef skia::CanvasPaintT CanvasPaint; +#endif + +} // namespace gfx; + +#endif // #ifndef APP_GFX_CANVAS_H_ 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 + +#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 diff --git a/app/gfx/canvas_win.cc b/app/gfx/canvas_win.cc new file mode 100644 index 0000000..2d818d4 --- /dev/null +++ b/app/gfx/canvas_win.cc @@ -0,0 +1,268 @@ +// Copyright (c) 2006-2008 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 + +#include "app/gfx/font.h" +#include "app/l10n_util.h" +#include "base/gfx/rect.h" +#include "third_party/skia/include/core/SkShader.h" + +namespace { + +// We make sure that LTR text we draw in an RTL context is modified +// appropriately to make sure it maintains it LTR orientation. +void DoDrawText(HDC hdc, const std::wstring& text, + RECT* text_bounds, int flags) { + std::wstring localized_text; + const wchar_t* string_ptr = text.c_str(); + int string_size = static_cast(text.length()); + // Only adjust string directionality if both of the following are true: + // 1. The current locale is RTL. + // 2. The string itself has RTL directionality. + if (flags & DT_RTLREADING) { + if (l10n_util::AdjustStringForLocaleDirection(text, &localized_text)) { + string_ptr = localized_text.c_str(); + string_size = static_cast(localized_text.length()); + } + } + + DrawText(hdc, string_ptr, string_size, text_bounds, flags); +} + +// Compute the windows flags necessary to implement the provided text Canvas +// flags. +int ComputeFormatFlags(int flags, const std::wstring& text) { + int f = 0; + + // Setting the text alignment explicitly in case it hasn't already been set. + // This will make sure that we don't align text to the left on RTL locales + // just because no alignment flag was passed to DrawStringInt(). + if (!(flags & (gfx::Canvas::TEXT_ALIGN_CENTER | + gfx::Canvas::TEXT_ALIGN_RIGHT | + gfx::Canvas::TEXT_ALIGN_LEFT))) { + flags |= l10n_util::DefaultCanvasTextAlignment(); + } + + if (flags & gfx::Canvas::HIDE_PREFIX) + f |= DT_HIDEPREFIX; + else if ((flags & gfx::Canvas::SHOW_PREFIX) == 0) + f |= DT_NOPREFIX; + + if (flags & gfx::Canvas::MULTI_LINE) { + f |= DT_WORDBREAK; + if (flags & gfx::Canvas::CHARACTER_BREAK) + f |= DT_EDITCONTROL; + } else { + f |= DT_SINGLELINE | DT_VCENTER; + if (!(flags & gfx::Canvas::NO_ELLIPSIS)) + f |= DT_END_ELLIPSIS; + } + + // vertical alignment + if (flags & gfx::Canvas::TEXT_VALIGN_TOP) + f |= DT_TOP; + else if (flags & gfx::Canvas::TEXT_VALIGN_BOTTOM) + f |= DT_BOTTOM; + else + f |= DT_VCENTER; + + // horizontal alignment + if (flags & gfx::Canvas::TEXT_ALIGN_CENTER) + f |= DT_CENTER; + else if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT) + f |= DT_RIGHT; + else + f |= DT_LEFT; + + // In order to make sure RTL/BiDi strings are rendered correctly, we must + // pass the flag DT_RTLREADING to DrawText (when the locale's language is + // a right-to-left language) so that Windows does the right thing. + // + // In addition to correctly displaying text containing both RTL and LTR + // elements (for example, a string containing a telephone number within a + // sentence in Hebrew, or a sentence in Hebrew that contains a word in + // English) this flag also makes sure that if there is not enough space to + // display the entire string, the ellipsis is displayed on the left hand side + // of the truncated string and not on the right hand side. + // + // We make a distinction between Chrome UI strings and text coming from a web + // page. + // + // For text coming from a web page we determine the alignment based on the + // first character with strong directionality. If the directionality of the + // first character with strong directionality in the text is LTR, the + // alignment is set to DT_LEFT, and the directionality should not be set as + // DT_RTLREADING. + // + // This heuristic doesn't work for Chrome UI strings since even in RTL + // locales, some of those might start with English text but we know they're + // localized so we always want them to be right aligned, and their + // directionality should be set as DT_RTLREADING. + // + // Caveat: If the string is purely LTR, don't set DTL_RTLREADING since when + // the flag is set, LRE-PDF don't have the desired effect of rendering + // multiline English-only text as LTR. + if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT && + (f & DT_RIGHT)) { + if (l10n_util::StringContainsStrongRTLChars(text)) { + f |= DT_RTLREADING; + } + } + return f; +} + +} // anonymous namespace + +namespace gfx { + +Canvas::Canvas(int width, int height, bool is_opaque) + : skia::PlatformCanvasWin(width, height, is_opaque) { +} + +Canvas::Canvas() : skia::PlatformCanvasWin() { +} + +Canvas::~Canvas() { +} + +// static +void Canvas::SizeStringInt(const std::wstring& text, + const gfx::Font& font, + int *width, int *height, int flags) { + HDC dc = GetDC(NULL); + HFONT old_font = static_cast(SelectObject(dc, font.hfont())); + RECT b; + b.left = 0; + b.top = 0; + b.right = *width; + if (b.right == 0 && !text.empty()) { + // Width needs to be at least 1 or else DoDrawText will not resize it. + b.right = 1; + } + b.bottom = *height; + DoDrawText(dc, text, &b, ComputeFormatFlags(flags, text) | DT_CALCRECT); + + // Restore the old font. This way we don't have to worry if the caller + // deletes the font and the DC lives longer. + SelectObject(dc, old_font); + *width = b.right; + *height = b.bottom; + + ReleaseDC(NULL, dc); +} + +void Canvas::DrawStringInt(const std::wstring& text, HFONT font, + const SkColor& color, int x, int y, int w, int h, + int flags) { + if (!IntersectsClipRectInt(x, y, w, h)) + return; + + RECT text_bounds = { x, y, x + w, y + h }; + HDC dc = beginPlatformPaint(); + SetBkMode(dc, TRANSPARENT); + HFONT old_font = (HFONT)SelectObject(dc, font); + COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), + SkColorGetB(color)); + SetTextColor(dc, brush_color); + + int f = ComputeFormatFlags(flags, text); + DoDrawText(dc, text, &text_bounds, f); + endPlatformPaint(); + + // Restore the old font. This way we don't have to worry if the caller + // deletes the font and the DC lives longer. + SelectObject(dc, old_font); + + // Windows will have cleared the alpha channel of the text we drew. Assume + // we're drawing to an opaque surface, or at least the text rect area is + // opaque. + getTopPlatformDevice().makeOpaque(x, y, w, h); +} + +void Canvas::DrawStringInt(const std::wstring& text, + const gfx::Font& font, + const SkColor& color, + int x, int y, int w, int h, int flags) { + DrawStringInt(text, font.hfont(), color, x, y, w, h, flags); +} + +// Checks each pixel immediately adjacent to the given pixel in the bitmap. If +// any of them are not the halo color, returns true. This defines the halo of +// pixels that will appear around the text. Note that we have to check each +// pixel against both the halo color and transparent since DrawStringWithHalo +// will modify the bitmap as it goes, and clears pixels shouldn't count as +// changed. +static bool pixelShouldGetHalo(const SkBitmap& bitmap, int x, int y, + SkColor halo_color) { + if (x > 0 && + *bitmap.getAddr32(x - 1, y) != halo_color && + *bitmap.getAddr32(x - 1, y) != 0) + return true; // Touched pixel to the left. + if (x < bitmap.width() - 1 && + *bitmap.getAddr32(x + 1, y) != halo_color && + *bitmap.getAddr32(x + 1, y) != 0) + return true; // Touched pixel to the right. + if (y > 0 && + *bitmap.getAddr32(x, y - 1) != halo_color && + *bitmap.getAddr32(x, y - 1) != 0) + return true; // Touched pixel above. + if (y < bitmap.height() - 1 && + *bitmap.getAddr32(x, y + 1) != halo_color && + *bitmap.getAddr32(x, y + 1) != 0) + return true; // Touched pixel below. + return false; +} + +void Canvas::DrawStringWithHalo(const std::wstring& text, + const gfx::Font& font, + const SkColor& text_color, + const SkColor& halo_color_in, + int x, int y, int w, int h, + int flags) { + // Some callers will have semitransparent halo colors, which we don't handle + // (since the resulting image can have 1-bit transparency only). + SkColor halo_color = halo_color_in | 0xFF000000; + + // Create a temporary buffer filled with the halo color. It must leave room + // for the 1-pixel border around the text. + Canvas text_canvas(w + 2, h + 2, true); + SkPaint bkgnd_paint; + bkgnd_paint.setColor(halo_color); + text_canvas.FillRectInt(0, 0, w + 2, h + 2, bkgnd_paint); + + // Draw the text into the temporary buffer. This will have correct + // ClearType since the background color is the same as the halo color. + text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); + + // Windows will have cleared the alpha channel for the pixels it drew. Make it + // opaque. We have to do this first since pixelShouldGetHalo will check for + // 0 to see if a pixel has been modified to transparent, and black text that + // Windows draw will look transparent to it! + text_canvas.getTopPlatformDevice().makeOpaque(0, 0, w + 2, h + 2); + + uint32_t halo_premul = SkPreMultiplyColor(halo_color); + SkBitmap& text_bitmap = const_cast( + text_canvas.getTopPlatformDevice().accessBitmap(true)); + for (int cur_y = 0; cur_y < h + 2; cur_y++) { + uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); + for (int cur_x = 0; cur_x < w + 2; cur_x++) { + if (text_row[cur_x] == halo_premul) { + // This pixel was not touched by the text routines. See if it borders + // a touched pixel in any of the 4 directions (not diagonally). + if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) + text_row[cur_x] = 0; // Make transparent. + } else { + text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. + } + } + } + + // Draw the halo bitmap with blur. + drawBitmap(text_bitmap, SkIntToScalar(x - 1), SkIntToScalar(y - 1)); +} + +} // namespace gfx diff --git a/app/gfx/chrome_canvas.cc b/app/gfx/chrome_canvas.cc deleted file mode 100644 index 4419b0f..0000000 --- a/app/gfx/chrome_canvas.cc +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (c) 2006-2008 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/chrome_canvas.h" - -#include - -#include "app/gfx/chrome_font.h" -#include "app/l10n_util.h" -#include "base/gfx/rect.h" -#include "base/logging.h" -#include "third_party/skia/include/core/SkShader.h" - -bool ChromeCanvas::GetClipRect(gfx::Rect* r) { - SkRect clip; - if (!getClipBounds(&clip)) { - if (r) - r->SetRect(0, 0, 0, 0); - return false; - } - r->SetRect(SkScalarRound(clip.fLeft), SkScalarRound(clip.fTop), - SkScalarRound(clip.fRight - clip.fLeft), - SkScalarRound(clip.fBottom - clip.fTop)); - return true; -} - -bool ChromeCanvas::ClipRectInt(int x, int y, int w, int h) { - SkRect new_clip; - new_clip.set(SkIntToScalar(x), SkIntToScalar(y), - SkIntToScalar(x + w), SkIntToScalar(y + h)); - return clipRect(new_clip); -} - -bool ChromeCanvas::IntersectsClipRectInt(int x, int y, int w, int h) { - SkRect clip; - return getClipBounds(&clip) && - clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), - SkIntToScalar(y + h)); -} - -void ChromeCanvas::TranslateInt(int x, int y) { - translate(SkIntToScalar(x), SkIntToScalar(y)); -} - -void ChromeCanvas::ScaleInt(int x, int y) { - scale(SkIntToScalar(x), SkIntToScalar(y)); -} - -void ChromeCanvas::FillRectInt(const SkColor& color, - int x, int y, int w, int h) { - SkPaint paint; - paint.setColor(color); - paint.setStyle(SkPaint::kFill_Style); - paint.setPorterDuffXfermode(SkPorterDuff::kSrcOver_Mode); - FillRectInt(x, y, w, h, paint); -} - -void ChromeCanvas::FillRectInt(int x, int y, int w, int h, - const SkPaint& paint) { - SkIRect rc = {x, y, x + w, y + h}; - drawIRect(rc, paint); -} - -void ChromeCanvas::DrawRectInt(const SkColor& color, - int x, int y, int w, int h) { - DrawRectInt(color, x, y, w, h, SkPorterDuff::kSrcOver_Mode); -} - -void ChromeCanvas::DrawRectInt(const SkColor& color, - int x, int y, int w, int h, - SkPorterDuff::Mode mode) { - SkPaint paint; - paint.setColor(color); - paint.setStyle(SkPaint::kStroke_Style); - // Set a stroke width of 0, which will put us down the stroke rect path. If - // we set a stroke width of 1, for example, this will internally create a - // path and fill it, which causes problems near the edge of the canvas. - paint.setStrokeWidth(SkIntToScalar(0)); - paint.setPorterDuffXfermode(mode); - - SkIRect rc = {x, y, x + w, y + h}; - drawIRect(rc, paint); -} - -void ChromeCanvas::DrawLineInt(const SkColor& color, - int x1, int y1, int x2, int y2) { - SkPaint paint; - paint.setColor(color); - paint.setStrokeWidth(SkIntToScalar(1)); - drawLine(SkIntToScalar(x1), SkIntToScalar(y1), SkIntToScalar(x2), - SkIntToScalar(y2), paint); -} - -void ChromeCanvas::DrawFocusRect(int x, int y, int width, int height) { - // Create a 2D bitmap containing alternating on/off pixels - we do this - // so that you never get two pixels of the same color around the edges - // of the focus rect (this may mean that opposing edges of the rect may - // have a dot pattern out of phase to each other). - static SkBitmap* dots = NULL; - if (!dots) { - int col_pixels = 32; - int row_pixels = 32; - - dots = new SkBitmap; - dots->setConfig(SkBitmap::kARGB_8888_Config, col_pixels, row_pixels); - dots->allocPixels(); - dots->eraseARGB(0, 0, 0, 0); - - uint32_t* dot = dots->getAddr32(0, 0); - for (int i = 0; i < row_pixels; i++) { - for (int u = 0; u < col_pixels; u++) { - if ((u % 2 + i % 2) % 2 != 0) { - dot[i * row_pixels + u] = SK_ColorGRAY; - } - } - } - } - - // First the horizontal lines. - - // Make a shader for the bitmap with an origin of the box we'll draw. This - // shader is refcounted and will have an initial refcount of 1. - SkShader* shader = SkShader::CreateBitmapShader( - *dots, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); - // Assign the shader to the paint & release our reference. The paint will - // now own the shader and the shader will be destroyed when the paint goes - // out of scope. - SkPaint paint; - paint.setShader(shader); - shader->unref(); - - SkRect rect; - rect.set(SkIntToScalar(x), SkIntToScalar(y), - SkIntToScalar(x + width), SkIntToScalar(y + 1)); - drawRect(rect, paint); - rect.set(SkIntToScalar(x), SkIntToScalar(y + height - 1), - SkIntToScalar(x + width), SkIntToScalar(y + height)); - drawRect(rect, paint); - - rect.set(SkIntToScalar(x), SkIntToScalar(y), - SkIntToScalar(x + 1), SkIntToScalar(y + height)); - drawRect(rect, paint); - rect.set(SkIntToScalar(x + width - 1), SkIntToScalar(y), - SkIntToScalar(x + width), SkIntToScalar(y + height)); - drawRect(rect, paint); -} - -void ChromeCanvas::DrawBitmapInt(const SkBitmap& bitmap, int x, int y) { - drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y)); -} - -void ChromeCanvas::DrawBitmapInt(const SkBitmap& bitmap, int x, int y, - const SkPaint& paint) { - drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), &paint); -} - -void ChromeCanvas::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, - int src_w, int src_h, int dest_x, int dest_y, - int dest_w, int dest_h, - bool filter) { - SkPaint p; - DrawBitmapInt(bitmap, src_x, src_y, src_w, src_h, dest_x, dest_y, - dest_w, dest_h, filter, p); -} - -void ChromeCanvas::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, - int src_w, int src_h, int dest_x, int dest_y, - int dest_w, int dest_h, - bool filter, const SkPaint& paint) { - DLOG_ASSERT(src_x + src_w < std::numeric_limits::max() && - src_y + src_h < std::numeric_limits::max()); - if (src_w <= 0 || src_h <= 0 || dest_w <= 0 || dest_h <= 0) { - NOTREACHED() << "Attempting to draw bitmap to/from an empty rect!"; - return; - } - - if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) - return; - - SkRect dest_rect = { SkIntToScalar(dest_x), - SkIntToScalar(dest_y), - SkIntToScalar(dest_x + dest_w), - SkIntToScalar(dest_y + dest_h) }; - - if (src_w == dest_w && src_h == dest_h) { - // Workaround for apparent bug in Skia that causes image to occasionally - // shift. - SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h }; - drawBitmapRect(bitmap, &src_rect, dest_rect, &paint); - return; - } - - // Make a bitmap shader that contains the bitmap we want to draw. This is - // basically what SkCanvas.drawBitmap does internally, but it gives us - // more control over quality and will use the mipmap in the source image if - // it has one, whereas drawBitmap won't. - SkShader* shader = SkShader::CreateBitmapShader(bitmap, - SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode); - SkMatrix shader_scale; - shader_scale.setScale(SkFloatToScalar(static_cast(dest_w) / src_w), - SkFloatToScalar(static_cast(dest_h) / src_h)); - shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y)); - shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y)); - shader->setLocalMatrix(shader_scale); - - // Set up our paint to use the shader & release our reference (now just owned - // by the paint). - SkPaint p(paint); - p.setFilterBitmap(filter); - p.setShader(shader); - shader->unref(); - - // The rect will be filled by the bitmap. - drawRect(dest_rect, p); -} - -void ChromeCanvas::DrawStringInt(const std::wstring& text, - const gfx::Font& font, - const SkColor& color, - int x, int y, - int w, int h) { - DrawStringInt(text, font, color, x, y, w, h, - l10n_util::DefaultCanvasTextAlignment()); -} - -void ChromeCanvas::TileImageInt(const SkBitmap& bitmap, - int x, int y, int w, int h) { - TileImageInt(bitmap, 0, 0, x, y, w, h); -} - -void ChromeCanvas::TileImageInt(const SkBitmap& bitmap, int src_x, int src_y, - int dest_x, int dest_y, int w, int h) { - if (!IntersectsClipRectInt(dest_x, dest_y, w, h)) - return; - - SkPaint paint; - - SkShader* shader = SkShader::CreateBitmapShader(bitmap, - SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode); - paint.setShader(shader); - paint.setPorterDuffXfermode(SkPorterDuff::kSrcOver_Mode); - - // CreateBitmapShader returns a Shader with a reference count of one, we - // need to unref after paint takes ownership of the shader. - shader->unref(); - save(); - translate(SkIntToScalar(dest_x - src_x), SkIntToScalar(dest_y - src_y)); - ClipRectInt(src_x, src_y, w, h); - drawPaint(paint); - restore(); -} - -SkBitmap ChromeCanvas::ExtractBitmap() { - const SkBitmap& device_bitmap = getDevice()->accessBitmap(false); - - // Make a bitmap to return, and a canvas to draw into it. We don't just want - // to call extractSubset or the copy constuctor, since we want an actual copy - // of the bitmap. - SkBitmap result; - device_bitmap.copyTo(&result, SkBitmap::kARGB_8888_Config); - return result; -} diff --git a/app/gfx/chrome_canvas.h b/app/gfx/chrome_canvas.h deleted file mode 100644 index 84c5320..0000000 --- a/app/gfx/chrome_canvas.h +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright (c) 2006-2008 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. - -#ifndef APP_GFX_CHROME_CANVAS_H_ -#define APP_GFX_CHROME_CANVAS_H_ - -#if defined(OS_WIN) -#include -#endif - -#include - -#include "base/basictypes.h" -#include "skia/ext/platform_canvas.h" - -namespace gfx { -class Font; -class Rect; -} - -#if defined(OS_LINUX) -typedef struct _cairo cairo_t; -#endif - -// ChromeCanvas is the SkCanvas used by Views for all painting. It -// provides a handful of methods for the common operations used throughout -// Views. With few exceptions, you should NOT create a ChromeCanvas directly, -// rather one will be passed to you via the various paint methods in view. -// -// All methods that take integer arguments (as is used throughout views) -// end with Int. If you need to use methods provided by the superclass -// you'll need to do a conversion. In particular you'll need to use -// macro SkIntToScalar(xxx), or if converting from a scalar to an integer -// SkScalarRound. -// -// A handful of methods in this class are overloaded providing an additional -// argument of type SkPorterDuff::Mode. SkPorterDuff::Mode specifies how the -// source and destination colors are combined. Unless otherwise specified, -// the variant that does not take a SkPorterDuff::Mode uses a transfer mode -// of kSrcOver_Mode. -class ChromeCanvas : public skia::PlatformCanvas { - public: - // Specifies the alignment for text rendered with the DrawStringInt method. - enum { - TEXT_ALIGN_LEFT = 1, - TEXT_ALIGN_CENTER = 2, - TEXT_ALIGN_RIGHT = 4, - TEXT_VALIGN_TOP = 8, - TEXT_VALIGN_MIDDLE = 16, - TEXT_VALIGN_BOTTOM = 32, - - // Specifies the text consists of multiple lines. - MULTI_LINE = 64, - - // By default DrawStringInt does not process the prefix ('&') character - // specially. That is, the string "&foo" is rendered as "&foo". When - // rendering text from a resource that uses the prefix character for - // mnemonics, the prefix should be processed and can be rendered as an - // underline (SHOW_PREFIX), or not rendered at all (HIDE_PREFIX). - SHOW_PREFIX = 128, - HIDE_PREFIX = 256, - - // Prevent ellipsizing - NO_ELLIPSIS = 512, - - // Specifies if words can be split by new lines. - // This only works with MULTI_LINE. - CHARACTER_BREAK = 1024, - }; - - // Creates an empty ChromeCanvas. Callers must use initialize before using - // the canvas. - ChromeCanvas(); - - ChromeCanvas(int width, int height, bool is_opaque); - - virtual ~ChromeCanvas(); - - // Retrieves the clip rectangle and sets it in the specified rectangle if any. - // Returns true if the clip rect is non-empty. - bool GetClipRect(gfx::Rect* clip_rect); - - // Wrapper function that takes integer arguments. - // Returns true if the clip is non-empty. - // See clipRect for specifics. - bool ClipRectInt(int x, int y, int w, int h); - - // Test whether the provided rectangle intersects the current clip rect. - bool IntersectsClipRectInt(int x, int y, int w, int h); - - // Wrapper function that takes integer arguments. - // See translate() for specifics. - void TranslateInt(int x, int y); - - // Wrapper function that takes integer arguments. - // See scale() for specifics. - void ScaleInt(int x, int y); - - // Fills the given rectangle with the given paint's parameters. - void FillRectInt(int x, int y, int w, int h, const SkPaint& paint); - - // Fills the specified region with the specified color using a transfer - // mode of SkPorterDuff::kSrcOver_Mode. - void FillRectInt(const SkColor& color, int x, int y, int w, int h); - - // Draws a single pixel rect in the specified region with the specified - // color, using a transfer mode of SkPorterDuff::kSrcOver_Mode. - // - // NOTE: if you need a single pixel line, use DraLineInt. - void DrawRectInt(const SkColor& color, int x, int y, int w, int h); - - // Draws a single pixel rect in the specified region with the specified - // color and transfer mode. - // - // NOTE: if you need a single pixel line, use DraLineInt. - void DrawRectInt(const SkColor& color, int x, int y, int w, int h, - SkPorterDuff::Mode mode); - - // Draws a single pixel line with the specified color. - void DrawLineInt(const SkColor& color, int x1, int y1, int x2, int y2); - - // Draws a bitmap with the origin at the specified location. The upper left - // corner of the bitmap is rendered at the specified location. - void DrawBitmapInt(const SkBitmap& bitmap, int x, int y); - - // Draws a bitmap with the origin at the specified location, using the - // specified paint. The upper left corner of the bitmap is rendered at the - // specified location. - void DrawBitmapInt(const SkBitmap& bitmap, int x, int y, - const SkPaint& paint); - - // Draws a portion of a bitmap in the specified location. The src parameters - // correspond to the region of the bitmap to draw in the region defined - // by the dest coordinates. - // - // If the width or height of the source differs from that of the destination, - // the bitmap will be scaled. When scaling down, it is highly recommended - // that you call buildMipMap(false) on your bitmap to ensure that it has - // a mipmap, which will result in much higher-quality output. Set |filter| - // to use filtering for bitmaps, otherwise the nearest-neighbor algorithm - // is used for resampling. - // - // An optional custom SkPaint can be provided. - void DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, int src_w, - int src_h, int dest_x, int dest_y, int dest_w, int dest_h, - bool filter); - void DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, int src_w, - int src_h, int dest_x, int dest_y, int dest_w, int dest_h, - bool filter, const SkPaint& paint); - - // Draws text with the specified color, font and location. The text is - // aligned to the left, vertically centered, clipped to the region. If the - // text is too big, it is truncated and '...' is added to the end. - void DrawStringInt(const std::wstring& text, const gfx::Font& font, - const SkColor& color, int x, int y, int w, int h); - - // Draws text with the specified color, font and location. The last argument - // specifies flags for how the text should be rendered. It can be one of - // TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT or TEXT_ALIGN_LEFT. - void DrawStringInt(const std::wstring& text, const gfx::Font& font, - const SkColor& color, int x, int y, int w, int h, - int flags); - -#ifdef OS_WIN // Only implemented on Windows for now. - // Draws text with a 1-pixel halo around it of the given color. It allows - // ClearType to be drawn to an otherwise transparenct bitmap for drag images. - // Drag images have only 1-bit of transparency, so we don't do any fancy - // blurring. - void DrawStringWithHalo(const std::wstring& text, const gfx::Font& font, - const SkColor& text_color, const SkColor& halo_color, - int x, int y, int w, int h, int flags); -#endif - - // Draws a dotted gray rectangle used for focus purposes. - void DrawFocusRect(int x, int y, int width, int height); - - // Tiles the image in the specified region. - void TileImageInt(const SkBitmap& bitmap, int x, int y, int w, int h); - void TileImageInt(const SkBitmap& bitmap, int src_x, int src_y, - int dest_x, int dest_y, int w, int h); - - // Extracts a bitmap from the contents of this canvas. - SkBitmap ExtractBitmap(); - -#if defined(OS_LINUX) - // Applies current matrix on the canvas to the cairo context. This should be - // invoked anytime you plan on drawing directly to the cairo context. Be - // sure and set the matrix back to the identity when done. - void ApplySkiaMatrixToCairoContext(cairo_t* cr); -#endif - - // Compute the size required to draw some text with the provided font. - // Attempts to fit the text with the provided width and height. Increases - // height and then width as needed to make the text fit. This method - // supports multiple lines. - static void SizeStringInt(const std::wstring& test, const gfx::Font& font, - int *width, int* height, int flags); - - private: -#if defined(OS_WIN) - // Draws text with the specified color, font and location. The text is - // aligned to the left, vertically centered, clipped to the region. If the - // text is too big, it is truncated and '...' is added to the end. - void DrawStringInt(const std::wstring& text, HFONT font, - const SkColor& color, int x, int y, int w, int h, - int flags); -#endif - - DISALLOW_EVIL_CONSTRUCTORS(ChromeCanvas); -}; - -#if defined(OS_WIN) || defined(OS_LINUX) -typedef skia::CanvasPaintT ChromeCanvasPaint; -#endif - -#endif // APP_GFX_CHROME_CANVAS_H_ diff --git a/app/gfx/chrome_canvas_linux.cc b/app/gfx/chrome_canvas_linux.cc deleted file mode 100644 index 12602d9..0000000 --- a/app/gfx/chrome_canvas_linux.cc +++ /dev/null @@ -1,137 +0,0 @@ -// 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/chrome_canvas.h" - -#include - -#include "app/gfx/chrome_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 - -ChromeCanvas::ChromeCanvas(int width, int height, bool is_opaque) - : skia::PlatformCanvasLinux(width, height, is_opaque) { -} - -ChromeCanvas::ChromeCanvas() : skia::PlatformCanvasLinux() { -} - -ChromeCanvas::~ChromeCanvas() { -} - -// static -void ChromeCanvas::SizeStringInt(const std::wstring& text, - const gfx::Font& font, - int* width, int* height, int flags) { - NOTIMPLEMENTED(); -} - -void ChromeCanvas::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 ChromeCanvas::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 ChromeCanvas flags. - if (!(flags & ChromeCanvas::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 & ChromeCanvas::TEXT_VALIGN_TOP) { - // Cairo should draw from the top left corner already. - } else if (flags & ChromeCanvas::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. -} diff --git a/app/gfx/chrome_canvas_win.cc b/app/gfx/chrome_canvas_win.cc deleted file mode 100644 index 267a510..0000000 --- a/app/gfx/chrome_canvas_win.cc +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (c) 2006-2008 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/chrome_canvas.h" - -#include - -#include "app/gfx/chrome_font.h" -#include "app/l10n_util.h" -#include "base/gfx/rect.h" -#include "third_party/skia/include/core/SkShader.h" - -namespace { - -// We make sure that LTR text we draw in an RTL context is modified -// appropriately to make sure it maintains it LTR orientation. -void DoDrawText(HDC hdc, const std::wstring& text, - RECT* text_bounds, int flags) { - std::wstring localized_text; - const wchar_t* string_ptr = text.c_str(); - int string_size = static_cast(text.length()); - // Only adjust string directionality if both of the following are true: - // 1. The current locale is RTL. - // 2. The string itself has RTL directionality. - if (flags & DT_RTLREADING) { - if (l10n_util::AdjustStringForLocaleDirection(text, &localized_text)) { - string_ptr = localized_text.c_str(); - string_size = static_cast(localized_text.length()); - } - } - - DrawText(hdc, string_ptr, string_size, text_bounds, flags); -} - -// Compute the windows flags necessary to implement the provided text -// ChromeCanvas flags. -int ComputeFormatFlags(int flags, const std::wstring& text) { - int f = 0; - - // Setting the text alignment explicitly in case it hasn't already been set. - // This will make sure that we don't align text to the left on RTL locales - // just because no alignment flag was passed to DrawStringInt(). - if (!(flags & (ChromeCanvas::TEXT_ALIGN_CENTER | - ChromeCanvas::TEXT_ALIGN_RIGHT | - ChromeCanvas::TEXT_ALIGN_LEFT))) { - flags |= l10n_util::DefaultCanvasTextAlignment(); - } - - if (flags & ChromeCanvas::HIDE_PREFIX) - f |= DT_HIDEPREFIX; - else if ((flags & ChromeCanvas::SHOW_PREFIX) == 0) - f |= DT_NOPREFIX; - - if (flags & ChromeCanvas::MULTI_LINE) { - f |= DT_WORDBREAK; - if (flags & ChromeCanvas::CHARACTER_BREAK) - f |= DT_EDITCONTROL; - } else { - f |= DT_SINGLELINE | DT_VCENTER; - if (!(flags & ChromeCanvas::NO_ELLIPSIS)) - f |= DT_END_ELLIPSIS; - } - - // vertical alignment - if (flags & ChromeCanvas::TEXT_VALIGN_TOP) - f |= DT_TOP; - else if (flags & ChromeCanvas::TEXT_VALIGN_BOTTOM) - f |= DT_BOTTOM; - else - f |= DT_VCENTER; - - // horizontal alignment - if (flags & ChromeCanvas::TEXT_ALIGN_CENTER) - f |= DT_CENTER; - else if (flags & ChromeCanvas::TEXT_ALIGN_RIGHT) - f |= DT_RIGHT; - else - f |= DT_LEFT; - - // In order to make sure RTL/BiDi strings are rendered correctly, we must - // pass the flag DT_RTLREADING to DrawText (when the locale's language is - // a right-to-left language) so that Windows does the right thing. - // - // In addition to correctly displaying text containing both RTL and LTR - // elements (for example, a string containing a telephone number within a - // sentence in Hebrew, or a sentence in Hebrew that contains a word in - // English) this flag also makes sure that if there is not enough space to - // display the entire string, the ellipsis is displayed on the left hand side - // of the truncated string and not on the right hand side. - // - // We make a distinction between Chrome UI strings and text coming from a web - // page. - // - // For text coming from a web page we determine the alignment based on the - // first character with strong directionality. If the directionality of the - // first character with strong directionality in the text is LTR, the - // alignment is set to DT_LEFT, and the directionality should not be set as - // DT_RTLREADING. - // - // This heuristic doesn't work for Chrome UI strings since even in RTL - // locales, some of those might start with English text but we know they're - // localized so we always want them to be right aligned, and their - // directionality should be set as DT_RTLREADING. - // - // Caveat: If the string is purely LTR, don't set DTL_RTLREADING since when - // the flag is set, LRE-PDF don't have the desired effect of rendering - // multiline English-only text as LTR. - if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT && - (f & DT_RIGHT)) { - if (l10n_util::StringContainsStrongRTLChars(text)) { - f |= DT_RTLREADING; - } - } - return f; -} - -} // anonymous namespace - -ChromeCanvas::ChromeCanvas(int width, int height, bool is_opaque) - : skia::PlatformCanvasWin(width, height, is_opaque) { -} - -ChromeCanvas::ChromeCanvas() : skia::PlatformCanvasWin() { -} - -ChromeCanvas::~ChromeCanvas() { -} - -// static -void ChromeCanvas::SizeStringInt(const std::wstring& text, - const gfx::Font& font, - int *width, int *height, int flags) { - HDC dc = GetDC(NULL); - HFONT old_font = static_cast(SelectObject(dc, font.hfont())); - RECT b; - b.left = 0; - b.top = 0; - b.right = *width; - if (b.right == 0 && !text.empty()) { - // Width needs to be at least 1 or else DoDrawText will not resize it. - b.right = 1; - } - b.bottom = *height; - DoDrawText(dc, text, &b, ComputeFormatFlags(flags, text) | DT_CALCRECT); - - // Restore the old font. This way we don't have to worry if the caller - // deletes the font and the DC lives longer. - SelectObject(dc, old_font); - *width = b.right; - *height = b.bottom; - - ReleaseDC(NULL, dc); -} - -void ChromeCanvas::DrawStringInt(const std::wstring& text, HFONT font, - const SkColor& color, int x, int y, int w, - int h, int flags) { - if (!IntersectsClipRectInt(x, y, w, h)) - return; - - RECT text_bounds = { x, y, x + w, y + h }; - HDC dc = beginPlatformPaint(); - SetBkMode(dc, TRANSPARENT); - HFONT old_font = (HFONT)SelectObject(dc, font); - COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), - SkColorGetB(color)); - SetTextColor(dc, brush_color); - - int f = ComputeFormatFlags(flags, text); - DoDrawText(dc, text, &text_bounds, f); - endPlatformPaint(); - - // Restore the old font. This way we don't have to worry if the caller - // deletes the font and the DC lives longer. - SelectObject(dc, old_font); - - // Windows will have cleared the alpha channel of the text we drew. Assume - // we're drawing to an opaque surface, or at least the text rect area is - // opaque. - getTopPlatformDevice().makeOpaque(x, y, w, h); -} - -void ChromeCanvas::DrawStringInt(const std::wstring& text, - const gfx::Font& font, - const SkColor& color, - int x, int y, int w, int h, int flags) { - DrawStringInt(text, font.hfont(), color, x, y, w, h, flags); -} - -// Checks each pixel immediately adjacent to the given pixel in the bitmap. If -// any of them are not the halo color, returns true. This defines the halo of -// pixels that will appear around the text. Note that we have to check each -// pixel against both the halo color and transparent since DrawStringWithHalo -// will modify the bitmap as it goes, and clears pixels shouldn't count as -// changed. -static bool pixelShouldGetHalo(const SkBitmap& bitmap, int x, int y, - SkColor halo_color) { - if (x > 0 && - *bitmap.getAddr32(x - 1, y) != halo_color && - *bitmap.getAddr32(x - 1, y) != 0) - return true; // Touched pixel to the left. - if (x < bitmap.width() - 1 && - *bitmap.getAddr32(x + 1, y) != halo_color && - *bitmap.getAddr32(x + 1, y) != 0) - return true; // Touched pixel to the right. - if (y > 0 && - *bitmap.getAddr32(x, y - 1) != halo_color && - *bitmap.getAddr32(x, y - 1) != 0) - return true; // Touched pixel above. - if (y < bitmap.height() - 1 && - *bitmap.getAddr32(x, y + 1) != halo_color && - *bitmap.getAddr32(x, y + 1) != 0) - return true; // Touched pixel below. - return false; -} - -void ChromeCanvas::DrawStringWithHalo(const std::wstring& text, - const gfx::Font& font, - const SkColor& text_color, - const SkColor& halo_color_in, - int x, int y, int w, int h, - int flags) { - // Some callers will have semitransparent halo colors, which we don't handle - // (since the resulting image can have 1-bit transparency only). - SkColor halo_color = halo_color_in | 0xFF000000; - - // Create a temporary buffer filled with the halo color. It must leave room - // for the 1-pixel border around the text. - ChromeCanvas text_canvas(w + 2, h + 2, true); - SkPaint bkgnd_paint; - bkgnd_paint.setColor(halo_color); - text_canvas.FillRectInt(0, 0, w + 2, h + 2, bkgnd_paint); - - // Draw the text into the temporary buffer. This will have correct - // ClearType since the background color is the same as the halo color. - text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); - - // Windows will have cleared the alpha channel for the pixels it drew. Make it - // opaque. We have to do this first since pixelShouldGetHalo will check for - // 0 to see if a pixel has been modified to transparent, and black text that - // Windows draw will look transparent to it! - text_canvas.getTopPlatformDevice().makeOpaque(0, 0, w + 2, h + 2); - - uint32_t halo_premul = SkPreMultiplyColor(halo_color); - SkBitmap& text_bitmap = const_cast( - text_canvas.getTopPlatformDevice().accessBitmap(true)); - for (int cur_y = 0; cur_y < h + 2; cur_y++) { - uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); - for (int cur_x = 0; cur_x < w + 2; cur_x++) { - if (text_row[cur_x] == halo_premul) { - // This pixel was not touched by the text routines. See if it borders - // a touched pixel in any of the 4 directions (not diagonally). - if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) - text_row[cur_x] = 0; // Make transparent. - } else { - text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. - } - } - } - - // Draw the halo bitmap with blur. - drawBitmap(text_bitmap, SkIntToScalar(x - 1), SkIntToScalar(y - 1)); -} diff --git a/app/gfx/chrome_font.h b/app/gfx/chrome_font.h deleted file mode 100644 index a4b14e9..0000000 --- a/app/gfx/chrome_font.h +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (c) 2006-2008 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. - -#ifndef APP_GFX_FONT_H_ -#define APP_GFX_FONT_H_ - -#include "build/build_config.h" - -#include - -#if defined(OS_WIN) -typedef struct HFONT__* HFONT; -#elif defined(OS_LINUX) -#include "third_party/skia/include/core/SkRefCnt.h" -class SkPaint; -class SkTypeface; -#endif - -#if defined(OS_WIN) -typedef struct HFONT__* NativeFont; -#elif defined(OS_MACOSX) -#ifdef __OBJC__ -@class NSFont; -#else -class NSFont; -#endif -typedef NSFont* NativeFont; -#elif defined(OS_LINUX) -class SkTypeface; -typedef SkTypeface* NativeFont; -#else // null port. -#error No known OS defined -#endif - -#include "base/basictypes.h" -#include "base/ref_counted.h" -#include "base/scoped_ptr.h" - -namespace gfx { - -// Font provides a wrapper around an underlying font. Copy and assignment -// operators are explicitly allowed, and cheap. -class Font { - public: - // The following constants indicate the font style. - enum { - NORMAL = 0, - BOLD = 1, - ITALIC = 2, - UNDERLINED = 4, - }; - - // Creates a Font given font name (e.g. arial), font size (e.g. 12). - // Skia actually expects a family name and not a font name. - static Font CreateFont(const std::wstring& font_name, int font_size); - - ~Font() { } - - // Returns a new Font derived from the existing font. - // size_deta is the size to add to the current font. For example, a value - // of 5 results in a font 5 units bigger than this font. - Font DeriveFont(int size_delta) const { - return DeriveFont(size_delta, style()); - } - - // Returns a new Font derived from the existing font. - // size_deta is the size to add to the current font. See the single - // argument version of this method for an example. - // The style parameter specifies the new style for the font, and is a - // bitmask of the values: BOLD, ITALIC and UNDERLINED. - Font DeriveFont(int size_delta, int style) const; - - // Returns the number of vertical pixels needed to display characters from - // the specified font. - int height() const; - - // Returns the baseline, or ascent, of the font. - int baseline() const; - - // Returns the average character width for the font. - int ave_char_width() const; - - // Returns the number of horizontal pixels needed to display the specified - // string. - int GetStringWidth(const std::wstring& text) const; - - // Returns the expected number of horizontal pixels needed to display - // the specified length of characters. - // Call GetStringWidth() to retrieve the actual number. - int GetExpectedTextWidth(int length) const; - - // Returns the style of the font. - int style() const; - - // Font Name. - // It is actually a font family name, because Skia expects a family name - // and not a font name. - std::wstring FontName(); - - // Font Size. - int FontSize(); - - NativeFont nativeFont() const; - - // Creates a font with the default name and style. - Font(); - -#if defined(OS_WIN) - // Creates a Font from the specified HFONT. The supplied HFONT is effectively - // copied. - static Font CreateFont(HFONT hfont); - - // Returns the handle to the underlying HFONT. This is used by ChromeCanvas to - // draw text. - HFONT hfont() const { return font_ref_->hfont(); } - - // Dialog units to pixels conversion. - // See http://support.microsoft.com/kb/145994 for details. - int horizontal_dlus_to_pixels(int dlus) { - return dlus * font_ref_->dlu_base_x() / 4; - } - int vertical_dlus_to_pixels(int dlus) { - return dlus * font_ref_->height() / 8; - } -#elif defined(OS_LINUX) - // We need a copy constructor and assignment operator to deal with - // the Skia reference counting. - Font(const Font& other); - Font& operator=(const Font& other); - // Setup a Skia context to use the current typeface - void PaintSetup(SkPaint* paint) const; -#endif - - private: - -#if defined(OS_WIN) - // Chrome text drawing bottoms out in the Windows GDI functions that take an - // HFONT (an opaque handle into Windows). To avoid lots of GDI object - // allocation and destruction, Font indirectly refers to the HFONT by way of - // an HFontRef. That is, every Font has an HFontRef, which has an HFONT. - // - // HFontRef is reference counted. Upon deletion, it deletes the HFONT. - // By making HFontRef maintain the reference to the HFONT, multiple - // HFontRefs can share the same HFONT, and Font can provide value semantics. - class HFontRef : public base::RefCounted { - public: - // This constructor takes control of the HFONT, and will delete it when - // the HFontRef is deleted. - HFontRef(HFONT hfont, - int height, - int baseline, - int ave_char_width, - int style, - int dlu_base_x); - ~HFontRef(); - - // Accessors - HFONT hfont() const { return hfont_; } - int height() const { return height_; } - int baseline() const { return baseline_; } - int ave_char_width() const { return ave_char_width_; } - int style() const { return style_; } - int dlu_base_x() const { return dlu_base_x_; } - - private: - const HFONT hfont_; - const int height_; - const int baseline_; - const int ave_char_width_; - const int style_; - // Constants used in converting dialog units to pixels. - const int dlu_base_x_; - - DISALLOW_COPY_AND_ASSIGN(HFontRef); - }; - - // Returns the base font ref. This should ONLY be invoked on the - // UI thread. - static HFontRef* GetBaseFontRef(); - - // Creates and returns a new HFONTRef from the specified HFONT. - static HFontRef* CreateHFontRef(HFONT font); - - explicit Font(HFontRef* font_ref) : font_ref_(font_ref) { } - - // Reference to the base font all fonts are derived from. - static HFontRef* base_font_ref_; - - // Indirect reference to the HFontRef, which references the underlying HFONT. - scoped_refptr font_ref_; -#elif defined(OS_LINUX) - explicit Font(SkTypeface* typeface, const std::wstring& name, - int size, int style); - // Calculate and cache the font metrics. - void calculateMetrics(); - // Make |this| a copy of |other|. - void CopyFont(const Font& other); - - // The default font, used for the default constructor. - static Font* default_font_; - - // These two both point to the same SkTypeface. We use the SkAutoUnref to - // handle the reference counting, but without @typeface_ we would have to - // cast the SkRefCnt from @typeface_helper_ every time. - scoped_ptr typeface_helper_; - SkTypeface *typeface_; - - // Additional information about the face - // Skia actually expects a family name and not a font name. - std::wstring font_family_; - int font_size_; - int style_; - - // Cached metrics, generated at construction - int height_; - int ascent_; - int avg_width_; -#elif defined(OS_MACOSX) - explicit Font(const std::wstring& font_name, int font_size, int style); - - // Calculate and cache the font metrics. - void calculateMetrics(); - - std::wstring font_name_; - int font_size_; - int style_; - - // Cached metrics, generated at construction - int height_; - int ascent_; - int avg_width_; -#endif - -}; - -} // namespace gfx - -#endif // APP_GFX_FONT_H_ diff --git a/app/gfx/chrome_font_gtk.cc b/app/gfx/chrome_font_gtk.cc deleted file mode 100644 index babeff5..0000000 --- a/app/gfx/chrome_font_gtk.cc +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2006-2008 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/chrome_font.h" - -#include -#include - -#include "base/string_util.h" - -namespace gfx { - -Font* Font::default_font_ = NULL; - -// Find the best match font for |family_name| in the same way as Skia -// to make sure CreateFont() successfully creates default font. -// In Skia, it only checks the best match font. If it failed to find, -// SkTypeface will be NULL for that font family. It eventually causes segfault. -// For example, family_name = "Sans" and system may have various fonts. -// The first font family in FcPattern will be "DejaVu Sans" but a font family -// returned by FcFontMatch will be "VL PGothic". -// In this case, SkTypeface for "Sans" returns NULL even if system has font -// for "Sans" font family. -// See FontMatch() in skia/ports/SkFontHost_fontconfig.cpp for more detail. -static std::wstring FindBestMatchFontFamilyName(const char* family_name) { - FcPattern* pattern = FcPatternCreate(); - FcValue fcvalue; - fcvalue.type = FcTypeString; - char* family_name_copy = strdup(family_name); - fcvalue.u.s = reinterpret_cast(family_name_copy); - FcPatternAdd(pattern, FC_FAMILY, fcvalue, 0); - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - FcResult result; - FcPattern* match = FcFontMatch(0, pattern, &result); - DCHECK(match) << "Could not find font: " << family_name; - FcChar8* match_family; - FcPatternGetString(match, FC_FAMILY, 0, &match_family); - - std::wstring font_family = UTF8ToWide( - reinterpret_cast(match_family)); - FcPatternDestroy(match); - FcPatternDestroy(pattern); - free(family_name_copy); - return font_family; -} - -// Get the default gtk system font (name and size). -Font::Font() { - if (default_font_ == NULL) { - gtk_init(NULL, NULL); - GtkSettings* settings = gtk_settings_get_default(); - - GValue value = {0}; - g_value_init(&value, G_TYPE_STRING); - g_object_get_property(G_OBJECT(settings), "gtk-font-name", &value); - - // gtk-font-name may be wrapped in quotes. - gchar* font_name = g_strdup_value_contents(&value); - gchar* font_ptr = font_name; - if (font_ptr[0] == '\"') - font_ptr++; - if (font_ptr[strlen(font_ptr) - 1] == '\"') - font_ptr[strlen(font_ptr) - 1] = '\0'; - - PangoFontDescription* desc = - pango_font_description_from_string(font_ptr); - gint size = pango_font_description_get_size(desc); - const char* family_name = pango_font_description_get_family(desc); - - // Find best match font for |family_name| to make sure we can get - // SkTypeface for default font. - // TODO(agl): remove this. - std::wstring font_family = FindBestMatchFontFamilyName(family_name); - - default_font_ = new Font(CreateFont(font_family, size / PANGO_SCALE)); - - pango_font_description_free(desc); - g_free(font_name); - g_value_unset(&value); - - DCHECK(default_font_); - } - - CopyFont(*default_font_); -} - -} // namespace gfx diff --git a/app/gfx/chrome_font_mac.mm b/app/gfx/chrome_font_mac.mm deleted file mode 100644 index 885c3b1..0000000 --- a/app/gfx/chrome_font_mac.mm +++ /dev/null @@ -1,90 +0,0 @@ -// 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/chrome_font.h" - -#include - -#include "base/logging.h" -#include "base/sys_string_conversions.h" - -namespace gfx { - -// static -Font Font::CreateFont(const std::wstring& font_name, int font_size) { - return Font(font_name, font_size, NORMAL); -} - -Font::Font(const std::wstring& font_name, int font_size, int style) - : font_name_(font_name), - font_size_(font_size), - style_(style) { - calculateMetrics(); -} - -Font::Font() - : font_size_([NSFont systemFontSize]), - style_(NORMAL) { - NSFont* system_font = [NSFont systemFontOfSize:font_size_]; - font_name_ = base::SysNSStringToWide([system_font fontName]); - calculateMetrics(); -} - -void Font::calculateMetrics() { - NSFont* font = nativeFont(); - height_ = [font xHeight]; - ascent_ = [font ascender]; - avg_width_ = [font boundingRectForGlyph:[font glyphWithName:@"x"]].size.width; -} - -Font Font::DeriveFont(int size_delta, int style) const { - return Font(font_name_, font_size_ + size_delta, style); -} - -int Font::height() const { - return height_; -} - -int Font::baseline() const { - return ascent_; -} - -int Font::ave_char_width() const { - return avg_width_; -} - -int Font::GetStringWidth(const std::wstring& text) const { - NSFont* font = nativeFont(); - NSString* ns_string = base::SysWideToNSString(text); - NSDictionary* attributes = - [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName]; - NSSize string_size = [ns_string sizeWithAttributes:attributes]; - return string_size.width; -} - -int Font::GetExpectedTextWidth(int length) const { - return length * avg_width_; -} - -int Font::style() const { - return style_; -} - -std::wstring Font::FontName() { - return font_name_; -} - -int Font::FontSize() { - return font_size_; -} - -NativeFont Font::nativeFont() const { - // TODO(pinkerton): apply |style_| to font. - // We could cache this, but then we'd have to conditionally change the - // dtor just for MacOS. Not sure if we want to/need to do that. - return [NSFont fontWithName:base::SysWideToNSString(font_name_) - size:font_size_]; -} - -} // namespace gfx diff --git a/app/gfx/chrome_font_skia.cc b/app/gfx/chrome_font_skia.cc deleted file mode 100644 index 9622a70..0000000 --- a/app/gfx/chrome_font_skia.cc +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (c) 2006-2008 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/chrome_font.h" - -#include "base/logging.h" -#include "base/sys_string_conversions.h" - -#include "third_party/skia/include/core/SkTypeface.h" -#include "third_party/skia/include/core/SkPaint.h" - -namespace gfx { - -Font::Font(const Font& other) { - CopyFont(other); -} - -Font& Font::operator=(const Font& other) { - CopyFont(other); - return *this; -} - -Font::Font(SkTypeface* tf, const std::wstring& font_family, int font_size, - int style) - : typeface_helper_(new SkAutoUnref(tf)), - typeface_(tf), - font_family_(font_family), - font_size_(font_size), - style_(style) { - tf->ref(); - calculateMetrics(); -} - -void Font::calculateMetrics() { - SkPaint paint; - SkPaint::FontMetrics metrics; - - PaintSetup(&paint); - paint.getFontMetrics(&metrics); - - ascent_ = SkScalarRound(-metrics.fAscent); - height_ = SkScalarRound(-metrics.fAscent + metrics.fDescent + - metrics.fLeading); - - if (metrics.fAvgCharWidth) { - avg_width_ = SkScalarRound(metrics.fAvgCharWidth); - } else { - static const char x_char = 'x'; - paint.setTextEncoding(SkPaint::kUTF8_TextEncoding); - SkScalar width = paint.measureText(&x_char, 1); - - avg_width_ = static_cast(ceilf(SkScalarToFloat(width))); - } -} - -void Font::CopyFont(const Font& other) { - typeface_helper_.reset(new SkAutoUnref(other.typeface_)); - typeface_ = other.typeface_; - typeface_->ref(); - font_family_ = other.font_family_; - font_size_ = other.font_size_; - style_ = other.style_; - height_ = other.height_; - ascent_ = other.ascent_; - avg_width_ = other.avg_width_; -} - -int Font::height() const { - return height_; -} - -int Font::baseline() const { - return ascent_; -} - -int Font::ave_char_width() const { - return avg_width_; -} - -Font Font::CreateFont(const std::wstring& font_family, int font_size) { - DCHECK_GT(font_size, 0); - - SkTypeface* tf = SkTypeface::CreateFromName( - base::SysWideToUTF8(font_family).c_str(), SkTypeface::kNormal); - DCHECK(tf) << "Could not find font: " << base::SysWideToUTF8(font_family); - SkAutoUnref tf_helper(tf); - - return Font(tf, font_family, font_size, NORMAL); -} - -Font Font::DeriveFont(int size_delta, int style) const { - // If the delta is negative, if must not push the size below 1 - if (size_delta < 0) { - DCHECK_LT(-size_delta, font_size_); - } - - if (style == style_) { - // Fast path, we just use the same typeface at a different size - return Font(typeface_, font_family_, font_size_ + size_delta, style_); - } - - // If the style has changed we may need to load a new face - int skstyle = SkTypeface::kNormal; - if (BOLD & style) - skstyle |= SkTypeface::kBold; - if (ITALIC & style) - skstyle |= SkTypeface::kItalic; - - SkTypeface* tf = SkTypeface::CreateFromName( - base::SysWideToUTF8(font_family_).c_str(), - static_cast(skstyle)); - SkAutoUnref tf_helper(tf); - - return Font(tf, font_family_, font_size_ + size_delta, skstyle); -} - -void Font::PaintSetup(SkPaint* paint) const { - paint->setAntiAlias(false); - paint->setSubpixelText(false); - paint->setTextSize(SkFloatToScalar(font_size_)); - paint->setTypeface(typeface_); - paint->setFakeBoldText((BOLD & style_) && !typeface_->isBold()); - paint->setTextSkewX((ITALIC & style_) && !typeface_->isItalic() ? - -SK_Scalar1/4 : 0); -} - -int Font::GetStringWidth(const std::wstring& text) const { - const std::string utf8(base::SysWideToUTF8(text)); - - SkPaint paint; - PaintSetup(&paint); - paint.setTextEncoding(SkPaint::kUTF8_TextEncoding); - SkScalar width = paint.measureText(utf8.data(), utf8.size()); - - int breadth = static_cast(ceilf(SkScalarToFloat(width))); - // Check for overflow. We should probably be returning an unsigned - // int, but in practice we'll never have a screen massive enough - // to show that much text anyway. - if (breadth < 0) - return INT_MAX; - - return breadth; -} - -int Font::GetExpectedTextWidth(int length) const { - return length * avg_width_; -} - - -int Font::style() const { - return style_; -} - -std::wstring Font::FontName() { - return font_family_; -} - -int Font::FontSize() { - return font_size_; -} - -NativeFont Font::nativeFont() const { - return typeface_; -} - -} // namespace gfx diff --git a/app/gfx/chrome_font_unittest.cc b/app/gfx/chrome_font_unittest.cc deleted file mode 100644 index 0bb840b4..0000000 --- a/app/gfx/chrome_font_unittest.cc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2006-2008 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/chrome_font.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -using gfx::Font; - -class FontTest : public testing::Test { -}; - -TEST_F(FontTest, LoadArial) { - Font cf(Font::CreateFont(L"Arial", 16)); - ASSERT_TRUE(cf.nativeFont()); - ASSERT_EQ(cf.style(), Font::NORMAL); - ASSERT_EQ(cf.FontSize(), 16); - ASSERT_EQ(cf.FontName(), L"Arial"); -} - -TEST_F(FontTest, LoadArialBold) { - Font cf(Font::CreateFont(L"Arial", 16)); - Font bold(cf.DeriveFont(0, Font::BOLD)); - ASSERT_TRUE(bold.nativeFont()); - ASSERT_EQ(bold.style(), Font::BOLD); -} - -TEST_F(FontTest, Ascent) { - Font cf(Font::CreateFont(L"Arial", 16)); - ASSERT_GT(cf.baseline(), 2); - ASSERT_LT(cf.baseline(), 20); -} - -TEST_F(FontTest, Height) { - Font cf(Font::CreateFont(L"Arial", 16)); - ASSERT_GT(cf.baseline(), 2); - ASSERT_LT(cf.baseline(), 20); -} - -TEST_F(FontTest, AvgWidths) { - Font cf(Font::CreateFont(L"Arial", 16)); - ASSERT_EQ(cf.GetExpectedTextWidth(0), 0); - ASSERT_GT(cf.GetExpectedTextWidth(1), cf.GetExpectedTextWidth(0)); - ASSERT_GT(cf.GetExpectedTextWidth(2), cf.GetExpectedTextWidth(1)); - ASSERT_GT(cf.GetExpectedTextWidth(3), cf.GetExpectedTextWidth(2)); -} - -TEST_F(FontTest, Widths) { - Font cf(Font::CreateFont(L"Arial", 16)); - ASSERT_EQ(cf.GetStringWidth(L""), 0); - ASSERT_GT(cf.GetStringWidth(L"a"), cf.GetStringWidth(L"")); - ASSERT_GT(cf.GetStringWidth(L"ab"), cf.GetStringWidth(L"a")); - ASSERT_GT(cf.GetStringWidth(L"abc"), cf.GetStringWidth(L"ab")); -} - -} // anonymous namespace diff --git a/app/gfx/chrome_font_win.cc b/app/gfx/chrome_font_win.cc deleted file mode 100644 index 1cbe500..0000000 --- a/app/gfx/chrome_font_win.cc +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) 2006-2008 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/chrome_font.h" - -#include -#include - -#include - -#include "app/l10n_util_win.h" -#include "base/logging.h" -#include "base/win_util.h" -#include "grit/generated_resources.h" -#include "grit/locale_settings.h" - -namespace gfx { - -/*static*/ -Font::HFontRef* Font::base_font_ref_; - -// If the tmWeight field of a TEXTMETRIC structure has a value >= this, the -// font is bold. -static const int kTextMetricWeightBold = 700; - -// -// Font -// - -Font::Font() - : font_ref_(GetBaseFontRef()) { -} - -int Font::height() const { - return font_ref_->height(); -} - -int Font::baseline() const { - return font_ref_->baseline(); -} - -int Font::ave_char_width() const { - return font_ref_->ave_char_width(); -} - -int Font::GetExpectedTextWidth(int length) const { - return length * std::min(font_ref_->dlu_base_x(), ave_char_width()); -} - -int Font::style() const { - return font_ref_->style(); -} - -NativeFont Font::nativeFont() const { - return hfont(); -} - -// static -Font Font::CreateFont(HFONT font) { - DCHECK(font); - LOGFONT font_info; - GetObject(font, sizeof(LOGFONT), &font_info); - return Font(CreateHFontRef(CreateFontIndirect(&font_info))); -} - -Font Font::CreateFont(const std::wstring& font_name, int font_size) { - HDC hdc = GetDC(NULL); - long lf_height = -MulDiv(font_size, GetDeviceCaps(hdc, LOGPIXELSY), 72); - ReleaseDC(NULL, hdc); - HFONT hf = ::CreateFont(lf_height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - font_name.c_str()); - return Font::CreateFont(hf); -} - -// static -Font::HFontRef* Font::GetBaseFontRef() { - if (base_font_ref_ == NULL) { - NONCLIENTMETRICS metrics; - win_util::GetNonClientMetrics(&metrics); - - l10n_util::AdjustUIFont(&metrics.lfMessageFont); - - // See comment in Font::DeriveFont() about font size. - // TODO(jungshik): Add a per-locale resource entry for the minimum - // font size and actually enforce the lower-bound. 5 is way too small - // for CJK, Thai, and Indian locales. - DCHECK_GE(abs(metrics.lfMessageFont.lfHeight), 5); - HFONT font = CreateFontIndirect(&metrics.lfMessageFont); - DLOG_ASSERT(font); - base_font_ref_ = Font::CreateHFontRef(font); - // base_font_ref_ is global, up the ref count so it's never deleted. - base_font_ref_->AddRef(); - } - return base_font_ref_; -} - -std::wstring Font::FontName() { - LOGFONT font_info; - GetObject(hfont(), sizeof(LOGFONT), &font_info); - return (std::wstring(font_info.lfFaceName)); -} - -int Font::FontSize() { - LOGFONT font_info; - GetObject(hfont(), sizeof(LOGFONT), &font_info); - long lf_height = font_info.lfHeight; - HDC hdc = GetDC(NULL); - int device_caps = GetDeviceCaps(hdc, LOGPIXELSY); - int font_size = 0; - if (device_caps != 0) { - float font_size_float = -static_cast(lf_height)*72/device_caps; - font_size = static_cast(::ceil(font_size_float - 0.5)); - } - ReleaseDC(NULL, hdc); - return font_size; -} - -Font::HFontRef::HFontRef(HFONT hfont, - int height, - int baseline, - int ave_char_width, - int style, - int dlu_base_x) - : hfont_(hfont), - height_(height), - baseline_(baseline), - ave_char_width_(ave_char_width), - style_(style), - dlu_base_x_(dlu_base_x) { - DLOG_ASSERT(hfont); -} - -Font::HFontRef::~HFontRef() { - DeleteObject(hfont_); -} - - -Font Font::DeriveFont(int size_delta, int style) const { - LOGFONT font_info; - GetObject(hfont(), sizeof(LOGFONT), &font_info); - // LOGFONT returns two types of font heights, negative is measured slightly - // differently (character height, vs cell height). - if (font_info.lfHeight < 0) { - font_info.lfHeight -= size_delta; - } else { - font_info.lfHeight += size_delta; - } - // Even with "Small Fonts", the smallest readable font size is 5. It is easy - // to create a non-drawing font and forget about the fact that text should be - // drawn in the UI. This test ensures that the font will be readable. - DCHECK_GE(abs(font_info.lfHeight), 5); - font_info.lfUnderline = ((style & UNDERLINED) == UNDERLINED); - font_info.lfItalic = ((style & ITALIC) == ITALIC); - font_info.lfWeight = (style & BOLD) ? FW_BOLD : FW_NORMAL; - - HFONT hfont = CreateFontIndirect(&font_info); - return Font(CreateHFontRef(hfont)); -} - -int Font::GetStringWidth(const std::wstring& text) const { - int width = 0; - HDC dc = GetDC(NULL); - HFONT previous_font = static_cast(SelectObject(dc, hfont())); - SIZE size; - if (GetTextExtentPoint32(dc, text.c_str(), static_cast(text.size()), - &size)) { - width = size.cx; - } else { - width = 0; - } - SelectObject(dc, previous_font); - ReleaseDC(NULL, dc); - return width; -} - -Font::HFontRef* Font::CreateHFontRef(HFONT font) { - TEXTMETRIC font_metrics; - HDC screen_dc = GetDC(NULL); - HFONT previous_font = static_cast(SelectObject(screen_dc, font)); - int last_map_mode = SetMapMode(screen_dc, MM_TEXT); - GetTextMetrics(screen_dc, &font_metrics); - // Yes, this is how Microsoft recommends calculating the dialog unit - // conversions. - SIZE ave_text_size; - GetTextExtentPoint32(screen_dc, - L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", - 52, &ave_text_size); - const int dlu_base_x = (ave_text_size.cx / 26 + 1) / 2; - // To avoid the DC referencing font_handle_, select the previous font. - SelectObject(screen_dc, previous_font); - SetMapMode(screen_dc, last_map_mode); - ReleaseDC(NULL, screen_dc); - - const int height = std::max(1, static_cast(font_metrics.tmHeight)); - const int baseline = std::max(1, static_cast(font_metrics.tmAscent)); - const int ave_char_width = - std::max(1, static_cast(font_metrics.tmAveCharWidth)); - int style = 0; - if (font_metrics.tmItalic) { - style |= Font::ITALIC; - } - if (font_metrics.tmUnderlined) { - style |= Font::UNDERLINED; - } - if (font_metrics.tmWeight >= kTextMetricWeightBold) { - style |= Font::BOLD; - } - - return new HFontRef(font, height, baseline, ave_char_width, style, - dlu_base_x); -} - -} // namespace gfx diff --git a/app/gfx/font.h b/app/gfx/font.h new file mode 100644 index 0000000..bf759f75 --- /dev/null +++ b/app/gfx/font.h @@ -0,0 +1,239 @@ +// Copyright (c) 2006-2008 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. + +#ifndef APP_GFX_FONT_H_ +#define APP_GFX_FONT_H_ + +#include "build/build_config.h" + +#include + +#if defined(OS_WIN) +typedef struct HFONT__* HFONT; +#elif defined(OS_LINUX) +#include "third_party/skia/include/core/SkRefCnt.h" +class SkPaint; +class SkTypeface; +#endif + +#if defined(OS_WIN) +typedef struct HFONT__* NativeFont; +#elif defined(OS_MACOSX) +#ifdef __OBJC__ +@class NSFont; +#else +class NSFont; +#endif +typedef NSFont* NativeFont; +#elif defined(OS_LINUX) +class SkTypeface; +typedef SkTypeface* NativeFont; +#else // null port. +#error No known OS defined +#endif + +#include "base/basictypes.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" + +namespace gfx { + +// Font provides a wrapper around an underlying font. Copy and assignment +// operators are explicitly allowed, and cheap. +class Font { + public: + // The following constants indicate the font style. + enum { + NORMAL = 0, + BOLD = 1, + ITALIC = 2, + UNDERLINED = 4, + }; + + // Creates a Font given font name (e.g. arial), font size (e.g. 12). + // Skia actually expects a family name and not a font name. + static Font CreateFont(const std::wstring& font_name, int font_size); + + ~Font() { } + + // Returns a new Font derived from the existing font. + // size_deta is the size to add to the current font. For example, a value + // of 5 results in a font 5 units bigger than this font. + Font DeriveFont(int size_delta) const { + return DeriveFont(size_delta, style()); + } + + // Returns a new Font derived from the existing font. + // size_deta is the size to add to the current font. See the single + // argument version of this method for an example. + // The style parameter specifies the new style for the font, and is a + // bitmask of the values: BOLD, ITALIC and UNDERLINED. + Font DeriveFont(int size_delta, int style) const; + + // Returns the number of vertical pixels needed to display characters from + // the specified font. + int height() const; + + // Returns the baseline, or ascent, of the font. + int baseline() const; + + // Returns the average character width for the font. + int ave_char_width() const; + + // Returns the number of horizontal pixels needed to display the specified + // string. + int GetStringWidth(const std::wstring& text) const; + + // Returns the expected number of horizontal pixels needed to display + // the specified length of characters. + // Call GetStringWidth() to retrieve the actual number. + int GetExpectedTextWidth(int length) const; + + // Returns the style of the font. + int style() const; + + // Font Name. + // It is actually a font family name, because Skia expects a family name + // and not a font name. + std::wstring FontName(); + + // Font Size. + int FontSize(); + + NativeFont nativeFont() const; + + // Creates a font with the default name and style. + Font(); + +#if defined(OS_WIN) + // Creates a Font from the specified HFONT. The supplied HFONT is effectively + // copied. + static Font CreateFont(HFONT hfont); + + // Returns the handle to the underlying HFONT. This is used by gfx::Canvas to + // draw text. + HFONT hfont() const { return font_ref_->hfont(); } + + // Dialog units to pixels conversion. + // See http://support.microsoft.com/kb/145994 for details. + int horizontal_dlus_to_pixels(int dlus) { + return dlus * font_ref_->dlu_base_x() / 4; + } + int vertical_dlus_to_pixels(int dlus) { + return dlus * font_ref_->height() / 8; + } +#elif defined(OS_LINUX) + // We need a copy constructor and assignment operator to deal with + // the Skia reference counting. + Font(const Font& other); + Font& operator=(const Font& other); + // Setup a Skia context to use the current typeface + void PaintSetup(SkPaint* paint) const; +#endif + + private: + +#if defined(OS_WIN) + // Chrome text drawing bottoms out in the Windows GDI functions that take an + // HFONT (an opaque handle into Windows). To avoid lots of GDI object + // allocation and destruction, Font indirectly refers to the HFONT by way of + // an HFontRef. That is, every Font has an HFontRef, which has an HFONT. + // + // HFontRef is reference counted. Upon deletion, it deletes the HFONT. + // By making HFontRef maintain the reference to the HFONT, multiple + // HFontRefs can share the same HFONT, and Font can provide value semantics. + class HFontRef : public base::RefCounted { + public: + // This constructor takes control of the HFONT, and will delete it when + // the HFontRef is deleted. + HFontRef(HFONT hfont, + int height, + int baseline, + int ave_char_width, + int style, + int dlu_base_x); + ~HFontRef(); + + // Accessors + HFONT hfont() const { return hfont_; } + int height() const { return height_; } + int baseline() const { return baseline_; } + int ave_char_width() const { return ave_char_width_; } + int style() const { return style_; } + int dlu_base_x() const { return dlu_base_x_; } + + private: + const HFONT hfont_; + const int height_; + const int baseline_; + const int ave_char_width_; + const int style_; + // Constants used in converting dialog units to pixels. + const int dlu_base_x_; + + DISALLOW_COPY_AND_ASSIGN(HFontRef); + }; + + // Returns the base font ref. This should ONLY be invoked on the + // UI thread. + static HFontRef* GetBaseFontRef(); + + // Creates and returns a new HFONTRef from the specified HFONT. + static HFontRef* CreateHFontRef(HFONT font); + + explicit Font(HFontRef* font_ref) : font_ref_(font_ref) { } + + // Reference to the base font all fonts are derived from. + static HFontRef* base_font_ref_; + + // Indirect reference to the HFontRef, which references the underlying HFONT. + scoped_refptr font_ref_; +#elif defined(OS_LINUX) + explicit Font(SkTypeface* typeface, const std::wstring& name, + int size, int style); + // Calculate and cache the font metrics. + void calculateMetrics(); + // Make |this| a copy of |other|. + void CopyFont(const Font& other); + + // The default font, used for the default constructor. + static Font* default_font_; + + // These two both point to the same SkTypeface. We use the SkAutoUnref to + // handle the reference counting, but without @typeface_ we would have to + // cast the SkRefCnt from @typeface_helper_ every time. + scoped_ptr typeface_helper_; + SkTypeface *typeface_; + + // Additional information about the face + // Skia actually expects a family name and not a font name. + std::wstring font_family_; + int font_size_; + int style_; + + // Cached metrics, generated at construction + int height_; + int ascent_; + int avg_width_; +#elif defined(OS_MACOSX) + explicit Font(const std::wstring& font_name, int font_size, int style); + + // Calculate and cache the font metrics. + void calculateMetrics(); + + std::wstring font_name_; + int font_size_; + int style_; + + // Cached metrics, generated at construction + int height_; + int ascent_; + int avg_width_; +#endif + +}; + +} // namespace gfx + +#endif // APP_GFX_FONT_H_ diff --git a/app/gfx/font_gtk.cc b/app/gfx/font_gtk.cc new file mode 100644 index 0000000..3b78d02 --- /dev/null +++ b/app/gfx/font_gtk.cc @@ -0,0 +1,89 @@ +// Copyright (c) 2006-2008 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/font.h" + +#include +#include + +#include "base/string_util.h" + +namespace gfx { + +Font* Font::default_font_ = NULL; + +// Find the best match font for |family_name| in the same way as Skia +// to make sure CreateFont() successfully creates default font. +// In Skia, it only checks the best match font. If it failed to find, +// SkTypeface will be NULL for that font family. It eventually causes segfault. +// For example, family_name = "Sans" and system may have various fonts. +// The first font family in FcPattern will be "DejaVu Sans" but a font family +// returned by FcFontMatch will be "VL PGothic". +// In this case, SkTypeface for "Sans" returns NULL even if system has font +// for "Sans" font family. +// See FontMatch() in skia/ports/SkFontHost_fontconfig.cpp for more detail. +static std::wstring FindBestMatchFontFamilyName(const char* family_name) { + FcPattern* pattern = FcPatternCreate(); + FcValue fcvalue; + fcvalue.type = FcTypeString; + char* family_name_copy = strdup(family_name); + fcvalue.u.s = reinterpret_cast(family_name_copy); + FcPatternAdd(pattern, FC_FAMILY, fcvalue, 0); + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + FcResult result; + FcPattern* match = FcFontMatch(0, pattern, &result); + DCHECK(match) << "Could not find font: " << family_name; + FcChar8* match_family; + FcPatternGetString(match, FC_FAMILY, 0, &match_family); + + std::wstring font_family = UTF8ToWide( + reinterpret_cast(match_family)); + FcPatternDestroy(match); + FcPatternDestroy(pattern); + free(family_name_copy); + return font_family; +} + +// Get the default gtk system font (name and size). +Font::Font() { + if (default_font_ == NULL) { + gtk_init(NULL, NULL); + GtkSettings* settings = gtk_settings_get_default(); + + GValue value = {0}; + g_value_init(&value, G_TYPE_STRING); + g_object_get_property(G_OBJECT(settings), "gtk-font-name", &value); + + // gtk-font-name may be wrapped in quotes. + gchar* font_name = g_strdup_value_contents(&value); + gchar* font_ptr = font_name; + if (font_ptr[0] == '\"') + font_ptr++; + if (font_ptr[strlen(font_ptr) - 1] == '\"') + font_ptr[strlen(font_ptr) - 1] = '\0'; + + PangoFontDescription* desc = + pango_font_description_from_string(font_ptr); + gint size = pango_font_description_get_size(desc); + const char* family_name = pango_font_description_get_family(desc); + + // Find best match font for |family_name| to make sure we can get + // SkTypeface for default font. + // TODO(agl): remove this. + std::wstring font_family = FindBestMatchFontFamilyName(family_name); + + default_font_ = new Font(CreateFont(font_family, size / PANGO_SCALE)); + + pango_font_description_free(desc); + g_free(font_name); + g_value_unset(&value); + + DCHECK(default_font_); + } + + CopyFont(*default_font_); +} + +} // namespace gfx diff --git a/app/gfx/font_mac.mm b/app/gfx/font_mac.mm new file mode 100644 index 0000000..b39ebea --- /dev/null +++ b/app/gfx/font_mac.mm @@ -0,0 +1,90 @@ +// 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/font.h" + +#include + +#include "base/logging.h" +#include "base/sys_string_conversions.h" + +namespace gfx { + +// static +Font Font::CreateFont(const std::wstring& font_name, int font_size) { + return Font(font_name, font_size, NORMAL); +} + +Font::Font(const std::wstring& font_name, int font_size, int style) + : font_name_(font_name), + font_size_(font_size), + style_(style) { + calculateMetrics(); +} + +Font::Font() + : font_size_([NSFont systemFontSize]), + style_(NORMAL) { + NSFont* system_font = [NSFont systemFontOfSize:font_size_]; + font_name_ = base::SysNSStringToWide([system_font fontName]); + calculateMetrics(); +} + +void Font::calculateMetrics() { + NSFont* font = nativeFont(); + height_ = [font xHeight]; + ascent_ = [font ascender]; + avg_width_ = [font boundingRectForGlyph:[font glyphWithName:@"x"]].size.width; +} + +Font Font::DeriveFont(int size_delta, int style) const { + return Font(font_name_, font_size_ + size_delta, style); +} + +int Font::height() const { + return height_; +} + +int Font::baseline() const { + return ascent_; +} + +int Font::ave_char_width() const { + return avg_width_; +} + +int Font::GetStringWidth(const std::wstring& text) const { + NSFont* font = nativeFont(); + NSString* ns_string = base::SysWideToNSString(text); + NSDictionary* attributes = + [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName]; + NSSize string_size = [ns_string sizeWithAttributes:attributes]; + return string_size.width; +} + +int Font::GetExpectedTextWidth(int length) const { + return length * avg_width_; +} + +int Font::style() const { + return style_; +} + +std::wstring Font::FontName() { + return font_name_; +} + +int Font::FontSize() { + return font_size_; +} + +NativeFont Font::nativeFont() const { + // TODO(pinkerton): apply |style_| to font. + // We could cache this, but then we'd have to conditionally change the + // dtor just for MacOS. Not sure if we want to/need to do that. + return [NSFont fontWithName:base::SysWideToNSString(font_name_) + size:font_size_]; +} + +} // namespace gfx diff --git a/app/gfx/font_skia.cc b/app/gfx/font_skia.cc new file mode 100644 index 0000000..0b0b979 --- /dev/null +++ b/app/gfx/font_skia.cc @@ -0,0 +1,167 @@ +// Copyright (c) 2006-2008 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/font.h" + +#include "base/logging.h" +#include "base/sys_string_conversions.h" + +#include "third_party/skia/include/core/SkTypeface.h" +#include "third_party/skia/include/core/SkPaint.h" + +namespace gfx { + +Font::Font(const Font& other) { + CopyFont(other); +} + +Font& Font::operator=(const Font& other) { + CopyFont(other); + return *this; +} + +Font::Font(SkTypeface* tf, const std::wstring& font_family, int font_size, + int style) + : typeface_helper_(new SkAutoUnref(tf)), + typeface_(tf), + font_family_(font_family), + font_size_(font_size), + style_(style) { + tf->ref(); + calculateMetrics(); +} + +void Font::calculateMetrics() { + SkPaint paint; + SkPaint::FontMetrics metrics; + + PaintSetup(&paint); + paint.getFontMetrics(&metrics); + + ascent_ = SkScalarRound(-metrics.fAscent); + height_ = SkScalarRound(-metrics.fAscent + metrics.fDescent + + metrics.fLeading); + + if (metrics.fAvgCharWidth) { + avg_width_ = SkScalarRound(metrics.fAvgCharWidth); + } else { + static const char x_char = 'x'; + paint.setTextEncoding(SkPaint::kUTF8_TextEncoding); + SkScalar width = paint.measureText(&x_char, 1); + + avg_width_ = static_cast(ceilf(SkScalarToFloat(width))); + } +} + +void Font::CopyFont(const Font& other) { + typeface_helper_.reset(new SkAutoUnref(other.typeface_)); + typeface_ = other.typeface_; + typeface_->ref(); + font_family_ = other.font_family_; + font_size_ = other.font_size_; + style_ = other.style_; + height_ = other.height_; + ascent_ = other.ascent_; + avg_width_ = other.avg_width_; +} + +int Font::height() const { + return height_; +} + +int Font::baseline() const { + return ascent_; +} + +int Font::ave_char_width() const { + return avg_width_; +} + +Font Font::CreateFont(const std::wstring& font_family, int font_size) { + DCHECK_GT(font_size, 0); + + SkTypeface* tf = SkTypeface::CreateFromName( + base::SysWideToUTF8(font_family).c_str(), SkTypeface::kNormal); + DCHECK(tf) << "Could not find font: " << base::SysWideToUTF8(font_family); + SkAutoUnref tf_helper(tf); + + return Font(tf, font_family, font_size, NORMAL); +} + +Font Font::DeriveFont(int size_delta, int style) const { + // If the delta is negative, if must not push the size below 1 + if (size_delta < 0) { + DCHECK_LT(-size_delta, font_size_); + } + + if (style == style_) { + // Fast path, we just use the same typeface at a different size + return Font(typeface_, font_family_, font_size_ + size_delta, style_); + } + + // If the style has changed we may need to load a new face + int skstyle = SkTypeface::kNormal; + if (BOLD & style) + skstyle |= SkTypeface::kBold; + if (ITALIC & style) + skstyle |= SkTypeface::kItalic; + + SkTypeface* tf = SkTypeface::CreateFromName( + base::SysWideToUTF8(font_family_).c_str(), + static_cast(skstyle)); + SkAutoUnref tf_helper(tf); + + return Font(tf, font_family_, font_size_ + size_delta, skstyle); +} + +void Font::PaintSetup(SkPaint* paint) const { + paint->setAntiAlias(false); + paint->setSubpixelText(false); + paint->setTextSize(SkFloatToScalar(font_size_)); + paint->setTypeface(typeface_); + paint->setFakeBoldText((BOLD & style_) && !typeface_->isBold()); + paint->setTextSkewX((ITALIC & style_) && !typeface_->isItalic() ? + -SK_Scalar1/4 : 0); +} + +int Font::GetStringWidth(const std::wstring& text) const { + const std::string utf8(base::SysWideToUTF8(text)); + + SkPaint paint; + PaintSetup(&paint); + paint.setTextEncoding(SkPaint::kUTF8_TextEncoding); + SkScalar width = paint.measureText(utf8.data(), utf8.size()); + + int breadth = static_cast(ceilf(SkScalarToFloat(width))); + // Check for overflow. We should probably be returning an unsigned + // int, but in practice we'll never have a screen massive enough + // to show that much text anyway. + if (breadth < 0) + return INT_MAX; + + return breadth; +} + +int Font::GetExpectedTextWidth(int length) const { + return length * avg_width_; +} + + +int Font::style() const { + return style_; +} + +std::wstring Font::FontName() { + return font_family_; +} + +int Font::FontSize() { + return font_size_; +} + +NativeFont Font::nativeFont() const { + return typeface_; +} + +} // namespace gfx diff --git a/app/gfx/font_unittest.cc b/app/gfx/font_unittest.cc new file mode 100644 index 0000000..3a13e2f6 --- /dev/null +++ b/app/gfx/font_unittest.cc @@ -0,0 +1,59 @@ +// Copyright (c) 2006-2008 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/font.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +using gfx::Font; + +class FontTest : public testing::Test { +}; + +TEST_F(FontTest, LoadArial) { + Font cf(Font::CreateFont(L"Arial", 16)); + ASSERT_TRUE(cf.nativeFont()); + ASSERT_EQ(cf.style(), Font::NORMAL); + ASSERT_EQ(cf.FontSize(), 16); + ASSERT_EQ(cf.FontName(), L"Arial"); +} + +TEST_F(FontTest, LoadArialBold) { + Font cf(Font::CreateFont(L"Arial", 16)); + Font bold(cf.DeriveFont(0, Font::BOLD)); + ASSERT_TRUE(bold.nativeFont()); + ASSERT_EQ(bold.style(), Font::BOLD); +} + +TEST_F(FontTest, Ascent) { + Font cf(Font::CreateFont(L"Arial", 16)); + ASSERT_GT(cf.baseline(), 2); + ASSERT_LT(cf.baseline(), 20); +} + +TEST_F(FontTest, Height) { + Font cf(Font::CreateFont(L"Arial", 16)); + ASSERT_GT(cf.baseline(), 2); + ASSERT_LT(cf.baseline(), 20); +} + +TEST_F(FontTest, AvgWidths) { + Font cf(Font::CreateFont(L"Arial", 16)); + ASSERT_EQ(cf.GetExpectedTextWidth(0), 0); + ASSERT_GT(cf.GetExpectedTextWidth(1), cf.GetExpectedTextWidth(0)); + ASSERT_GT(cf.GetExpectedTextWidth(2), cf.GetExpectedTextWidth(1)); + ASSERT_GT(cf.GetExpectedTextWidth(3), cf.GetExpectedTextWidth(2)); +} + +TEST_F(FontTest, Widths) { + Font cf(Font::CreateFont(L"Arial", 16)); + ASSERT_EQ(cf.GetStringWidth(L""), 0); + ASSERT_GT(cf.GetStringWidth(L"a"), cf.GetStringWidth(L"")); + ASSERT_GT(cf.GetStringWidth(L"ab"), cf.GetStringWidth(L"a")); + ASSERT_GT(cf.GetStringWidth(L"abc"), cf.GetStringWidth(L"ab")); +} + +} // anonymous namespace diff --git a/app/gfx/font_win.cc b/app/gfx/font_win.cc new file mode 100644 index 0000000..7323e9c --- /dev/null +++ b/app/gfx/font_win.cc @@ -0,0 +1,213 @@ +// Copyright (c) 2006-2008 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/font.h" + +#include +#include + +#include + +#include "app/l10n_util_win.h" +#include "base/logging.h" +#include "base/win_util.h" +#include "grit/generated_resources.h" + +namespace gfx { + +/*static*/ +Font::HFontRef* Font::base_font_ref_; + +// If the tmWeight field of a TEXTMETRIC structure has a value >= this, the +// font is bold. +static const int kTextMetricWeightBold = 700; + +// +// Font +// + +Font::Font() + : font_ref_(GetBaseFontRef()) { +} + +int Font::height() const { + return font_ref_->height(); +} + +int Font::baseline() const { + return font_ref_->baseline(); +} + +int Font::ave_char_width() const { + return font_ref_->ave_char_width(); +} + +int Font::GetExpectedTextWidth(int length) const { + return length * std::min(font_ref_->dlu_base_x(), ave_char_width()); +} + +int Font::style() const { + return font_ref_->style(); +} + +NativeFont Font::nativeFont() const { + return hfont(); +} + +// static +Font Font::CreateFont(HFONT font) { + DCHECK(font); + LOGFONT font_info; + GetObject(font, sizeof(LOGFONT), &font_info); + return Font(CreateHFontRef(CreateFontIndirect(&font_info))); +} + +Font Font::CreateFont(const std::wstring& font_name, int font_size) { + HDC hdc = GetDC(NULL); + long lf_height = -MulDiv(font_size, GetDeviceCaps(hdc, LOGPIXELSY), 72); + ReleaseDC(NULL, hdc); + HFONT hf = ::CreateFont(lf_height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + font_name.c_str()); + return Font::CreateFont(hf); +} + +// static +Font::HFontRef* Font::GetBaseFontRef() { + if (base_font_ref_ == NULL) { + NONCLIENTMETRICS metrics; + win_util::GetNonClientMetrics(&metrics); + + l10n_util::AdjustUIFont(&metrics.lfMessageFont); + + // See comment in Font::DeriveFont() about font size. + // TODO(jungshik): Add a per-locale resource entry for the minimum + // font size and actually enforce the lower-bound. 5 is way too small + // for CJK, Thai, and Indian locales. + DCHECK_GE(abs(metrics.lfMessageFont.lfHeight), 5); + HFONT font = CreateFontIndirect(&metrics.lfMessageFont); + DLOG_ASSERT(font); + base_font_ref_ = Font::CreateHFontRef(font); + // base_font_ref_ is global, up the ref count so it's never deleted. + base_font_ref_->AddRef(); + } + return base_font_ref_; +} + +std::wstring Font::FontName() { + LOGFONT font_info; + GetObject(hfont(), sizeof(LOGFONT), &font_info); + return (std::wstring(font_info.lfFaceName)); +} + +int Font::FontSize() { + LOGFONT font_info; + GetObject(hfont(), sizeof(LOGFONT), &font_info); + long lf_height = font_info.lfHeight; + HDC hdc = GetDC(NULL); + int device_caps = GetDeviceCaps(hdc, LOGPIXELSY); + int font_size = 0; + if (device_caps != 0) { + float font_size_float = -static_cast(lf_height)*72/device_caps; + font_size = static_cast(::ceil(font_size_float - 0.5)); + } + ReleaseDC(NULL, hdc); + return font_size; +} + +Font::HFontRef::HFontRef(HFONT hfont, + int height, + int baseline, + int ave_char_width, + int style, + int dlu_base_x) + : hfont_(hfont), + height_(height), + baseline_(baseline), + ave_char_width_(ave_char_width), + style_(style), + dlu_base_x_(dlu_base_x) { + DLOG_ASSERT(hfont); +} + +Font::HFontRef::~HFontRef() { + DeleteObject(hfont_); +} + + +Font Font::DeriveFont(int size_delta, int style) const { + LOGFONT font_info; + GetObject(hfont(), sizeof(LOGFONT), &font_info); + // LOGFONT returns two types of font heights, negative is measured slightly + // differently (character height, vs cell height). + if (font_info.lfHeight < 0) { + font_info.lfHeight -= size_delta; + } else { + font_info.lfHeight += size_delta; + } + // Even with "Small Fonts", the smallest readable font size is 5. It is easy + // to create a non-drawing font and forget about the fact that text should be + // drawn in the UI. This test ensures that the font will be readable. + DCHECK_GE(abs(font_info.lfHeight), 5); + font_info.lfUnderline = ((style & UNDERLINED) == UNDERLINED); + font_info.lfItalic = ((style & ITALIC) == ITALIC); + font_info.lfWeight = (style & BOLD) ? FW_BOLD : FW_NORMAL; + + HFONT hfont = CreateFontIndirect(&font_info); + return Font(CreateHFontRef(hfont)); +} + +int Font::GetStringWidth(const std::wstring& text) const { + int width = 0; + HDC dc = GetDC(NULL); + HFONT previous_font = static_cast(SelectObject(dc, hfont())); + SIZE size; + if (GetTextExtentPoint32(dc, text.c_str(), static_cast(text.size()), + &size)) { + width = size.cx; + } else { + width = 0; + } + SelectObject(dc, previous_font); + ReleaseDC(NULL, dc); + return width; +} + +Font::HFontRef* Font::CreateHFontRef(HFONT font) { + TEXTMETRIC font_metrics; + HDC screen_dc = GetDC(NULL); + HFONT previous_font = static_cast(SelectObject(screen_dc, font)); + int last_map_mode = SetMapMode(screen_dc, MM_TEXT); + GetTextMetrics(screen_dc, &font_metrics); + // Yes, this is how Microsoft recommends calculating the dialog unit + // conversions. + SIZE ave_text_size; + GetTextExtentPoint32(screen_dc, + L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + 52, &ave_text_size); + const int dlu_base_x = (ave_text_size.cx / 26 + 1) / 2; + // To avoid the DC referencing font_handle_, select the previous font. + SelectObject(screen_dc, previous_font); + SetMapMode(screen_dc, last_map_mode); + ReleaseDC(NULL, screen_dc); + + const int height = std::max(1, static_cast(font_metrics.tmHeight)); + const int baseline = std::max(1, static_cast(font_metrics.tmAscent)); + const int ave_char_width = + std::max(1, static_cast(font_metrics.tmAveCharWidth)); + int style = 0; + if (font_metrics.tmItalic) { + style |= Font::ITALIC; + } + if (font_metrics.tmUnderlined) { + style |= Font::UNDERLINED; + } + if (font_metrics.tmWeight >= kTextMetricWeightBold) { + style |= Font::BOLD; + } + + return new HFontRef(font, height, baseline, ave_char_width, style, + dlu_base_x); +} + +} // namespace gfx diff --git a/app/gfx/icon_util.h b/app/gfx/icon_util.h index 9066df9..f7199ea 100644 --- a/app/gfx/icon_util.h +++ b/app/gfx/icon_util.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_COMMON_ICON_UTIL_H__ -#define CHROME_COMMON_ICON_UTIL_H__ +#ifndef APP_ICON_UTIL_H_ +#define APP_ICON_UTIL_H_ #include #include @@ -190,4 +190,4 @@ class IconUtil { DISALLOW_IMPLICIT_CONSTRUCTORS(IconUtil); }; -#endif // CHROME_COMMON_ICON_UTIL_H__ +#endif // APP_ICON_UTIL_H_ diff --git a/app/gfx/insets.h b/app/gfx/insets.h index 741de3a2..a90e3a4 100644 --- a/app/gfx/insets.h +++ b/app/gfx/insets.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_COMMON_GFX_INSETS_H__ -#define CHROME_COMMON_GFX_INSETS_H__ +#ifndef APP_GFX_INSETS_H_ +#define APP_GFX_INSETS_H_ namespace gfx { @@ -66,4 +66,4 @@ class Insets { } // namespace -#endif // CHROME_COMMON_GFX_INSETS_H__ +#endif // APP_GFX_INSETS_H_ diff --git a/app/gfx/path.h b/app/gfx/path.h index ac7537c..9c70209 100644 --- a/app/gfx/path.h +++ b/app/gfx/path.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_COMMON_GFX_CHROME_PATH_H_ -#define CHROME_COMMON_GFX_CHROME_PATH_H_ +#ifndef APP_GFX_PATH_H_ +#define APP_GFX_PATH_H_ #include "base/basictypes.h" @@ -37,4 +37,4 @@ class Path : public SkPath { } -#endif // #ifndef CHROME_COMMON_GFX_CHROME_PATH_H_ +#endif // #ifndef APP_GFX_PATH_H_ diff --git a/app/gfx/text_elider.cc b/app/gfx/text_elider.cc index 93653e0..7568aef 100644 --- a/app/gfx/text_elider.cc +++ b/app/gfx/text_elider.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "app/gfx/chrome_font.h" +#include "app/gfx/font.h" #include "app/gfx/text_elider.h" #include "base/file_path.h" #include "base/string_util.h" diff --git a/app/gfx/text_elider.h b/app/gfx/text_elider.h index 5872ed4..c0d0be6 100644 --- a/app/gfx/text_elider.h +++ b/app/gfx/text_elider.h @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_COMMON_GFX_TEXT_ELIDER_H_ -#define CHROME_COMMON_GFX_TEXT_ELIDER_H_ +#ifndef APP_GFX_TEXT_ELIDER_H_ +#define APP_GFX_TEXT_ELIDER_H_ #include #include -#include "app/gfx/chrome_font.h" +#include "app/gfx/font.h" #include "base/basictypes.h" #include "base/string16.h" @@ -96,4 +96,4 @@ class SortedDisplayURL { } // namespace gfx. -#endif // CHROME_COMMON_GFX_TEXT_ELIDER_H_ +#endif // APP_GFX_TEXT_ELIDER_H_ diff --git a/app/gfx/text_elider_unittest.cc b/app/gfx/text_elider_unittest.cc index 28691d7..7887d68 100644 --- a/app/gfx/text_elider_unittest.cc +++ b/app/gfx/text_elider_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "app/gfx/chrome_font.h" +#include "app/gfx/font.h" #include "app/gfx/text_elider.h" #include "base/file_path.h" #include "base/string_util.h" diff --git a/app/l10n_util.cc b/app/l10n_util.cc index adbef03..611c21a 100644 --- a/app/l10n_util.cc +++ b/app/l10n_util.cc @@ -7,7 +7,7 @@ #include "app/l10n_util.h" #include "app/app_switches.h" -#include "app/gfx/chrome_canvas.h" +#include "app/gfx/canvas.h" #include "app/resource_bundle.h" #include "base/command_line.h" #include "base/file_util.h" @@ -611,9 +611,9 @@ void WrapPathWithLTRFormatting(const FilePath& path, int DefaultCanvasTextAlignment() { if (GetTextDirection() == LEFT_TO_RIGHT) { - return ChromeCanvas::TEXT_ALIGN_LEFT; + return gfx::Canvas::TEXT_ALIGN_LEFT; } else { - return ChromeCanvas::TEXT_ALIGN_RIGHT; + return gfx::Canvas::TEXT_ALIGN_RIGHT; } } diff --git a/app/l10n_util.h b/app/l10n_util.h index aafd658..bbf04eb 100644 --- a/app/l10n_util.h +++ b/app/l10n_util.h @@ -188,12 +188,12 @@ void WrapPathWithLTRFormatting(const FilePath& path, string16* rtl_safe_path); // Returns the default text alignment to be used when drawing text on a -// ChromeCanvas based on the directionality of the system locale language. This -// function is used by ChromeCanvas::DrawStringInt when the text alignment is +// gfx::Canvas based on the directionality of the system locale language. This +// function is used by gfx::Canvas::DrawStringInt when the text alignment is // not specified. // -// This function returns either ChromeCanvas::TEXT_ALIGN_LEFT or -// ChromeCanvas::TEXT_ALIGN_RIGHT. +// This function returns either gfx::Canvas::TEXT_ALIGN_LEFT or +// gfx::Canvas::TEXT_ALIGN_RIGHT. int DefaultCanvasTextAlignment(); // Compares the two strings using the specified collator. diff --git a/app/resource_bundle.cc b/app/resource_bundle.cc index 96bc714..2ee2243 100644 --- a/app/resource_bundle.cc +++ b/app/resource_bundle.cc @@ -4,7 +4,7 @@ #include "app/resource_bundle.h" -#include "app/gfx/chrome_font.h" +#include "app/gfx/font.h" #include "base/gfx/png_decoder.h" #include "base/logging.h" #include "base/string_piece.h" diff --git a/app/resource_bundle_linux.cc b/app/resource_bundle_linux.cc index 2d47ae5..6f4b43f 100644 --- a/app/resource_bundle_linux.cc +++ b/app/resource_bundle_linux.cc @@ -6,7 +6,7 @@ #include -#include "app/gfx/chrome_font.h" +#include "app/gfx/font.h" #include "app/gfx/gtk_util.h" #include "app/l10n_util.h" #include "base/base_paths.h" diff --git a/app/resource_bundle_mac.mm b/app/resource_bundle_mac.mm index 710364b..f8aab45 100644 --- a/app/resource_bundle_mac.mm +++ b/app/resource_bundle_mac.mm @@ -6,7 +6,7 @@ #import -#include "app/gfx/chrome_font.h" +#include "app/gfx/font.h" #include "app/l10n_util.h" #include "base/base_paths.h" #include "base/data_pack.h" diff --git a/app/resource_bundle_win.cc b/app/resource_bundle_win.cc index f65ee2b..1d0d28f 100644 --- a/app/resource_bundle_win.cc +++ b/app/resource_bundle_win.cc @@ -6,7 +6,7 @@ #include -#include "app/gfx/chrome_font.h" +#include "app/gfx/font.h" #include "app/l10n_util.h" #include "base/file_util.h" #include "base/logging.h" diff --git a/app/win_util.h b/app/win_util.h index 2b5bdce..19bbba7 100644 --- a/app/win_util.h +++ b/app/win_util.h @@ -10,7 +10,7 @@ #include #include -#include "app/gfx/chrome_font.h" +#include "app/gfx/font.h" #include "base/fix_wp64.h" #include "base/gfx/rect.h" #include "base/scoped_handle.h" -- cgit v1.1