18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (c) 2007 Hiroyuki Ikezoe
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (c) 2007 Kouhei Sutou
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Alp Toker <alp@atoker.com>
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Xan Lopez <xan@gnome.org>
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Nuanti Ltd.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * All rights reserved.
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Font.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "CairoUtilities.h"
376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "ContextShadow.h"
382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "GOwnPtr.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h"
40f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "NotImplemented.h"
412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "PlatformContextCairo.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SimpleFontData.h"
43ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "TextRun.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <cairo.h>
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <gdk/gdk.h>
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <pango/pango.h>
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <pango/pangocairo.h>
486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
492bde8e466a4451c7319e3a072d118917957d6554Steve Block#if USE(FREETYPE)
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <pango/pangofc-fontmap.h>
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#ifdef GTK_API_VERSION_2
566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennertypedef GdkRegion* PangoRegionType;
576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid destroyPangoRegion(PangoRegionType region)
596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    gdk_region_destroy(region);
616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerIntRect getPangoRegionExtents(PangoRegionType region)
646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    GdkRectangle rectangle;
666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    gdk_region_get_clipbox(region, &rectangle);
676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return IntRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#else
706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennertypedef cairo_region_t* PangoRegionType;
716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid destroyPangoRegion(PangoRegionType region)
736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
746b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    cairo_region_destroy(region);
756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerIntRect getPangoRegionExtents(PangoRegionType region)
786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    cairo_rectangle_int_t rectangle;
806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    cairo_region_get_extents(region, &rectangle);
816b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return IntRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#endif
846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define IS_HIGH_SURROGATE(u)  ((UChar)(u) >= (UChar)0xd800 && (UChar)(u) <= (UChar)0xdbff)
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define IS_LOW_SURROGATE(u)  ((UChar)(u) >= (UChar)0xdc00 && (UChar)(u) <= (UChar)0xdfff)
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic gchar* utf16ToUtf8(const UChar* aText, gint aLength, gint &length)
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gboolean needCopy = FALSE;
912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (int i = 0; i < aLength; i++) {
932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!aText[i] || IS_LOW_SURROGATE(aText[i])) {
942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            needCopy = TRUE;
952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            break;
962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (IS_HIGH_SURROGATE(aText[i])) {
992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (i < aLength - 1 && IS_LOW_SURROGATE(aText[i+1]))
1002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                i++;
1012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            else {
1022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                needCopy = TRUE;
1032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                break;
1042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            }
1052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    GOwnPtr<UChar> copiedString;
1092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (needCopy) {
1102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        /* Pango doesn't correctly handle nuls.  We convert them to 0xff. */
1112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        /* Also "validate" UTF-16 text to make sure conversion doesn't fail. */
1122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        copiedString.set(static_cast<UChar*>(g_memdup(aText, aLength * sizeof(aText[0]))));
1142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        UChar* p = copiedString.get();
1152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        /* don't need to reset i */
1172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        for (int i = 0; i < aLength; i++) {
1182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (!p[i] || IS_LOW_SURROGATE(p[i]))
1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                p[i] = 0xFFFD;
1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            else if (IS_HIGH_SURROGATE(p[i])) {
1212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                if (i < aLength - 1 && IS_LOW_SURROGATE(aText[i+1]))
1222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    i++;
1232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                else
1242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    p[i] = 0xFFFD;
1252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            }
1262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
1272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        aText = p;
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gchar* utf8Text;
1322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    glong itemsWritten;
1332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    utf8Text = g_utf16_to_utf8(static_cast<const gunichar2*>(aText), aLength, 0, &itemsWritten, 0);
1342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    length = itemsWritten;
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return utf8Text;
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic gchar* convertUniCharToUTF8(const UChar* characters, gint length, int from, int to)
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gint newLength = 0;
1422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    GOwnPtr<gchar> utf8Text(utf16ToUtf8(characters, length, newLength));
1432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!utf8Text)
1442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gchar* pos = utf8Text.get();
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (from > 0) {
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // discard the first 'from' characters
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // FIXME: we should do this before the conversion probably
1502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        pos = g_utf8_offset_to_pointer(utf8Text.get(), from);
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gint len = strlen(pos);
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    GString* ret = g_string_new_len(NULL, len);
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // replace line break by space
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (len > 0) {
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gint index, start;
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pango_find_paragraph_boundary(pos, len, &index, &start);
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        g_string_append_len(ret, pos, index);
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (index == start)
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        g_string_append_c(ret, ' ');
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pos += start;
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        len -= start;
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return g_string_free(ret, FALSE);
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void setPangoAttributes(const Font* font, const TextRun& run, PangoLayout* layout)
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1722bde8e466a4451c7319e3a072d118917957d6554Steve Block#if USE(FREETYPE)
1735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (font->primaryFont()->platformData().m_pattern) {
17468513a70bcd92384395513322f1b801e7bf9c729Steve Block        PangoFontDescription* desc = pango_fc_font_description_from_pattern(font->primaryFont()->platformData().m_pattern.get(), FALSE);
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pango_layout_set_font_description(layout, desc);
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pango_font_description_free(desc);
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1782bde8e466a4451c7319e3a072d118917957d6554Steve Block#elif USE(PANGO)
1795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (font->primaryFont()->platformData().m_font) {
1805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        PangoFontDescription* desc = pango_font_describe(font->primaryFont()->platformData().m_font);
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pango_layout_set_font_description(layout, desc);
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pango_font_description_free(desc);
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_layout_set_auto_dir(layout, FALSE);
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PangoContext* pangoContext = pango_layout_get_context(layout);
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PangoDirection direction = run.rtl() ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_context_set_base_dir(pangoContext, direction);
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PangoAttrList* list = pango_attr_list_new();
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PangoAttribute* attr;
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    attr = pango_attr_size_new_absolute(font->pixelSize() * PANGO_SCALE);
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    attr->end_index = G_MAXUINT;
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_attr_list_insert_before(list, attr);
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!run.spacingDisabled()) {
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        attr = pango_attr_letter_spacing_new(font->letterSpacing() * PANGO_SCALE);
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        attr->end_index = G_MAXUINT;
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pango_attr_list_insert_before(list, attr);
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Pango does not yet support synthesising small caps
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // See http://bugs.webkit.org/show_bug.cgi?id=15610
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_layout_set_attributes(layout, list);
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_attr_list_unref(list);
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool Font::canReturnFallbackFontsForComplexText()
2125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
2135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return false;
2145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
2155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2162fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool Font::canExpandAroundIdeographsInComplexText()
2172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
2182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return false;
2192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
2202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2212bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint& point, PangoLayoutLine* layoutLine, PangoRegionType renderRegion)
2226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ContextShadow* shadow = graphicsContext->contextShadow();
2246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(shadow);
2256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
226f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!(graphicsContext->textDrawingMode() & TextModeFill) || shadow->m_type == ContextShadow::NoShadow)
2276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
2286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    FloatPoint totalOffset(point + shadow->m_offset);
2306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Optimize non-blurry shadows, by just drawing text without the ContextShadow.
232cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!shadow->mustUseContextShadow(graphicsContext)) {
2332bde8e466a4451c7319e3a072d118917957d6554Steve Block        cairo_t* context = graphicsContext->platformContext()->cr();
2346b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        cairo_save(context);
2356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        cairo_translate(context, totalOffset.x(), totalOffset.y());
2366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        setSourceRGBAFromColor(context, shadow->m_color);
2386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        gdk_cairo_region(context, renderRegion);
2396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        cairo_clip(context);
2406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        pango_cairo_show_layout_line(context, layoutLine);
2416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        cairo_restore(context);
2436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
2446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    FloatRect extents(getPangoRegionExtents(renderRegion));
2476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    extents.setLocation(FloatPoint(point.x(), point.y() - extents.height()));
248cad810f21b803229eb11403f9209855525a25d57Steve Block    cairo_t* shadowContext = shadow->beginShadowLayer(graphicsContext, extents);
2496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (shadowContext) {
2506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        cairo_translate(shadowContext, point.x(), point.y());
2516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        pango_cairo_show_layout_line(shadowContext, layoutLine);
2526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // We need the clipping region to be active when we blit the blurred shadow back,
2546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // because we don't want any bits and pieces of characters out of range to be
2556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // drawn. Since ContextShadow expects a consistent transform, we have to undo the
2566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // translation before calling endShadowLayer as well.
2572bde8e466a4451c7319e3a072d118917957d6554Steve Block        cairo_t* context = graphicsContext->platformContext()->cr();
2586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        cairo_save(context);
2596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        cairo_translate(context, totalOffset.x(), totalOffset.y());
2606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        gdk_cairo_region(context, renderRegion);
2616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        cairo_clip(context);
2626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        cairo_translate(context, -totalOffset.x(), -totalOffset.y());
2636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
264cad810f21b803229eb11403f9209855525a25d57Steve Block        shadow->endShadowLayer(graphicsContext);
2656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        cairo_restore(context);
2666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
269a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
270ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{
2712bde8e466a4451c7319e3a072d118917957d6554Steve Block#if USE(FREETYPE)
272a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!primaryFont()->platformData().m_pattern) {
273a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        drawSimpleText(context, run, point, from, to);
274a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
275ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    }
276ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block#endif
277ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
2782bde8e466a4451c7319e3a072d118917957d6554Steve Block    cairo_t* cr = context->platformContext()->cr();
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PangoLayout* layout = pango_cairo_create_layout(cr);
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    setPangoAttributes(this, run, layout);
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_layout_set_text(layout, utf8, -1);
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Our layouts are single line
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0);
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Get the region where this text will be laid out. We will use it to clip
2896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // the Cairo context, for when we are only painting part of the text run and
2906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // to calculate the size of the shadow buffer.
2916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    PangoRegionType partialRegion = 0;
2926b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    char* start = g_utf8_offset_to_pointer(utf8, from);
2936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    char* end = g_utf8_offset_to_pointer(start, to - from);
2946b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    int ranges[] = {start - utf8, end - utf8};
2956b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1);
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2972bde8e466a4451c7319e3a072d118917957d6554Steve Block    drawGlyphsShadow(context, point, layoutLine, partialRegion);
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2996b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    cairo_save(cr);
3006b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    cairo_translate(cr, point.x(), point.y());
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3026b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    float red, green, blue, alpha;
3036b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    context->fillColor().getRGBA(red, green, blue, alpha);
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    cairo_set_source_rgba(cr, red, green, blue, alpha);
3056b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    gdk_cairo_region(cr, partialRegion);
3066b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    cairo_clip(cr);
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_cairo_show_layout_line(cr, layoutLine);
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
310f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (context->textDrawingMode() & TextModeStroke) {
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Color strokeColor = context->strokeColor();
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        strokeColor.getRGBA(red, green, blue, alpha);
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        cairo_set_source_rgba(cr, red, green, blue, alpha);
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pango_cairo_layout_line_path(cr, layoutLine);
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        cairo_set_line_width(cr, context->strokeThickness());
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        cairo_stroke(cr);
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Pango sometimes leaves behind paths we don't want
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    cairo_new_path(cr);
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    destroyPangoRegion(partialRegion);
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    g_free(utf8);
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    g_object_unref(layout);
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    cairo_restore(cr);
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
329f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
330f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
331f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    notImplemented();
332f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
333f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// We should create the layout with our actual context but we can't access it from here.
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic PangoLayout* getDefaultPangoLayout(const TextRun& run)
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static PangoFontMap* map = pango_cairo_font_map_get_default();
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if PANGO_VERSION_CHECK(1,21,5)
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static PangoContext* pangoContext = pango_font_map_create_context(map);
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Deprecated in Pango 1.21.
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static PangoContext* pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(map));
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PangoLayout* layout = pango_layout_new(pangoContext);
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return layout;
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
349a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochfloat Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* overflow) const
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3512bde8e466a4451c7319e3a072d118917957d6554Steve Block#if USE(FREETYPE)
352a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!primaryFont()->platformData().m_pattern)
353a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return floatWidthForSimpleText(run, 0, fallbackFonts, overflow);
354a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif
355a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (run.length() == 0)
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0.0f;
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PangoLayout* layout = getDefaultPangoLayout(run);
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    setPangoAttributes(this, run, layout);
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_layout_set_text(layout, utf8, -1);
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int width;
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_layout_get_pixel_size(layout, &width, 0);
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    g_free(utf8);
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    g_object_unref(layout);
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return width;
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
37406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenint Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3762bde8e466a4451c7319e3a072d118917957d6554Steve Block#if USE(FREETYPE)
377a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!primaryFont()->platformData().m_pattern)
378a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return offsetForPositionForSimpleText(run, xFloat, includePartialGlyphs);
379a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif
38006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
38106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
38206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    int x = static_cast<int>(xFloat);
38306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PangoLayout* layout = getDefaultPangoLayout(run);
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    setPangoAttributes(this, run, layout);
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_layout_set_text(layout, utf8, -1);
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int index, trailing;
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_layout_xy_to_index(layout, x * PANGO_SCALE, 1, &index, &trailing);
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    glong offset = g_utf8_pointer_to_offset(utf8, utf8 + index);
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (includePartialGlyphs)
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        offset += trailing;
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    g_free(utf8);
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    g_object_unref(layout);
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return offset;
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
40206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenFloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4042bde8e466a4451c7319e3a072d118917957d6554Steve Block#if USE(FREETYPE)
405a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!primaryFont()->platformData().m_pattern)
406a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return selectionRectForSimpleText(run, point, h, from, to);
407a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif
408a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PangoLayout* layout = getDefaultPangoLayout(run);
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    setPangoAttributes(this, run, layout);
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pango_layout_set_text(layout, utf8, -1);
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char* start = g_utf8_offset_to_pointer(utf8, from);
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char* end = g_utf8_offset_to_pointer(start, to - from);
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (run.ltr()) {
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        from = start - utf8;
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        to = end - utf8;
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        from = end - utf8;
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        to = start - utf8;
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0);
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int x_pos;
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    x_pos = 0;
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (from < layoutLine->length)
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pango_layout_line_index_to_x(layoutLine, from, FALSE, &x_pos);
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float beforeWidth = PANGO_PIXELS_FLOOR(x_pos);
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    x_pos = 0;
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (run.ltr() || to < layoutLine->length)
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pango_layout_line_index_to_x(layoutLine, to, FALSE, &x_pos);
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float afterWidth = PANGO_PIXELS(x_pos);
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    g_free(utf8);
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    g_object_unref(layout);
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return FloatRect(point.x() + beforeWidth, point.y(), afterWidth - beforeWidth, h);
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
446