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