1/* 2 * Copyright (C) 2007 Kevin Ollivier. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "Font.h" 28 29#include "FontFallbackList.h" 30#include "GlyphBuffer.h" 31#include "GraphicsContext.h" 32#include "IntRect.h" 33#include "NotImplemented.h" 34#include "SimpleFontData.h" 35#include "TextRun.h" 36 37#if OS(WINDOWS) 38#include "UniscribeController.h" 39typedef WebCore::UniscribeController ComplexTextController; 40#endif 41 42#if OS(DARWIN) 43#include "mac/ComplexTextController.h" 44#endif 45 46#include <wx/dcclient.h> 47#include "fontprops.h" 48#include "non-kerned-drawing.h" 49 50namespace WebCore { 51 52bool Font::canReturnFallbackFontsForComplexText() 53{ 54#if OS(WINDOWS) || OS(DARWIN) 55 return true; 56#else 57 return false; 58#endif 59} 60 61bool Font::canExpandAroundIdeographsInComplexText() 62{ 63#if OS(DARWIN) 64 return true; 65#else 66 return false; 67#endif 68} 69 70void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, 71 int from, int numGlyphs, const FloatPoint& point) const 72{ 73 // prepare DC 74 Color color = graphicsContext->fillColor(); 75 76 // We can't use wx drawing methods on Win/Linux because they automatically kern text 77 // so we've created a function with platform dependent drawing implementations that 78 // will hopefully be folded into wx once the API has solidified. 79 // see platform/wx/wxcode/<platform> for the implementations. 80 drawTextWithSpacing(graphicsContext, font, color, glyphBuffer, from, numGlyphs, point); 81} 82 83FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const 84{ 85#if OS(WINDOWS) || OS(DARWIN) 86 ComplexTextController it(this, run); 87 it.advance(from); 88 float beforeWidth = it.runWidthSoFar(); 89 it.advance(to); 90 float afterWidth = it.runWidthSoFar(); 91 92 // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning 93 if (run.rtl()) { 94#if OS(WINDOWS) 95 it.advance(run.length()); 96 float totalWidth = it.runWidthSoFar(); 97 return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); 98#else 99 float totalWidth = it.totalWidth(); 100 return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); 101#endif 102 } 103 104 return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h); 105#else 106 notImplemented(); 107 return FloatRect(); 108#endif 109} 110 111float Font::getGlyphsAndAdvancesForComplexText(const TextRun& /* run */, int /* from */, int /* to */, GlyphBuffer& /* glyphBuffer */, ForTextEmphasisOrNot /* forTextEmphasis */) const 112{ 113 // FIXME: Implement this by moving most of the drawComplexText() implementation in here. Set up the 114 // ComplexTextController according to forTextEmphasis. 115 notImplemented(); 116 return 0; 117} 118 119void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const 120{ 121#if OS(WINDOWS) || OS(DARWIN) 122 // This glyph buffer holds our glyphs + advances + font data for each glyph. 123 GlyphBuffer glyphBuffer; 124 125 float startX = point.x(); 126 ComplexTextController controller(this, run); 127 controller.advance(from); 128 float beforeWidth = controller.runWidthSoFar(); 129 controller.advance(to, &glyphBuffer); 130 131 // We couldn't generate any glyphs for the run. Give up. 132 if (glyphBuffer.isEmpty()) 133 return; 134 135 float afterWidth = controller.runWidthSoFar(); 136 137 if (run.rtl()) { 138#if OS(WINDOWS) 139 controller.advance(run.length()); 140 startX += controller.runWidthSoFar() - afterWidth; 141#else 142 startX += controller.totalWidth() - afterWidth; 143 for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end) 144 glyphBuffer.swap(i, end); 145#endif 146 } else 147 startX += beforeWidth; 148 149 // Draw the glyph buffer now at the starting point returned in startX. 150 FloatPoint startPoint(startX, point.y()); 151 drawGlyphBuffer(context, glyphBuffer, startPoint); 152#else 153 notImplemented(); 154#endif 155} 156 157void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const 158{ 159 GlyphBuffer glyphBuffer; 160 float initialAdvance = getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer, ForTextEmphasis); 161 162 if (glyphBuffer.isEmpty()) 163 return; 164 165 drawEmphasisMarks(context, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); 166} 167 168float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const 169{ 170#if OS(WINDOWS) || OS(DARWIN) 171 ComplexTextController controller(this, run, fallbackFonts); 172#if OS(WINDOWS) 173 controller.advance(run.length()); 174 return controller.runWidthSoFar(); 175#else 176 return controller.totalWidth(); 177#endif 178#else 179 notImplemented(); 180 return 0; 181#endif 182} 183 184int Font::offsetForPositionForComplexText(const TextRun& run, float x, bool includePartialGlyphs) const 185{ 186#if OS(WINDOWS) || OS(DARWIN) 187 ComplexTextController controller(this, run); 188 return controller.offsetForPosition(x, includePartialGlyphs); 189#else 190 notImplemented(); 191 return 0; 192#endif 193} 194} 195