Home | History | Annotate | Download | only in gtk
      1 /*
      2  * Copyright (C) 2007 Kevin Watters, Kevin Ollivier.  All rights reserved.
      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 #include "GlyphBuffer.h"
     28 #include "GraphicsContext.h"
     29 #include "SimpleFontData.h"
     30 
     31 #include <wx/dc.h>
     32 #include <wx/dcgraph.h>
     33 #include <wx/defs.h>
     34 #include <wx/dcclient.h>
     35 #include <wx/gdicmn.h>
     36 #include <vector>
     37 
     38 #if USE(WXGC)
     39 #include <cairo.h>
     40 #include <assert.h>
     41 
     42 #include <pango/pango.h>
     43 #include <pango/pangocairo.h>
     44 
     45 // Use cairo-ft if a recent enough Pango version isn't available
     46 #if !PANGO_VERSION_CHECK(1,18,0)
     47 #include <cairo-ft.h>
     48 #include <pango/pangofc-fontmap.h>
     49 #endif
     50 
     51 #endif
     52 
     53 #include <gtk/gtk.h>
     54 
     55 namespace WebCore {
     56 
     57 #if USE(WXGC)
     58 static PangoFontMap* g_fontMap;
     59 
     60 PangoFontMap* pangoFontMap()
     61 {
     62     if (!g_fontMap)
     63         g_fontMap = pango_cairo_font_map_get_default();
     64 
     65     return g_fontMap;
     66 }
     67 
     68 PangoFont* createPangoFontForFont(const wxFont* wxfont)
     69 {
     70     ASSERT(wxfont && wxfont->Ok());
     71 
     72     const char* face = wxfont->GetFaceName().mb_str(wxConvUTF8);
     73     char const* families[] = {
     74         face,
     75         0
     76     };
     77 
     78     switch (wxfont->GetFamily()) {
     79     case wxFONTFAMILY_ROMAN:
     80         families[1] = "serif";
     81         break;
     82     case wxFONTFAMILY_SWISS:
     83         families[1] = "sans";
     84         break;
     85     case wxFONTFAMILY_MODERN:
     86         families[1] = "monospace";
     87         break;
     88     default:
     89         families[1] = "sans";
     90     }
     91 
     92     PangoFontDescription* description = pango_font_description_new();
     93     pango_font_description_set_absolute_size(description, wxfont->GetPointSize() * PANGO_SCALE);
     94 
     95     PangoFont* pangoFont = 0;
     96     PangoContext* pangoContext = 0;
     97 
     98     switch (wxfont->GetWeight()) {
     99     case wxFONTWEIGHT_LIGHT:
    100         pango_font_description_set_weight(description, PANGO_WEIGHT_LIGHT);
    101         break;
    102     case wxFONTWEIGHT_NORMAL:
    103         pango_font_description_set_weight(description, PANGO_WEIGHT_NORMAL);
    104         break;
    105     case wxFONTWEIGHT_BOLD:
    106         pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD);
    107         break;
    108     }
    109 
    110     switch (wxfont->GetStyle()) {
    111     case wxFONTSTYLE_NORMAL:
    112         pango_font_description_set_style(description, PANGO_STYLE_NORMAL);
    113         break;
    114     case wxFONTSTYLE_ITALIC:
    115         pango_font_description_set_style(description, PANGO_STYLE_ITALIC);
    116         break;
    117     case wxFONTSTYLE_SLANT:
    118         pango_font_description_set_style(description, PANGO_STYLE_OBLIQUE);
    119         break;
    120     }
    121 
    122     PangoFontMap* fontMap = pangoFontMap();
    123 
    124     pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(fontMap));
    125     for (unsigned i = 0; !pangoFont && i < G_N_ELEMENTS(families); i++) {
    126         pango_font_description_set_family(description, families[i]);
    127         pango_context_set_font_description(pangoContext, description);
    128         pangoFont = pango_font_map_load_font(fontMap, pangoContext, description);
    129     }
    130     pango_font_description_free(description);
    131 
    132     return pangoFont;
    133 }
    134 
    135 cairo_scaled_font_t* createScaledFontForFont(const wxFont* wxfont)
    136 {
    137     ASSERT(wxfont && wxfont->Ok());
    138 
    139     cairo_scaled_font_t* scaledFont = NULL;
    140     PangoFont* pangoFont = createPangoFontForFont(wxfont);
    141 
    142 #if PANGO_VERSION_CHECK(1,18,0)
    143     if (pangoFont)
    144         scaledFont = cairo_scaled_font_reference(pango_cairo_font_get_scaled_font(PANGO_CAIRO_FONT(pangoFont)));
    145 #endif
    146 
    147     return scaledFont;
    148 }
    149 
    150 PangoGlyph pango_font_get_glyph(PangoFont* font, PangoContext* context, gunichar wc)
    151 {
    152     PangoGlyph result = 0;
    153     gchar buffer[7];
    154 
    155     gint  length = g_unichar_to_utf8(wc, buffer);
    156     g_return_val_if_fail(length, 0);
    157 
    158     GList* items = pango_itemize(context, buffer, 0, length, NULL, NULL);
    159 
    160     if (g_list_length(items) == 1) {
    161         PangoItem* item = static_cast<PangoItem*>(items->data);
    162         PangoFont* tmpFont = item->analysis.font;
    163         item->analysis.font = font;
    164 
    165         PangoGlyphString* glyphs = pango_glyph_string_new();
    166         pango_shape(buffer, length, &item->analysis, glyphs);
    167 
    168         item->analysis.font = tmpFont;
    169 
    170         if (glyphs->num_glyphs == 1)
    171             result = glyphs->glyphs[0].glyph;
    172         else
    173             g_warning("didn't get 1 glyph but %d", glyphs->num_glyphs);
    174 
    175         pango_glyph_string_free(glyphs);
    176     }
    177 
    178     g_list_foreach(items, (GFunc)pango_item_free, NULL);
    179     g_list_free(items);
    180 
    181     return result;
    182 }
    183 #endif // USE(WXGC)
    184 
    185 
    186 void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* font, const wxColour& color, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point)
    187 {
    188 #if USE(WXGC)
    189     wxGCDC* dc = static_cast<wxGCDC*>(graphicsContext->platformContext());
    190     wxGraphicsContext* gc = dc->GetGraphicsContext();
    191     gc->PushState();
    192     cairo_t* cr = (cairo_t*)gc->GetNativeContext();
    193 
    194     wxFont* wxfont = font->getWxFont();
    195     PangoFont* pangoFont = createPangoFontForFont(wxfont);
    196     PangoFontMap* fontMap = pangoFontMap();
    197     PangoContext* pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(fontMap));
    198     cairo_scaled_font_t* scaled_font = createScaledFontForFont(wxfont);
    199     ASSERT(scaled_font);
    200 
    201     cairo_glyph_t* glyphs = NULL;
    202     glyphs = static_cast<cairo_glyph_t*>(malloc(sizeof(cairo_glyph_t) * numGlyphs));
    203 
    204     float offset = point.x();
    205 
    206     for (int i = 0; i < numGlyphs; i++) {
    207         glyphs[i].index = pango_font_get_glyph(pangoFont, pangoContext, glyphBuffer.glyphAt(from + i));
    208         glyphs[i].x = offset;
    209         glyphs[i].y = point.y();
    210         offset += glyphBuffer.advanceAt(from + i);
    211     }
    212 
    213     cairo_set_source_rgba(cr, color.Red()/255.0, color.Green()/255.0, color.Blue()/255.0, color.Alpha()/255.0);
    214     cairo_set_scaled_font(cr, scaled_font);
    215 
    216     cairo_show_glyphs(cr, glyphs, numGlyphs);
    217 
    218     cairo_scaled_font_destroy(scaled_font);
    219     gc->PopState();
    220 #else
    221     wxDC* dc = graphicsContext->platformContext();
    222 
    223     wxFont* wxfont = font->getWxFont();
    224     if (wxfont && wxfont->IsOk())
    225         dc->SetFont(*wxfont);
    226     dc->SetTextForeground(color);
    227 
    228     // convert glyphs to wxString
    229     GlyphBufferGlyph* glyphs = const_cast<GlyphBufferGlyph*>(glyphBuffer.glyphs(from));
    230     int offset = point.x();
    231     wxString text = wxEmptyString;
    232     for (unsigned i = 0; i < numGlyphs; i++) {
    233         text = text.Append((wxChar)glyphs[i]);
    234         offset += glyphBuffer.advanceAt(from + i);
    235     }
    236 
    237     // the y point is actually the bottom point of the text, turn it into the top
    238     float height = font->ascent() - font->descent();
    239     wxCoord ypoint = (wxCoord) (point.y() - height);
    240 
    241     dc->DrawText(text, (wxCoord)point.x(), ypoint);
    242 #endif
    243 }
    244 
    245 }
    246