1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org */ 828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 1028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#ifndef SkPDFFont_DEFINED 1128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#define SkPDFFont_DEFINED 1228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 139db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org#include "SkAdvancedTypefaceMetrics.h" 149859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "SkBitSet.h" 1528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkPDFTypes.h" 1628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkTDArray.h" 1728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkThread.h" 189859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "SkTypeface.h" 1928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 2028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.orgclass SkPaint; 219859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgclass SkPDFCatalog; 229859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgclass SkPDFFont; 239859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 24e3beb6bd7de7fa211681abbb0be58e80b19885e0commit-bot@chromium.orgclass SkPDFGlyphSet : SkNoncopyable { 259859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgpublic: 269859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkPDFGlyphSet(); 279859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 289859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org void set(const uint16_t* glyphIDs, int numGlyphs); 299859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org bool has(uint16_t glyphID) const; 309859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org void merge(const SkPDFGlyphSet& usage); 3117e66e2d341ab684eec7841fd383af85bb4aa625vandebo@chromium.org void exportTo(SkTDArray<uint32_t>* glyphIDs) const; 329859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 339859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgprivate: 349859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkBitSet fBitSet; 359859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org}; 369859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 37e3beb6bd7de7fa211681abbb0be58e80b19885e0commit-bot@chromium.orgclass SkPDFGlyphSetMap : SkNoncopyable { 389859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgpublic: 399859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org struct FontGlyphSetPair { 409859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org FontGlyphSetPair(SkPDFFont* font, SkPDFGlyphSet* glyphSet); 419859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 429859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkPDFFont* fFont; 439859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkPDFGlyphSet* fGlyphSet; 449859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org }; 459859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 469859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkPDFGlyphSetMap(); 479859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org ~SkPDFGlyphSetMap(); 489859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 499859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org class F2BIter { 509859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org public: 51a5c7234e81748f76cbeede40e619351146e5286actguil@chromium.org explicit F2BIter(const SkPDFGlyphSetMap& map); 52aa537d4bdb2384cdcd0644a02a2ab7fb0ecdd3b3commit-bot@chromium.org const FontGlyphSetPair* next() const; 539859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org void reset(const SkPDFGlyphSetMap& map); 549859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 559859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org private: 569859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org const SkTDArray<FontGlyphSetPair>* fMap; 579859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org mutable int fIndex; 589859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org }; 599859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 609859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org void merge(const SkPDFGlyphSetMap& usage); 619859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org void reset(); 629859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 639859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org void noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs, 649859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org int numGlyphs); 659859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 669859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgprivate: 679859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkPDFGlyphSet* getGlyphSetForFont(SkPDFFont* font); 689859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 699859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkTDArray<FontGlyphSetPair> fMap; 709859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org}; 719859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 7228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 7328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org/** \class SkPDFFont 7428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org A PDF Object class representing a font. The font may have resources 7528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org attached to it in order to embed the font. SkPDFFonts are canonicalized 7628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org so that resource deduplication will only include one copy of a font. 7728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org This class uses the same pattern as SkPDFGraphicState, a static weak 7828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org reference to each instantiated class. 7928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org*/ 8028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.orgclass SkPDFFont : public SkPDFDict { 81ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org SK_DECLARE_INST_COUNT(SkPDFFont) 8228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.orgpublic: 837d6c8f997f8fe2c222f9d6d31f984c2e7cf16cc5vandebo@chromium.org virtual ~SkPDFFont(); 8428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 856addb1930013ebb2f984045141650fd7afcfa90fedisonn@google.com virtual void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 866addb1930013ebb2f984045141650fd7afcfa90fedisonn@google.com SkTSet<SkPDFObject*>* newResourceObjects); 8728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 889db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org /** Returns the typeface represented by this class. Returns NULL for the 899db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org * default typeface. 9028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org */ 917d6c8f997f8fe2c222f9d6d31f984c2e7cf16cc5vandebo@chromium.org SkTypeface* typeface(); 9228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 93f0ec2666d9a3f0f1662f0d63b5147628c49648aavandebo@chromium.org /** Returns the font type represented in this font. For Type0 fonts, 94f0ec2666d9a3f0f1662f0d63b5147628c49648aavandebo@chromium.org * returns the type of the decendant font. 95f0ec2666d9a3f0f1662f0d63b5147628c49648aavandebo@chromium.org */ 967d6c8f997f8fe2c222f9d6d31f984c2e7cf16cc5vandebo@chromium.org virtual SkAdvancedTypefaceMetrics::FontType getType(); 972a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 989859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org /** Returns true if this font encoding supports glyph IDs above 255. 9928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org */ 1007d6c8f997f8fe2c222f9d6d31f984c2e7cf16cc5vandebo@chromium.org virtual bool multiByteGlyphs() const = 0; 10128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 1020f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo /** Returns true if the machine readable licensing bits allow embedding. 1030f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo */ 1040f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo bool canEmbed() const; 1050f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo 1060f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo /** Returns true if the machine readable licensing bits allow subsetting. 1070f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo */ 1080f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo bool canSubset() const; 1090f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo 1109859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org /** Return true if this font has an encoding for the passed glyph id. 11131dcee7b84ac8a50fe8269a39ac0431b01da48d1vandebo@chromium.org */ 1127d6c8f997f8fe2c222f9d6d31f984c2e7cf16cc5vandebo@chromium.org bool hasGlyph(uint16_t glyphID); 11331dcee7b84ac8a50fe8269a39ac0431b01da48d1vandebo@chromium.org 1140129410fbe4b88a0632fb7aa5185610b30e69852vandebo@chromium.org /** Convert (in place) the input glyph IDs into the font encoding. If the 1150129410fbe4b88a0632fb7aa5185610b30e69852vandebo@chromium.org * font has more glyphs than can be encoded (like a type 1 font with more 1160129410fbe4b88a0632fb7aa5185610b30e69852vandebo@chromium.org * than 255 glyphs) this method only converts up to the first out of range 1172a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org * glyph ID. 1182a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org * @param glyphIDs The input text as glyph IDs. 1192a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org * @param numGlyphs The number of input glyphs. 1202a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org * @return Returns the number of glyphs consumed. 12128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org */ 122aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com int glyphsToPDFFontEncoding(uint16_t* glyphIDs, int numGlyphs); 1232a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 1249db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org /** Get the font resource for the passed typeface and glyphID. The 1252a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org * reference count of the object is incremented and it is the caller's 1262a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org * responsibility to unreference it when done. This is needed to 1272a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org * accommodate the weak reference pattern used when the returned object 1282a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org * is new and has no other references. 1299db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org * @param typeface The typeface to find. 1309db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org * @param glyphID Specify which section of a large font is of interest. 13128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org */ 1320f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo static SkPDFFont* GetFontResource(SkTypeface* typeface, uint16_t glyphID); 13328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 1349859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org /** Subset the font based on usage set. Returns a SkPDFFont instance with 1359859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org * subset. 1369859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org * @param usage Glyph subset requested. 1379859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org * @return NULL if font does not support subsetting, a new instance 1389859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org * of SkPDFFont otherwise. 1399859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org */ 1407d6c8f997f8fe2c222f9d6d31f984c2e7cf16cc5vandebo@chromium.org virtual SkPDFFont* getFontSubset(const SkPDFGlyphSet* usage); 1419859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 1429859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgprotected: 1439859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // Common constructor to handle common members. 1449859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkPDFFont(SkAdvancedTypefaceMetrics* fontInfo, SkTypeface* typeface, 145e2e8113baa69b5d1a0bae9652a095c1eb44b3a53sugoi@google.com SkPDFDict* relatedFontDescriptor); 1469859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 1479859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // Accessors for subclass. 1489859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkAdvancedTypefaceMetrics* fontInfo(); 14937ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org void setFontInfo(SkAdvancedTypefaceMetrics* info); 1509859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org uint16_t firstGlyphID() const; 1519859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org uint16_t lastGlyphID() const; 1529859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org void setLastGlyphID(uint16_t glyphID); 1539859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 1549859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // Add object to resource list. 1559859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org void addResource(SkPDFObject* object); 1569859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 1579859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // Accessors for FontDescriptor associated with this object. 1589859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkPDFDict* getFontDescriptor(); 1599859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org void setFontDescriptor(SkPDFDict* descriptor); 1609859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 1619859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // Add common entries to FontDescriptor. 1629859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org bool addCommonFontDescriptorEntries(int16_t defaultWidth); 1639859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 1649859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org /** Set fFirstGlyphID and fLastGlyphID to span at most 255 glyphs, 1659859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org * including the passed glyphID. 1669859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org */ 1679859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org void adjustGlyphRangeForSingleByteEncoding(int16_t glyphID); 1689859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 1699859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // Generate ToUnicode table according to glyph usage subset. 1709859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // If subset is NULL, all available glyph ids will be used. 1719859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org void populateToUnicodeTable(const SkPDFGlyphSet* subset); 1729859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 1739859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // Create instances of derived types based on fontInfo. 1749859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org static SkPDFFont* Create(SkAdvancedTypefaceMetrics* fontInfo, 1759859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkTypeface* typeface, uint16_t glyphID, 176e2e8113baa69b5d1a0bae9652a095c1eb44b3a53sugoi@google.com SkPDFDict* relatedFontDescriptor); 1779859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 1789859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org static bool Find(uint32_t fontID, uint16_t glyphID, int* index); 1799859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 18028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.orgprivate: 1819859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org class FontRec { 1829859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org public: 1839859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkPDFFont* fFont; 1849859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org uint32_t fFontID; 1859859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org uint16_t fGlyphID; 1869859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 1879859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // A fGlyphID of 0 with no fFont always matches. 1889859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org bool operator==(const FontRec& b) const; 1899859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org FontRec(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID); 1909859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org }; 1919859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 192d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org SkAutoTUnref<SkTypeface> fTypeface; 19328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 1942a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org // The glyph IDs accessible with this font. For Type1 (non CID) fonts, 1952a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org // this will be a subset if the font has more than 255 glyphs. 1962a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org uint16_t fFirstGlyphID; 1972a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org uint16_t fLastGlyphID; 198d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org SkAutoTUnref<SkAdvancedTypefaceMetrics> fFontInfo; 19928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkTDArray<SkPDFObject*> fResources; 200d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org SkAutoTUnref<SkPDFDict> fDescriptor; 20128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 2029859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org SkAdvancedTypefaceMetrics::FontType fFontType; 20328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 20428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org // This should be made a hash table if performance is a problem. 205f6c3ebdeb135dcdb9af225bd7af77f1fe1f92787reed@google.com static SkTDArray<FontRec>& CanonicalFonts(); 2061771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.com static SkBaseMutex& CanonicalFontsMutex(); 207ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org typedef SkPDFDict INHERITED; 20828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org}; 20928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 21028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#endif 211