1635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project/* 2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved. 3635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 4635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Redistribution and use in source and binary forms, with or without 5635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * modification, are permitted provided that the following conditions are 6635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * met: 7635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 8635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * * Redistributions of source code must retain the above copyright 9635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * notice, this list of conditions and the following disclaimer. 10635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * * Redistributions in binary form must reproduce the above 11635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * copyright notice, this list of conditions and the following disclaimer 12635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * in the documentation and/or other materials provided with the 13635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * distribution. 14635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * * Neither the name of Google Inc. nor the names of its 15635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * contributors may be used to endorse or promote products derived from 16635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * this software without specific prior written permission. 17635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 18635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project */ 30635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 31635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "config.h" 32635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "UniscribeHelper.h" 33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "Font.h" 35635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "FontUtilsChromiumWin.h" 368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "PlatformContextSkia.h" 378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "SkiaFontWin.h" 388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "SkPoint.h" 392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include <windows.h> 40635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/Assertions.h> 41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 42635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectnamespace WebCore { 43635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 44635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// HFONT is the 'incarnation' of 'everything' about font, but it's an opaque 45635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// handle and we can't directly query it to make a new HFONT sharing 46635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// its characteristics (height, style, etc) except for family name. 47635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// This function uses GetObject to convert HFONT back to LOGFONT, 48635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// resets the fields of LOGFONT and calculates style to use later 49635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// for the creation of a font identical to HFONT other than family name. 50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void setLogFontAndStyle(HFONT hfont, LOGFONT *logfont, int *style) 51635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 52635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(hfont && logfont); 53635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!hfont || !logfont) 54635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return; 55635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 56635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project GetObject(hfont, sizeof(LOGFONT), logfont); 57635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // We reset these fields to values appropriate for CreateFontIndirect. 58635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // while keeping lfHeight, which is the most important value in creating 59635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // a new font similar to hfont. 60635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project logfont->lfWidth = 0; 61635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project logfont->lfEscapement = 0; 62635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project logfont->lfOrientation = 0; 63635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project logfont->lfCharSet = DEFAULT_CHARSET; 64635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project logfont->lfOutPrecision = OUT_TT_ONLY_PRECIS; 65635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project logfont->lfQuality = DEFAULT_QUALITY; // Honor user's desktop settings. 66635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project logfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; 67635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (style) 68635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *style = getStyleFromLogfont(logfont); 69635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 70635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 71635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectUniscribeHelper::UniscribeHelper(const UChar* input, 72635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int inputLength, 73635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bool isRtl, 74635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HFONT hfont, 75635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project SCRIPT_CACHE* scriptCache, 762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch SCRIPT_FONTPROPERTIES* fontProperties, 772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch WORD spaceGlyph) 78635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project : m_input(input) 79635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_inputLength(inputLength) 80635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_isRtl(isRtl) 81635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_hfont(hfont) 82635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_scriptCache(scriptCache) 83635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_fontProperties(fontProperties) 842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch , m_spaceGlyph(spaceGlyph) 85635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_directionalOverride(false) 86635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_inhibitLigate(false) 87635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_letterSpacing(0) 88635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_spaceWidth(0) 89635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_wordSpacing(0) 90635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_ascent(0) 918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian , m_disableFontFallback(false) 928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 93635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 94635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_logfont.lfFaceName[0] = 0; 95635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 96635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 97635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectUniscribeHelper::~UniscribeHelper() 98635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 99635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 100635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 101635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid UniscribeHelper::initWithOptionalLengthProtection(bool lengthProtection) 102635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 103635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // We cap the input length and just don't do anything. We'll allocate a lot 104635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // of things of the size of the number of characters, so the allocated 105635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // memory will be several times the input length. Plus shaping such a large 106635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // buffer may be a form of denial of service. No legitimate text should be 107635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // this long. It also appears that Uniscribe flatly rejects very long 108635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // strings, so we don't lose anything by doing this. 109635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // 110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The input length protection may be disabled by the unit tests to cause 111635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // an error condition. 112635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project static const int kMaxInputLength = 65535; 113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_inputLength == 0 || (lengthProtection && m_inputLength > kMaxInputLength)) 114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return; 115635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 116635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project fillRuns(); 117635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project fillShapes(); 118635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project fillScreenOrder(); 119635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 120635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 121635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectint UniscribeHelper::width() const 122635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 123635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int width = 0; 124635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int itemIndex = 0; itemIndex < static_cast<int>(m_runs.size()); itemIndex++) 125635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project width += advanceForItem(itemIndex); 126635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return width; 127635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 128635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 129635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid UniscribeHelper::justify(int additionalSpace) 130635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 131635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Count the total number of glyphs we have so we know how big to make the 132635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // buffers below. 133635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int totalGlyphs = 0; 134635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t run = 0; run < m_runs.size(); run++) { 135635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int runIndex = m_screenOrder[run]; 136635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project totalGlyphs += static_cast<int>(m_shapes[runIndex].glyphLength()); 137635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 138635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (totalGlyphs == 0) 139635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return; // Nothing to do. 140635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 141635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // We make one big buffer in screen order of all the glyphs we are drawing 142635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // across runs so that the justification function will adjust evenly across 143635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // all glyphs. 144635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Vector<SCRIPT_VISATTR, 64> visualAttributes; 145635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project visualAttributes.resize(totalGlyphs); 146635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Vector<int, 64> advances; 147635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project advances.resize(totalGlyphs); 148635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Vector<int, 64> justify; 149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project justify.resize(totalGlyphs); 150635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 151635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Build the packed input. 152635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int destIndex = 0; 153635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t run = 0; run < m_runs.size(); run++) { 154635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int runIndex = m_screenOrder[run]; 155635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const Shaping& shaping = m_shapes[runIndex]; 156635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 157635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int i = 0; i < shaping.glyphLength(); i++, destIndex++) { 158635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project memcpy(&visualAttributes[destIndex], &shaping.m_visualAttributes[i], 159635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project sizeof(SCRIPT_VISATTR)); 160635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project advances[destIndex] = shaping.m_advance[i]; 161635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 162635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 163635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 164635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The documentation for Scriptjustify is wrong, the parameter is the space 165635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // to add and not the width of the column you want. 166635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const int minKashida = 1; // How do we decide what this should be? 167635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ScriptJustify(&visualAttributes[0], &advances[0], totalGlyphs, 168635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project additionalSpace, minKashida, &justify[0]); 169635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 170635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Now we have to unpack the justification amounts back into the runs so 171635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // the glyph indices match. 172635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int globalGlyphIndex = 0; 173635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t run = 0; run < m_runs.size(); run++) { 174635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int runIndex = m_screenOrder[run]; 175635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Shaping& shaping = m_shapes[runIndex]; 176635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 177635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_justify.resize(shaping.glyphLength()); 178635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int i = 0; i < shaping.glyphLength(); i++, globalGlyphIndex++) 179635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_justify[i] = justify[globalGlyphIndex]; 180635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 181635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 182635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 183635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectint UniscribeHelper::characterToX(int offset) const 184635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 185635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HRESULT hr; 186635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(offset <= m_inputLength); 187635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 188635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Our algorithm is to traverse the items in screen order from left to 189635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // right, adding in each item's screen width until we find the item with 190635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // the requested character in it. 191635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int width = 0; 192635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) { 193635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Compute the length of this run. 194635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int itemIndex = m_screenOrder[screenIndex]; 195635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const SCRIPT_ITEM& item = m_runs[itemIndex]; 196635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const Shaping& shaping = m_shapes[itemIndex]; 197635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int itemLength = shaping.charLength(); 198635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 199635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (offset >= item.iCharPos && offset <= item.iCharPos + itemLength) { 200635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Character offset is in this run. 201635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int charLength = offset - item.iCharPos; 202635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 203635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int curX = 0; 204635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project hr = ScriptCPtoX(charLength, FALSE, itemLength, 205635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.glyphLength(), 206635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project &shaping.m_logs[0], &shaping.m_visualAttributes[0], 207635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.effectiveAdvances(), &item.a, &curX); 208635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (FAILED(hr)) 209635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 210635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 211635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project width += curX + shaping.m_prePadding; 212635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(width >= 0); 213635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return width; 214635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 215635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 216635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Move to the next item. 217635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project width += advanceForItem(itemIndex); 218635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 219635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(width >= 0); 220635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return width; 221635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 222635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 223635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectint UniscribeHelper::xToCharacter(int x) const 224635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 225635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // We iterate in screen order until we find the item with the given pixel 226635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // position in it. When we find that guy, we ask Uniscribe for the 227635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // character index. 228635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HRESULT hr; 229635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) { 230635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int itemIndex = m_screenOrder[screenIndex]; 231635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int itemAdvance = advanceForItem(itemIndex); 232635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 233635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Note that the run may be empty if shaping failed, so we want to skip 234635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // over it. 235635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const Shaping& shaping = m_shapes[itemIndex]; 236635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int itemLength = shaping.charLength(); 237635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (x <= itemAdvance && itemLength > 0) { 238635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The requested offset is within this item. 239635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const SCRIPT_ITEM& item = m_runs[itemIndex]; 240635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 241635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Account for the leading space we've added to this run that 242635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Uniscribe doesn't know about. 243635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project x -= shaping.m_prePadding; 244635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 245635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int charX = 0; 246635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int trailing; 247635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project hr = ScriptXtoCP(x, itemLength, shaping.glyphLength(), 248635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project &shaping.m_logs[0], &shaping.m_visualAttributes[0], 249635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.effectiveAdvances(), &item.a, &charX, 250635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project &trailing); 251635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 252635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The character offset is within the item. We need to add the 253635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // item's offset to transform it into the space of the TextRun 254635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return charX + item.iCharPos; 255635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 256635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 257635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The offset is beyond this item, account for its length and move on. 258635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project x -= itemAdvance; 259635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 260635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 261635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Error condition, we don't know what to do if we don't have that X 262635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // position in any of our items. 263635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 264635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 265635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid UniscribeHelper::draw(GraphicsContext* graphicsContext, 2678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian HDC dc, int x, int y, int from, int to) 268635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 269635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HGDIOBJ oldFont = 0; 270635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int curX = x; 271635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bool firstRun = true; 2728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian bool useWindowsDrawing = windowsCanHandleTextDrawing(graphicsContext); 273635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 274635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) { 275635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int itemIndex = m_screenOrder[screenIndex]; 276635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const SCRIPT_ITEM& item = m_runs[itemIndex]; 277635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const Shaping& shaping = m_shapes[itemIndex]; 278635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 279635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Character offsets within this run. THESE MAY NOT BE IN RANGE and may 280635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // be negative, etc. The code below handles this. 281635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int fromChar = from - item.iCharPos; 282635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int toChar = to - item.iCharPos; 283635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 284635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // See if we need to draw any characters in this item. 285635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (shaping.charLength() == 0 || 286635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project fromChar >= shaping.charLength() || toChar <= 0) { 287635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // No chars in this item to display. 288635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project curX += advanceForItem(itemIndex); 289635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project continue; 290635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 291635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 292635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Compute the starting glyph within this span. |from| and |to| are 293635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // global offsets that may intersect arbitrarily with our local run. 294635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int fromGlyph, afterGlyph; 295635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (item.a.fRTL) { 296635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // To compute the first glyph when going RTL, we use |to|. 297635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (toChar >= shaping.charLength()) 298635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The end of the text is after (to the left) of us. 299635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project fromGlyph = 0; 300635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project else { 301635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Since |to| is exclusive, the first character we draw on the 302635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // left is actually the one right before (to the right) of 303635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // |to|. 304635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project fromGlyph = shaping.m_logs[toChar - 1]; 305635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 306635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 307635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The last glyph is actually the first character in the range. 308635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (fromChar <= 0) { 309635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The first character to draw is before (to the right) of this 310635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // span, so draw all the way to the end. 311635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project afterGlyph = shaping.glyphLength(); 312635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 313635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // We want to draw everything up until the character to the 314635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // right of |from|. To the right is - 1, so we look that up 315635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // (remember our character could be more than one glyph, so we 316635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // can't look up our glyph and add one). 317635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project afterGlyph = shaping.m_logs[fromChar - 1]; 318635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 319635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 320635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Easy case, everybody agrees about directions. We only need to 321635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // handle boundary conditions to get a range inclusive at the 322635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // beginning, and exclusive at the ending. We have to do some 323635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // computation to see the glyph one past the end. 324635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project fromGlyph = shaping.m_logs[fromChar < 0 ? 0 : fromChar]; 325635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (toChar >= shaping.charLength()) 326635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project afterGlyph = shaping.glyphLength(); 327635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project else 328635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project afterGlyph = shaping.m_logs[toChar]; 329635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 330635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 331635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Account for the characters that were skipped in this run. When 332635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // WebKit asks us to draw a subset of the run, it actually tells us 333635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // to draw at the X offset of the beginning of the run, since it 334635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // doesn't know the internal position of any of our characters. 335635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const int* effectiveAdvances = shaping.effectiveAdvances(); 336635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int innerOffset = 0; 337635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int i = 0; i < fromGlyph; i++) 338635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project innerOffset += effectiveAdvances[i]; 339635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 340635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Actually draw the glyphs we found. 341635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int glyphCount = afterGlyph - fromGlyph; 342635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (fromGlyph >= 0 && glyphCount > 0) { 3438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Account for the preceding space we need to add to this run. We 344635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // don't need to count for the following space because that will be 345635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // counted in advanceForItem below when we move to the next run. 346635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project innerOffset += shaping.m_prePadding; 347635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 348635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Pass 0 in when there is no justification. 349635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const int* justify = shaping.m_justify.size() == 0 ? 0 : &shaping.m_justify[fromGlyph]; 350635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 351231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (useWindowsDrawing) { 352231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (firstRun) { 353231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block oldFont = SelectObject(dc, shaping.m_hfont); 354231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block firstRun = false; 355231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } else 356231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block SelectObject(dc, shaping.m_hfont); 357231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 358635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 359635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Fonts with different ascents can be used to render different 360635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // runs. 'Across-runs' y-coordinate correction needs to be 361635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // adjusted for each font. 3628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian bool textOutOk = false; 363635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int executions = 0; executions < 2; ++executions) { 3648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (useWindowsDrawing) { 3658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian HRESULT hr = ScriptTextOut(dc, shaping.m_scriptCache, 3668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian curX + innerOffset, 3678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian y - shaping.m_ascentOffset, 3688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 0, 0, &item.a, 0, 0, 3698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian &shaping.m_glyphs[fromGlyph], 3708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian glyphCount, 3718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian &shaping.m_advance[fromGlyph], 3728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian justify, 3738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian &shaping.m_offsets[fromGlyph]); 3748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian textOutOk = (hr == S_OK); 3758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else { 3768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian SkPoint origin; 3778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian origin.fX = curX + + innerOffset; 378231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block origin.fY = y + m_ascent; 3798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian textOutOk = paintSkiaText(graphicsContext, 3808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian shaping.m_hfont, 3818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian glyphCount, 3828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian &shaping.m_glyphs[fromGlyph], 3838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian &shaping.m_advance[fromGlyph], 3848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian &shaping.m_offsets[fromGlyph], 3858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian &origin); 3868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 3878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!textOutOk && 0 == executions) { 3898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // If TextOut is called from the renderer it might fail 3908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // because the sandbox is preventing it from opening the 3918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // font files. If we are running in the renderer, 3928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // TryToPreloadFont is overridden to ask the browser to 3938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // preload the font for us so we can access it. 394635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project tryToPreloadFont(shaping.m_hfont); 395635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project continue; 396635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 397635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 398635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 399635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 400635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 401635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project curX += advanceForItem(itemIndex); 402635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 403635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 404635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (oldFont) 405635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project SelectObject(dc, oldFont); 406635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 407635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 408635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectWORD UniscribeHelper::firstGlyphForCharacter(int charOffset) const 409635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 410635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Find the run for the given character. 411635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int i = 0; i < static_cast<int>(m_runs.size()); i++) { 412635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int firstChar = m_runs[i].iCharPos; 413635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const Shaping& shaping = m_shapes[i]; 414635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int localOffset = charOffset - firstChar; 415635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (localOffset >= 0 && localOffset < shaping.charLength()) { 416635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The character is in this run, return the first glyph for it 417635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // (should generally be the only glyph). It seems Uniscribe gives 418635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // glyph 0 for empty, which is what we want to return in the 419635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // "missing" case. 420635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t glyphIndex = shaping.m_logs[localOffset]; 421635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (glyphIndex >= shaping.m_glyphs.size()) { 422635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The glyph should be in this run, but the run has too few 423635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // actual characters. This can happen when shaping the run 424635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // fails, in which case, we should have no data in the logs at 425635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // all. 426635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(shaping.m_glyphs.size() == 0); 427635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 428635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 429635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return shaping.m_glyphs[glyphIndex]; 430635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 431635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 432635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 433635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 434635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 435635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 436635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid UniscribeHelper::fillRuns() 437635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 438635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HRESULT hr; 439635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_runs.resize(UNISCRIBE_HELPER_STACK_RUNS); 440635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 441635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project SCRIPT_STATE inputState; 442635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project inputState.uBidiLevel = m_isRtl; 443635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project inputState.fOverrideDirection = m_directionalOverride; 444635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project inputState.fInhibitSymSwap = false; 445635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project inputState.fCharShape = false; // Not implemented in Uniscribe 446635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project inputState.fDigitSubstitute = false; // Do we want this for Arabic? 447635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project inputState.fInhibitLigate = m_inhibitLigate; 448635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project inputState.fDisplayZWG = false; // Don't draw control characters. 449635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project inputState.fArabicNumContext = m_isRtl; // Do we want this for Arabic? 450635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project inputState.fGcpClusters = false; 451635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project inputState.fReserved = 0; 452635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project inputState.fEngineReserved = 0; 453635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The psControl argument to ScriptItemize should be non-0 for RTL text, 454635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // per http://msdn.microsoft.com/en-us/library/ms776532.aspx . So use a 455635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // SCRIPT_CONTROL that is set to all zeros. Zero as a locale ID means the 456635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // neutral locale per http://msdn.microsoft.com/en-us/library/ms776294.aspx 457635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project static SCRIPT_CONTROL inputControl = {0, // uDefaultLanguage :16; 458635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 0, // fContextDigits :1; 459635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 0, // fInvertPreBoundDir :1; 460635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 0, // fInvertPostBoundDir :1; 461635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 0, // fLinkStringBefore :1; 462635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 0, // fLinkStringAfter :1; 463635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 0, // fNeutralOverride :1; 464635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 0, // fNumericOverride :1; 465635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 0, // fLegacyBidiClass :1; 466635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 0, // fMergeNeutralItems :1; 467635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 0};// fReserved :7; 468635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Calling ScriptApplyDigitSubstitution( 0, &inputControl, &inputState) 469635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // here would be appropriate if we wanted to set the language ID, and get 470635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // local digit substitution behavior. For now, don't do it. 471635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 472635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (true) { 473635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int numberOfItems = 0; 474635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 475635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Ideally, we would have a way to know the runs before and after this 476635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // one, and put them into the control parameter of ScriptItemize. This 477635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // would allow us to shape characters properly that cross style 478635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // boundaries (WebKit bug 6148). 479635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // 480635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // We tell ScriptItemize that the output list of items is one smaller 481635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // than it actually is. According to Mozilla bug 366643, if there is 482635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // not enough room in the array on pre-SP2 systems, ScriptItemize will 483635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // write one past the end of the buffer. 484635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // 485635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // ScriptItemize is very strange. It will often require a much larger 486635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // ITEM buffer internally than it will give us as output. For example, 487635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // it will say a 16-item buffer is not big enough, and will write 488635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // interesting numbers into all those items. But when we give it a 32 489635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // item buffer and it succeeds, it only has one item output. 490635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // 491635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // It seems to be doing at least two passes, the first where it puts a 492635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // lot of intermediate data into our items, and the second where it 493635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // collates them. 494635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project hr = ScriptItemize(m_input, m_inputLength, 495635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project static_cast<int>(m_runs.size()) - 1, &inputControl, 496635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project &inputState, 497635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project &m_runs[0], &numberOfItems); 498635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (SUCCEEDED(hr)) { 499635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_runs.resize(numberOfItems); 500635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 501635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 502635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (hr != E_OUTOFMEMORY) { 503635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Some kind of unexpected error. 504635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_runs.resize(0); 505635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 506635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 507635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // There was not enough items for it to write into, expand. 508635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_runs.resize(m_runs.size() * 2); 509635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 510635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 511635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 512635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectbool UniscribeHelper::shape(const UChar* input, 513635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int itemLength, 514635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int numGlyphs, 515635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project SCRIPT_ITEM& run, 516635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Shaping& shaping) 517635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 518635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HFONT hfont = m_hfont; 519635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project SCRIPT_CACHE* scriptCache = m_scriptCache; 520635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project SCRIPT_FONTPROPERTIES* fontProperties = m_fontProperties; 521635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int ascent = m_ascent; 5222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch WORD spaceGlyph = m_spaceGlyph; 523635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HDC tempDC = 0; 524635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HGDIOBJ oldFont = 0; 525635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HRESULT hr; 5268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // When used to fill up glyph pages for simple scripts in non-BMP, 5278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // we don't want any font fallback in this class. The simple script 5288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // font path can take care of font fallback. 5298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian bool lastFallbackTried = m_disableFontFallback; 530635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bool result; 531635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 532635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int generatedGlyphs = 0; 533635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 534635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // In case HFONT passed in ctor cannot render this run, we have to scan 535635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // other fonts from the beginning of the font list. 536635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resetFontIndex(); 537635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 538635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Compute shapes. 539635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (true) { 540635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_logs.resize(itemLength); 541635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_glyphs.resize(numGlyphs); 542635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_visualAttributes.resize(numGlyphs); 543635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 544635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifdef PURIFY 545635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // http://code.google.com/p/chromium/issues/detail?id=5309 546635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Purify isn't able to track the assignments that ScriptShape makes to 547635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // shaping.m_glyphs. Consequently, any bytes with value 0xCD that it 548635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // writes, will be considered un-initialized data. 549635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // 550635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // This hack avoid the false-positive UMRs by marking the buffer as 551635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // initialized. 552635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // 553635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: A better solution would be to use Purify's API and mark only 554635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // the populated range as initialized: 555635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // 556635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // PurifyMarkAsInitialized( 557635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // &shaping.m_glyphs[0], 558635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // sizeof(shaping.m_glyphs[0] * generatedGlyphs); 5598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 560635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ZeroMemory(&shaping.m_glyphs[0], 561635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project sizeof(shaping.m_glyphs[0]) * shaping.m_glyphs.size()); 562635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 563635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 564635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Firefox sets SCRIPT_ANALYSIS.SCRIPT_STATE.fDisplayZWG to true 565635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // here. Is that what we want? It will display control characters. 566635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project hr = ScriptShape(tempDC, scriptCache, input, itemLength, 567635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project numGlyphs, &run.a, 568635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project &shaping.m_glyphs[0], &shaping.m_logs[0], 569635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project &shaping.m_visualAttributes[0], &generatedGlyphs); 570635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (hr == E_PENDING) { 571635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Allocate the DC. 572635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project tempDC = GetDC(0); 573635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project oldFont = SelectObject(tempDC, hfont); 574635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project continue; 575635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else if (hr == E_OUTOFMEMORY) { 576635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project numGlyphs *= 2; 577635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project continue; 5782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } else if (SUCCEEDED(hr) && (lastFallbackTried || !containsMissingGlyphs(shaping, run, fontProperties))) 579635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 580635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 581635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The current font can't render this run. clear DC and try 582635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // next font. 583635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (tempDC) { 584635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project SelectObject(tempDC, oldFont); 585635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ReleaseDC(0, tempDC); 586635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project tempDC = 0; 587635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 588635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 5898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!m_disableFontFallback && 5908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian nextWinFontData(&hfont, &scriptCache, &fontProperties, &ascent)) { 591635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The primary font does not support this run. Try next font. 592635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // In case of web page rendering, they come from fonts specified in 593635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // CSS stylesheets. 594635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project continue; 595635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else if (!lastFallbackTried) { 596635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project lastFallbackTried = true; 597635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 598635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Generate a last fallback font based on the script of 599635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // a character to draw while inheriting size and styles 600635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // from the primary font 601635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!m_logfont.lfFaceName[0]) 602635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project setLogFontAndStyle(m_hfont, &m_logfont, &m_style); 603635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 604635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // TODO(jungshik): generic type should come from webkit for 605635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // UniscribeHelperTextRun (a derived class used in webkit). 606635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const UChar *family = getFallbackFamily(input, itemLength, 607635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FontDescription::StandardFamily, 0, 0); 608635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bool fontOk = getDerivedFontData(family, m_style, &m_logfont, 6092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch &ascent, &hfont, &scriptCache, 6102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch &spaceGlyph); 6112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 612635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 613635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!fontOk) { 614635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // If this GetDerivedFontData is called from the renderer it 615635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // might fail because the sandbox is preventing it from opening 616635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // the font files. If we are running in the renderer, 617635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // TryToPreloadFont is overridden to ask the browser to preload 618635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // the font for us so we can access it. 619635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project tryToPreloadFont(hfont); 620635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 621635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Try again. 622635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project fontOk = getDerivedFontData(family, m_style, &m_logfont, 6232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch &ascent, &hfont, &scriptCache, 6242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch &spaceGlyph); 625635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(fontOk); 626635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 627635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 628635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // TODO(jungshik) : Currently GetDerivedHFont always returns a 629635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // a valid HFONT, but in the future, I may change it to return 0. 630635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(hfont); 631635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 632635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // We don't need a font_properties for the last resort fallback font 633635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // because we don't have anything more to try and are forced to 634635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // accept empty glyph boxes. If we tried a series of fonts as 635635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // 'last-resort fallback', we'd need it, but currently, we don't. 636635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project continue; 637635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) { 638635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project run.a.eScript = SCRIPT_UNDEFINED; 639635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project continue; 640635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else if (FAILED(hr)) { 641635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Error shaping. 642635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project generatedGlyphs = 0; 643635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project result = false; 644635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project goto cleanup; 645635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 646635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 647635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 648635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Sets Windows font data for this run to those corresponding to 649635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // a font supporting this run. we don't need to store font_properties 650635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // because it's not used elsewhere. 651635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_hfont = hfont; 652635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_scriptCache = scriptCache; 6532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch shaping.m_spaceGlyph = spaceGlyph; 654635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 655635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The ascent of a font for this run can be different from 656635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // that of the primary font so that we need to keep track of 657635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // the difference per run and take that into account when calling 658635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // ScriptTextOut in |draw|. Otherwise, different runs rendered by 659635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // different fonts would not be aligned vertically. 660635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_ascentOffset = m_ascent ? ascent - m_ascent : 0; 661635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project result = true; 662635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 663635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cleanup: 664635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_glyphs.resize(generatedGlyphs); 665635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_visualAttributes.resize(generatedGlyphs); 666635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_advance.resize(generatedGlyphs); 667635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_offsets.resize(generatedGlyphs); 668635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (tempDC) { 669635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project SelectObject(tempDC, oldFont); 670635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ReleaseDC(0, tempDC); 671635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 672635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // On failure, our logs don't mean anything, so zero those out. 673635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!result) 674635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_logs.clear(); 675635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 676635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return result; 677635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 678635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 679635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid UniscribeHelper::fillShapes() 680635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 681635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_shapes.resize(m_runs.size()); 682635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t i = 0; i < m_runs.size(); i++) { 683635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int startItem = m_runs[i].iCharPos; 684635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int itemLength = m_inputLength - startItem; 685635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (i < m_runs.size() - 1) 686635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project itemLength = m_runs[i + 1].iCharPos - startItem; 687635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 688635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int numGlyphs; 689635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (itemLength < UNISCRIBE_HELPER_STACK_CHARS) { 690635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // We'll start our buffer sizes with the current stack space 691635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // available in our buffers if the current input fits. As long as 692635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // it doesn't expand past that we'll save a lot of time mallocing. 693635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project numGlyphs = UNISCRIBE_HELPER_STACK_CHARS; 694635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 695635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // When the input doesn't fit, give up with the stack since it will 696635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // almost surely not be enough room (unless the input actually 697635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // shrinks, which is unlikely) and just start with the length 698635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // recommended by the Uniscribe documentation as a "usually fits" 699635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // size. 700635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project numGlyphs = itemLength * 3 / 2 + 16; 701635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 702635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 703635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Convert a string to a glyph string trying the primary font, fonts in 704635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // the fallback list and then script-specific last resort font. 705635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Shaping& shaping = m_shapes[i]; 706635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!shape(&m_input[startItem], itemLength, numGlyphs, m_runs[i], shaping)) 707635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project continue; 708635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 7098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // At the moment, the only time m_disableFontFallback is set is 7108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // when we look up glyph indices for non-BMP code ranges. So, 7118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // we can skip the glyph placement. When that becomes not the case 7128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // any more, we have to add a new flag to control glyph placement. 7138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (m_disableFontFallback) 7148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian continue; 7158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 716635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Compute placements. Note that offsets is documented incorrectly 717635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // and is actually an array. 718635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 719635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // DC that we lazily create if Uniscribe commands us to. 720635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // (this does not happen often because scriptCache is already 721635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // updated when calling ScriptShape). 722635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HDC tempDC = 0; 723635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HGDIOBJ oldFont = 0; 724635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HRESULT hr; 725635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (true) { 726635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_prePadding = 0; 727635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project hr = ScriptPlace(tempDC, shaping.m_scriptCache, 728635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project &shaping.m_glyphs[0], 729635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project static_cast<int>(shaping.m_glyphs.size()), 730635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project &shaping.m_visualAttributes[0], &m_runs[i].a, 731635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project &shaping.m_advance[0], &shaping.m_offsets[0], 732635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project &shaping.m_abc); 733635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (hr != E_PENDING) 734635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 735635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 736635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Allocate the DC and run the loop again. 737635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project tempDC = GetDC(0); 738635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project oldFont = SelectObject(tempDC, shaping.m_hfont); 739635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 740635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 741635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (FAILED(hr)) { 742635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Some error we don't know how to handle. Nuke all of our data 743635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // since we can't deal with partially valid data later. 744635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_runs.clear(); 745635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_shapes.clear(); 746635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_screenOrder.clear(); 747635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 748635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 749635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (tempDC) { 750635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project SelectObject(tempDC, oldFont); 751635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ReleaseDC(0, tempDC); 752635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 753635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 754635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 755635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project adjustSpaceAdvances(); 756635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 757635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_letterSpacing != 0 || m_wordSpacing != 0) 758635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project applySpacing(); 759635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 760635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 761635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid UniscribeHelper::fillScreenOrder() 762635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 763635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_screenOrder.resize(m_runs.size()); 764635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 765635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // We assume that the input has only one text direction in it. 766635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // TODO(brettw) are we sure we want to keep this restriction? 767635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_isRtl) { 768635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int i = 0; i < static_cast<int>(m_screenOrder.size()); i++) 769635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_screenOrder[static_cast<int>(m_screenOrder.size()) - i - 1] = i; 770635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 771635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int i = 0; i < static_cast<int>(m_screenOrder.size()); i++) 772635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_screenOrder[i] = i; 773635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 774635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 775635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 776635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid UniscribeHelper::adjustSpaceAdvances() 777635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 778635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_spaceWidth == 0) 779635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return; 780635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 781635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int spaceWidthWithoutLetterSpacing = m_spaceWidth - m_letterSpacing; 782635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 783635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // This mostly matches what WebKit's UniscribeController::shapeAndPlaceItem. 784635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t run = 0; run < m_runs.size(); run++) { 785635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Shaping& shaping = m_shapes[run]; 786635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 7872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // FIXME: This loop is not UTF-16-safe. Unicode 6.0 has a couple 7882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // of complex script blocks in Plane 1. 789635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int i = 0; i < shaping.charLength(); i++) { 7902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch UChar c = m_input[m_runs[run].iCharPos + i]; 7912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch bool treatAsSpace = Font::treatAsSpace(c); 7922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!treatAsSpace && !Font::treatAsZeroWidthSpaceInComplexScript(c)) 793635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project continue; 794635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 795635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int glyphIndex = shaping.m_logs[i]; 796635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int currentAdvance = shaping.m_advance[glyphIndex]; 797635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 7982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (treatAsSpace) { 7992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // currentAdvance does not include additional letter-spacing, 8002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // but m_spaceWidth does. Here we find out how off we are from 8012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // the correct width (spaceWidthWithoutLetterSpacing) and 8022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // just subtract that diff. 8032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch int diff = currentAdvance - spaceWidthWithoutLetterSpacing; 8042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // The shaping can consist of a run of text, so only subtract 8052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // the difference in the width of the glyph. 8062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch shaping.m_advance[glyphIndex] -= diff; 8072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch shaping.m_abc.abcB -= diff; 8082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch continue; 8092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 8102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 8112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // For characters treated as zero-width space in complex 8122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // scripts, set the advance width to zero, adjust 8132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // |abcB| of the current run accordingly and set 8142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // the glyph to m_spaceGlyph (invisible). 8152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch shaping.m_advance[glyphIndex] = 0; 8162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch shaping.m_abc.abcB -= currentAdvance; 8172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch shaping.m_offsets[glyphIndex].du = 0; 8182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch shaping.m_offsets[glyphIndex].dv = 0; 8192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch shaping.m_glyphs[glyphIndex] = shaping.m_spaceGlyph; 820635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 821635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 822635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 823635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 824635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid UniscribeHelper::applySpacing() 825635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 826635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t run = 0; run < m_runs.size(); run++) { 827635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Shaping& shaping = m_shapes[run]; 828635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bool isRtl = m_runs[run].a.fRTL; 829635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 830635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_letterSpacing != 0) { 831635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // RTL text gets padded to the left of each character. We increment 832635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // the run's advance to make this happen. This will be balanced out 833635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // by NOT adding additional advance to the last glyph in the run. 834635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (isRtl) 835635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_prePadding += m_letterSpacing; 836635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 837635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Go through all the glyphs in this run and increase the "advance" 838635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // to account for letter spacing. We adjust letter spacing only on 839635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // cluster boundaries. 840635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // 841635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // This works for most scripts, but may have problems with some 842635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // indic scripts. This behavior is better than Firefox or IE for 843635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Hebrew. 844635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int i = 0; i < shaping.glyphLength(); i++) { 845635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (shaping.m_visualAttributes[i].fClusterStart) { 846635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Ick, we need to assign the extra space so that the glyph 847635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // comes first, then is followed by the space. This is 848635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // opposite for RTL. 849635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (isRtl) { 850635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (i != shaping.glyphLength() - 1) { 851635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // All but the last character just get the spacing 852635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // applied to their advance. The last character 853635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // doesn't get anything, 854635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_advance[i] += m_letterSpacing; 855635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_abc.abcB += m_letterSpacing; 856635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 857635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 858635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // LTR case is easier, we just add to the advance. 859635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_advance[i] += m_letterSpacing; 860635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_abc.abcB += m_letterSpacing; 861635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 862635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 863635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 864635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 865635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 866635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Go through all the characters to find whitespace and insert the 867635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // extra wordspacing amount for the glyphs they correspond to. 868635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_wordSpacing != 0) { 869635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int i = 0; i < shaping.charLength(); i++) { 8702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!Font::treatAsSpace(m_input[m_runs[run].iCharPos + i])) 871635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project continue; 872635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 873635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The char in question is a word separator... 874635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int glyphIndex = shaping.m_logs[i]; 875635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 876635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Spaces will not have a glyph in Uniscribe, it will just add 877635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // additional advance to the character to the left of the 878635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // space. The space's corresponding glyph will be the character 879635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // following it in reading order. 880635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (isRtl) { 881635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // In RTL, the glyph to the left of the space is the same 882635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // as the first glyph of the following character, so we can 883635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // just increment it. 884635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_advance[glyphIndex] += m_wordSpacing; 885635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_abc.abcB += m_wordSpacing; 886635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 887635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // LTR is actually more complex here, we apply it to the 888635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // previous character if there is one, otherwise we have to 889635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // apply it to the leading space of the run. 890635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (glyphIndex == 0) 891635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_prePadding += m_wordSpacing; 892635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project else { 893635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_advance[glyphIndex - 1] += m_wordSpacing; 894635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_abc.abcB += m_wordSpacing; 895635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 896635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 897635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 898635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } // m_wordSpacing != 0 899635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 900635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Loop for next run... 901635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 902635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 903635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 904635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// The advance is the ABC width of the run 905635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectint UniscribeHelper::advanceForItem(int itemIndex) const 906635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 907635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int accum = 0; 908635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const Shaping& shaping = m_shapes[itemIndex]; 909635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 910635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (shaping.m_justify.size() == 0) { 911635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Easy case with no justification, the width is just the ABC width of 912635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // the run. (The ABC width is the sum of the advances). 913635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return shaping.m_abc.abcA + shaping.m_abc.abcB + 914635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shaping.m_abc.abcC + shaping.m_prePadding; 915635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 916635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 917635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // With justification, we use the justified amounts instead. The 918635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // justification array contains both the advance and the extra space 919635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // added for justification, so is the width we want. 920635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int justification = 0; 921635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t i = 0; i < shaping.m_justify.size(); i++) 922635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project justification += shaping.m_justify[i]; 923635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 924635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return shaping.m_prePadding + justification; 925635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 926635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 9272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// SCRIPT_FONTPROPERTIES contains glyph indices for default, invalid 9282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// and blank glyphs. Just because ScriptShape succeeds does not mean 9292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// that a text run is rendered correctly. Some characters may be rendered 9302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// with default/invalid/blank glyphs. Therefore, we need to check if the glyph 9312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// array returned by ScriptShape contains any of those glyphs to make 9322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// sure that the text run is rendered successfully. 9332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// However, we should not subject zero-width characters to this test. 9342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 9352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool UniscribeHelper::containsMissingGlyphs(const Shaping& shaping, 9362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch const SCRIPT_ITEM& run, 9372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch const SCRIPT_FONTPROPERTIES* properties) const 9382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 9392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch for (int i = 0; i < shaping.charLength(); i++) { 9402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch UChar c = m_input[run.iCharPos + i]; 9412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // Skip zero-width space characters because they're not considered to be missing in a font. 9422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (Font::treatAsZeroWidthSpaceInComplexScript(c)) 9432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch continue; 9442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch int glyphIndex = shaping.m_logs[i]; 9452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch WORD glyph = shaping.m_glyphs[glyphIndex]; 9462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (glyph == properties->wgDefault 9472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch || (glyph == properties->wgInvalid && glyph != properties->wgBlank)) 9482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return true; 9492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 9502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return false; 9512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 9522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 9532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 954635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} // namespace WebCore 955