Home | History | Annotate | Download | only in gtk
      1 /*
      2  * Copyright (C) 2007 Kevin Ollivier <kevino (at) theolliviers.com>
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 // this needs to be included before fontprops.h for UChar* to be defined.
     28 #include <wtf/unicode/Unicode.h>
     29 
     30 #include <wx/defs.h>
     31 #include <wx/gdicmn.h>
     32 #include <wx/font.h>
     33 #include <wx/fontutil.h>
     34 #include "fontprops.h"
     35 #include "non-kerned-drawing.h"
     36 
     37 #include <gdk/gdk.h>
     38 
     39 #include <cairo.h>
     40 #include <pango/pango.h>
     41 #include <pango/pangocairo.h>
     42 
     43 wxFontProperties::wxFontProperties(wxFont* font):
     44 m_ascent(0), m_descent(0), m_lineGap(0), m_lineSpacing(0), m_xHeight(0)
     45 {
     46     ASSERT(font && font->Ok());
     47 
     48 #if USE(WXGC)
     49     cairo_font_extents_t font_extents;
     50     cairo_text_extents_t text_extents;
     51     cairo_scaled_font_t* scaled_font = WebCore::createScaledFontForFont(font);
     52 
     53     cairo_scaled_font_extents(scaled_font, &font_extents);
     54     m_ascent = static_cast<int>(font_extents.ascent);
     55     m_descent = static_cast<int>(font_extents.descent);
     56     m_lineSpacing = static_cast<int>(font_extents.height);
     57     cairo_scaled_font_text_extents(scaled_font, "x", &text_extents);
     58     m_xHeight = text_extents.height;
     59     cairo_scaled_font_text_extents(scaled_font, " ", &text_extents);
     60     m_lineGap = m_lineSpacing - m_ascent - m_descent;
     61 
     62     cairo_scaled_font_destroy(scaled_font);
     63 #else
     64     PangoContext* context = gdk_pango_context_get_for_screen( gdk_screen_get_default() );
     65     PangoLayout* layout = pango_layout_new(context);
     66     // and use it if it's valid
     67     if ( font && font->Ok() )
     68     {
     69         pango_layout_set_font_description
     70         (
     71             layout,
     72             font->GetNativeFontInfo()->description
     73         );
     74     }
     75 
     76     PangoFontMetrics* metrics = pango_context_get_metrics (context, font->GetNativeFontInfo()->description, NULL);
     77 
     78     int height = font->GetPixelSize().GetHeight();
     79 
     80     m_ascent = PANGO_PIXELS(pango_font_metrics_get_ascent(metrics));
     81     m_descent = PANGO_PIXELS(pango_font_metrics_get_descent(metrics));
     82 
     83     int h;
     84 
     85     const char* x = "x";
     86     pango_layout_set_text( layout, x, strlen(x) );
     87     pango_layout_get_pixel_size( layout, NULL, &h );
     88 
     89     m_xHeight = h;
     90     m_lineGap = (m_ascent + m_descent) / 4; // FIXME: How can we calculate this via Pango?
     91     m_lineSpacing = m_ascent + m_descent;
     92 
     93     pango_font_metrics_unref(metrics);
     94 #endif
     95 }
     96 
     97 bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int length)
     98 {
     99     return true;
    100 }
    101 
    102 void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height,
    103                             wxCoord *descent, wxCoord *externalLeading )
    104 {
    105     if ( width )
    106         *width = 0;
    107     if ( height )
    108         *height = 0;
    109     if ( descent )
    110         *descent = 0;
    111     if ( externalLeading )
    112         *externalLeading = 0;
    113 
    114     if (str.empty())
    115         return;
    116 
    117 // FIXME: Doesn't support height, descent or external leading, though we don't need this for WebKit
    118 // it will need to be implemented before merging into wx unless we craft a new API.
    119 #if USE(WXGC)
    120     PangoFont* pangoFont = WebCore::createPangoFontForFont(&font);
    121     PangoContext* pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(WebCore::pangoFontMap()));
    122     PangoGlyph pangoGlyph = WebCore::pango_font_get_glyph(pangoFont, pangoContext, (gunichar)g_utf8_get_char(str.ToUTF8()));
    123     cairo_glyph_t cglyph = { pangoGlyph, 0, 0 };
    124     cairo_text_extents_t extents;
    125     cairo_scaled_font_t* scaled_font = WebCore::createScaledFontForFont(&font);
    126     cairo_scaled_font_glyph_extents(scaled_font, &cglyph, 1, &extents);
    127 
    128     if (cairo_scaled_font_status(scaled_font) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0)
    129         *width = (wxCoord)extents.x_advance;
    130 
    131     cairo_scaled_font_destroy(scaled_font);
    132     g_object_unref(pangoContext);
    133     g_object_unref(pangoFont);
    134 #else
    135     PangoContext* context = gdk_pango_context_get_for_screen( gdk_screen_get_default() );
    136     PangoLayout* m_layout = pango_layout_new(context);
    137     // and use it if it's valid
    138     if ( font && font->IsOk() )
    139     {
    140         pango_layout_set_font_description
    141         (
    142             m_layout,
    143             font->GetNativeFontInfo()->description
    144         );
    145     }
    146 
    147     // Set layout's text
    148     const wxCharBuffer dataUTF8 = wxConvUTF8.cWX2MB(str);
    149     if ( !dataUTF8 )
    150     {
    151         // hardly ideal, but what else can we do if conversion failed?
    152         return;
    153     }
    154 
    155     pango_layout_set_text( m_layout, dataUTF8, strlen(dataUTF8) );
    156 
    157     int h = 0;
    158     pango_layout_get_pixel_size( m_layout, width, &h );
    159 
    160     if (descent)
    161     {
    162         PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
    163         int baseline = pango_layout_iter_get_baseline(iter);
    164         pango_layout_iter_free(iter);
    165         *descent = h - PANGO_PIXELS(baseline);
    166     }
    167 
    168     if (height)
    169         *height = (wxCoord) h;
    170 #endif
    171 }
    172 
    173