18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Kevin Ollivier. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Font.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FontFallbackList.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GlyphBuffer.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "IntRect.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "NotImplemented.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SimpleFontData.h" 352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "TextRun.h" 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#if OS(WINDOWS) 388a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#include "UniscribeController.h" 395af96e2c7b73ebc627c6894727826a7576d31758Leon Clarketypedef WebCore::UniscribeController ComplexTextController; 4021939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif 4121939df44de1705786c545cd1bf519d47250322dBen Murdoch 4221939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(DARWIN) 4321939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "mac/ComplexTextController.h" 448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif 458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wx/dcclient.h> 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "fontprops.h" 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "non-kerned-drawing.h" 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool Font::canReturnFallbackFontsForComplexText() 535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 5421939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) || OS(DARWIN) 558a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return true; 568a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#else 575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return false; 588a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif 595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 612fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool Font::canExpandAroundIdeographsInComplexText() 622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#if OS(DARWIN) 642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return true; 652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#else 662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#endif 682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int from, int numGlyphs, const FloatPoint& point) const 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // prepare DC 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Color color = graphicsContext->fillColor(); 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We can't use wx drawing methods on Win/Linux because they automatically kern text 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // so we've created a function with platform dependent drawing implementations that 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // will hopefully be folded into wx once the API has solidified. 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // see platform/wx/wxcode/<platform> for the implementations. 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project drawTextWithSpacing(graphicsContext, font, color, glyphBuffer, from, numGlyphs, point); 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenFloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8521939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) || OS(DARWIN) 8621939df44de1705786c545cd1bf519d47250322dBen Murdoch ComplexTextController it(this, run); 878a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block it.advance(from); 888a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block float beforeWidth = it.runWidthSoFar(); 898a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block it.advance(to); 908a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block float afterWidth = it.runWidthSoFar(); 918a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 928a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning 938a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (run.rtl()) { 9421939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) 958a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block it.advance(run.length()); 968a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block float totalWidth = it.runWidthSoFar(); 978a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); 9821939df44de1705786c545cd1bf519d47250322dBen Murdoch#else 9921939df44de1705786c545cd1bf519d47250322dBen Murdoch float totalWidth = it.totalWidth(); 10021939df44de1705786c545cd1bf519d47250322dBen Murdoch return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); 10121939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif 1028a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block } 1038a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 1048a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h); 1058a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#else 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return FloatRect(); 1088a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 111f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochfloat Font::getGlyphsAndAdvancesForComplexText(const TextRun& /* run */, int /* from */, int /* to */, GlyphBuffer& /* glyphBuffer */, ForTextEmphasisOrNot /* forTextEmphasis */) const 112f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 113f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // FIXME: Implement this by moving most of the drawComplexText() implementation in here. Set up the 114f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // ComplexTextController according to forTextEmphasis. 115f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch notImplemented(); 116f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 118f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockvoid Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12121939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) || OS(DARWIN) 1228a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block // This glyph buffer holds our glyphs + advances + font data for each glyph. 1238a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block GlyphBuffer glyphBuffer; 1248a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 1258a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block float startX = point.x(); 12621939df44de1705786c545cd1bf519d47250322dBen Murdoch ComplexTextController controller(this, run); 1278a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block controller.advance(from); 1288a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block float beforeWidth = controller.runWidthSoFar(); 1298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block controller.advance(to, &glyphBuffer); 1308a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 1318a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block // We couldn't generate any glyphs for the run. Give up. 1328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (glyphBuffer.isEmpty()) 1338a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return; 1348a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 1358a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block float afterWidth = controller.runWidthSoFar(); 1368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 1378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (run.rtl()) { 13821939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) 1398a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block controller.advance(run.length()); 1408a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block startX += controller.runWidthSoFar() - afterWidth; 14121939df44de1705786c545cd1bf519d47250322dBen Murdoch#else 14281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch startX += controller.totalWidth() - afterWidth; 14321939df44de1705786c545cd1bf519d47250322dBen Murdoch for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end) 14421939df44de1705786c545cd1bf519d47250322dBen Murdoch glyphBuffer.swap(i, end); 14521939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif 1468a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block } else 1478a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block startX += beforeWidth; 1488a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 1498a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block // Draw the glyph buffer now at the starting point returned in startX. 1508a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block FloatPoint startPoint(startX, point.y()); 151f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch drawGlyphBuffer(context, glyphBuffer, startPoint); 1528a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#else 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 1548a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 157f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const 158f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 159f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphBuffer glyphBuffer; 160f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float initialAdvance = getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer, ForTextEmphasis); 161f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 162f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (glyphBuffer.isEmpty()) 163f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 164f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 165f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch drawEmphasisMarks(context, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); 166f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 1678a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 168dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfloat Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const 1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 17021939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) || OS(DARWIN) 17121939df44de1705786c545cd1bf519d47250322dBen Murdoch ComplexTextController controller(this, run, fallbackFonts); 1728a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#if OS(WINDOWS) 1738a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block controller.advance(run.length()); 1748a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return controller.runWidthSoFar(); 1758a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#else 17621939df44de1705786c545cd1bf519d47250322dBen Murdoch return controller.totalWidth(); 17721939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif 17821939df44de1705786c545cd1bf519d47250322dBen Murdoch#else 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 1818a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 18406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenint Font::offsetForPositionForComplexText(const TextRun& run, float x, bool includePartialGlyphs) const 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 18621939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) || OS(DARWIN) 18721939df44de1705786c545cd1bf519d47250322dBen Murdoch ComplexTextController controller(this, run); 1888a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return controller.offsetForPosition(x, includePartialGlyphs); 1898a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#else 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 1928a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 195