11830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com/* 21830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com * Copyright 2011 Google Inc. 31830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com * 41830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com * Use of this source code is governed by a BSD-style license that can be 51830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com * found in the LICENSE file. 61830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com */ 7bf0001d0472d727266762c5967ec0d919a6df083reed@google.com 81830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SampleCode.h" 91830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkDumpCanvas.h" 101830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkView.h" 111830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkCanvas.h" 121830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkGradientShader.h" 131830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkGraphics.h" 141830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkImageDecoder.h" 15796763e0b2c06a7789185322561a1135e5484688djsollen@google.com#include "SkOSFile.h" 161830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkPath.h" 171830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkPicture.h" 18770963f23f4fc313db0fa3bac18b1b8aafb55f17robertphillips@google.com#include "SkPictureRecorder.h" 191830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkRandom.h" 201830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkRegion.h" 211830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkShader.h" 221830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkUtils.h" 231830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkColorPriv.h" 241830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkColorFilter.h" 251830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkTime.h" 261830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkTypeface.h" 271830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkXfermode.h" 281830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com 291830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkStream.h" 30636d87a3f411507020a21c6b0641da795eb5d275reed@google.com#include "SkSurface.h" 311830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#include "SkXMLParser.h" 321830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com 331830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.comclass PictFileView : public SampleView { 34bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.orgpublic: 35bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org PictFileView(const char name[] = NULL) 36bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org : fFilename(name) 37bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org , fBBox(kNo_BBoxType) 38bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org , fTileSize(SkSize::Make(0, 0)) { 399a65e2c22dc3f0d4823520ab3d561f57ff09198cfmalita@google.com for (int i = 0; i < kBBoxTypeCount; ++i) { 40bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org fPictures[i] = NULL; 41bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 42bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 43bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org 44bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org virtual ~PictFileView() { 459a65e2c22dc3f0d4823520ab3d561f57ff09198cfmalita@google.com for (int i = 0; i < kBBoxTypeCount; ++i) { 46bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org SkSafeUnref(fPictures[i]); 47bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 48bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 49bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org 50bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org virtual void onTileSizeChanged(const SkSize &tileSize) SK_OVERRIDE { 51bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org if (tileSize != fTileSize) { 52bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org fTileSize = tileSize; 53bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org SkSafeSetNull(fPictures[kTileGrid_BBoxType]); 54bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 55bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 56bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org 57bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.orgprotected: 58bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org // overrides from SkEventSink 59bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org virtual bool onQuery(SkEvent* evt) SK_OVERRIDE { 60bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org if (SampleCode::TitleQ(*evt)) { 61bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org SkString name("P:"); 62bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org const char* basename = strrchr(fFilename.c_str(), SkPATH_SEPARATOR); 63bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org name.append(basename ? basename+1: fFilename.c_str()); 64c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org switch (fBBox) { 65c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org case kNo_BBoxType: 66c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org // No name appended 67c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org break; 68c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org case kRTree_BBoxType: 69c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org name.append(" <bbox: R>"); 70c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org break; 71c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org case kTileGrid_BBoxType: 72c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org name.append(" <bbox: T>"); 73c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org break; 74c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org default: 75c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org SkASSERT(false); 76c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org break; 77bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 78bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org SampleCode::TitleR(evt, name.c_str()); 79bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org return true; 80bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 81bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org return this->INHERITED::onQuery(evt); 82bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 83bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org 84bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org virtual bool onEvent(const SkEvent& evt) SK_OVERRIDE { 85bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org if (evt.isType("PictFileView::toggleBBox")) { 86bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org fBBox = (BBoxType)((fBBox + 1) % kBBoxTypeCount); 87bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org return true; 88bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 89bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org return this->INHERITED::onEvent(evt); 90bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 91bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org 92bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org virtual void onDrawContent(SkCanvas* canvas) SK_OVERRIDE { 938c6f4b3261fde699f17016e289aa6aceee4ea63acommit-bot@chromium.org SkASSERT(static_cast<int>(fBBox) < kBBoxTypeCount); 94bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org SkPicture** picture = fPictures + fBBox; 95bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org 96bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org if (!*picture) { 97bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org *picture = LoadPicture(fFilename.c_str(), fBBox); 98bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 99bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org if (*picture) { 1009b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips canvas->drawPicture(*picture); 101bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 102bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org } 103bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org 104bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.orgprivate: 105bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org enum BBoxType { 106bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org kNo_BBoxType, 107bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org kRTree_BBoxType, 108bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org kTileGrid_BBoxType, 109bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org 110bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org kLast_BBoxType = kTileGrid_BBoxType 111bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org }; 112e6a98d4259532d2f1d899131b72c6c4cd58f2903fmalita@google.com static const int kBBoxTypeCount = kLast_BBoxType + 1; 113bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org 1141830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com SkString fFilename; 115bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org SkPicture* fPictures[kBBoxTypeCount]; 116bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org BBoxType fBBox; 117bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org SkSize fTileSize; 118ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com 119bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org SkPicture* LoadPicture(const char path[], BBoxType bbox) { 12084b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com SkAutoTUnref<SkPicture> pic; 121b196374e6f5b66ba911a2be6ddb31c6692a3615areed@google.com 122b196374e6f5b66ba911a2be6ddb31c6692a3615areed@google.com SkBitmap bm; 123b196374e6f5b66ba911a2be6ddb31c6692a3615areed@google.com if (SkImageDecoder::DecodeFile(path, &bm)) { 124b196374e6f5b66ba911a2be6ddb31c6692a3615areed@google.com bm.setImmutable(); 12584b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com SkPictureRecorder recorder; 126a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips SkCanvas* can = recorder.beginRecording(SkIntToScalar(bm.width()), 127a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips SkIntToScalar(bm.height()), 128a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips NULL, 0); 129b196374e6f5b66ba911a2be6ddb31c6692a3615areed@google.com can->drawBitmap(bm, 0, 0, NULL); 13084b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com pic.reset(recorder.endRecording()); 131b196374e6f5b66ba911a2be6ddb31c6692a3615areed@google.com } else { 132b196374e6f5b66ba911a2be6ddb31c6692a3615areed@google.com SkFILEStream stream(path); 133b196374e6f5b66ba911a2be6ddb31c6692a3615areed@google.com if (stream.isValid()) { 13484b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com pic.reset(SkPicture::CreateFromStream(&stream)); 135b8b830e012d5009bc2ac195f2ac5309f8ae7bb4areed@google.com } else { 136b8b830e012d5009bc2ac195f2ac5309f8ae7bb4areed@google.com SkDebugf("coun't load picture at \"path\"\n", path); 137b196374e6f5b66ba911a2be6ddb31c6692a3615areed@google.com } 13811f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com 139636d87a3f411507020a21c6b0641da795eb5d275reed@google.com if (false) { 140a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips SkSurface* surf = SkSurface::NewRasterPMColor(SkScalarCeilToInt(pic->cullRect().width()), 141a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips SkScalarCeilToInt(pic->cullRect().height())); 1429b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips surf->getCanvas()->drawPicture(pic); 143636d87a3f411507020a21c6b0641da795eb5d275reed@google.com surf->unref(); 144636d87a3f411507020a21c6b0641da795eb5d275reed@google.com } 1450a5c18ba79862ee4a348eff42cd4fbeb5ef12feereed@google.com if (false) { // re-record 14684b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com SkPictureRecorder recorder; 147c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips pic->playback(recorder.beginRecording(pic->cullRect().width(), 148c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips pic->cullRect().height(), 149c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips NULL, 0)); 15084b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com SkAutoTUnref<SkPicture> p2(recorder.endRecording()); 15111f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com 1520a5c18ba79862ee4a348eff42cd4fbeb5ef12feereed@google.com SkString path2(path); 1530a5c18ba79862ee4a348eff42cd4fbeb5ef12feereed@google.com path2.append(".new.skp"); 1540a5c18ba79862ee4a348eff42cd4fbeb5ef12feereed@google.com SkFILEWStream writer(path2.c_str()); 15584b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com p2->serialize(&writer); 1560a5c18ba79862ee4a348eff42cd4fbeb5ef12feereed@google.com } 157b196374e6f5b66ba911a2be6ddb31c6692a3615areed@google.com } 158796763e0b2c06a7789185322561a1135e5484688djsollen@google.com 15984b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com if (NULL == pic) { 160bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org return NULL; 161796763e0b2c06a7789185322561a1135e5484688djsollen@google.com } 162ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com 1635fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org SkAutoTDelete<SkBBHFactory> factory; 164bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org switch (bbox) { 165bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org case kNo_BBoxType: 166bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org // no bbox playback necessary 16784b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com return pic.detach(); 168bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org case kRTree_BBoxType: 1695fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org factory.reset(SkNEW(SkRTreeFactory)); 170bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org break; 171bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org case kTileGrid_BBoxType: { 172bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org SkASSERT(!fTileSize.isEmpty()); 1735fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org SkTileGridFactory::TileGridInfo gridInfo; 174bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org gridInfo.fMargin = SkISize::Make(0, 0); 175bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org gridInfo.fOffset = SkIPoint::Make(0, 0); 176bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org gridInfo.fTileInterval = fTileSize.toRound(); 1775fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org factory.reset(SkNEW_ARGS(SkTileGridFactory, (gridInfo))); 17884b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com break; 17984b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com } 180bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org default: 181bbe43a9ce0513d37cbd5dca583c391b7b1e39b3acommit-bot@chromium.org SkASSERT(false); 1821830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com } 183ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com 1845fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org SkPictureRecorder recorder; 185c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips pic->playback(recorder.beginRecording(pic->cullRect().width(), 186c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips pic->cullRect().height(), 187c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips factory.get(), 0)); 18884b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com return recorder.endRecording(); 1891830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com } 190ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com 1911830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com typedef SampleView INHERITED; 1921830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com}; 1931830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com 1941830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.comSampleView* CreateSamplePictFileView(const char filename[]); 1951830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.comSampleView* CreateSamplePictFileView(const char filename[]) { 1961830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com return new PictFileView(filename); 1971830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com} 1981830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com 1991830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com////////////////////////////////////////////////////////////////////////////// 2001830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com 2011830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#if 0 2021830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.comstatic SkView* MyFactory() { return new PictFileView; } 2031830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.comstatic SkViewRegister reg(MyFactory); 2041830c7aa3c4045af438fb24ee0bd22598f1bfca7reed@google.com#endif 205