gfx/thebes/gfxScriptItemizer.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * This file is based on usc_impl.c from ICU 4.2.0.1, slightly adapted
michael@0 8 * for use within Mozilla Gecko, separate from a standard ICU build.
michael@0 9 *
michael@0 10 * The original ICU license of the code follows:
michael@0 11 *
michael@0 12 * ICU License - ICU 1.8.1 and later
michael@0 13 *
michael@0 14 * COPYRIGHT AND PERMISSION NOTICE
michael@0 15 *
michael@0 16 * Copyright (c) 1995-2009 International Business Machines Corporation and
michael@0 17 * others
michael@0 18 *
michael@0 19 * All rights reserved.
michael@0 20 *
michael@0 21 * Permission is hereby granted, free of charge, to any person obtaining a
michael@0 22 * copy of this software and associated documentation files (the "Software"),
michael@0 23 * to deal in the Software without restriction, including without limitation
michael@0 24 * the rights to use, copy, modify, merge, publish, distribute, and/or sell
michael@0 25 * copies of the Software, and to permit persons to whom the Software is
michael@0 26 * furnished to do so, provided that the above copyright notice(s) and this
michael@0 27 * permission notice appear in all copies of the Software and that both the
michael@0 28 * above copyright notice(s) and this permission notice appear in supporting
michael@0 29 * documentation.
michael@0 30 *
michael@0 31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
michael@0 32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
michael@0 33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
michael@0 34 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
michael@0 35 * BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
michael@0 36 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
michael@0 37 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
michael@0 38 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
michael@0 39 * SOFTWARE.
michael@0 40 *
michael@0 41 * Except as contained in this notice, the name of a copyright holder shall
michael@0 42 * not be used in advertising or otherwise to promote the sale, use or other
michael@0 43 * dealings in this Software without prior written authorization of the
michael@0 44 * copyright holder.
michael@0 45 *
michael@0 46 * All trademarks and registered trademarks mentioned herein are the property
michael@0 47 * of their respective owners.
michael@0 48 */
michael@0 49
michael@0 50 #include "gfxScriptItemizer.h"
michael@0 51 #include "nsUnicodeProperties.h"
michael@0 52 #include "nsCharTraits.h"
michael@0 53 #include "harfbuzz/hb.h"
michael@0 54
michael@0 55 #define MOD(sp) ((sp) % PAREN_STACK_DEPTH)
michael@0 56 #define LIMIT_INC(sp) (((sp) < PAREN_STACK_DEPTH)? (sp) + 1 : PAREN_STACK_DEPTH)
michael@0 57 #define INC(sp,count) (MOD((sp) + (count)))
michael@0 58 #define INC1(sp) (INC(sp, 1))
michael@0 59 #define DEC(sp,count) (MOD((sp) + PAREN_STACK_DEPTH - (count)))
michael@0 60 #define DEC1(sp) (DEC(sp, 1))
michael@0 61 #define STACK_IS_EMPTY() (pushCount <= 0)
michael@0 62 #define STACK_IS_NOT_EMPTY() (! STACK_IS_EMPTY())
michael@0 63 #define TOP() (parenStack[parenSP])
michael@0 64 #define SYNC_FIXUP() (fixupCount = 0)
michael@0 65
michael@0 66 void
michael@0 67 gfxScriptItemizer::push(uint32_t endPairChar, int32_t scriptCode)
michael@0 68 {
michael@0 69 pushCount = LIMIT_INC(pushCount);
michael@0 70 fixupCount = LIMIT_INC(fixupCount);
michael@0 71
michael@0 72 parenSP = INC1(parenSP);
michael@0 73 parenStack[parenSP].endPairChar = endPairChar;
michael@0 74 parenStack[parenSP].scriptCode = scriptCode;
michael@0 75 }
michael@0 76
michael@0 77 void
michael@0 78 gfxScriptItemizer::pop()
michael@0 79 {
michael@0 80 if (STACK_IS_EMPTY()) {
michael@0 81 return;
michael@0 82 }
michael@0 83
michael@0 84 if (fixupCount > 0) {
michael@0 85 fixupCount -= 1;
michael@0 86 }
michael@0 87
michael@0 88 pushCount -= 1;
michael@0 89 parenSP = DEC1(parenSP);
michael@0 90
michael@0 91 /* If the stack is now empty, reset the stack
michael@0 92 pointers to their initial values.
michael@0 93 */
michael@0 94 if (STACK_IS_EMPTY()) {
michael@0 95 parenSP = -1;
michael@0 96 }
michael@0 97 }
michael@0 98
michael@0 99 void
michael@0 100 gfxScriptItemizer::fixup(int32_t scriptCode)
michael@0 101 {
michael@0 102 int32_t fixupSP = DEC(parenSP, fixupCount);
michael@0 103
michael@0 104 while (fixupCount-- > 0) {
michael@0 105 fixupSP = INC1(fixupSP);
michael@0 106 parenStack[fixupSP].scriptCode = scriptCode;
michael@0 107 }
michael@0 108 }
michael@0 109
michael@0 110 static inline bool
michael@0 111 SameScript(int32_t runScript, int32_t currCharScript)
michael@0 112 {
michael@0 113 return runScript <= MOZ_SCRIPT_INHERITED ||
michael@0 114 currCharScript <= MOZ_SCRIPT_INHERITED ||
michael@0 115 currCharScript == runScript;
michael@0 116 }
michael@0 117
michael@0 118 // Return whether the char has a mirrored-pair counterpart.
michael@0 119 // NOTE that this depends on the implementation of nsCharProps records in
michael@0 120 // nsUnicodeProperties, and may need to be updated if those structures change
michael@0 121 static inline bool
michael@0 122 HasMirroredChar(uint32_t aCh)
michael@0 123 {
michael@0 124 return GetCharProps1(aCh).mMirrorOffsetIndex != 0;
michael@0 125 }
michael@0 126
michael@0 127 gfxScriptItemizer::gfxScriptItemizer(const char16_t *src, uint32_t length)
michael@0 128 : textPtr(src), textLength(length)
michael@0 129 {
michael@0 130 reset();
michael@0 131 }
michael@0 132
michael@0 133 void
michael@0 134 gfxScriptItemizer::SetText(const char16_t *src, uint32_t length)
michael@0 135 {
michael@0 136 textPtr = src;
michael@0 137 textLength = length;
michael@0 138
michael@0 139 reset();
michael@0 140 }
michael@0 141
michael@0 142 bool
michael@0 143 gfxScriptItemizer::Next(uint32_t& aRunStart, uint32_t& aRunLimit,
michael@0 144 int32_t& aRunScript)
michael@0 145 {
michael@0 146 /* if we've fallen off the end of the text, we're done */
michael@0 147 if (scriptLimit >= textLength) {
michael@0 148 return false;
michael@0 149 }
michael@0 150
michael@0 151 SYNC_FIXUP();
michael@0 152 scriptCode = MOZ_SCRIPT_COMMON;
michael@0 153
michael@0 154 for (scriptStart = scriptLimit; scriptLimit < textLength; scriptLimit += 1) {
michael@0 155 uint32_t ch;
michael@0 156 int32_t sc;
michael@0 157 uint32_t startOfChar = scriptLimit;
michael@0 158
michael@0 159 ch = textPtr[scriptLimit];
michael@0 160
michael@0 161 /* decode UTF-16 (may be surrogate pair) */
michael@0 162 if (NS_IS_HIGH_SURROGATE(ch) && scriptLimit < textLength - 1) {
michael@0 163 uint32_t low = textPtr[scriptLimit + 1];
michael@0 164 if (NS_IS_LOW_SURROGATE(low)) {
michael@0 165 ch = SURROGATE_TO_UCS4(ch, low);
michael@0 166 scriptLimit += 1;
michael@0 167 }
michael@0 168 }
michael@0 169
michael@0 170 // Get the nsCharProps2 record for the current character,
michael@0 171 // so we can read the script and (if needed) the gen category
michael@0 172 // without needing to do two multi-level lookups.
michael@0 173 // NOTE that this means we're relying on an implementation detail
michael@0 174 // of the nsUnicodeProperties tables, and might have to revise this
michael@0 175 // if the nsCharProps records used there are modified in future.
michael@0 176 const nsCharProps2& charProps = GetCharProps2(ch);
michael@0 177
michael@0 178 // Initialize gc to UNASSIGNED; we'll only set it to the true GC
michael@0 179 // if the character has script=COMMON, otherwise we don't care.
michael@0 180 uint8_t gc = HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
michael@0 181
michael@0 182 sc = charProps.mScriptCode;
michael@0 183 if (sc == MOZ_SCRIPT_COMMON) {
michael@0 184 /*
michael@0 185 * Paired character handling:
michael@0 186 *
michael@0 187 * if it's an open character, push it onto the stack.
michael@0 188 * if it's a close character, find the matching open on the
michael@0 189 * stack, and use that script code. Any non-matching open
michael@0 190 * characters above it on the stack will be popped.
michael@0 191 *
michael@0 192 * We only do this if the script is COMMON; for chars with
michael@0 193 * specific script assignments, we just use them as-is.
michael@0 194 */
michael@0 195 gc = charProps.mCategory;
michael@0 196 if (gc == HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION) {
michael@0 197 uint32_t endPairChar = mozilla::unicode::GetMirroredChar(ch);
michael@0 198 if (endPairChar != ch) {
michael@0 199 push(endPairChar, scriptCode);
michael@0 200 }
michael@0 201 } else if (gc == HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION &&
michael@0 202 HasMirroredChar(ch))
michael@0 203 {
michael@0 204 while (STACK_IS_NOT_EMPTY() && TOP().endPairChar != ch) {
michael@0 205 pop();
michael@0 206 }
michael@0 207
michael@0 208 if (STACK_IS_NOT_EMPTY()) {
michael@0 209 sc = TOP().scriptCode;
michael@0 210 }
michael@0 211 }
michael@0 212 }
michael@0 213
michael@0 214 if (SameScript(scriptCode, sc)) {
michael@0 215 if (scriptCode <= MOZ_SCRIPT_INHERITED &&
michael@0 216 sc > MOZ_SCRIPT_INHERITED)
michael@0 217 {
michael@0 218 scriptCode = sc;
michael@0 219 fixup(scriptCode);
michael@0 220 }
michael@0 221
michael@0 222 /*
michael@0 223 * if this character is a close paired character,
michael@0 224 * pop the matching open character from the stack
michael@0 225 */
michael@0 226 if (gc == HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION &&
michael@0 227 HasMirroredChar(ch)) {
michael@0 228 pop();
michael@0 229 }
michael@0 230 } else {
michael@0 231 /*
michael@0 232 * reset scriptLimit in case it was advanced during reading a
michael@0 233 * multiple-code-unit character
michael@0 234 */
michael@0 235 scriptLimit = startOfChar;
michael@0 236
michael@0 237 break;
michael@0 238 }
michael@0 239 }
michael@0 240
michael@0 241 aRunStart = scriptStart;
michael@0 242 aRunLimit = scriptLimit;
michael@0 243 aRunScript = scriptCode;
michael@0 244
michael@0 245 return true;
michael@0 246 }

mercurial